Skip to content

Files

150 lines (104 loc) · 4.53 KB

TESTING.md

File metadata and controls

150 lines (104 loc) · 4.53 KB

Introduction

The @testing-library family of packages helps you test UI components in a user-centric way.

Documentation

For some functions for example toBeInTheDocument(), jest-dom needs to be install .

Useful links

Common mistakes with RTL

Testing implementation details

Using userEvent vs fireEvent

Rendering Components

import { render } from '@testing-library/react';

const { container } = render(<MyComponent />);
expect(container).toMatchSnapshot();

Rerender Components

Use when changing props. Note that if you use render twice, it will render the component again, and you will have 2 instances in the DOM.

import { render } from '@testing-library/react';

const { rerender, container } = render(<MyComponent />);
rerender(<MyComponent isArrowUp> </MyComponent>);

Finding Elements using screen description

import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

render(<MyComponent />);
const button = screen.getByRole('button', { name: 'click me' });
expect(button).toBeInTheDocument();

Sometimes the element is rendered in the DOM but for some reason it is hidden and you want to test that the element is there but it is not visible. Using toBeInTheDocument it will always return a positive status. To test this, we should use toBeVisible

import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

// eg. Button2 is hidden using CSS
render(
    <div>
        <Button1 />
        <Button2 isHidden />
    </div>
);
const button = screen.getAllByRole('button');
expect(button[0]).toBeVisible();
expect(button[1]).not.toBeVisible();

Simulating Events.

Prefer to use userEvent instead of fireEvent.

Using userEvent

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

const { container } = render(<MyComponent />);
const user = userEvent.setup();
await user.type(screen.getByDisplayValue(''), 'Utrecht');
expect(screen.getByDisplayValue('Utrecht')).toBeInTheDocument();
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

const handleClick = jest.fn();
render(<MyComponent onClick={handleClick} />);
const button = screen.getByRole('button', { name: 'click me' });
const user = userEvent.setup();
await user.click(button);
expect(handleClick).toHaveBeenCalled();

User events with fake timers

When fake timers are used, the user event will not happen, unless we progress the timers. We need to add that option during user setup like this:

jest.useFakeTimers()
// ...
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });

Using fireEvent

If you want to dispatch a specific DOM event you should use fireEvent. Not all events are possible using userEvent for example focusing a element.

import { render, fireEvent } from '@testing-library/react';

const handleOnFocus = jest.fn();
render(<MyComponent onFocus={handleOnFocus} />);
const button = screen.getByRole('button', { name: 'click me' });
fireEvent.focus(button);

expect(handleOnFocus).toHaveBeenCalled();

Checking for HTML Attributes

import '@testing-library/jest-dom';

expect(view.container.firstChild).toHaveClass('Callout--context_cautious');
import '@testing-library/jest-dom';

expect(screen.getByRole('button')).toHaveAttribute('data-test', 'something');

Snapshot the component

Using container

import { render } from '@testing-library/react';

const { container } = render(<MyComponent />);
expect(container).toMatchSnapshot();

Sometimes the container is not sufficient for example when working with Dialogs, use baseElement instead

import { render } from '@testing-library/react';

const { baseElement } = render(<MyComponent />);
expect(baseElement).toMatchSnapshot();