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.
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
- You must have
React
installed (https://react.dev). - You must have
tsx
installed (https://tsx.is).
Installing React
npm install react react-dom tsx
pnpm install react react-dom tsx
yarn add react react-dom tsx
bun add react react-dom tsx
Update package.json
Add the following command to your package.json
file:
{ "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:
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 withReact.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 forcontainer.querySelector
.$$
alias forcontainer.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:
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.
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.
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.
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.
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.
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.
describe('Check DOM after Rendering React Components', () => { it('should eventually has button', async () => { await expect(<Button text="Click me" />).react.toEventuallyContain("button", 1000); });})