Audit and improve web accessibility following WCAG 2.1 guidelines. Use when the task involves `improve accessibility`, `a11y audit`, `WCAG compliance`, `screen reader support`, `keyboard navigation`, or `make accessible`.
日本語の概要は準備中です。原文の説明を表示しています。
Testing Library patterns for user-centric, accessibility-driven component testing. Covers query priority, user events, async utilities, and practical patterns for testing React, Vue, and DOM components the way users interact with them. Use when the task involves `Testing Library`, `@testing-library/react`, `React component testing`, `accessible testing`, or `user-centric testing`.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
@testing-library/react, @testing-library/vue, or
@testing-library/dom.getByRole — accessible roles (button, textbox, heading)getByLabelText — form fields with labelsgetByPlaceholderText — when no label existsgetByText — visible text contentgetByDisplayValue — current input valuesgetByAltText — imagesgetByTitle — title attributegetByTestId — LAST RESORT only@testing-library/user-event for interactions. It
simulates real browser behavior (focus, keydown, keyup, input) while fireEvent dispatches a
single synthetic event.findBy queries (which return Promises) or wrap assertions in waitFor
for any UI that updates asynchronously.import { render, screen } from "@testing-library/react";
import { SignupForm } from "./SignupForm";
it("renders the signup form with accessible elements", () => {
render(<SignupForm />);
// BEST — getByRole with accessible name
screen.getByRole("heading", { name: /create account/i });
screen.getByRole("textbox", { name: /email/i });
screen.getByRole("button", { name: /sign up/i });
// GOOD — getByLabelText for form fields
screen.getByLabelText(/password/i);
// ACCEPTABLE — getByText for static content
screen.getByText(/already have an account/i);
// LAST RESORT — only when element has no accessible role or text
screen.getByTestId("captcha-widget");
});
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { SearchBar } from "./SearchBar";
describe("SearchBar", () => {
it("calls onSearch when user types and submits", async () => {
const user = userEvent.setup(); // Always call setup() first
const onSearch = jest.fn();
render(<SearchBar onSearch={onSearch} />);
const input = screen.getByRole("searchbox", { name: /search/i });
await user.type(input, "testing library");
await user.keyboard("{Enter}");
expect(onSearch).toHaveBeenCalledWith("testing library");
});
it("clears input when clear button is clicked", async () => {
const user = userEvent.setup();
render(<SearchBar onSearch={jest.fn()} />);
const input = screen.getByRole("searchbox", { name: /search/i });
await user.type(input, "some query");
expect(input).toHaveValue("some query");
await user.click(screen.getByRole("button", { name: /clear/i }));
expect(input).toHaveValue("");
});
});
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { UserProfile } from "./UserProfile";
it("loads and displays user data", async () => {
render(<UserProfile userId="1" />);
// findBy queries wait for the element to appear (default timeout: 1000ms)
const heading = await screen.findByRole("heading", { name: /alice/i });
expect(heading).toBeInTheDocument();
});
it("shows error state when fetch fails", async () => {
server.use(
rest.get("/api/users/1", (_req, res, ctx) =>
res(ctx.status(500))
)
);
render(<UserProfile userId="1" />);
// waitFor retries the assertion until it passes
await waitFor(() => {
expect(screen.getByRole("alert")).toHaveTextContent(/failed to load/i);
});
});
it("shows loading then content", async () => {
render(<UserProfile userId="1" />);
// Loading state appears first
expect(screen.getByText(/loading/i)).toBeInTheDocument();
// Content replaces loading
await waitFor(() => {
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
});
expect(screen.getByRole("heading", { name: /alice/i })).toBeInTheDocument();
});
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ContactForm } from "./ContactForm";
describe("ContactForm", () => {
it("submits form with valid data", async () => {
const user = userEvent.setup();
const onSubmit = jest.fn();
render(<ContactForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText(/name/i), "Alice");
await user.type(screen.getByLabelText(/email/i), "alice@example.com");
// Select from dropdown — use selectOptions
await user.selectOptions(
screen.getByRole("combobox", { name: /topic/i }),
"support"
);
// Checkbox
await user.click(screen.getByRole("checkbox", { name: /agree to terms/i }));
await user.click(screen.getByRole("button", { name: /submit/i }));
expect(onSubmit).toHaveBeenCalledWith({
name: "Alice",
email: "alice@example.com",
topic: "support",
agreedToTerms: true,
});
});
it("displays validation errors for empty required fields", async () => {
const user = userEvent.setup();
render(<ContactForm onSubmit={jest.fn()} />);
await user.click(screen.getByRole("button", { name: /submit/i }));
expect(screen.getByText(/name is required/i)).toBeInTheDocument();
expect(screen.getByText(/email is required/i)).toBeInTheDocument();
});
});
import { render, screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ConfirmDialog } from "./ConfirmDialog";
it("opens and confirms deletion", async () => {
const user = userEvent.setup();
const onConfirm = jest.fn();
render(<ConfirmDialog onConfirm={onConfirm} trigger="Delete Item" />);
// Open dialog
await user.click(screen.getByRole("button", { name: /delete item/i }));
// Scope assertions to the dialog
const dialog = screen.getByRole("dialog");
expect(within(dialog).getByText(/are you sure/i)).toBeInTheDocument();
// Confirm
await user.click(within(dialog).getByRole("button", { name: /confirm/i }));
expect(onConfirm).toHaveBeenCalledTimes(1);
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
});
import { render } from "@testing-library/react";
import { axe, toHaveNoViolations } from "jest-axe";
import { Navigation } from "./Navigation";
expect.extend(toHaveNoViolations);
it("has no accessibility violations", async () => {
const { container } = render(<Navigation />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
// test-utils.tsx
import { render, RenderOptions } from "@testing-library/react";
import { ThemeProvider } from "./ThemeProvider";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
function AllProviders({ children }: { children: React.ReactNode }) {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>{children}</ThemeProvider>
</QueryClientProvider>
);
}
export function renderWithProviders(
ui: React.ReactElement,
options?: Omit<RenderOptions, "wrapper">,
) {
return render(ui, { wrapper: AllProviders, ...options });
}
// Re-export everything from testing-library
export * from "@testing-library/react";
export { renderWithProviders as render };
screen for all queries — it's always scoped to document.body and requires no
destructuring.within() to scope queries to a specific container (dialog, list item, section).getByRole as your default query — it verifies accessibility and finds elements reliably./submit/i) for text matching — it's resilient to casing
changes.render function that includes your app's providers (theme, router, query
client).container.querySelector(".my-class") — it tests implementation details, not user
behavior.fireEvent when userEvent is available — fireEvent doesn't simulate real browser
behavior.getByTestId as your first choice — it means the element lacks proper accessible roles
or labels. Fix the component first.act() manually in most cases — userEvent and findBy handle it internally.waitFor with getBy inside — use findBy instead, which is getBy + waitFor
combined.waitFor — it adds unnecessary complexity and hides
synchronous bugs.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Audit and improve web accessibility following WCAG 2.1 guidelines. Use when the task involves `improve accessibility`, `a11y audit`, `WCAG compliance`, `screen reader support`, `keyboard navigation`, or `make accessible`.
日本語の概要は準備中です。原文の説明を表示しています。
Skill for building with the Astro web framework. Helps create Astro components and pages, configure SSR adapters, set up content collections, deploy static sites, and manage project structure and CLI commands. Use when the user needs to work with Astro, mentions .astro files, asks about static site generation (SSG), islands architecture, content collections, or deploying an Astro project.
日本語の概要は準備中です。原文の説明を表示しています。
Astro framework patterns and best practices for content-focused sites. Trigger: When working with .astro files, content collections, or Astro routing.
日本語の概要は準備中です。原文の説明を表示しています。
Apply modern web development best practices for security, compatibility, and code quality. Use when the task involves `apply best practices`, `security audit`, `modernize code`, `code quality review`, or `check for vulnerabilities`.
日本語の概要は準備中です。原文の説明を表示しています。
Comprehensive Cloudflare platform skill covering Workers, Pages, storage (KV, D1, R2), AI (Workers AI, Vectorize, Agents SDK), networking (Tunnel, Spectrum), security (WAF, DDoS), and infrastructure-as-code (Terraform, Pulumi). Use for any Cloudflare development task. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.
日本語の概要は準備中です。原文の説明を表示しています。
Deploy applications and infrastructure to Cloudflare using Workers, Pages, and related platform services. Use when the user asks to deploy, host, publish, or set up a project on Cloudflare.
日本語の概要は準備中です。原文の説明を表示しています。