Detailed explanation of Vue-Jest automated testing basic configuration

Detailed explanation of Vue-Jest automated testing basic configuration

Testing is a very important part in developing large-scale applications. Jest can be used for unit testing in Vue projects. Jest is a testing framework launched by Facebook, which integrates Mocha, chai, jsdom, sinon and other functions. Jest has been integrated in the Vue scaffolding, so using Jest for unit testing in Vue projects is the best choice. From the examples provided, it seems very simple to configure and test successfully. However, there are many differences in actual projects. I reported many errors when testing one of my business components. This article summarizes my own experience and helps readers quickly solve configuration problems.

Install

You can create a Vue project directly through the official @vue/cli, and then select the Unit Testing option

? Check the features needed for your project:
 ◉ Choose Vue version
 ◉ Babel
❯◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
 ◯ Linter / Formatter
 ◉ Unit Testing
 ◯ E2E Testing

Then select Jest in the test framework

? Pick a unit testing solution: Jest
? Where do you prefer placing config for Babel, ESLint, etc.? In a dedicated console
fig files

The jest.config.js configuration file finally generated by the Vue + Ts project looks like this, as if telling us that I have set it up for you, just use it directly. However, for the project, you still need to manually configure compatibility, otherwise many errors will be reported and you will not be able to proceed.

module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel'
}

Configuration

First, let's take a look at what is written in this preset configuration. Find the @vue/cli-plugin-unit-jest/presets/typescript-and-babel package. In fact, the output configuration is as follows:

module.exports = {
  moduleFileExtensions: [ // Test file type 'js',
    'jsx',
    'json',
    // tell Jest to handle *.vue files
    'vue',
    'ts',
    'tsx'
  ],
  transform: { // Transformation method // process *.vue files with vue-jest
    '^.+\\.vue$': require.resolve('vue-jest'),
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
    require.resolve('jest-transform-stub'),
    '^.+\\.jsx?$': require.resolve('babel-jest'),
    '^.+\\.tsx?$': require.resolve('ts-jest'),
  },
  transformIgnorePatterns: ['/node_modules/'], // Ignore node_modules during transformation
  // support the same @ -> src alias mapping in source code
  moduleNameMapper: { // @ symbol indicates the src of the current project
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  testEnvironment: 'jest-environment-jsdom-fifteen',
  // serializer for snapshots
  snapshotSerializers: [ // snapshot configuration 'jest-serializer-vue'
  ],
  testMatch: [ // Default test file '**/tests/unit/**/*.spec.[jt]s?(x)',
    '**/__tests__/*.[jt]s?(x)'
  ],
  // https://github.com/facebook/jest/issues/6766
  testURL: 'http://localhost/',
  watchPlugins: [
    require.resolve('jest-watch-typeahead/filename'),
    require.resolve('jest-watch-typeahead/testname')
  ],
  globals:
    'ts-jest': {
      babelConfig: true
    }
  }
}

Among them, the more important configurations are also the ones we use more to solve problems:

  • moduleFileExtensions: The file types to be tested. The default configuration here basically covers all file types, so there is generally no need to change it.
  • transform : transformation method. The matching files must be translated before they can be recognized, otherwise an error will be reported.
  • transformIgnorePatterns : Transformation ignore configuration
  • moduleNameMapper: module alias, fill it in if it is used

Common Mistakes

SyntaxError: Syntax error, most likely due to no conversion, such as the following prompt:

 /Users/zhuangbing.cai/Documents/workspace/projects/wms-ui/node_modules/vue-runtime-helpers/dist/normalize-component.mjs:76
    export default normalizeComponent;
    ^^^^^^

    SyntaxError: Unexpected token 'export'

Since we did not convert the .mjs file, the error occurred. The fastest solution is to add the .mjs conversion in transform

transform:
     '^.+\\.mjs$': 'babel-jest'
}

You just need to provide the conversion method for the .mjs file.

