Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计通过

react-testing-libraryReact 测试 library

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

13,171

周安装

560

GitHub Stars

14

下载量

4,614
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:react-testing-library(React 测试 library)
来源仓库:https://github.com/itechmeat/llm-code
仓库路径:skills/react-testing-library
安装命令:
npx skills add https://github.com/itechmeat/llm-code --skill react-testing-library
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/itechmeat/llm-code --skill react-testing-library

简介

辅助 React Testing Library 测试用例生成与审查。

  • 适用于生成或审查用户视角下的组件交互测试代码。react-testing-library 属于研究检索类 Skill,可作为该场景下的辅助能力补充。
  • 可整理查询方式、异步操作与 mock 策略实现。
  • 需结合项目测试框架与组件复杂度使用,避免过度 mock。
  • 建议在核心交互路径上配合 E2E 测试与手动验证。

SKILL.md

React Testing Library Skill

Quick Navigation


Installation

Install: npm install --save-dev @testing-library/react @testing-library/dom. Recommended extras: @testing-library/user-event and @testing-library/jest-dom. React 19 requires v16.1.0+.

Core Philosophy

"The more your tests resemble the way your software is used, the more confidence they can give you."

Avoid testing:

  • Internal state of components
  • Internal methods
  • Lifecycle methods
  • Child component implementation details

Test instead:

  • What users see and interact with
  • Behavior from user's perspective
  • Accessibility (queries by role, label)

Query Priority

Use queries in this order of preference:

1. Accessible to Everyone (Preferred)

// Best — by ARIA role
getByRole("button", { name: /submit/i });
getByRole("textbox", { name: /email/i });

// Form fields — by label
getByLabelText("Email");

// Non-interactive content — by text
getByText("Welcome back!");

2. Semantic Queries

// Images
getByAltText("Company logo");

// Title attribute (less reliable)
getByTitle("Close");

3. Test IDs (Escape Hatch)

// Only when other queries don't work
getByTestId("custom-element");

Query Types

TypeNo Match1 Match>1 MatchAsync
getBy...throwreturnthrowNo
queryBy...nullreturnthrowNo
findBy...throwreturnthrowYes
getAllBy...throwarrayarrayNo
queryAllBy...[]arrayarrayNo
findAllBy...throwarrayarrayYes

When to use:

  • getBy* — element exists
  • queryBy* — element may not exist (assertions like expect(...).not.toBeInTheDocument())
  • findBy* — element appears asynchronously

Basic Test Pattern

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("shows greeting after login", async () => {
  const user = userEvent.setup();
  render(<App />);

  // Act — simulate user interactions
  await user.type(screen.getByLabelText(/username/i), "john");
  await user.click(screen.getByRole("button", { name: /login/i }));

  // Assert — verify outcome
  expect(await screen.findByText(/welcome, john/i)).toBeInTheDocument();
});

User Events

Always use @testing-library/user-event over fireEvent:

import userEvent from "@testing-library/user-event";

test("user interactions", async () => {
  const user = userEvent.setup();

  // Click
  await user.click(element);
  await user.dblClick(element);
  await user.tripleClick(element);

  // Type
  await user.type(input, "Hello");
  await user.clear(input);

  // Select
  await user.selectOptions(select, ["option1", "option2"]);

  // Keyboard
  await user.keyboard("{Enter}");
  await user.keyboard("[ShiftLeft>]a[/ShiftLeft]"); // Shift+A

  // Clipboard
  await user.copy();
  await user.paste();

  // Pointer
  await user.hover(element);
  await user.unhover(element);
});

Async Patterns

waitFor — Retry Until Success

await waitFor(() => {
  expect(screen.getByText("Loaded")).toBeInTheDocument();
});

// With options
await waitFor(() => expect(callback).toHaveBeenCalled(), {
  timeout: 5000,
  interval: 100,
});

findBy — Built-in waitFor

// Equivalent to: await waitFor(() => getByText('Loaded'))
const element = await screen.findByText("Loaded");

waitForElementToBeRemoved

await waitForElementToBeRemoved(() => screen.queryByText("Loading..."));

Common Patterns

Custom Render with Providers

// test-utils.tsx
import { render } from "@testing-library/react";
import { ThemeProvider } from "./ThemeProvider";
import { AuthProvider } from "./AuthProvider";

