Testing JSX components with Jest in NuxtJS
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
ornpm i @types/mocha
and then addjest
ormocha
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 tobabel.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.