Ejemplo
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Inicio rápido
Esta es una configuración mínima para comenzar. Si deseas ver una descripción de lo que hace cada línea, desplázate hasta la versión anotada. Desplázate hasta el Ejemplo Completo para ver una configuración de pruebas más avanzada.
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import '@testing-library/jest-dom'
import Fetch from './fetch'
test('loads and displays greeting', async () => {
// ARRANGE
render(<Fetch url="/greeting" />)
// ACT
await userEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('heading')
// ASSERT
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
Quickstart (Annotated Example)
// import react-testing methods
import {render, screen} from '@testing-library/react'
// userEvent library simulates user interactions by dispatching the events that would happen if the interaction took place in a browser.
import userEvent from '@testing-library/user-event'
// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from './fetch'
test('loads and displays greeting', async () => {
// Render a React element into the DOM
render(<Fetch url="/greeting" />)
await userEvent.click(screen.getByText('Load Greeting'))
// wait before throwing an error if it cannot find an element
await screen.findByRole('heading')
// assert that the alert message is correct using
// toHaveTextContent, a custom matcher from jest-dom.
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
Ejemplo Completo
Consulta las siguientes secciones para un desglose detallado de la prueba
Recomendamos usar la biblioteca
Mock Service Worker (MSW) para simular
declarativamente la comunicación API en tus pruebas, en lugar de hacer stubs de
window.fetch o depender de adaptadores de terceros.
Nuestro ejemplo aquí usa axios para realizar llamadas API. Si tu aplicación usa fetch() para sus llamadas API, ten en cuenta que por defecto JSDOM no incluye fetch. Si usas vitest como runner de pruebas, estará incluido. Para jest, puedes agregar manualmente un polyfill para fetch() o usar el entorno jest-fixed-jsdom que incluye fetch.
import React from 'react'
import {http, HttpResponse} from 'msw'
import {setupServer} from 'msw/node'
import {render, fireEvent, screen} from '@testing-library/react'
import '@testing-library/jest-dom'
import Fetch from '../fetch'
const server = setupServer(
http.get('/greeting', () => {
return HttpResponse.json({greeting: 'hello there'})
}),
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
test('loads and displays greeting', async () => {
render(<Fetch url="/greeting" />)
fireEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('heading')
expect(screen.getByRole('heading')).toHaveTextContent('hello there')
expect(screen.getByRole('button')).toBeDisabled()
})
test('handles server error', async () => {
server.use(
http.get('/greeting', () => {
return new HttpResponse(null, {status: 500})
}),
)
render(<Fetch url="/greeting" />)
fireEvent.click(screen.getByText('Load Greeting'))
await screen.findByRole('alert')
expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
expect(screen.getByRole('button')).not.toBeDisabled()
})
Paso a Paso
Importaciones
// import dependencies
import React from 'react'
// import API mocking utilities from Mock Service Worker
import {http, HttpResponse} from 'msw'
import {setupServer} from 'msw/node'
// import react-testing methods
import {render, fireEvent, screen} from '@testing-library/react'
// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from '../fetch'
test('loads and displays greeting', async () => {
// Arrange
// Act
// Assert
})
Simulación
Usa la función setupServer de msw para simular una solicitud API que realiza nuestro componente bajo prueba.
// declare which API requests to mock
const server = setupServer(
// capture "GET /greeting" requests
http.get('/greeting', (req, res, ctx) => {
// respond using a mocked JSON body
return HttpResponse.json({greeting: 'hello there'})
}),
)
// establish API mocking before all tests
beforeAll(() => server.listen())
// reset any request handlers that are declared as a part of our tests
// (i.e. for testing one-time error scenarios)
afterEach(() => server.resetHandlers())
// clean up once the tests are done
afterAll(() => server.close())
// ...
test('handles server error', async () => {
server.use(
// override the initial "GET /greeting" request handler
// to return a 500 Server Error
http.get('/greeting', (req, res, ctx) => {
return new HttpResponse(null, {status: 500})
}),
)
// ...
})
Preparación
El método render renderiza un elemento React en el DOM.
render(<Fetch url="/greeting" />)
Ejecución
El método fireEvent permite lanzar eventos para simular acciones del usuario.
fireEvent.click(screen.getByText('Load Greeting'))
// wait until the `get` request promise resolves and
// the component calls setState and re-renders,
// throwing an error if it cannot find an element
await screen.findByRole('heading')
Verificación
// assert that the alert message is correct using
// toHaveTextContent, a custom matcher from jest-dom.
expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
// assert that the button is not disabled using
// toBeDisabled, a custom matcher from jest-dom.
expect(screen.getByRole('button')).not.toBeDisabled()
Sistema Bajo Prueba
import React, {useState, useReducer} from 'react'
import axios from 'axios'
const initialState = {
error: null,
greeting: null,
}
function greetingReducer(state, action) {
switch (action.type) {
case 'SUCCESS': {
return {
error: null,
greeting: action.greeting,
}
}
case 'ERROR': {
return {
error: action.error,
greeting: null,
}
}
default: {
return state
}
}
}
export default function Fetch({url}) {
const [{error, greeting}, dispatch] = useReducer(
greetingReducer,
initialState,
)
const [buttonClicked, setButtonClicked] = useState(false)
const fetchGreeting = async url =>
axios
.get(url)
.then(response => {
const {data} = response
const {greeting} = data
dispatch({type: 'SUCCESS', greeting})
setButtonClicked(true)
})
.catch(error => {
dispatch({type: 'ERROR', error})
})
const buttonText = buttonClicked ? 'Ok' : 'Load Greeting'
return (
<div>
<button onClick={() => fetchGreeting(url)} disabled={buttonClicked}>
{buttonText}
</button>
{greeting && <h1>{greeting}</h1>}
{error && <p role="alert">Oops, failed to fetch!</p>}
</div>
)
}