Table of contents
1.
Introduction
2.
Loading an emulated DOM with JSDOM
3.
Enzyme's find
4.
Jest and JSDOM replacement default example configuration
5.
Configuring enzyme with other test libraries and include JSDOM
6.
FAQs
7.
Key Takeaways
Last Updated: Mar 27, 2024
Easy

Using Enzyme with JSDom

Author Toohina Barua
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Enzyme is a React JavaScript Testing tool that makes it easier to assert, manipulate, and traverse the output of your React Components. It was created at Airbnb before being transferred to a separate organization.
JSDOM is a headless browser based on JavaScript that can be used to simulate a real-world testing environment.
This article will teach us how to use Enzyme with JSDom. So let's get started.

Loading an emulated DOM with JSDOM

An emulated DOM must be loaded to use the enzyme's mount until a React Native adapter is available.
All of the enzyme behavior you'd expect is supported by JSDOM. While Jest snapshot testing is possible with this approach, it is not recommended and is only supported through wrapper. debug().

Enzyme's find

It's worth noting that React Native has a testID prop, which can be used as a selector in the same way that className is used in standard React:

<View key={key} style={styles.todo} testID="todo-item">
      <Text testID="todo-title" style={styles.title}>{todo.title}</Text>
    </View>

expect(wrapper.findWhere((node) => node.prop('testID') === 'todo-item')).toExist();

Jest and JSDOM replacement default example configuration

It is suggested that you use a setup script, such as Jest's setupFilesAfterEnv setting, to perform the necessary configuration in your testing framework.
To include the setupFilesAfterEnv setting, create or update a jest.config.js file at the root of your project:

// jest.config.js

module.exports = {
  // Load setup-tests.js before test execution
  setupFilesAfterEnv: '<rootDir>setup-tests.js',

  // ...


Then, in the project root, create or update the file specified in setupFilesAfterEnv, in this case setup-tests.js:

// setup-tests.js

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

/**
 * Set up DOM in node.js environment for Enzyme to mount to
 */
const { JSDOM } = require('jsdom');

const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;

function copyProps(src, target) {
  Object.defineProperties(target, {
    ...Object.getOwnPropertyDescriptors(src),
    ...Object.getOwnPropertyDescriptors(target),
  });
}

global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
};
copyProps(window, global);

/**
 * Set up Enzyme to mount to DOM, simulate events,
 * and inspect the DOM in tests.
 */
Enzyme.configure({ adapter: new Adapter() });

Configuring enzyme with other test libraries and include JSDOM

Update the setupFilesAfterEnv file, setup-tests.js in this case, in the project root:

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

/**
 * Set up Enzyme to mount to DOM, simulate events,
 * and inspect the DOM in tests.
 */
Enzyme.configure({ adapter: new Adapter() });
Creating a Separate Test File
Create a component.enzyme.test.js file with the enzyme.test.ts prefix:
/**
 * @jest-environment jsdom
 */
import React from 'react';
import { mount } from 'enzyme';
import { Text } from '../../../component/text';

describe('Component tested with enzyme', () => {
  test('App mount with enzyme', () => {
    const wrapper = mount(<Text />);
    // other tests operations
  });
});


The most important part is to make sure the test runs with jestEnvironment set to jsdom, which you can do by adding a /* @jest-environment jsdom */ comment at the top of the file.
After that, you should be able to begin writing tests!
Note that if you want to perform snapshot testing against React Native components, you may want to do some additional mocking around native components. To avoid random React keys that cause snapshots to always fail, you may need to mock React Navigation's KeyGenerator in this case.

import React from 'react';
import renderer from 'react-test-renderer';
import { mount, ReactWrapper } from 'enzyme';
import { Provider } from 'mobx-react';
import { Text } from 'native-base';

import { TodoItem } from './todo-item';
import { TodoList } from './todo-list';
import { todoStore } from '../../stores/todo-store';

// React Navigation generates random React keys, which makes
// snapshot testing fail. Mock the randomness to keep from failing.
jest.mock('react-navigation/src/routers/KeyGenerator', () => ({
  generateKey: jest.fn(() => 123),
}));

describe('todo-list', () => {
  describe('enzyme tests', () => {
    it('can add a Todo with Enzyme', () => {
      const wrapper = mount(
        <Provider keyLength={0} todoStore={todoStore}>
          <TodoList />
        </Provider>,
      );

      const newTodoText = 'I need to do something...';
      const newTodoTextInput = wrapper.find('Input').first();
      const addTodoButton = wrapper
        .find('Button')
        .findWhere((w) => w.text() === 'Add Todo')
        .first();

      newTodoTextInput.props().onChangeText(newTodoText);

      // Enzyme usually allows wrapper.simulate() alternatively, but this doesn't support 'press' events.
      addTodoButton.props().onPress();

      // Make sure to call update if external events (e.g. Mobx state changes)
      // result in updating the component props.
      wrapper.update();

      // You can either check for a testID prop, similar to className in React:
      expect(
        wrapper.findWhere((node) => node.prop('testID') === 'todo-item'),
      ).toExist();

      // Or even just find a component itself, if you broke the JSX out into its own component:
      expect(wrapper.find(TodoItem)).toExist();

      // You can even do snapshot testing,
      // if you pull in enzyme-to-json and configure
      // it in snapshotSerializers in package.json
      expect(wrapper.find(TodoList)).toMatchSnapshot();
    });
  });
});

FAQs

  1. How do use JSDom and Mocha together?
    Before running the test suite with JSDOM, you must first run the setup.js file. If you're using Mocha, you can do this using the --require option from the command line:
    mocha --require setup.js --recursive path/to/test/dir
  2. Which version of JSDom node supports?
    Jsdom requires node 4 or above. As a result, if you want to use it with mount, you will need to make sure node 4 or iojs is on your machine.
  3. How to use JSDom with older versions of node?
    If you are with an older version of Node, a browser-based test runner like Karma might be a good option.
  4. How to switch between different versions of node?
    You may need to switch between different versions of node from time to time. To do so, use the CLI tool nvm.
    Use the curl script from http://nvm.sh to install nvm, and then:
    nvm install 4
    Node 4 will now be running on your machine. To switch between the two environments, use the nvm use command:
    nvm use 0.12
    nvm use 4
  5. What is mount in Enzyme?
    If the component is not currently mounted, mount is a method that remounts it. This can be used to simulate the unmount/mount lifecycle of a component.

Key Takeaways

In this article, we have extensively discussed using Enzyme with JSDom.
We hope that this blog has helped you enhance your knowledge regarding using Enzyme with JSDom and if you would like to learn more, check out our articles on Coding Ninjas Studio. Do upvote our blog to help other ninjas grow. Happy Coding!

Live masterclass