function AllProviders({ children }) {
  return (
    <ThemeProvider>
      <AuthProvider>{children}</AuthProvider>
    </ThemeProvider>
  );
}

const customRender = (ui, options) => render(ui, { wrapper: AllProviders, ...options });

export * from "@testing-library/react";
export { customRender as render };

Testing Hooks

import { renderHook, act } from "@testing-library/react";

test("useCounter increments", () => {
  const { result } = renderHook(() => useCounter());

  expect(result.current.count).toBe(0);

  act(() => {
    result.current.increment();
  });

  expect(result.current.count).toBe(1);
});

Rerender with New Props

const { rerender } = render(<Counter count={1} />);
expect(screen.getByText("Count: 1")).toBeInTheDocument();

rerender(<Counter count={2} />);
expect(screen.getByText("Count: 2")).toBeInTheDocument();

Query Within Container

import { within } from "@testing-library/react";

const modal = screen.getByRole("dialog");
const submitBtn = within(modal).getByRole("button", { name: /submit/i });

Debugging

// Print entire DOM
screen.debug();

// Print specific element
screen.debug(screen.getByRole("button"));

// Log available roles
import { logRoles } from "@testing-library/react";
logRoles(container);

// With prettyDOM options
screen.debug(undefined, 10000); // max length

jest-dom Matchers

import "@testing-library/jest-dom";

expect(element).toBeInTheDocument();
expect(element).toBeVisible();
expect(element).toBeEnabled();
expect(element).toBeDisabled();
expect(element).toHaveTextContent("Hello");
expect(element).toHaveValue("input value");
expect(element).toHaveAttribute("href", "/home");
expect(element).toHaveClass("active");
expect(element).toHaveFocus();
expect(element).toBeChecked();

Configuration

import { configure } from "@testing-library/react";

configure({
  // Custom test ID attribute
  testIdAttribute: "data-my-test-id",

  // Async timeout
  asyncUtilTimeout: 5000,

  // Default hidden
  defaultHidden: true,

  // Throw suggestions (debugging)
  throwSuggestions: true,
});

❌ Prohibitions (Anti-patterns)

// ❌ Don't query by class/id
container.querySelector(".my-class");

// ❌ Don't use container.firstChild
const { container } = render(<Component />);
expect(container.firstChild).toHaveClass("active");

// ❌ Don't use fireEvent when userEvent works
fireEvent.click(button); // Use userEvent.click instead

// ❌ Don't test implementation details
expect(component.state.loading).toBe(false);

// ❌ Don't use waitFor with findBy
await waitFor(() => screen.findByText("x")); // findBy already waits

// ❌ Don't assert inside waitFor callback (unless necessary)
await waitFor(() => {
  expect(mockFn).toHaveBeenCalled(); // OK - need to wait for call
});

✅ Best Practices

// ✅ Use screen for all queries
import { render, screen } from "@testing-library/react";
render(<Component />);
screen.getByRole("button"); // Good

// ✅ Prefer userEvent over fireEvent
const user = userEvent.setup();
await user.click(button);

// ✅ Use findBy for async elements
const element = await screen.findByText("Loaded");

// ✅ Use queryBy for non-existence assertions
expect(screen.queryByText("Error")).not.toBeInTheDocument();

// ✅ Use within for scoped queries
const form = screen.getByRole("form");
within(form).getByLabelText("Email");

// ✅ Use accessible queries (role, label, text)
getByRole("button", { name: /submit/i });

TextMatch Options

// Exact match (default)
getByText("Hello World");

// Substring match
getByText("llo Worl", { exact: false });

// Regex
getByText(/hello world/i);

// Custom function
getByText((content, element) => {
  return element.tagName === "SPAN" && content.startsWith("Hello");
});

Quick Reference

ImportUsage
renderRender component to DOM
screenQuery the rendered DOM
cleanupUnmount components (auto in Jest)
actWrap state updates
renderHookTest custom hooks
withinScope queries to element
waitForRetry until assertion passes
configureSet global options
userEvent.setup()Create user event instance

Links

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

github-copilot

31.31%
按下载量换算1,445

OpenCode

22.88%
按下载量换算1,056

Claude Code

17.67%
按下载量换算815

Cursor

13.11%
按下载量换算605

Codex

7.28%
按下载量换算336

Antigravity

3.06%
按下载量换算141

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills