Introduction to the

Enzyme is a JavaScript test tool of React open-source by Airbnb that makes the output of the React component easier to extrapolate. The Enzyme API is as flexible and easy to use as jQuery to manipulate the DOM, because it uses the Cheerio library to parse the virtual DOM, whereas Cheerio’s goal is to do jQuery on the server. Enzyme is compatible with most assertion libraries and test frameworks, such as Chai, Mocha, Jasmine, etc.

Installation and Configuration

To use enzyme, you need to install the enzyme dependency in the project, using the following command:

npm install --save-dev enzyme
Copy the code

Since the React project relies on something with React, make sure the following modules are installed.

npm install --save react react-dom babel-preset-react
Copy the code

To complete the render test, you need the support of the enzyme Adapter library in addition to the React version. The adapter and React mappings are as follows:

Enzyme Adapter Package React semver compatibility
enzyme-adapter-react-16 ^ 16.0.0
enzyme-adapter-react-15 ^ 15.5.0
Enzyme – adapter – react – 14.4 ^ 15.5.0
enzyme-adapter-react-14 ^ 0.14.0
enzyme-adapter-react-13 ^ 0.13.0

The enzyme supports three rendering methods: shallow: shallow rendering, which encapsulates the official shallow Renderer. Rendering a component as a virtual DOM object is very efficient because only the first layer is rendered and the child components are not rendered. You don’t need a DOM environment and can access component information using jQuery. Render the React component into a static HTML string, then use the Cheerio library to parse the string and return an instance of Cheerio that can be used to analyze the HTML structure of the component. Mount: Full render, which loads a component render into a real DOM node to test the INTERACTION of the DOM API and the life cycle of the component, using jsDOM to simulate the browser environment.

Commonly used functions

There are several core functions in enzyme that need to be paid attention to as follows:

  • Simulate (event, mock) : Used to simulate event triggering. Event is the event name and mock is an event object.
  • Instance () : Returns an instance of the test component;
  • Find (selector) : finds a node according to a selector. A selector can be a CSS selector, a constructor of a component, or a display name of a component.
  • At (index) : Returns a rendered object;
  • Get (index) : Returns a React node. To test it, re-render it.
  • Contains (nodeOrNodes) : Specifies whether the current object contains nodes that are the main parameters. The parameter type is react object or object array.
  • Text () : Returns the text content of the current component;
  • HTML () : Returns the HTML code form of the current component;
  • Props () : Returns all properties of the root component;
  • Prop (key) : Returns the specified property of the root component;
  • State () : Returns the state of the root component;
  • SetState (nextState) : Sets the state of the root component;
  • SetProps (nextProps) : Sets the properties of the root component;

use

To explain the usage of the Enzyme test, we will first create a new Enzyme test file. The code is as follows:

import React from 'react'

const Example=(props)=>{
    return (<div>
        <button>{props.text}</button>
    </div>)
}
export default Example
Copy the code

Shallow shallow rendering

Shallow Rendering as mentioned earlier, Shallow Rendering is used to render a component into a virtual DOM object, but only the first layer is rendered and not all the child components are rendered, so processing is very fast. And it doesn’t need a DOM environment, because it’s not loaded into the DOM at all.

To perform the shallow render test, we create a new test file named enzyme. Test.js.

import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '.. /enzyme'

const {shallow}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme shallow'.function () {
    it('Example component'.function () {
        const name='Button name'
        let app = shallow(<Example text={name} />)
       let btnName=app.find('button').text();
       console.log('button Name:'+btnName)
    })
})
Copy the code

Run the yarn test command, and the following output is displayed:

To avoid writing this to every test file, we can create a new configuration file feeding me_config.test.js under the test directory. The content of the document is as follows:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({
    adapter: new Adapter(),
});

export default Enzyme;
Copy the code

Then, create a new file setup.js under the test directory:

import jsdom from 'jsdom';
const { JSDOM } = jsdom;

if (typeof document === 'undefined') {
    const dom=new JSDOM('
      ');
    global.window =dom.window;
    global.document = global.window.document;
    global.navigator = global.window.navigator;
}
Copy the code

Modify our test script in package.json to the following configuration:

 "scripts": {
    "test": "mocha --require babel-core/register --require ./test/setup.js"
  }
Copy the code

Our shallow test code can now be changed to:

import React from 'react'
import Enzyme from './enzyme.config';
import Example from '.. /enzyme'

const {shallow}=Enzyme

describe('Enzyme shallow'.function () {
    it('Example component'.function () {
        const name='Button name'
        let app = shallow(<Example text={name} />)
        let btnName= app.find('button').text()
        console.log('button Name:'+btnName)
    })
})
Copy the code

Fully render mount

The mount rendering is used to load the React component as a real DOM node. However, real DOM requires a browser environment. To solve this problem, we can use JsDOM, which means we can use JsDOM to simulate a browser environment to load real DOM nodes. First, install the JsDOM emulated browser environment using the following command:

npm install --save-dev jsdom
Copy the code

Then we add a fully rendered test code:

import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '.. /src/example'

const {shallow,mount}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme mount DOM Rendering (Full DOM Rendering) '.function () {
  it('The name of the button in the Example component is the value of span in the sub-component Sub'.function () {
    const name='Button name'
    let app = mount(<Example text={name} />)

    const buttonObj=app.find('button')
    const spanObj=app.find('span'Console. info(' Number of buttons found:${buttonObj.length}') console.info(' Number of found spans:${spanObj.length}`)

   buttonObj.text(),spanObj.text()
  })
})

Copy the code

Note that there seems to be a problem with the configuration to complete the test, so the code here is not running properly.

Static render

Render the React component into a static HTML string, then use the Cheerio library to parse the string and return an instance of Cheerio, which can be used to analyze the HTML structure of the component. For the previous enzyme. Js file, the code for our static rendering test is as follows:

import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Example from '.. /enzyme'

const {shallow,mount,render}=Enzyme

Enzyme.configure({ adapter: new Adapter() })

describe('Enzyme render test'.function () {
    it('Example render'.function () {
        const name='Button name'
        let app = render(<Example text={name} />)

        const buttonObj=app.find('button')
        const spanObj=app.find('span'Console. info(' Number of buttons found:${buttonObj.length}') console.info(' Number of found spans:${spanObj.length}`)

        buttonObj.text(),spanObj.text()
    })
})
Copy the code

Execute the above code and the test results are as follows:

contrast

To compare the three testing frameworks, let’s take a look:

describe('shallow vs render vs mount'.function () {
    it(Test shallow 500 times, () = > {for (let i = 0; i < 500; i++) {
            const app = shallow(<Example/>)
            app.find('button').text()
        }
    })

    it('Test Render500 times', () = > {for (let i = 0; i < 500; i++) {
            const app = render(<Example/>)
            app.find('button').text()
        }
    })

    it('test mount500 times', () = > {for (let i = 0; i < 500; i++) {
            const app = mount(<Example/>)
            app.find('button').text()
        }
    })
})
Copy the code

The running result is shown as follows:

Shallow is the fastest, as shown above, due to the shallow limitation of rendering only the first layer and not all child components. Render turns out to be twice as efficient as Mount. So what is the value of mount? Shallow and mount are, of course, valuable, as they are both DOM objects that can simulate interactions.