46
loading...
This website collects cookies to deliver better user experience
create-react-app
and we do not need to install them separately. React Testing Library (RTL) is built on top of the DOM testing library, as in the tests will work with the actual DOM. This allows the tests to simulate the ways that users will interact with DOM, as closer as possible. It is super easy to use, provides an array of assertion methods (extended from Jest), user-events simulation and etc.create-react-app
uses Jest as its test runner. Jest will look for the test files name with the following naming conventions (according to official site):create-react-app
project:npx create-react-app testing-react-demo
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
import React, { useState } from 'react';
import "./SubscribeForm.css";
const SubscribeForm = () => {
const [isDisabled, setIsDisabled] = useState(true);
const [email, setEmail] = useState("");
function handleChange(e){
setEmail(e.target.value);
setIsDisabled(e.target.value === "");
}
return (
<div className="container">
<h1>Subscribe To Our Newsletter</h1>
<form className="form">
<label htmlFor="email">Email Address</label>
<input onChange={handleChange} type="email" id="email" name="email" placeholder="Email Address" value={email} />
<input type="checkbox" name="agreement_checkbox" id="agreement_checkbox" />
<label htmlFor="agreement_checkbox">I agree to disagree whatever the terms and conditions are.</label>
<button name="subscribe-button" type="submit" className="button" disabled={isDisabled} >Subscribe</button>
</form>
</div>
);
};
export default SubscribeForm;
import React, { useEffect, useState } from 'react';
const PokeSearch = () => {
const [pokemon, setPokemon] = useState({});
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
fetch(`https://pokeapi.co/api/v2/pokemon/bulbasaur`)
.then((res) => res.json())
.then((result) => {
setPokemon(result);
setIsLoading(false);
})
.catch((err) => console.log(err));
}, [])
return (
<div>
{isLoading
? <h3>...Loading...</h3>
: <p>{pokemon.name}</p>
}
</div>
);
}
export default PokeSearch;
render
and screen
from testing-library/react and the user events from testing-library/user-event. Besides, remember to import the component that we want to test.import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SubscribeForm from './SubscribeForm';
it("The subscribe button is disabled before typing anything in the input text box", () => {
render(<SubscribeForm />);
expect(screen.getByRole("button", {name: /subscribe/i})).toBeDisabled();
});
<div data-testid="test-element" />
screen.getByTestId('test-element')
screen.getByRole("")
in the test for that component, it will fail but give you the accessibility information and the name of those elements.Here are the accessible roles:
heading:
Name "Subscribe To Our Newsletter":
<h1 />
--------------------------------------------------
textbox:
Name "Email Address":
<input
id="email"
name="email"
placeholder="Email Address"
type="email"
value=""
/>
--------------------------------------------------
checkbox:
Name "I agree to disagree whatever the terms and conditions are.":
<input
id="agreement_checkbox"
name="agreement_checkbox"
type="checkbox"
/>
--------------------------------------------------
button:
Name "Subscribe":
<button
class="button"
disabled=""
name="subscribe-button"
type="submit"
/>
--------------------------------------------------
{name: /subscribe/i}
). After getting that button, we want to check if this button is disabled (it should be disabled). it("The subscribe button becomes enabled when we start typing in the input text box", () => {
render(<SubscribeForm />);
userEvent.type(screen.getByRole("textbox", {name: /email/i}), "[email protected]");
expect(screen.getByRole("button", {name: /subscribe/i})).toBeEnabled();
});
userEvent.type()
is the text that you want to input. After the text has been typed, we can now expect the button to be enabled.npm install react-test-renderer
it("Test to match snapshot of component", () => {
const subscribeFormTree = renderer.create(<SubscribeForm />).toJSON();
expect(subscribeFormTree).toMatchSnapshot();
})
PASS src/components/PokeSearch/PokeSearch.test.js
PASS src/components/SubscribeForm/SubscribeForm.test.js
› 1 snapshot written.
Snapshot Summary
› 1 snapshot written from 1 test suite.
Test Suites: 2 passed, 2 total
Tests: 5 passed, 5 total
Snapshots: 1 written, 1 total
Time: 2.519 s
Ran all test suites.
Watch Usage: Press w to show more.
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Test to match snapshot of component 1`] = `
<div
className="container"
>
<h1>
Subscribe To Our Newsletter
</h1>
<form
className="form"
>
<label
htmlFor="email"
>
Email Address
</label>
<input
id="email"
name="email"
onChange={[Function]}
placeholder="Email Address"
type="email"
value=""
/>
<input
id="agreement_checkbox"
name="agreement_checkbox"
type="checkbox"
/>
<label
htmlFor="agreement_checkbox"
>
I agree to disagree whatever the terms and conditions are.
</label>
<button
className="button"
disabled={true}
name="subscribe-button"
type="submit"
>
Subscribe
</button>
</form>
</div>
`;
<h1>Subscribe To Their Newsletter</h1>
PASS src/components/PokeSearch/PokeSearch.test.js
FAIL src/components/SubscribeForm/SubscribeForm.test.js
● Test to match snapshot of component
expect(received).toMatchSnapshot()
Snapshot name: `Test to match snapshot of component 1`
- Snapshot - 1
+ Received + 1
@@ -1,10 +1,10 @@
<div
className="container"
>
<h1>
- Subscribe To Our Newsletter
+ Subscribe To Their Newsletter
</h1>
<form
className="form"
>
<label
22 | it("Test to match snapshot of component", () => {
23 | const subscribeFormTree = renderer.create(<SubscribeForm />).toJSON();
> 24 | expect(subscribeFormTree).toMatchSnapshot();
| ^
25 | })
at Object.<anonymous> (src/components/SubscribeForm/SubscribeForm.test.js:24:31)
› 1 snapshot failed.
Snapshot Summary
› 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 failed, 4 passed, 5 total
Snapshots: 1 failed, 1 total
Time: 3.817 s
Ran all test suites.
Watch Usage: Press w to show more.
PASS src/components/PokeSearch/PokeSearch.test.js
PASS src/components/SubscribeForm/SubscribeForm.test.js
› 1 snapshot updated.
Snapshot Summary
› 1 snapshot updated from 1 test suite.
Test Suites: 2 passed, 2 total
Tests: 5 passed, 5 total
Snapshots: 1 updated, 1 total
Time: 2.504 s
Ran all test suites.
Watch Usage: Press w to show more.
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import renderer from 'react-test-renderer';
import SubscribeForm from './SubscribeForm';
it("The subscribe button is disabled before typing anything in the input text box", () => {
render(<SubscribeForm />);
expect(screen.getByRole("button", {name: /subscribe/i})).toBeDisabled();
});
it("The subscribe button becomes enabled when we start typing in the input text box", () => {
render(<SubscribeForm />);
userEvent.type(screen.getByRole("textbox", {name: /email/i}), "[email protected]");
expect(screen.getByRole("button", {name: /subscribe/i})).toBeEnabled();
});
it("Test to match snapshot of component", () => {
const subscribeFormTree = renderer.create(<SubscribeForm />).toJSON();
expect(subscribeFormTree).toMatchSnapshot();
})
afterEach(cleanup)
) done to prevent memory leak automatically by Jest (injected globally) after each test.import React from 'react';
import { render,screen,waitForElementToBeRemoved } from '@testing-library/react';
import PokeSearch from './PokeSearch';
it("Loading is shown until the Pokemon is fetched", async () => {
render(<PokeSearch />);
expect(screen.getByText('...Loading...')).toBeInTheDocument();
await waitForElementToBeRemoved(screen.queryByText('...Loading...'));
});
queryBy...
to query for the element to disappear from DOM.findBy...
(use findBy...
for asynchronous case) to find for the element that has text "bulbasaur", and check if the element is in the DOM.it("The Pokemon name is displayed correctly after it has been fetched", async () => {
// Mock the browser fetch function
window.fetch = jest.fn(() => {
const pokemon = { name: 'bulbasaur', weight: 69, height: 7 };
return Promise.resolve({
json: () => Promise.resolve(pokemon),
});
});
render(<PokeSearch />);
const pokemonName = await screen.findByText('bulbasaur');
expect(pokemonName).toBeInTheDocument();
});