React Testing
affaan-m/ECC
React component testing with React Testing Library, Vitest/Jest, MSW for network mocking, accessibility assertions with axe, and the decision boundary between component tests and Playwright/Cypress…
A skill your agent uses when writing or fixing frontend unit, component or custom-hook tests with Vitest or Jest plus Testing Library — rendering a component in jsdom, testing a hook in isolation…
$ npx skills add ericrisco/rsc-harness --skill testing-web -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ericrisco/rsc-harness testing-web --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/testing-web .claude/skills/testing-web && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .claude/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-webType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add ericrisco/rsc-harness --skill testing-web -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ericrisco/rsc-harness testing-web --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/testing-web .agents/skills/testing-web && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .agents/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ericrisco/rsc-harness --skill testing-web -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ericrisco/rsc-harness testing-web --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/testing-web .cursor/skills/testing-web && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .cursor/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/ericrisco/rsc-harness.git --path skills/testing-web--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add ericrisco/rsc-harness --skill testing-web -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ericrisco/rsc-harness testing-web --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/testing-web .gemini/skills/testing-web && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .gemini/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ericrisco/rsc-harness testing-webInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ericrisco/rsc-harness --skill testing-web -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/testing-web .github/skills/testing-web && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .github/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ericrisco/rsc-harness --skill testing-web -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ericrisco/rsc-harness testing-web --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/testing-web .opencode/skills/testing-web && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "testing-web" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/testing-web into .opencode/skills/testing-web/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "testing-web", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
testing-webA skill your agent uses when writing or fixing frontend unit, component or custom-hook tests with Vitest or Jest plus Testing Library — rendering a component in jsdom, testing a hook in isolation…
Testing Web is an agent skill from ericrisco/rsc-harness. Use when writing or fixing frontend unit, component or custom-hook tests with Vitest or Jest plus Testing Library — rendering a component in jsdom, testing a hook in isolation, choosing between sync and async queries, silencing act warnings, mocking fetch, or migrating a Jest suite to Vitest. NOT real-browser multi-page journeys (that is e2e-testing), NOT pytest suites (that is testing-py), NOT accessibility auditing (that is accessibility).
Its SKILL.md is about 3.3k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including scripts and reference files (for example `evals/README.md`, `evals/cases.yaml` and `references/jest-setup.md`).
It sits in Testing & QA, covering Unit testing. It works with Vitest, Jest, pytest and Testing Library. The repository describes itself as: Your agent invents things because it has no memory, and can't touch your database because it has no arms. rsc is the meta-harness that gives it both, plus the trade to know the… The licence is MIT.
Read from SKILL.md and the folder at commit 92fde8f. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/ (Shell), which the agent can run.
Shell commands in SKILL.md call:
npxvitestFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Testing Web loads about 3.3k tokens when it runs, and up to ~5k if it reads all its reference files. Until then it costs about 116 tokens; SKILL.md has 1,365 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from ericrisco/rsc-harness at commit 92fde8f, republished under its MIT licence (© ericrisco). 1,365 words, ~3,313 tokens.
.claude/skills/testing-web/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.A frontend test is only worth keeping if it survives a refactor and fails for the right reason.
The way to get there is boring and non-negotiable: render the thing, query it the way a user finds
it, drive it with real events, and assert on what the user can see. Everything in this skill bends
toward that. Tests that reach into className, state, props, or instance methods pass while the UI
is broken and break while the UI is fine — delete that instinct.
This skill owns unit, component, and custom-hook tests that run in a simulated DOM (jsdom) or Vitest Browser Mode at component granularity. The moment scope crosses a boundary, switch skills:
../e2e-testing/SKILL.md.../testing-py/SKILL.md.../accessibility/SKILL.md. (You will use role queries here; auditing is not the job.)../debug/SKILL.md for diagnosis.../react/SKILL.md or ../nextjs/SKILL.md.| Project shape | Runner | Why |
|---|---|---|
| New Vite / React 19 / Next 16 repo | Vitest 4 | Shares your vite.config, zero second transform pipeline, Browser Mode is stable as of v4.0 (Oct 2025). |
| Established Jest / CRA / React Native repo | Jest 30 | Migration cost outweighs the win; Jest 30 is current (min Node 18.x, min TS 5.4). |
| Both installed | pick one and rip the other out | Two runners means two configs, two mock APIs, doubled CI — and tests that pass in one, fail in the other. |
Vitest is the de-facto default for new frontend projects in 2026; Jest stays where it already lives.
Jest 30 specifics (ts-jest vs babel, the jsdom v26 window.location break) live in
references/jest-setup.md.
Pin current majors: vitest ^4.0, @testing-library/react ^16.3, @testing-library/jest-dom ^6.9,
@testing-library/user-event ^14.6, jsdom, @vitejs/plugin-react.
// vitest.config.ts
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
environment: "jsdom", // give the test a DOM; default 'node' has no document
globals: true, // describe/it/expect without imports; jest-dom matchers register globally
setupFiles: ["./vitest.setup.ts"],
},
});// vitest.setup.ts
import "@testing-library/jest-dom/vitest"; // the /vitest entry — NOT the bare import (that is Jest's)The /vitest import path matters: the bare @testing-library/jest-dom registers against Jest's
expect. Wrong path = toBeInTheDocument is not a function.
Query and assert on the rendered output a human perceives, never the mechanism. This is what makes a test outlive a refactor — rename a state variable, swap a class library, restructure the tree, and a behavioral test still passes.
// Bad — coupled to internals; passes when broken, breaks when fine
expect(wrapper.find(".btn--loading")).toHaveLength(1);
expect(component.state.isOpen).toBe(true);
// Good — coupled to user-observable behavior
expect(screen.getByRole("button", { name: /saving/i })).toBeDisabled();
expect(screen.getByRole("dialog")).toBeVisible();Reach for the highest query that fits. getByTestId is the fire escape, not the front door — it
asserts nothing about accessibility or labels.
| Priority | Query | Use for |
|---|---|---|
| 1 | getByRole(name) | Almost everything: buttons, headings, inputs, dialogs, links. |
| 2 | getByLabelText | Form fields tied to a <label>. |
| 3 | getByPlaceholderText | Inputs with only a placeholder (prefer a real label). |
| 4 | getByText | Non-interactive copy, paragraphs, list items. |
| 5 | getByDisplayValue | Asserting a filled-in input's current value. |
| last | getByTestId | Only when no role/label/text identifies the node. |
Pick the right variant by what you expect:
| Variant | Returns | Throws if absent? | Use when |
|---|---|---|---|
getBy* | element now | yes | element must already be there |
queryBy* | element or null | no (returns null) | asserting absence (expect(...).toBeNull()) |
findBy* | Promise of element | rejects after timeout | element appears later (after fetch/async) |
Never getBy something that arrives asynchronously — it throws before the element mounts. That is what
findBy is for.
Set up user-event once per test and await every interaction. It dispatches the full realistic event
sequence (pointerdown -> mousedown -> focus -> mouseup -> click), so it catches handlers fireEvent
silently skips.
import userEvent from "@testing-library/user-event";
it("submits the typed name", async () => {
const user = userEvent.setup(); // call setup() before interacting
render(<Greeter />);
await user.type(screen.getByLabelText(/name/i), "Ada"); // await — these are async
await user.click(screen.getByRole("button", { name: /greet/i }));
expect(screen.getByText(/hello, ada/i)).toBeInTheDocument();
});Reach for fireEvent only for events user-event has no verb for (e.g. scroll). A missing await
is the single most common source of "passes locally, flakes in CI."
"An update to X was not wrapped in act(...)" means state updated after your assertion ran — the test
finished, the component kept working, React complained. The fix in a component test is almost never
a manual act(). It is to wait for the observable result:
// Bad — asserts before the fetch resolves; state lands "outside act"
render(<Profile id="1" />);
expect(screen.getByText("Ada")).toBeInTheDocument(); // throws / act warning
// Good — findBy retries until the node appears, inside RTL's act wrapper
render(<Profile id="1" />);
expect(await screen.findByText("Ada")).toBeInTheDocument();For a transition you can't pin to a single element, wrap the assertion in waitFor. Bare act() in a
component test is a code smell — it belongs to hook tests (next section).
renderHook ships inside @testing-library/react itself. Do not install or import the long-deprecated
@testing-library/react-hooks. Read live values off result.current; wrap any setter call you trigger
yourself in act(); re-run with new props via rerender; await async settle with waitFor.
import { renderHook, act, waitFor } from "@testing-library/react";
it("counts down then stops at zero", async () => {
const { result, rerender } = renderHook(({ from }) => useCountdown(from), {
initialProps: { from: 3 },
});
expect(result.current.value).toBe(3);
act(() => result.current.start()); // a setter YOU invoke -> wrap in act
await waitFor(() => expect(result.current.value).toBe(0)); // async settle -> waitFor
rerender({ from: 10 }); // feed new props
expect(result.current.value).toBe(10);
});Mock at the edge your code talks to the outside world — the network or the imported module — never the internal function you are trying to verify. Mock the unit under test and the test proves nothing.
http.get(...) handlers) so components hit a real fetch/axios path. It survives client-library swaps.vi.mock("./api") (Vitest) / jest.mock("./api") (Jest) for non-network collaborators.vi.useFakeTimers() for timers/debounce; advance with vi.advanceTimersByTime(ms), then restore in cleanup.import { vi } from "vitest";
vi.mock("./flags", () => ({ isEnabled: () => true })); // a boundary module, not the componentRunnable copy-paste recipes — form submit, controlled input, MSW async data, a provider-wrapping custom
render, fake timers, a hook with an effect + cleanup, an error-boundary test — live in
references/recipes.md.
Default to explicit behavioral assertions. A snapshot proves nothing about correctness — it proves output
didn't change, and a giant DOM snapshot gets blindly --updated the first time it breaks. Snapshot only
small, stable, serializable output (a formatted currency string, a normalized config object). Never
snapshot a full component tree as your primary assertion.
Coverage tells you which code ran. It cannot tell you whether any test would have noticed if that code were wrong — and a render() with no assertion, or a snapshot nobody reads, raises coverage while detecting nothing. Mutation testing plants bugs on purpose: if the suite still passes, the mutant survived and you have found a test that asserts nothing.
// stryker.config.json — scope is not optional here
{ "testRunner": "vitest", "mutate": ["src/cart/total.ts", "src/cart/discount.ts"] }npx stryker runReach for the real tool over a hand-written mutant list: Stryker generates mutants from the syntax tree, so it cannot apply one to code that moved and cannot report one it never ran.
mutate to the files you changed. A whole-project Stryker run on a real front-end does not finish in a useful amount of time; that is the main reason teams try it once and abandon it.| Anti-pattern | Why it's wrong | Do instead |
|---|---|---|
getByTestId as first choice | Asserts nothing about a11y or labels; survives broken markup | Climb the ladder: role > label > text first |
getBy* for async content | Throws before the element mounts | await findBy* / await waitFor(...) |
Interaction without await | Assertion runs before the event settles; flakes in CI | await user.click(...) every time |
fireEvent.click by default | Skips the realistic pointer/focus sequence | userEvent.setup() then await user.click |
Manual act() in a component test | Masks the real fix (waiting for output) | Await findBy/waitFor instead |
Asserting on state/props/className | Couples the test to internals; breaks on refactor | Assert on rendered role/text the user sees |
setTimeout/sleep to wait | Arbitrary delay = slow + still flaky | findBy/waitFor retries until ready |
| Mocking the unit under test | The test verifies the mock, not the code | Mock the network/module boundary only |
Importing @testing-library/react-hooks | Deprecated; folded into @testing-library/react | Import renderHook from @testing-library/react |
Bare @testing-library/jest-dom in Vitest | Registers against Jest's expect -> matcher missing | Import @testing-library/jest-dom/vitest |
| Running Jest and Vitest in one suite | Two configs/mock APIs; passes in one, fails in other | Pick one runner, remove the other |
A test file with zero expect(...) | Renders but verifies nothing; green by accident | Every test asserts an observable outcome |
Run the linter against a test file or directory to catch these shape violations before review:
scripts/verify.sh src/components/__tests__It hard-fails on tests with no assertion and on un-awaited interactions, and warns on testid-first
queries, raw fireEvent, stray act() in component files, and setTimeout-based waiting. It checks
artifact shape, not whether your assertions are true.
© ericrisco, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, references) in skills/testing-web of ericrisco/rsc-harness.
Open the folder on GitHubat commit 92fde8f
Testing Web next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Testing Web this skillericrisco/rsc-harness | 156 | — | ~3.3k | Automated safety check: Pass | MIT | |
| React Testingaffaan-m/ECC | 274k | 1 repos | ~3.3k | Automated safety check: Pass | MIT | |
| React TestingHoangNguyen0403/agent-skills-standard | 570 | — | ~1.3k | Automated safety check: Pass | MIT | |
| Test GuardamElnagdy/guard-skills | 1.3k | 2 repos | ~2.1k | Automated safety check: Pass | MIT | |
| Designing TestsCloudAI-X/claude-workflow-v2 | 1.4k | 1 repos | ~1.5k | Automated safety check: Pass | MIT | |
| Playwright Testingchongdashu/vibejam-starter-pack | 149 | — | ~2.1k | Automated safety check: Pass | None |
affaan-m/ECC
React component testing with React Testing Library, Vitest/Jest, MSW for network mocking, accessibility assertions with axe, and the decision boundary between component tests and Playwright/Cypress…
HoangNguyen0403/agent-skills-standard
Test React components with RTL and Jest/Vitest. An agent skill from HoangNguyen0403/agent-skills-standard.
amElnagdy/guard-skills
Reviews newly written or edited tests against nine rules that cut test bloat, such as mock-heavy checks and near-duplicate cases, before they are committed.
CloudAI-X/claude-workflow-v2
Designs and implements testing strategies for any codebase. An agent skill from CloudAI-X/claude-workflow-v2.
chongdashu/vibejam-starter-pack
Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.
modu-ai/moai-adk
Drives test-first development through the RED, GREEN, REFACTOR cycle, with a config switch that selects between TDD and a DDD workflow for existing code.
ericrisco/rsc-harness
A skill your agent uses when designing or analyzing a controlled experiment — falsifiable hypothesis, sample size from an MDE, reading significance/CI/power, CUPED, or rescuing tests that won't go…
ericrisco/rsc-harness
A skill your agent uses when making a web UI conform to WCAG 2.2 Level AA — axe-core or Lighthouse a11y violations, keyboard operability, focus management, ARIA roles/names/live regions, contrast…
ericrisco/rsc-harness
A skill your agent uses when running or fixing paid acquisition on Google or Meta — campaign structure (Performance Max, Demand Gen, Search, Advantage+), platform-fit creative, budget/scaling rules…
ericrisco/rsc-harness
A skill your agent uses when measuring whether an LLM or agent system actually got better and gating merges on it: golden sets, fixing an inflated LLM-as-judge, scoring RAG (faithfulness, contextual…
ericrisco/rsc-harness
A skill your agent uses when a creative goal must become a finished media file: pick and order generative-media models per modality — AI voiceover, image-to-video clips, score — then glue them with…
ericrisco/rsc-harness
A skill your agent uses when instrumenting product or web analytics — GA4/PostHog SDK wiring, event taxonomy, funnels, double-counted events, consent gating, PII scrubbing.
Works with
Categories
A skill your agent uses when writing or fixing frontend unit, component or custom-hook tests with Vitest or Jest plus Testing Library — rendering a component in jsdom, testing a hook in isolation…. Testing Web is an agent skill from ericrisco/rsc-harness. Use when writing or fixing frontend unit, component or custom-hook tests with Vitest or Jest plus Testing Library — rendering a component in jsdom, testing a hook in isolation, choosing between sync and async queries, silencing act warnings, mocking fetch, or migrating a Jest suite to Vitest.
Testing Web fits situations like: fixing frontend unit; custom-hook tests with Vitest; jest plus Testing Library — rendering a component in jsdom; testing a hook in isolation.
Run `npx skills add ericrisco/rsc-harness --skill testing-web -a claude-code`. Or copy the skill folder (skills/testing-web in ericrisco/rsc-harness) into .claude/skills/testing-web in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ericrisco/rsc-harness --skill testing-web -a codex`. Or copy the skill folder (skills/testing-web in ericrisco/rsc-harness) into .agents/skills/testing-web in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ericrisco/rsc-harness --skill testing-web -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/testing-web, .gemini/skills/testing-web, .github/skills/testing-web and .opencode/skills/testing-web in your project.
Going by SKILL.md and its folder, Testing Web needs a shell for the scripts in its folder and the command-line tools its instructions call (npx and vitest). Our summary lists: Python 3; Node.js; A Bash shell.
SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Testing Web is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.3k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.7k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Testing Web: React Testing (affaan-m/ECC, 274k stars), React Testing (HoangNguyen0403/agent-skills-standard, 570 stars), Test Guard (amElnagdy/guard-skills, 1.3k stars) and Designing Tests (CloudAI-X/claude-workflow-v2, 1.4k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ericrisco (a GitHub user) maintains it in ericrisco/rsc-harness, which has 156 GitHub stars. The repository holds 229 skills in this directory. The repository was last updated on October 6, 2026.
Source: ericrisco/rsc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.