Agent skill

Testing

by radix-ng in radix-ng/primitives

Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR…

MITAuto-check passedTesting & QA

Install Testing

skills CLI
$ npx skills add radix-ng/primitives --skill testing -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install radix-ng/primitives testing --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/radix-ng/primitives.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/testing .claude/skills/testing && rm -rf skills-src

Use ~/.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/

Facts

Skill name
testing
GitHub stars
274
Token cost
~3.3k tokens
SKILL.md length
943 words
Files
1
Skills in repo
7
Repo updated
First seen
Licence
MIT

At a glance

Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR…

  • Works in 4 steps: Unit — Vitest, zoneless (the default) → Browser regression —… → SSR — apps/radix-ssr-testing → …
  • : writing/fixing/adding a test
  • SKILL.md covers Decision matrix — what changed…, 1. Unit — Vitest, zoneless…, 2. Browser regression —… and 3. SSR — apps/radix-ssr-testing, plus 4 more sections
  • Calls pnpm and nx

What it does

Testing is an agent skill from radix-ng/primitives. Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR (apps/radix-ssr-testing), and perf benches (apps/radix-perf-testing). Enforces the rule that layout / positioning / part-visibility / opens-without-error fixes need a browser test — jsdom can't see them. Use when: writing/fixing/adding a test, "напиши тест", "добавь тест", "почему баг не поймали", "покрой тестом", "write a test", "add a…

Its SKILL.md is about 3.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering Unit testing, Accessibility and Design systems. It works with Vitest, Playwright and Jest. The repository describes itself as: Headless, signals-first UI primitives for Angular. Accessible. Customizable. The licence is MIT.

When your agent uses it

  • : writing/fixing/adding a test
  • Почему баг не поймали
  • Add a regression test
  • Choosing a test type

Example prompts

  • “t see them. Use when: writing/fixing/adding a test,”
  • “write a test”
  • “add a regression test”
  • “/testing”

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Unit — Vitest, zoneless (the default)
  2. Browser regression — apps/visual-regression (Playwright over the built Storybook)
  3. SSR — apps/radix-ssr-testing
  4. Performance — apps/radix-perf-testing

What it can do on your machine

Read from SKILL.md and the folder at commit eed2a31. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    Shell commands in SKILL.md call:

    • pnpm
    • nx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Testing loads about 3.3k tokens when it runs. Until then it costs about 167 tokens; SKILL.md has 943 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~167
When it runs · the whole SKILL.md, loaded when a task matches
~3.3k

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.

Safety

Auto-check passed

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); files beside SKILL.md are not scanned.

SKILL.md

The full file from radix-ng/primitives at commit eed2a31, republished under its MIT licence (© radix-ng). 943 words, ~3,282 tokens.

