React Components Testing with Jest & Enzyme

by Alyona Pysarenko

Jest and Enzyme

React Components Testing with Jest & Enzyme

by Alyona Pysarenko

Agenda

  1. Introduction to Jest and Enzyme
  2. Define the correct order of components’ testing based on project structure
  3. Find what to omit in test coverage
  4. Identify the necessity of Snapshot Testing
  5. Define what to test in the component and in which order
  6. Provide detailed code examples
Jest config

Introduction
to Jest

Jest is used by Facebook to test all JavaScript code including React applications.

Why Jest:

  1. Fast and sandboxed
  2. Built-in code coverage reports
  3. Zero configuration
  4. Powerful mocking library
  5. Snapshot Testing
  6. Works with TypeScript

How to run tests

yarn test

Jest start

How to verify results

yarn test mmp/static/js/react/shared/forms/inputs/__tests__/RadiosInput.test.js

Success

Jest start success

Failed

Jest start failed
Enzyme

Enzyme

Enzyme is JavaScript Testing utilities for React

Basic Usage

  1. Shallow Rendering
  2. Full DOM Rendering
  3. Static Rendered Markup

Define the correct order of components’ testing based on project structure

Project structure

Queue for Test Coverage

The final components order

final components order

What should be omitted in test
coverage:

  1. third-party libraries
  2. constants
  3. inline styles
  4. things not related to the tested component

Combine two testing approaches:

  1. Snapshot Testing

    Capture snapshots of React trees to simplify testing and to analyze how state changes over time.

  2. Component logic testing

How to test with snapshots

Step 1. Use the .toMatchSnapshot() method in expect block to create the Snapshot itself:

text input testing

Step 2. Create directory __snapshots__ after first run containing autogenerated file with the extension .snap.

Snapshot view:

text input testing

Step 3. Push the snapshot into the repository and store it along
with the test.

If the component has been changed, you just need to update the snapshot with —updateSnapshot flag or use the short form u flag.

How snapshot works

1. The component has changed

  1. Run tests
  2. New snapshot is created, it compares with the stored snapshot
  3. Tests failed because snapshot is different
snapshot failed

How snapshot works

2. The component has not changed

  1. Run tests
  2. New snapshot is created, it compares with the stored snapshot
  3. Tests passed because snapshot is identical
snapshot success

Main instructions for component
testing:

  1. One snapshot per component
  2. Testing props
  3. Testing data types
  4. Events testing
  5. Testing conditions
  6. Testing state

Examples of Testing

1. Testing DateInput component

Code listing on github: DateInput.js

DateInput component

The DateInput component uses the library react-datepicker, with two utilities:

  1. valueToDate (converts value to date)
  2. dateToValue (converts date to value)

List of default props for component rendering:

default props

Mock date value:

mock date

Create HOC to pass defaultProps

create HOC

Remember about moment-timezone

moment-timezone

Make component wrapper before each test

mount

Now the date input component is ready for testing:

1. Create snapshot first:

snapshot

2. Testing props:

showMonthYearsDropdowns prop null value prop

3. Test proptypes for value, date expected to be string:

check the type of value

4. Test events:

First, check the onChange event.

  1. mock onChange callback and setProps
  2. simulate change event with new target value
  3. check that onChange event has been called with new value
onChange event

Ensure that the datepicker popup opens after a click on the date input

popup open event

Full tests listing: DateInput.test.js

2. HOC testing (Higher-Order Component)

BaseFieldLayout:

  1. is wrapper for the form components like TextInput, CheckboxInput, etc.
  2. creates component layout (rendering labels, tooltips, icons, errors, ...)
  3. is used in BaseFieldHOC for wrapping the inputComponent and redux-form `Field` component

Code listing for tested component: BaseFieldHOC.js

Analyzing the HOC:

  1. receives only one prop component:
    1. need to create this component
    2. wrap it in the BaseFieldHOC
  2. decorate the wrapped HOC with redux-form
  3. render field inside redux `Provider` component to make the store available

To mock the store, just do: const store = createStore(() => ({}));
Before each test do:

BaseFieldHOC

1. Create snapshot:

BaseFieldHOC snapshot

2. Ensure that the input component is wrapped in BaseFieldLayout after rendering:

BaseFieldHOC wrapper

Full tests listing: BaseFieldHOC.test.js

Test coverage

Test coverage

Test coverage

Test coverage

Thank you for your attention!