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

Summary of vue's webpack -v error solution

Xiaobai learned about Vue, then learned about web...

Access the MySQL database by entering the DOS window through cmd under Windows

1. Press win + R and type cmd to enter the DOS wi...

Use vue3 to implement a human-cat communication applet

Table of contents Preface Initialize the project ...

The impact of limit on query performance in MySQL

I. Introduction First, let me explain the version...

Toolkit: A more powerful front-end framework than Bootstrap

Note: Currently, the more popular front-end frame...

Tips on HTML formatting and long files for web design

<br />Related articles: 9 practical suggesti...

Introduction to Computed Properties in Vue

Table of contents 1. What is a calculated propert...

Ubuntu Basic Tutorial: apt-get Command

Preface The apt-get command is a package manageme...

CSS to achieve glowing text and a little bit of JS special effects

Implementation ideas: Use text-shadow in CSS to a...

How to use css variables in JS

How to use css variables in JS Use the :export ke...

VUE+Express+MongoDB front-end and back-end separation to realize a note wall

I plan to realize a series of sticky note walls. ...

How to set a fixed IP address in CentOS7 virtual machine

Since my development environment is to install Ce...