Download SKILL.mdSave it as .claude/skills/testing/SKILL.md (or your agent's skills folder).
name
testing
description
Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR (apps/radix-ssr-testing), and perf benches (apps/radix-perf-testing). Enforces the rule that layout / positioning / part-visibility / opens-without-error fixes need a browser test — jsdom can't see them. Use when: writing/fixing/adding a test, "напиши тест", "добавь тест", "почему баг не поймали", "покрой тестом", "write a test", "add a regression test", "verify the fix", choosing a test type, debugging a zoneless / NG0100 / NG0951 / NG0201 test failure, or running any suite.

Testing Radix NG Primitives

First pick the layer, then write the test. Most bugs in this library are caught by Vitest unit tests — but the suite runs in jsdom, which has no real layout (no box sizes, offsetHeight / scroll metrics, flexbox resolution, getComputedStyle geometry, or floating-ui positioning), and never opens an overlay the way a user does. Those gaps have their own layers. Match the change to the layer below before writing anything.

Decision matrix — what changed → which layer

The change you made / bug you fixedAdd / run the test here
Directive logic, state, signals, inputs/outputs, keyboard handlers, value/selection modelUnit — packages/primitives/<name>/__tests__/*.spec.ts
ARIA roles / aria-* / label associationsUnit + jest-axe in the same spec
Layout / flex / overflow / scroll, part visibility ([hidden]), sizing, z-indexBrowser — apps/visual-regression/tests/<name>.behavior.spec.ts (jsdom is blind)
Overlay positioning (side/align/collision), *rdxXxxPortal teleport target, anatomy nestingBrowser — behavior.spec.ts (+ overlays.visual.spec.ts for the open-state look)
A bug that throws only on open/interaction — NG0201 (missing provider), NG0951 (required query)Browser — behavior.spec.ts with pageerror/console listeners
Pixel-level visual / styling regressionBrowser — *.visual.spec.ts screenshot baseline
SSR render, hydration (ngh), SSR-stable ids, platform guardsSSR — apps/radix-ssr-testing/src/ssr-rendering.spec.ts (+ keep the page current)
Render/update performance of a primitivePerf — apps/radix-perf-testing/src/tests/<name>.bench.ts

The rule that bit us: a select restructure made rdxSelectList (inline flex:1) a direct flex child of the popup; its inline flex overrode the demo's fixed viewport height, so the viewport grew to fit all items, never overflowed, and both scroll buttons stayed [hidden]. Every unit test stayed green — jsdom has no flexbox. A layout / positioning / visibility / opens-without-error fix is not proven until a browser behavior.spec.ts covers it.


1. Unit — Vitest, zoneless (the default)

  • Where: packages/primitives/<name>/__tests__/<name>-<role>.spec.ts
  • Run: pnpm primitives:test · single file: nx run primitives:test --testFile packages/primitives/<name>/__tests__/<file>.spec.ts
  • Stack: Vitest + AnalogJS Angular plugin + @testing-library/angular. Setup packages/primitives/test-setup.ts sets provideZonelessChangeDetection, loads @testing-library/jest-dom/vitest + the jest-axe matcher, and does not load zone.js — the suite is zone-free.
  • Use Vitest APIs (vi.fn, vi.spyOn, vi.mock, vi.importActual), never Jest globals. xdescribe/xit map to .skip.

Zoneless gotchas (these are the common failures):

  • fakeAsync / tick / waitForAsync are unavailable. Instead:
    • setTimeout-based delays → vi.useFakeTimers() + vi.advanceTimersByTime(n)
    • render / effects settle → await fixture.whenStable()
    • drain a chained microtask queue → await new Promise((r) => setTimeout(r))
  • Mutating a plain (non-signal) field then calling fixture.detectChanges() throws NG0100 — call fixture.changeDetectorRef.markForCheck() first. Signal writes (input.set, model.set, componentRef.setInput) don't need it.

a11y in the same spec (matcher is pre-registered):

ts
import { axe } from 'jest-axe';
// …after rendering / opening:
expect(await axe(container)).toHaveNoViolations();

References to copy: drawer/__tests__/drawer.spec.ts, form/__tests__/form-a11y.spec.ts.

Standard-backed test names. When a spec verifies an accessibility behavior, prefix the it(...) title with the standard it backs: [APG <Pattern>] and/or [WCAG <x.y.z>], APG before WCAG, no lowercasing — e.g. it('[APG Dialog][WCAG 4.1.2] links the trigger and popup with accessible ids and roles', …). Tag only specs that map cleanly to a criterion (roles/labels, keyboard, focus trap/restore, axe), not plumbing. This mirrors each primitive's Accessibility-table rows so the suite reads as a traceability matrix (full convention: storybook-story skill). Reference: dialog/__tests__/dialog.spec.ts.


2. Browser regression — apps/visual-regression (Playwright over the built Storybook)

This is the layer for everything jsdom can't see. Two spec kinds live in apps/visual-regression/tests/:

<name>.behavior.spec.ts — DOM/behavior, not pixels

Open the story via its real interaction, then assert. Prefer auto-retrying web-first assertions (expect(locator).toBeVisible()) over fixed waitForTimeout so async open/positioning settles deterministically.

ts
import { expect, Page, test } from '@playwright/test';

async function gotoStory(page: Page, storyId: string) {
  await page.goto(`/iframe.html?id=${storyId}&viewMode=story`);
  await page.waitForSelector('#storybook-root', { state: 'attached' });
}

test('scroll viewport overflows and buttons toggle', async ({ page }) => {
  await gotoStory(page, 'primitives-select--with-scroll');
  await page.locator('[rdxSelectTrigger]').first().click();

  const up = page.locator('[rdxSelectScrollUpButton]');
  const down = page.locator('[rdxSelectScrollDownButton]');
  const list = page.locator('[rdxSelectList]');

  await expect(down).toBeVisible(); // parts use the [hidden] attribute
  await expect(up).toBeHidden();
  const m = await list.evaluate((el) => ({ sh: el.scrollHeight, ch: el.clientHeight }));
  expect(m.ch).toBeLessThan(m.sh); // a REAL overflow, not full-content expansion
  await list.evaluate((el) => el.scrollBy(0, 200));
  await expect(up).toBeVisible();
});

Catch open-time runtime errors (NG0201 / NG0951) — attach listeners before navigating:

ts
const errors: string[] = [];
page.on('pageerror', (e) => errors.push(e.message));
page.on('console', (m) => m.type() === 'error' && errors.push(m.text()));
await gotoStory(page, 'primitives-select--aligned-position');
await page.locator('[rdxSelectTrigger]').first().click();
await expect(page.locator('[rdxSelectPopup]')).toBeVisible();
expect(errors).toEqual([]);

Story id derivation: lowercase the CSF title, replace / with -, append --, then the kebab-cased export name. Example: title Primitives/Select + export WithScroll → primitives-select--with-scroll.

<name>.visual.spec.ts — screenshot diffing

toHaveScreenshot with animations: 'disabled' (asserts the settled state, not mid-motion). Baselines committed under tests/*-snapshots/, suffixed per project+platform (…-chromium-darwin.png). stories.visual.spec.ts auto-shoots every story; overlays.visual.spec.ts covers open-state positioning. Opt a story out of the auto sweep with the !visual CSF tag.

Show full SKILL.md (363 more words)Show less
Run
bash
pnpm test-visual          # CI path: build Storybook → serve :4400 → run every spec
pnpm test-visual:update   # regenerate screenshot baselines after an INTENTIONAL visual change
pnpm test-visual:report   # open the HTML actual/expected/diff report

# Local fast loop — reuse a running dev server, no full build:
pnpm storybook:primitives                                                              # keep on :4400
pnpm exec playwright test -c apps/visual-regression/playwright.config.ts <name>.behavior

playwright.config.ts sets reuseExistingServer: !CI, so a running :4400 dev Storybook is reused; iframe URLs resolve the same as the built site. test-results/ + playwright-report/ are gitignored; specs and *-snapshots/ baselines are committed. For a quick one-off investigation you can also write a throwaway Playwright script against :4400 (import { chromium } from 'playwright', run from repo root) — but land the finding as a committed behavior.spec.ts, don't leave the script.


3. SSR — apps/radix-ssr-testing

  • Run: nx run radix-ssr-testing:test (Vitest; still passWithNoTests).
  • src/ssr-rendering.spec.ts renders primitive pages via renderApplication (@angular/platform-server) and asserts: server render doesn't throw, markup is present, hydration annotations (ngh) are emitted, ids are SSR-stable. Needs import '@angular/compiler'; at the top (platform-server is partially compiled → JIT fallback).
  • CI excludes this app from test/build, so its pages aren't type-checked there. When you change a primitive's public API, update the matching page under src/app/components/<name>/page.ts — drift only surfaces through this spec (the select page once drifted onto a removed API).

4. Performance — apps/radix-perf-testing

  • Run: pnpm primitives:bench (Vitest browser mode — real Chromium, real layout).
  • Where: apps/radix-perf-testing/src/tests/<name>.bench.ts. Copy select.bench.ts / checkbox.bench.ts.
  • Design & how to read the report: ADR docs/adr/0009, and apps/radix-storybook/docs/guides/performance.docs.mdx (Guides/Performance). Keep a bench's anatomy in sync with the primitive (the select bench reproduces the real template).

Failure → cause quick reference

SymptomCause & fix
NG0100 (ExpressionChanged) after fixture.detectChanges()Plain (non-signal) field write didn't dirty the view → fixture.changeDetectorRef.markForCheck() first
NG0951 (required child query has no value)contentChild.required(X) found nothing — the template/anatomy no longer renders X; fix wiring, not the query
NG0201 (no provider for X) only when openingA directive injects a provider that the restructure moved to a descendant; read it off the child instead
fakeAsync/tick "is not a function"Suite is zoneless → use vi.useFakeTimers() / whenStable() / a macrotask (see §1)
Unit test green but the bug is layout/visibility/positioningjsdom blind spot → it needs a browser behavior.spec.ts (§2), not a unit test
Screenshot diff after an intentional visual changepnpm test-visual:update to re-baseline (review the diff first)

Commands cheat-sheet

bash
pnpm primitives:test                                              # unit (all)
nx run primitives:test --testFile <path>                         # unit (one file)
pnpm test-visual            /  :update  /  :report               # browser regression (build+run / re-baseline / report)
nx run radix-ssr-testing:test                                    # SSR
pnpm primitives:bench                                            # perf

Authoritative docs (don't duplicate — extend these)

  • CLAUDE.md → ## Tests — quick-reference for all layers (kept in sync with this skill).
  • .claude/skills/project-knowledge/references/patterns.md → ## Testing — zoneless conventions + the browser-regression subsection in depth.
  • Storybook handbook: Guides/Performance (benches), Guides/Server-Side Rendering (SSR), Overview/Accessibility (a11y patterns).
  • apps/visual-regression/README.md — baselines, platform suffixes, CI Docker note.

© radix-ng, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/testing of radix-ng/primitives.

Open the folder on GitHubat commit eed2a31

Compare with similar skills

Testing 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.

Testing compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Testing this skillradix-ng/primitives274—~3.3kAutomated safety check: PassMIT
Playwright Testingchongdashu/vibejam-starter-pack149—~2.2kAutomated safety check: PassNone
Playwright Testingchongdashu/vibejam-starter-pack149—~2.1kAutomated safety check: PassNone
Web Testing with Playwright and Vitestwithkynam/vibecode-pro-max-kit1.1k—~892Automated safety check: PassApache-2.0
React Testingaffaan-m/ECC275k1 repos~3.3kAutomated safety check: PassMIT
Test CommanderEliasOulkadi/shokunin114—~3kAutomated safety check: NotesMIT

Similar skills

  • Playwright Testing

    chongdashu/vibejam-starter-pack

    Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.

    149 GitHub stars~2.2k tokensUpdated 5 mo ago
    Testing & QAAuto-check passed
  • Playwright Testing

    chongdashu/vibejam-starter-pack

    Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.

    149 GitHub stars~2.1k tokensUpdated 5 mo ago
    Testing & QAAuto-check passed
  • Web Testing with Playwright and Vitest

    withkynam/vibecode-pro-max-kit

    Covers web testing from unit to E2E, load, visual, accessibility and security checks, with Playwright, Vitest and k6 guides plus a Playwright setup script.

    1.1k GitHub stars~892 tokensUpdated 3 mo ago
    Testing & QAAuto-check passed
  • 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…

    275k GitHub starsUsed in 1 repo~3.3k tokens
    Testing & QAAuto-check passed
  • Test Commander

    EliasOulkadi/shokunin

    Generate unit, integration, E2E, and visual regression tests following the Testing Trophy methodology (80% integration).

    114 GitHub stars~3k tokensUpdated 3 days ago
    Testing & QAAuto-check: notes
  • Test Migration

    petrkindlmann/qa-skills

    Migrate a test suite from one framework to another, incrementally and without losing coverage.

    165 GitHub stars~5.3k tokensUpdated 3 mo ago
    Testing & QAAuto-check passed

More from radix-ng/primitives

  • Radix Ng

    radix-ng/primitives

    Build correct, accessible UI with @radix-ng/primitives — the signals-first, headless Angular primitive library.

    274 GitHub stars~2.2k tokensUpdated 9 days ago
    Auto-check passed
  • Radix Ng Examples

    radix-ng/primitives

    Index of every documented @radix-ng/primitives example. An agent skill from radix-ng/primitives.

    274 GitHub stars~2.1k tokensUpdated 9 days ago
    Auto-check passed
  • Project Knowledge

    radix-ng/primitives

    A skill your agent uses when you need information about this project's architecture, tech stack, coding patterns, data model, deployment setup, git workflow, or UX guidelines.

    274 GitHub starsUsed in 1 repo~833 tokens
    Auto-check passed
  • Storybook Story

    radix-ng/primitives

    Write or update Storybook stories and docs MDX for a Radix NG primitive following project conventions.

    274 GitHub stars~3.7k tokensUpdated 9 days ago
    Auto-check passed
  • Documentation Writing

    radix-ng/primitives

    Maintain project documentation in .claude/skills/project-knowledge/: audit, edit, check consistency, track status.

    274 GitHub stars~1.4k tokensUpdated 9 days ago
    Auto-check passed
  • Angular Developer

    radix-ng/primitives

    Angular framework reference for building this signals-first, headless directive library.

    274 GitHub stars~1.2k tokensUpdated 9 days ago
    Auto-check passed

Categories

Questions about Testing

What does Testing do?

Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR…. Testing is an agent skill from radix-ng/primitives. Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR (apps/radix-ssr-testing), and perf benches (apps/radix-perf-testing).

When should I use Testing?

Testing fits situations like: : writing/fixing/adding a test; Почему баг не поймали; add a regression test; choosing a test type.

How do I install Testing in Claude Code?

Run `npx skills add radix-ng/primitives --skill testing -a claude-code`. Or copy the skill folder (.claude/skills/testing in radix-ng/primitives) into .claude/skills/testing in your project. Claude Code loads it when a task matches its description.

How do I install Testing in Codex?

Run `npx skills add radix-ng/primitives --skill testing -a codex`. Or copy the skill folder (.claude/skills/testing in radix-ng/primitives) into .agents/skills/testing in your project. Codex loads it when a task matches its description.

Can I use Testing in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add radix-ng/primitives --skill testing -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, .gemini/skills/testing, .github/skills/testing and .opencode/skills/testing in your project.

What does Testing need to run?

Going by SKILL.md and its folder, Testing needs the command-line tools its instructions call (pnpm and nx).

Does Testing access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Testing safe to install?

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. Review the folder before installing.

What licence does Testing use?

Testing is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Testing use?

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.

What are the alternatives to Testing?

Skills that share tags, products or a category with Testing: Playwright Testing (chongdashu/vibejam-starter-pack, 149 stars), Playwright Testing (chongdashu/vibejam-starter-pack, 149 stars), Web Testing with Playwright and Vitest (withkynam/vibecode-pro-max-kit, 1.1k stars) and React Testing (affaan-m/ECC, 275k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Testing?

radix-ng (a GitHub organization) maintains it in radix-ng/primitives, which has 274 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on September 28, 2026.

Source: radix-ng/primitives on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.