Skip to content

Testing React

Latte is a powerful testing framework that allows you to write tests for your applications with ease. This guide will help you set up Latte and run your first test for a React component.

Testing React Components

To enable React environment in Latte, you need to set --react option. You can use jsx syntax in your tests.

Terminal window
latte --dom --react

After that you have access to globals React and ReactDOM, and you can write your tests using the React Tools as R object, which provides a set of tools to help you test your React components or use React matchers.

Requirements

Installing React

Terminal window
npm install react react-dom tsx

Update package.json

Add the following command to your package.json file:

package.json
{
"scripts": {
"test": "NODE_OPTIONS=\"--import tsx\" latte --dom --react"
}
}

Read about tsx here.

Write your first React test

Create a new file named react.test.jsx in your project directory and add the following code:

react.test.jsx
const Button = ({ text, onClick }) => {
return <button onClick={onClick}>{text}</button>;
};
afterEach(() => {
document.body.innerHTML = '';
});
describe('React Button (JSX)', () => {
it('should render a button with text', async () => {
const { container } = await R.render(<Button text="Click me" />);
const button = container.querySelector('button');
expect(button).toBeHtmlElement().hasText('Click me');
});
});

React Tools

Latte provides a set of tools to help you test your React components. When you run your tests, Latte will automatically detect the React environment and provide you with the following tools in the R object:

  • R.render(): Renders a React component and returns the rendered output.
  • R.cleanup(): Clear body.

R.render()

R.render() is a function that renders a React component and returns the:

  • container: The rendered output of the component.
  • rerender: A function that allows you to re-render the component with new props. You can use this function only for components created with React.createElement.
  • unmount: A function that allows you to unmount the component.
  • debug: A function that allows you to debug the component.
  • getByText: A function that allows you to get the first element with content text.
  • getAllByText: A function that allows you to get all elements with content text.
  • getById: A function that allows you to get an element by id.
  • getByClass: A function that allows you to get an elements by class name.
  • $ alias for container.querySelector.
  • $$ alias for container.querySelectorAll.
  • fireEvent: This object contains methods to simulate events on the rendered component: click(element), change(element, val).

R.cleanup()

R.cleanup() is a function that clears the body of the document.

R.fireEvent

R.fireEvent is a function that simulates events on the rendered component. R.fireEvent includes next methods:

  • click(element): Simulates a click event on the specified element.
  • change(element, value): Simulates a change event on the specified element.
  • focus(element): Simulates a focus event on the specified element.
  • blur(element): Simulates a blur event on the specified element.
  • keydown(element, key): Simulates a keydown event on the specified element.
  • keyup(element, key): Simulates a keyup event on the specified element.
  • keypress(element, key): Simulates a keypress event on the specified element.
  • submit(element): Simulates a submit event on the specified element.
  • ivalid(element): Simulates an invalid event on the specified element.
  • reset(element): Simulates a reset event on the specified element.
  • select(element): Simulates a select event on the specified element.

Then you can use R.fireEvent to simulate events on the rendered component:

react.test.jsx
const Button = ({ text, onClick }) => {
return <button onClick={onClick}>{text}</button>;
};
describe('React Button (JSX)', () => {
it('should render a button with text', async () => {
let clicked = false;
const handleClick = () => {
clicked = true;
};
const { $ } = await R.render(<Button text="Click me" onClick={handleClick} />);
await R.fireEvent.click($('button'));
expect(clicked).toBeTrue();
});
});

React Matchers

Latte provides a set of matchers to test your React components. You must use React matchers with react getter. Getter react checks if React and ReactDOM are installed in your project.

toRenderWithoutError()

toRenderWithoutError(msg) is a matcher that checks if the component renders without throwing an error.

react.test.jsx
describe('Rendering React Components', () => {
it('should render without error', async () => {
expect(<Button text="Click me" />).react.toRenderWithoutError();
});
})

toRenderText()

toRenderText(text, msg) is a matcher that checks if the component renders with the specified text.

react.test.jsx
describe('Rendering React Components', () => {
it('should render with text', async () => {
await expect(<Button text="Click me" />).react.toRenderText('Click me');
});
})

toContainElement()

toContainElement(selector, msg) is a matcher that checks if the specified component exists after rendering.

react.test.jsx
describe('Check DOM after Rendering React Components', () => {
it('should has button', async () => {
await expect(<Button text="Click me" />).react.toContainElement("button");
});
})

toHaveElementCount()

toHaveElementCount(selector, count, msg) is a matcher that checks if the specified component has the specified number of elements after rendering.

react.test.jsx
describe('Check DOM after Rendering React Components', () => {
it('should has 1 button', async () => {
await expect(<Button text="Click me" />).react.toHaveElementCount("button", 1);
});
})

toTriggerEvent()

toTriggerEvent(selector, event, callback, data, msg) is a matcher that checks if the specified component triggers the specified event after rendering.

You can use data argument to pass: new value to the input or select elements or key for keypress, keyup, keydown events.

react.test.jsx
describe('Checks whether Callback is called after an event on an item', () => {
it('should trigger click event', async () => {
await expect(<Button text="Click me" />).react.toTriggerEvent('button', 'click');
});
})

toEventuallyContain()

toEventuallyContain(selector, timeout, msg) is a matcher that checks if the specified component eventually contains the specified element after rendering.

react.test.jsx
describe('Check DOM after Rendering React Components', () => {
it('should eventually has button', async () => {
await expect(<Button text="Click me" />).react.toEventuallyContain("button", 1000);
});
})