Another type of syntax error is that some files in node_module need to be transformed, but are ignored by the transformIgnorePatterns configuration.

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (eg binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/zhuangbing.cai/Documents/workspace/projects/wms-ui/node_modules/vue-runtime-helpers/dist/normalize-component.mjs:76
    export default normalizeComponent;
    ^^^^^^

    SyntaxError: Unexpected token 'export'

In the figure, vue-runtime-helpers is used, but because the configuration of transformIgnorePatterns ignores the transformation, it causes a syntax error. The solution is to change the configuration of transformIgnorePatterns as follows:

transformIgnorePatterns: [
    // Ignore node_modules when converting, but do not include vue-runtime-helpers
    '/node_modules/(?!(vue-runtime-helpers)/)',
  ],

After excluding vue-runtime-helpers, it will not be ignored during conversion, thus solving the problem of syntax errors.

Ts is of wrong type

 TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/views/inventory-map/__tests__/available.spec.ts:15:1 - error TS2304: Cannot find name 'beforeEach'.

    15 beforeEach(() => {
       ~~~~~~~~~~
    src/views/inventory-map/__tests__/available.spec.ts:19:1 - error TS2593: 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.

    19 describe('available-inventory-map', () => {
       ~~~~~~~~
    src/views/inventory-map/__tests__/available.spec.ts:20:3 - error TS2593: Cannot find name 'it'. 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.

According to the prompts, you need to add in tscofig.json

{
    "compilerOptions": {
    "types": [
      "webpack-env",
      "jest"
    ],
  }
}

Pre-test work

Before writing test cases, we need Jest to provide the component instance vm and the rendered DOM structure. How to obtain this business component to ensure double testing of code logic and page effects?

It is not possible to directly reference components, because your business components require a lot of dependencies, such as UI component libraries, tool functions, Vuex status, etc., so first we need to handle these dependencies.

Dealing with dependencies

First, you need to know what the business component to be tested depends on. The global dependencies can be found in the main.ts or main.js entry files, and the others can be determined based on the references in the components. How to get component instance in Jest after having dependency?

Vue provides a unit testing utility library - Vue Test Utils, which can be used when writing test cases. First, use createLocalVue to create a Vue class for you to add components, mixins and install plug-ins without polluting the global Vue class, and then reference the dependencies.

const _localVue = createLocalVue();
_localVue.use(Vuex);
_localVue.use(UI);
_localVue.use(i18nInstall);
_localVue.component('s-filter', SFilter);
_localVue.component('w-table', WTable);
_localVue.directive('xxx', {
  inserted: (el, binding) => {
    ....
  },
});
export const localVue = _localVue;

In this way, we get a Vue class containing dependencies, and then deal with Vuex, for example, we need enumeration values

import enums from './enums';
export const systemStore = new Vuex.Store({
  actions: {},
  state: {
    enums: {
      systemEnums: enums,
    },
  },
});

Generate instances and DOM

After getting localVue and store, we need to use it to generate results and render the components through mount.

import { localVue, systemStore } from '@/utils/unit-test/common';
import { mount } from '@vue/test-utils';
require('intersection-observer'); // Compatible with jsdom, does not support IntersectionObserver
import TaskList from '../available-inventory-map/index.vue'; // Reference the business to be tested let store: any;
beforeEach(() => {
  store = systemStore;
});

describe('available-inventory-map', () => {
  it('Filter item test', () => {
    const renderer = createRenderer();
    const wrapper = mount(TaskList, {
      localVue,
      store,
      attachToDocument: true,
    });
    const html = wrapper.html(); // Get the complete html structure const vm = wrapper.vm; // Component instance console.log(html, vm);
  })
}

LocalVue and store are mounted to finally get the instance and its DOM structure. Next, you can write your own test cases based on the instance and DOM.

Summarize

This article mainly introduces the summary of problems encountered in configuring Jest automated testing in Vue + Ts projects, introduces basic configuration and solutions to common errors, and how to get complete component information and DOM before starting to write test cases. Lay the foundation for the subsequent use case writing.

References

Vue Test Utils

This is the end of this article about the detailed configuration of Vue-Jest automated testing basics. For more relevant Vue-Jest automated testing content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How does Vue automatically package dist/test files for test environment and formal environment

<<:  15 important variables you must know about MySQL performance tuning (summary)

>>:  VMWare15 installs Mac OS system (graphic tutorial)

Recommend

How to elegantly back up MySQL account information

Preface: I recently encountered the problem of in...

WeChat applet implements countdown for sending SMS verification code

This article shares the specific code for the WeC...

React encapsulates the global bullet box method

This article example shares the specific code of ...

SQL implementation of LeetCode (197. Rising temperature)

[LeetCode] 197.Rising Temperature Given a Weather...

Do you know why vue data is a function?

Official website explanation: When a component is...

Implementation of Docker deployment of Nuxt.js project

Docker official documentation: https://docs.docke...

Quickly master how to get started with Vuex state management in Vue3.0

Vuex is a state management pattern developed spec...

Detailed explanation of TypeScript 2.0 marked union types

Table of contents Constructing payment methods us...

6 solutions for network failure in Docker container

6 solutions for network failure in Docker contain...

Apache Calcite code for dialect conversion

definition Calcite can unify Sql by parsing Sql i...

Web page creation for beginners: Learn to use HTML's hyperlink A tag

The hyperlink a tag represents a link point and i...

Thoughts on truncation of multi-line text with a "show more" button

I just happened to encounter this small requireme...

How to configure VMware multi-node environment

This tutorial uses CentOS 7 64-bit. Allocate 2GB ...

Detailed explanation of the pitfalls of MySQL 8.0

I updated MySQL 8.0 today. The first problem: Nav...

Download MySQL 5.7 and detailed installation diagram for MySql on Mac

1. Enter the following address in the browser htt...