Tools

Tooling is indeed crucial for our productivity. Let’s see what can be done on this front.

Let’s start with package manager…

Package Manager/Task Runner

Most of you are probably using npm, which was super annoying to use and slow until version 5. While npm is constantly improving, you don’t have to wait and instead you can switch to a better tool -> yarn

I’m not going to enumerate all the benefits, just a few time savers that you can leverage on daily basis.

How would you execute locally installed TypeScript from CLI with npm, or execute custom npm-script or pass additional arguments to your custom npm-script ? You’re smart and sure know how to do those, but with yarn it’s much easier. Comparison is on following image:

npm vs yarn ( from task runner perspective )

How are you bumping you dependencies ? Manually by hand ? Seriously ? We can do better with yarn:

yarn upgrade-interactive

Just to not be biased against npm, you can achieve the same via 3rd party package(npm-check) and npx via npx npm-check -u just sayin’...

Formatting

CLI comes with pre-configured TSLint supported by Codelyzer, which helps us lint our code and adhere to strictly set style guides within our project. TSLint takes also care of consistent spaces at various places ( functions, module imports, etc… ), empty lines, single/double quotes, semicolons/no-semicolons… But if you think that this is the right way to do formatting, you are fundamentally wrong. Anyway, Lint is for linting not for formatting !

So how can we efficiently/consistently format our codebase instead of using wrong tool for that job — yes I’m talking about you Mr. linter(TSlint) ?

Ladies and gentleman, please welcome, The humble Prettier!

is an opinionated formatter created by Facebook and OSS community. You can read more about it on prettier website.

We can add it to our CLI very easily:

Install:

yarn add -D prettier

and define a new npm script:

{

"scripts": {

"format": "prettier {src/e2e}/**/* --write"

}

}

By executing yarn format our whole codebase is formatted in matter of seconds and it's super fast!

That’s it? Not entirely! Because TSlint contains formatting rules, which has nothing to do with linting, we need to turn off these rules… Uff looks like lot of manual work !

tslint-config-prettier

Thanks to OSS we can leverage tslint-config-prettier package, which handles everything for us!

Install:

yarn add -D tslint-config-prettier

and extend tslint.json rules with it:

{

"extends": [

"tslint-config-prettier"

],

"rulesDirectory": [

"node_modules/codelyzer"

],

"rules": {...}

}

There are still issues though. CLI defines lot’s of rules within tslint.json which are overriding anything that extends our config. Again, tslint-config-prettier comes with a handy CLI tool, that detects those rules in conflict, which need to be removed:

By executing local binary:

yarn tslint-config-prettier-check ./tslint.json

We will get output like this:

tslint-config-prettier-check output

I see a great PR opportunity here, to automate removal of those conflicting lint rules ;)

Formatting/Linting Done!

There is room for improvement though! I don’t know about you, but I’m lazy and just the thought of manually executing former command to format/lint my code, makes me ill…

Hey Robot! Do your work!

Robots (I mean npm packages) can handle that for us. This can be achieved with following node libraries:

lint-staged 🚫💩 — Run linters/formatters on git staged files

husky 🐶 Git hooks made easy

Install:

yarn add -D lint-staged husky

Configure lint-staged:

lint-staged config within package.json

And add commit hook via custom npm script, which will be recognised by husky and executed on particular git-hook. In our case, we want to hook into pre-commit git life cycle and execute lint-staged binary which will consume our formerly defined configuration.

npm script, which will be executed by husky, looks like following:

{

"scripts": {

"precommit": "lint-staged"

}

}

Now, every time we will commit to the repo, our staged files will be formatted and linting violations will be fixed by TSLint (if they are auto-fixable), otherwise our commit will fail !

Excellent, you will never ever have to argue with your PR reviewer about semicolons vs no-semicolons, spaces…you name it…👌.

With that said, let’s switch to more serious stuff…

Unit Testing

If you’re not testing your codebase I will find you and I will… :D

Angular CLI comes with Karma test runner and Jasmine expectation/spy library. Those tests are run usually against browser.

Karma is indeed an old tool ( levorutionary at one point some years ago ) but let’s be honest, it’s slow, debugging test is cumbersome and it needs extensive configuration. We can look outside our Angular boundaries and we will discover the “ultimate salvation”.

Everyone please welcome, silver bullet to all our testing nightmares, Dr.Jest .

Jest is a complete testing solution, that includes both test runner and assertion/spy library and much more…

It’s super easy to setup, it’s blazingly fast and introduces a brand new type of testing — snapshot testing ( which can be leveraged with everything that is serializable — component snapshots, state snapshots, image snapshots …)

Jest integration with Angular CLI

To integrate Jest with Angular CLI, we need to install

jest

jest-preset-angular, which handles everything for test environment setup specific to Angular ( zones and stuff ya know ? )

yarn add -D jest jest-preset-angular

Now we need to configure jest, to consume our preset:

// jest.config.js

module.exports = {

preset: 'jest-preset-angular',

setupTestFrameworkScriptFile: '<rootDir>/src/setupJest.ts',

}

Now we can add new npm-scripts for testing:

{

"scripts": {

"test": "jest --watch",

"test:ci": "jest --runInBand",

"test:coverage": "jest --coverage"

}

}

Jest speed

I briefly mentioned, that Jest is fast. How fast ?

Unit testing speed comparison Karma vs Jest

Why is it so fast ? Well it runs against Node and JSDOM, tests are executed in parallel and efficiently cached.

Jest snapshot testing

Jest comes with snapshot testing, you just need to use toMatchSnapshot matcher within your test expectation on component fixture:

Component snapshot testing

This will save a snapshot footprint of your component in that particular moment(state) - a file physically on disk - and when something changes in the component implementation afterwards, you’ll get following failing test with detailed DIFF about what changed:

Component snapshot diff change

I love this !

Jest interactive mode

Jest comes with advanced watch mode — a CLI like tool with lot of perks, like filtering, running only tests that changed and various other features: