Unit Testing

Our unit test suites are primarily built on top of our storybook stories, as a lot of the setup leg work has already been done within this process, e.g. a default story, a story with a prop set, etc.

Tests should be written using jestopen in new window .

Any non-component tests should follow the same format as below, but interact with jestopen in new window directly.

Packages

Vue Storybook Test Utils

Link: @netsells/vue-storybook-test-utilsopen in new window

Most of your test composition and variants (e.g. props, slots) is already setup as part of storybook for use in component-first development and Visual Regression Testing process. It makes little sense to do this setup twice. This module allows you to pass your stories directly to the @vue/test-utilsopen in new window package and have the wrappers automatically generated with your provided props and story markup.

For further details and usage check out the module README.

Format

File Convention

Test files should be suffixed with .spec.js and should match the name of the file being tested. They should be placed alongside the source file in your application. For example, if we were to have a TextInput.vue component, our file structure would look something like so:

├─ TextInput/
│  ├─ TextInput.vue
│  ├─ TextInput.spec.js
│  └─ TextInput.stories.js

Doing so makes it easier to see where the tests are located for each part of your application.

Test Structure

It’s recommended that you structure your tests similar to a UAT. For example, at the root level you would specify your component, and then you would nest your tests as if they were a written sentence. For example, take the following sentence:

On the TextInput component, when the disabled prop is passed, the input will become disabled.

What we end up with are three pieces of information.

  • The entity being tested: TextInput
  • The functionality being tested: the disabled prop being passed
  • The desired outcome: the input will become disabled

Given, this information we can structure our test like so:

describe('TextInput', () => { // the entity
    describe('when the `disabled` prop is provided', () => { // the functionality
        test('the input is disabled', () => { // the outcome
            // Run tests to satisfy the UAT
        });
    });
});

The idea behind this format is to avoid cases where you might have a test named updates data appropriately. What does “appropriately” mean? If a new developer were to modify this component and update the test in future would they know what the individual requirements of the component are?

Eventually you will end up with a complete, living UAT document within the codebase.

Fixtures

When testing against data, rather than hardcoding your data within your test, it's better to move this data to a fixture. A fixture is an immutable dataset that your tests are based on to mimic real data. For instance if you have a component which takes data from an endpoint and populates a users table, you might have a users.json fixture with your static data. You would then pull this into your test instead.

Fixtures should be placed in <root>/tests/fixtures/.

WARNING

It's important that your fixture remains immutable as to not introduce any essence of unpredictability into your tests