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 --reactAfter 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
Reactinstalled (https://react.dev). - You must have
tsxinstalled (https://tsx.is).
Installing React
npm install react react-dom tsxpnpm install react react-dom tsxyarn add react react-dom tsxbun add react react-dom tsxUpdate 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); });})