Skip to main content Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-react --skill react-testing-libraryEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio Build production-grade, accessible, and tested component libraries with Storybook, Chromatic, and design tokens
Build production-grade React apps with Next.js 14 App Router, Server Components, and Edge Runtime
Master React Hooks including useState, useEffect, useContext, useReducer, and custom hooks with production-grade patterns
Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
Explorador de archivos
4 archivos name react-testing-library description Write production-grade React tests with Testing Library, MSW, and comprehensive coverage patterns sasmp_version 2.0.0 bonded_agent 07-testing-deployment bond_type PRIMARY_BOND input_validation {"required_packages":[{"@testing-library/react":">=14.0.0"},{"@testing-library/user-event":">=14.0.0"},{"msw":">=2.0.0"}]} output_format {"code_examples":"jsx","coverage_target":80} error_handling {"patterns":["retry_flaky","async_waitfor","mock_error_states"]} observability {"logging":"jest_console","metrics":["test_duration","coverage"]}
React Testing Library Skill
Overview
Master React Testing Library for writing maintainable tests that focus on user behavior rather than implementation details.
Learning Objectives
Write component tests with RTL
Test user interactions
Handle async operations
Test hooks and context
Follow testing best practices
Quick Start
Installation
npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event
Setup
import '@testing-library/jest-dom' ;
Basic Component Testing
import { render, screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
import Button from './Button' ;
describe ('Button' , () => {
it ('renders button text' , () => {
render (<Button > Click me</Button > );
expect (screen.getByRole ('button' , { name : /click me/i })).toBeInTheDocument ();
});
it ('calls onClick when clicked' , async () => {
const handleClick = jest.fn ();
( );
userEvent. (screen. ( ));
(handleClick). ( );
});
( , {
( );
(screen. ( )). ();
});
});
render
<Button onClick ={handleClick} > Click me</Button >
await
click
getByRole
'button'
expect
toHaveBeenCalledTimes
1
it
'is disabled when disabled prop is true'
() =>
render
<Button disabled > Click me</Button >
expect
getByRole
'button'
toBeDisabled
Queries
Priority Order
screen.getByRole ('button' , { name : /submit/i });
screen.getByLabelText ('Email' );
screen.getByPlaceholderText ('Enter email' );
screen.getByText ('Welcome' );
screen.getByAltText ('Profile picture' );
screen.getByTitle ('Close' );
screen.getByTestId ('custom-element' );
Query Variants
screen.getByText ('Hello' );
screen.queryByText ('Hello' );
await screen.findByText ('Hello' );
Testing Forms
import { render, screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
import LoginForm from './LoginForm' ;
describe ('LoginForm' , () => {
it ('submits form with correct data' , async () => {
const handleSubmit = jest.fn ();
render (<LoginForm onSubmit ={handleSubmit} /> );
await userEvent.type (screen.getByLabelText (/email/i ), 'test@example.com' );
await userEvent.type (screen.getByLabelText (/password/i ), 'password123' );
await userEvent.click (screen.getByRole ('button' , { name : /login/i }));
expect (handleSubmit).toHaveBeenCalledWith ({
email : 'test@example.com' ,
password : 'password123'
});
});
it ('shows validation errors' , async () => {
render (<LoginForm onSubmit ={jest.fn()} /> );
await userEvent.click (screen.getByRole ('button' , { name : /login/i }));
expect (await screen.findByText (/email is required/i )).toBeInTheDocument ();
});
});
Testing Async Operations
import { render, screen, waitFor } from '@testing-library/react' ;
import { rest } from 'msw' ;
import { setupServer } from 'msw/node' ;
import UserProfile from './UserProfile' ;
const server = setupServer (
rest.get ('/api/users/:userId' , (req, res, ctx ) => {
return res (ctx.json ({ id : 1 , name : 'John Doe' }));
})
);
beforeAll (() => server.listen ());
afterEach (() => server.resetHandlers ());
afterAll (() => server.close ());
describe ('UserProfile' , () => {
it ('loads and displays user data' , async () => {
render (<UserProfile userId ={1} /> );
expect (screen.getByText (/loading/i )).toBeInTheDocument ();
expect (await screen.findByText ('John Doe' )).toBeInTheDocument ();
expect (screen.queryByText (/loading/i )).not .toBeInTheDocument ();
});
it ('handles API errors' , async () => {
server.use (
rest.get ('/api/users/:userId' , (req, res, ctx ) => {
return res (ctx.status (500 ));
})
);
render (<UserProfile userId ={1} /> );
expect (await screen.findByText (/error/i )).toBeInTheDocument ();
});
});
Testing Hooks
import { renderHook, act } from '@testing-library/react' ;
import useCounter from './useCounter' ;
describe ('useCounter' , () => {
it ('increments counter' , () => {
const { result } = renderHook (() => useCounter ());
act (() => {
result.current .increment ();
});
expect (result.current .count ).toBe (1 );
});
it ('resets to initial value' , () => {
const { result } = renderHook (() => useCounter (10 ));
act (() => {
result.current .increment ();
result.current .reset ();
});
expect (result.current .count ).toBe (10 );
});
});
Testing Context
import { render, screen } from '@testing-library/react' ;
import userEvent from '@testing-library/user-event' ;
import { ThemeProvider } from './ThemeContext' ;
import ThemeToggle from './ThemeToggle' ;
describe ('ThemeToggle' , () => {
it ('toggles theme' , async () => {
render (
<ThemeProvider >
<ThemeToggle />
</ThemeProvider >
);
expect (screen.getByText (/current theme: light/i )).toBeInTheDocument ();
await userEvent.click (screen.getByRole ('button' ));
expect (screen.getByText (/current theme: dark/i )).toBeInTheDocument ();
});
});
Custom Render Utility
import { render } from '@testing-library/react' ;
import { BrowserRouter } from 'react-router-dom' ;
import { ThemeProvider } from './ThemeContext' ;
function AllProviders ({ children } ) {
return (
<BrowserRouter >
<ThemeProvider >
{children}
</ThemeProvider >
</BrowserRouter >
);
}
function customRender (ui, options ) {
return render (ui, { wrapper : AllProviders , ...options });
}
export * from '@testing-library/react' ;
export { customRender as render };
Best Practices
Test user behavior, not implementation
Use accessible queries (role, label)
Avoid testing internal state
Use userEvent for realistic interactions
Mock external dependencies (API calls)
Test error states and edge cases
Keep tests simple and focused
Common Patterns
await waitFor (() => {
expect (screen.queryByText (/loading/i )).not .toBeInTheDocument ();
});
await waitFor (() => {
expect (screen.getAllByRole ('listitem' )).toHaveLength (3 );
});
screen.debug ();
screen.logTestingPlaygroundURL ();
Practice Exercises
Test form validation
Test async data fetching
Test user authentication flow
Test routing navigation
Test modal interactions
Test list filtering
Test error boundaries
Resources
Flaky Test Prevention
module .exports = {
testRetry : process.env .CI ? 2 : 0 ,
testTimeout : 10000 ,
};
it ('handles async operations reliably' , async () => {
render (<AsyncComponent /> );
expect (await screen.findByText (/loaded/i , {}, { timeout : 5000 }))
.toBeInTheDocument ();
await waitFor (() => {
expect (screen.queryByText (/loading/i )).not .toBeInTheDocument ();
});
});
MSW 2.0 Setup
import { http, HttpResponse } from 'msw' ;
export const handlers = [
http.get ('/api/users' , () => {
return HttpResponse .json ([{ id : 1 , name : 'John' }]);
}),
http.post ('/api/users' , async ({ request }) => {
const user = await request.json ();
return HttpResponse .json ({ ...user, id : Date .now () }, { status : 201 });
}),
http.get ('/api/error' , () => {
return HttpResponse .json ({ message : 'Server Error' }, { status : 500 });
}),
];
Coverage Configuration
module .exports = {
collectCoverageFrom : ['src/**/*.{js,jsx,ts,tsx}' , '!src/**/*.d.ts' ],
coverageThreshold : {
global : {
branches : 80 ,
functions : 80 ,
lines : 80 ,
statements : 80 ,
},
},
};
Version : 2.0.0
Last Updated : 2025-12-30
SASMP Version : 2.0.0
Difficulty : Intermediate
Estimated Time : 2-3 weeks
Prerequisites : React Fundamentals, Jest Basics
Changelog : Added MSW 2.0, flaky test prevention, and coverage config