5 things to include in your project ASAP
Tags: react, javascript, typescript, devops
Published: 2021-03-22 01:03:08

After the launch of **v2.0** of my current project (TabMerger), I decided to learn/integrate a few items that really pushed my skills to the next level. Best of all, adding these to my projects made me very excited to work on new projects and/or refactor existing ones.

Here is TabMerger's repository which you can view to get ideas about how to add any of the features discussed below.

{% github lbragile/TabMerger %}

Here are the concepts I urge you to learn as they will hopefully bring the same excitement into your coding life - don't fall into the trap of pushing them off/procrastinating.

## Table of Contents 📑

1. [Testing](#testing)
2. [Linting - Static Testing](#linting)
  * [Source Code Linting](#eslint)
  * [Style Sheet Linting](#stylelint)
3. [TypeScript](#typescript)
4. [Module Aliasing](#aliasing)
5. [Documentation](#documentation)
6. [Conclusion](#conclusion)

## 1. Testing 🧪 <a name="testing"/>
I highly recommend [Jest](https://jestjs.io/) as it is available right out of the box when you use React (CRA), but you could also use other test runners like [Mocha](https://mochajs.org/), [Karma](https://karma-runner.github.io/latest/index.html), etc.

#### Why?
Do you want to manually test every little feature of your code **every** time you change/update/add something?
 
Yeah, no thanks, I would rather have a testing script that <u>automates</u> this for me. Plus it is super rewarding once you understand the main concepts. This is probably the *most* time consuming of all the items listed here.

  - Start with the basics - [Unit Testing](https://en.wikipedia.org/wiki/Unit_testing)

  - Look into [Mutation Testing](https://en.wikipedia.org/wiki/Mutation_testing) - this is insanely amazing once you understand how to use it! [Stryker](https://stryker-mutator.io/docs/) is the way to go here.

  - Once you understand your coverage reports from Jest & Stryker, add [Integration Tests](https://en.wikipedia.org/wiki/Integration_testing) and [E2E Tests](https://www.tutorialspoint.com/software_testing_dictionary/end_to_end_testing.htm) with [Jest Puppeteer](https://jestjs.io/docs/puppeteer) which is another easy to integrate module with React. 
<u>Disclaimer:</u> I haven't done this step yet for TabMerger but experimented with this in the past and it is very fun - feel free to contribute 😊. This should be simpler than unit testing as it is "Black Box" since you do not care about the internal (just input and output) rather than a unit tests' "White Box" approach.

#### TabMerger Testing
Here is a brief snapshot of TabMerger's current testing performance:
![TabMerger v2.0.0 testing performance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rcsoebt8r8nhsei51b6.png)

As you can see, with these test scripts, I can check the logic of all the files in my application with the help of around **250 tests** in less than **20 seconds**. This gives me a great deal of confidence that new features do not break existing code. There is still some room for improvement (uncovered lines and not exactly 100%), but the current state lets me easily add new features without endlessly pursuing a 100% coverage report - after all 99.5% rounds up 😉.

You can use `npm run test:all` to get these results.

TabMerger also uses mutation testing and currently [scores](https://dashboard.stryker-mutator.io/reports/github.com/lbragile/TabMerger/master) above **95%** (only 67/1499 mutants are undetected across all files).

I've parallelized the mutation testing scripts with a [matrix build](https://github.com/lbragile/TabMerger/blob/master/.github/workflows/testing.yml#L49) in GitHub to speed up the lengthy execution - from 12 hours to 5 hours. 

As you can see from the below post, testing is a relatively "hidden" gem that many developers are not aware of or simply need the reason to get started. Additionally, almost all experienced testers recommended Stryker for mutation testing!
{% reddit https://www.reddit.com/r/webdev/comments/l36w9s/finally_understand_testing_and_fully_tested_my/ %}

## 2. Linting - Static Testing 📐 <a name="linting"/>
You must have heard about [linting](https://en.wikipedia.org/wiki/Lint_(software)) by now and how amazing it is, but never wanted to delve into it since it sounds too complicated for little to no benefits. I felt exactly the same way until I started using it - and let me tell you linting is beyond *amazing*.

#### Source Code Linting <a name="eslint"/>
Add [ESLint](https://eslint.org/) to your project (even if you plan to use TypeScript). Imagine writing a very long essay/thesis in a Word document without grammar highlighting - do you think you will be flawless? Isn't it nice to be warned of any inaccuracies/errors you made right away?

That's exactly ESLint's purpose inside your VSCode IDE (assuming everything is setup right). You can configure it to follow specific rules according to your liking. So far, this fixed **a lot** of issues in my code - from small to *large* - and even allowed me to learn new Javascript concepts. 

For example, I learned that `const` means constant <u>reference</u> rather than simply <u>value</u>, so you could actually have a `const` array whose elements can be changed, added or removed. The same is not true for a `const` variable. That is,
```typescript
const arr: number[] = [];
arr.push(1) // valid
console.log(arr) // [1]

const val = 5;
val = 1; // error
```
Here is an example of what ESLint looks like:
![ESLint in VS Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mry7x7mm03s5i4okao6a.png) 

As you can see, the instructions are very clear and you are even provided with quick actions from VSCode which can be accessed with `ctrl + .`
 
#### Style Sheet Linting <a name="stylelint"/>
Now that you have ESLint working, you should consider [StyleLint](https://stylelint.io/user-guide/get-started) for your styling files (CSS, SASS, LESS, etc.). 

This helps reduce duplicates that are scattered across your many files on large projects. StyleLint also enforces best standards such as the following:

###### Spacing Errors
![Stylelint Spacing Errors in VS Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v33t5aeqffp3keoyonml.png)

###### Unit Errors
![Stylelint Unit Errors in VS Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2shex6hamexn5ja2lra5.png)

###### Duplicates
![Stylelint Duplicates in VS Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4ahd3957lc1ta2b9kv2.png)
 
Additionally, StyleLint detects when you forget to add blank lines between blocks of styles and/or if you have an extra space in a block comment like: 
```css
/* <- space
 * comment
 */
```

#### TabMerger Linting
TabMerger uses both linting types dynamically (through the use of IDE extensions: `ESLint` & `stylelint`) and manually:
- `npm run lint` → ESLint
- `npm run lint:style` → StyleLint

Manually linting will produce a report in the command line that will outline all the errors across all files so that you can quickly find them (rather than opening each file one by one). Here is an example: 
![Manual Style Lint in TabMerger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2nom75u5lxzkcl5bsndr.png)

**Note:** a clean run will produce no output.
 
## 3. TypeScript ✍ <a name="typescript"/>
With both of these linters, you will be happy to know that [TypeScript](https://www.typescriptlang.org/) (TS) also offers "linting" in the form of <u>type control</u>. 

This is **super** useful when working on any project as you can quickly hover over **anything** (function, variable, etc.) to get more type specific information in your IDE. TypeScript is also very well integrated with VS Code.

Typing information can be seen by hovering:
![TypeScript Type Information](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jo6m6kycycewpz9fqrre.png)
 
Here is how TypeScript errors look like:
###### Error
![TypeScript Error Demonstration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3fmns9pqqhytzkqyae1.png)

###### No Error
![TypeScript Without Error Demonstration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92ln6hfi8aqvi0codtg0.png)

A good point about TypeScript is that you can slowly/incrementally modify your JavaScript files in existing projects and everything will still work fine - since TS files get compiled to JS. Check out [TabMerger's repository](https://github.com/lbragile/TabMerger) to see how I structured my project to incorporate and successfully run with TypeScript.

I am still in the process of learning TypeScript and in TabMerger I currently have around 100 places where I am not sure how to "type" properly - so I am by no means a master with TypeScript - but ever since I started using it, I haven't looked back. 

So far, I've refactored pretty much all my old projects to include TypeScript in one way or another. The typing information it provides and just the process of migrating to TypeScript is very rewarding and useful! 

It will take longer to get used to TypeScript than linting but it should not take too long before you start seeing how useful TS is.

## 4. Module Aliasing 💥 <a name="aliasing"/>
Tired of looking up your directory tree to know the relative path of your `import`?

This can certainly slow down your workflow and is not very practical when you consider the fact that users/contributors do not want to look up your structure just to use your module. It is very common for npm/yarn packages to have their module paths aliased to simpler names that are mapped to the correct paths.

To do this in TS, you can add the `baseURL` and `paths` options to your TS configuration file. If done right, this allows you to `import { A } from @A/A` instead of `import { A } from ../components/A/A`. 

Example from one of TabMerger's files:

###### Without Aliasing
![Without Module Aliasing in TabMerger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oyvbylg0ojqjjn5plj0d.png) 
 
###### With Aliasing
![With Module Aliasing in TabMerger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vgcpuqy5pg7uhv8ahme.png) 

Unfortunately, React's build scripts prevent the `paths` option in the `tsconfig.json`, so a work around is needed to get this working properly:

- `npm i -D react-app-rewired`
- Add `config-overrides.js` to root (see TabMerger's [file](https://github.com/lbragile/TabMerger/blob/master/config-overrides.js))
- Ensure `alias` object matches your aliases as shown in the file from the previous step
- change `start: react-scripts start` to `start: react-app-rewired start` and the same for the build script (see TabMerger's [file](https://github.com/lbragile/TabMerger/blob/master/package.json#L51))

You will also need to [adjust](https://github.com/lbragile/TabMerger/blob/master/config/jest.config.js#L14) your `jest.config.js` by adding the alias' and their corresponding true paths to the `moduleNameMapper` property. 

Note that you can use [RegExp variables](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/n) to shorten these key/value pairs.

## 5. Documentation 📚 <a name="documentation"/>
By now, you might have noticed that the functions I posted in some of the above images have a specific comment syntax. Something like:
![TabMerger's Documentation Comments](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lg93pihdp2avzz4f14i7.png)

This is done on purpose to generate good looking documentation as seen [here](https://lbragile.github.io/TabMerger/modules/app_app_functions.html). The main modules which generate these documentation reports are [jsDoc](https://jsdoc.app/) (Javascript) and [typeDoc](https://typedoc.org/) (TypeScript). 

Commenting your code like this will make it much easier to follow for anyone who visits it for the first time. It might also allow you to remember that hard to understand part in your code. The added bonus of using such comments for documentation is that it makes the transition from JS to TS much smoother as you can "infer" types from the comments using VS Code to automatically type your function arguments and return values.

You can [see](https://lbragile.github.io/TabMerger/) that only specific modules are shown on the documentation's main page. This can be controlled by a [configuration file](https://github.com/lbragile/TabMerger/blob/master/config/typedoc.config.json) and by adding the following to the top of your respective files:

```javascript
/**
 * @module MODULE_NAME
 */
```
#### TabMerger Documentation Generation
In TabMerger, you can use the following commands to generate documentation reports:
- `npm run jsdoc` (JavaScript)
- `npm run typedoc` (TypeScript)

## Conclusion <a name="conclusion"/>
I hope my suggestions are useful to some of you. I urge you to take action and add these items to your project as soon as possible. 

I can almost guarantee that you will instantly be more excited to work on your project(s) (granted everything works as expected). Worst thing that can happen is you cannot get one of the items to work properly or just don't find it that useful. In that case, you can simply revert back to the good old days 😊.

I am actually in the process of looking for work so have a "lot" of spare time to help anyone who is confused or stuck on any of these items.

Cheers 🥂