Test your Storybook
Tags: storybook, angular, nx, cypress
Published: 2022-02-13 17:01:18

---
title: Test your Storybook
published: true
date: 2022-02-12 13:52:26 UTC
tags: storybook,angular,nx,cypress
canonical_url: https://medium.com/@redin.gaetan/test-your-storybook-1eccbd1424af
---

Storybook for Angular

### Context

Nx 13 — Angular 13 — Storybook 6.5.0-alpha.36

### Why?

More your application grows more you risk to introduce bugs. In a recent project, we have to kind of tests: Unit tests (so many) and some integration tests. We work incrementally and add features during sprints and rework older ones with more functional rules. Even if we test all devs with unit test, there is a moment that you realize you couldn’t test everything with unit testing.

We have develop a Storybook which contains all our components / directives. Sometimes, we check some of it during a development and Ho surprise, it’s broken :-(. Yet All our unit tests are okay…

### How?

I was looking for a solution to introduce easily some functional tests without testing the interactions with the backend. Our goal was only to test functionally our HMI.

I already heard talking about [Cypress](https://www.cypress.io/) and after doing some research I found a perfect solution for us. [Nx](https://nx.dev/) offer the possibility to include an e2e application with Cypress configuration for testing our Storybook (Miracle).

I install all the requirements and start to write some functional tests. What a surprise, some tests failed whereas all our unit tests and integration tests works… As a lead dev, it was first a deception, because it means I didn’t guarantee the quality of our application. But, on second thought, what a joy to see I can still learn and discover new things! I’m sure many of us have already be in this situation. So let’s quit chatting, this is how to do it.

### Installation

I suppose you already have a Nx — Angular project with Storybook. Here we just talk about Cypress installation for Storybook.

```
nx generate [@nrwl/storybook](http://twitter.com/nrwl/storybook):cypress-project --name={your_app_name} --linter=eslint --no-interactive
```

My app is called “storybook” and that’s the result of the command:

```
nx generate [@nrwl/storybook](http://twitter.com/nrwl/storybook):cypress-project --name=storybook --linter=eslint --no-interactive
UPDATE package.json
CREATE apps/storybook-e2e/cypress.json             
CREATE apps/storybook-e2e/src/fixtures/example.json
CREATE apps/storybook-e2e/src/support/commands.ts  
CREATE apps/storybook-e2e/src/support/index.ts     
CREATE apps/storybook-e2e/tsconfig.json            
CREATE apps/storybook-e2e/project.json             
UPDATE workspace.json                              
CREATE apps/storybook-e2e/.eslintrc.json           
UPDATE nx.json
```

In the package.json , we can see two more dev dependencies: @nrwl/cypress and cypress , logic.

In the storybook-e2e/tsconfig.json , we have this:

```
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "sourceMap": _false_,
    "outDir": "../../dist/out-tsc",
    "allowJs": _true_,
    "types": ["cypress", "node"]
  },
  "include": ["src/ **/*.ts", "src/** /*.js"]
}
```

Nothing special, except the type “cypress”.

Now let’s have a look into the storybook-e2e/project.json file:

```
{
  "root": "apps/storybook-e2e",
  "sourceRoot": "apps/storybook-e2e/src",
  "projectType": "application",
  "targets": {
    "e2e": {
      "executor": "@nrwl/cypress:cypress",
      "options": {
        "cypressConfig": "apps/storybook-e2e/cypress.json",
        "devServerTarget": "storybook:storybook"
      },
      "configurations": {
        "ci": {
          "devServerTarget": "storybook:storybook:ci"
        }
      }
    },
    "lint": {
      "executor": "@nrwl/linter:eslint",
      "outputs": ["{options.outputFile}"],
      "options": {
        "lintFilePatterns": ["apps/storybook-e2e/**/*.{js,ts}"]
      }
    }
  },
  "tags": [],
  "implicitDependencies": ["storybook"]
}
```

As we can see, the target server is defined with our storybook app "devServerTarget":"storybook:storybook:ci" which is launch in ci mode. So there is an implicit dependency with our Storybook app "implicitDependencies": ["storybook"] .

You already can to try it:

```
nx e2e {your_app_name}-e2e
```

It will failed with something like:

```
Can't run because no spec files were found.

We searched for any files inside of this folder:

...\apps\storybook-e2e\src\integration
```

Yes, we don’t have write tests yet. If you don’t know how to write cypress tests, you can read the documentation [here](https://www.cypress.io/) which is perfect.

This commands is perfect for the testing in terminal. But some of us prefer to see it in a real window. To open cypress and execute the tests on demand, I suggest you to create another cypress.json like this:

```
// cypress.local.json
{
  "fileServerFolder": ".",
  "fixturesFolder": "apps/storybook-e2e/src/fixtures",
  "integrationFolder": "apps/storybook-e2e/src/integration",
  "modifyObstructiveCode": _false_,
  "supportFile": "apps/storybook-e2e/src/support/index.ts",
  "pluginsFile": _false_,
  "video": _true_,
  "videosFolder": "../../dist/cypress/apps/storybook-e2e/videos",
  "screenshotsFolder": "../../dist/cypress/apps/storybook-e2e/screenshots",
  "chromeWebSecurity": _false_,
  "baseUrl": "http://localhost:4400" // set the url of your local Storybook
}
```

Add this command into your package.json :

```
"test:storybook:local": "cypress open --browser ~\\chrome-win\\chrome.exe -C apps/storybook-e2e/cypress.local.json"
```

Here I use chromium as browser and I specify my local cypress config.

Now you can launch your local storybook and your local cypress:

```
nx run storybook:storybook
npm run test:storybook:local
```

It will fail until you will have write some tests.

To help writing test for Storybook, I suggest you to install the following [library](https://github.com/NicholasBoll/cypress-storybook):

```
npm i -D cypress-storybook
```

Then import the helper commands into the support index file:

```
// apps/storybook-e2e/src/support/index.ts
import 'cypress-storybook/cypress'
```

Then import that in the storybook preview file, it help storybook to understand the cypress commands:

```
// apps/storybook/.storybook/preview.js
import 'cypress-storybook/angular'
```

At last, in your test file what you have to do:

```
describe('MyComponent', () => {
    beforeEach(() => {
      cy.visitStorybook();
      cy.loadStory('title-of-my-story', 'MyStoryName');
    });

    it('my test', () => {
    ...
    });
});
```

In the documentation, it’s recommended to wrap the cy.visitStorybook(); in a before and not a beforeEach but when I tried, it does not reset the Story in form cases between each test.

### Conclusion

Now you will be more armed to defeat bugs! No excuse, particularly if you use Nx which helps a lot for the configuration. I suggest you to write some [commands](https://docs.cypress.io/api/cypress-api/custom-commands#Parent-Commands) to simplify writing tests like a fillForm command which get a fixture and a form tag for example. It will make your test more readable.

Thanks for reading.

### Learn more

- [Story for an Angular Directive V2](https://dev.to/gaetanrdn/story-for-an-angular-directive-v2-d0p-temp-slug-1683146)
- [Story for a Component With Content Projection](https://dev.to/gaetanrdn/story-for-a-component-with-content-projection-1ifg)
- [Install Jest for Angular](https://dev.to/gaetanrdn/jest-and-angular-install-fg3)
- [Angular for everyone: All about it](https://medium.com/@redin.gaetan/angular-for-every-one-table-of-contents-d24232940dd4)