Skip to main content سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-react --skill react-testing-libraryيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المزيد من هذا المستودع 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
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