Testing JSX components with Jest in NuxtJS

July 17th 2020 Jest NuxtJS Vue.js TypeScript

Even if you select TypeScript and Jest support when creating a new NuxtJS project, it still isn't fully configured for writing tests in TypeScript, let alone for testing components written with JSX syntax. This post describes my journey to a working configuration.

As soon as I've written my first describe call in a test, Visual Studio Code already reported an error:

Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try npm i @types/jest or npm i @types/mocha and then add jest or mocha to the types field in your tsconfig.

Thanks to the detailed error message, fixing this problem wasn't difficult. I installed the type definitions for Jest:

npm i -D @types/jest

And added them to tsconfig.json:

{
  "compilerOptions": {
    "types": ["@types/node", "@nuxt/types", "@types/jest"]
  }
}

I could now write my first test without any errors reported by Visual Studio Code:

import { shallowMount } from '@vue/test-utils';
import TsxTextInput, { TsxTextInputProps } from '../TsxTextInput';

describe('TsxTextInput component', () => {
  it('should render the input label', () => {
    const props: TsxTextInputProps = {
      id: 'id',
      label: 'Label:',
    };

    const wrapper = shallowMount(TsxTextInput, { propsData: props });

    expect(wrapper.find('label').text()).toBe(props.label);
  });
});

However, they failed to run:

Cannot find module '../TsxTextInput' from 'tsxTextInput.spec.ts'

However, Jest was able to find:
    '../TsxTextInput.tsx'

You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['ts', 'js', 'vue', 'json'].

Again, the error message was quite helpful. I had to add the .tsx file extension to jest.config.js:

module.exports = {
  //...
  moduleFileExtensions: ['ts', 'tsx', 'js', 'vue', 'json'],
  //...
};

This only caused a different error to be returned instead:

SyntaxError: Cannot use import statement outside a module

This one didn't include any helpful guidance. Still, it wasn't too difficult to figure out that the syntax was invalid because it was treated as pure JavaScript. I modified jest.config.js to have the .tsx files processed by ts-jest.

module.exports = {
  //...
  transform: {
    '^.+\\.tsx?: 'ts-jest',
    '^.+\\.js: 'babel-jest',
    '.*\\.(vue): 'vue-jest',
  },
  //...
};

And once again, this only resulted in a different error:

SyntaxError: Unexpected token '<'

For this one, I couldn't find a quick solution myself. In the end, I consulted a working example by Gregory Soloschenko. I had to reference two presets in my configuration files:

  • For Jest, I added the following at the top of jest.config.js:

    module.exports = {
      preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
      //...
    };
    
  • For Babel, I had to add @vue/cli-plugin-babel/preset. However, it didn't seem to work in .babelrc. Therefore, I changed the file to babel.config.js and ended up with the following:

    module.exports = {
      env: {
        test: {
          presets: [
            ['@vue/cli-plugin-babel/preset'],
            [
              '@babel/preset-env',
              {
                targets: {
                  node: 'current',
                },
              },
            ],
          ],
        },
      },
    };
    

Of course, I also had to install the corresponding NPM packages:

npm i -D @vue/cli-plugin-unit-jest
npm i -D @vue/cli-plugin-babel

Now, the tests passed. But there were still warnings because of version conflicts:

ts-jest[versions](WARN) Version 24.9.0 of jest installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=25.0.0 <26.0.0). Please do not report issues in ts-jest if you are using unsupported versions.

ts-jest[versions](WARN) Version 24.9.0 of babel-jest installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=25.0.0 <26.0.0). Please do not report issues in ts-jest if you are using unsupported versions.

To resolve them, I had to uninstall packages that were indirectly included in different versions. This put my node_modules folder in an inconsistent state and forced me to reinstall @vue/cli-plugin-unit-jest:

npm uninstall -D jest
npm uninstall -D ts-jest
npm uninstall -D vue-jest
npm i -D @vue/cli-plugin-unit-jest

Finally, the test run completed without any errors or warnings. To include my JSX components in the coverage report, a made one last modification to jest.config.js:

module.exports = {
  //...
  collectCoverageFrom: [
    '<rootDir>/components/**/*.{vue,tsx}',
    '<rootDir>/pages/**/*.{vue,tsx}',
  ],
  //...
};

If you have problems following my steps, I suggest you take a look at my repository on GitHub with a fully configured example.

Initial NuxtJS configuration for writing Jest tests in TypeScript for JSX components is incomplete. The guidance in error messages takes you only so far. To get everything working, it's best to rely on presets provided by the Vue CLI tooling.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Copyright
Creative Commons License