write-frontend-tests
Skill2 starsChanged 4 days agoMITView on GitHub
Test frontend behavior and change tests, stories, fixtures, mocks, or test configuration. Load when behavior needs coverage; always pair with write-frontend.
3 other projects use a version of this.
Adopted by
Most recently taken up by
- Significant-Gravitas/AutoGPTtheir own version, first seen Nov 4, 2026
- kennguyen887/agent-foundationtheir own version, first seen Jun 22, 2026
- jpoindexter/theft-kittheir own version, first seen May 20, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- Significant-Gravitas/AutoGPT★ 188ksame name
- jpoindexter/theft-kit★ 1same name
- kennguyen887/agent-foundation★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository40 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .agents/skills/AGENTS.mdAGENTS.md
- attribute-ai-commitsSkill
- check-accessSkill
- choose-dependencySkill
- coordinate-landingSkill
- develop-featureSkill
- document-codeSkill
- git-conventionsSkill
- implement-featureSkill
- manage-versionsSkill
- monitor-ciSkill
- open-pull-requestSkill
- plan-client-server-boundarySkill
- plan-featureSkill
- plan-ui-designSkill
- prefer-small-solutionsSkill
- prepare-releaseSkill
- register-ai-agentSkill
- resolve-pr-feedbackSkill
- triage-issuesSkill
- use-a-novel-cliSkill
- use-discordSkill
- write-bash-scriptsSkill
- write-design-systemSkill
- write-dockerfilesSkill
- write-frontendSkill
- write-github-actionsSkill
- write-go-kitSkill
- write-go-serviceSkill
- write-goSkill
- write-go-testsSkill
- write-infraSkill
- write-js-packageSkill
- write-openapiSkill
- write-platformSkill
- write-project-docsSkill
- write-protoSkill
- write-sqlSkill
- write-svelteSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
39 rules. 0 are common, 35 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
35
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 11
Read the production behavior before writing tests.
- Distinctive: line 17
Follow develop-feature. Early stories make a draft reviewable.
- Distinctive: line 25
Use the smallest layer that proves the user-visible contract:
- Distinctive: line 27
Test pure parsing, formatting, and state transitions as unit tests.
- Distinctive: line 28
Test component rendering and interaction through the DOM with Testing Library.
- Distinctive: line 29
Use Storybook stories as the exhaustive catalog of reusable component states.
- Distinctive: line 31
Use real-browser end-to-end tests for routing, focus across pages, browser APIs, hydration, multi-component journeys, and behavior an …
- Distinctive: line 34
Do not duplicate the same assertion at every layer.
- Distinctive: line 40
Use test IDs only when no semantic query exists.
- Distinctive: line 45
Use async queries for async UI.
- Distinctive: line 47
Prefer explicit assertions over broad snapshots.
- Distinctive: line 54
Default, supported variants, and boundary values.
- Distinctive: line 65
Do not manufacture cases that the public contract cannot reach.
- Distinctive: line 69
Keep tests deterministic and independent of order.
- Distinctive: line 73
Use real parsing, validation, and component composition when inexpensive.
- Distinctive: line 76
Use framework-supported request interception for network tests.
- Distinctive: line 91
Use Vitest APIs documented for the installed version.
- Very specific: line 104
Keep vi.mock scope and hoisting rules visible.
- Distinctive: line 108
Use the repository user-interaction helper when present.
- Distinctive: line 110
Put native lifecycle and teardown races in a browser project, not jsdom.
- Distinctive: line 123
Keep docs wrappers interaction-neutral so table or tile hover styles cannot masquerade as component behavior.
- Distinctive: line 125
Keep stories deterministic, self-contained, and free of production side effects.
- Distinctive: line 127
Use realistic interface content in visual examples.
- Distinctive: line 138
Add a docs page for every public component: intent, composition, accessibility contract, and examples.
- Distinctive: line 144
Run contrast assertions in the real browser against the exact rendered semantic pairs and states, not palette swatches alone.
- Distinctive: line 148
Treat a near-threshold contrast violation as a real failure.
- Distinctive: line 151
Treat automated accessibility output as a first pass.
- Distinctive: line 153
Keep stories and docs in a private workbench.
- Distinctive: line 161
Keep a representative framework or extraction fixture with the shared nodelib preset it validates.
- Distinctive: line 183
Test critical journeys and browser contracts, not every visual variant.
- Distinctive: line 184
Use accessible locators and observable readiness conditions.
- Distinctive: line 185
Keep test data isolated and clean it through supported product interfaces.
- Very specific: line 200
Run Authentication in a platform's stack with the callers production gives it.
- Very specific: line 206
Run the account platform's image in a client's stack, with a token drawn from the issuer at start, and register the client in OAUTH_CLIENTS …
- Distinctive: line 222
Run at least the repository browser baseline for compatibility-sensitive behavior.
- Distinctive: line 224
Before a repository first compares its screenshots against Drive reference batches, read Subscribe a repository to Drive visual tests for …
- Very specific: line 242
Treat the annotations as the inventory.
- Distinctive: line 251
Treat coverage as a map, not a percentage target.
- Distinctive: line 254
Run focused checks during iteration.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Frontend Test Conventions
Load write-frontend, plus write-svelte for Svelte targets and write-design-system for uikit.
Read the production behavior before writing tests. Read neighboring tests
and the official documentation for the installed testing tools. Preserve existing tests unless the
behavior they specify has been intentionally removed.
Timing
Follow develop-feature. Early stories make a draft reviewable; early tests should only resolve uncertainty, reproduce a defect, or protect a risky invariant. Complete the behavior matrix and full relevant regression suite after issue scope is approved. These conventions govern the quality of any test written at either stage, without requiring exhaustive coverage during exploration.
Test at the nearest truthful layer
Use the smallest layer that proves the user-visible contract:
- Test pure parsing, formatting, and state transitions as unit tests.
- Test component rendering and interaction through the DOM with Testing Library.
- Use Storybook stories as the exhaustive catalog of reusable component states; add interaction and accessibility assertions where supported.
- Use real-browser end-to-end tests for routing, focus across pages, browser APIs, hydration, multi-component journeys, and behavior an emulated DOM cannot prove.
Do not duplicate the same assertion at every layer. Keep one strong contract test and add broader tests only for integration risks.
User-centered assertions
- Query elements by accessible role and name first, then label, text, or other user-visible meaning. Use test IDs only when no semantic query exists.
- Interact as a user would: focus, type, click, submit, and press keys. Do not call component methods or mutate internal state to reach a condition.
- Assert observable output, accessible state, navigation, focus, and network contract. Do not assert private classes, framework internals, reactive calls, or implementation sequence.
- Use async queries for async UI. Wait for the condition the user observes, not an arbitrary timeout.
- Cover keyboard behavior and focus order for every custom interaction pattern.
- Prefer explicit assertions over broad snapshots. Use a snapshot only for a stable serialized contract whose meaningful review is easier as a whole than as targeted assertions.
Behavior matrix
Cover the states relevant to the changed contract:
- Default, supported variants, and boundary values.
- Loading, empty, error, retry, stale, and success.
- Disabled, readonly, required, invalid, expanded, selected, and pressed states where applicable.
- Text shorthand, composed snippets, and omitted optional regions for reusable content APIs.
- Keyboard-only operation, focus entry/exit, and focus restoration.
- Long text, missing optional content, localization, RTL, narrow viewport, and zoom/reflow.
- Dark theme, forced colors, reduced motion, and contrast-sensitive states for shared UI.
- Variant-by-state comparisons on every materially different backdrop: canvas, opaque island, translucent surface, popover, and dialog where applicable.
- Cancellation, out-of-order responses, and duplicate submission for asynchronous actions.
Do not manufacture cases that the public contract cannot reach.
Isolation and doubles
- Keep tests deterministic and independent of order. Restore timers, globals, storage, fetch mocks, and DOM mutations after each test.
- Mock at system boundaries, not inside the unit under test. Prefer a lightweight fake with behavior over a deep mock that repeats implementation details.
- Use real parsing, validation, and component composition when inexpensive. Over-mocking creates a test for the mock graph rather than the product.
- Control clock, randomness, locale, and network explicitly when they affect output.
- Use framework-supported request interception for network tests. Never call a live third-party
service from unit or component tests. The unit project of nodelib-config's
SvelteKitVitestruns offline: its globalfetchrejects every request a test does not stub, andvi.unstubAllGlobals()restores that rejection. - Make mock failures loud: reject unhandled requests and unexpected calls.
- Build a fresh
Responseper call (mockImplementation(async () => Response.json(…))). A body reads once, somockResolvedValue(response)hands every later call a consumed body, and the failure looks like a parsing bug in the code under test. - Pin performance contracts with direct assertions. To prove a body is released, keep the stubbed
Responseand assertresponse.bodyUsedafter the call. To prove calls run in parallel, return a promise that never resolves and assert synchronously that every independent call has started. A serial loop then fails at once instead of timing out.
Vitest and Testing Library
- Use Vitest APIs documented for the installed version. Prefer typed dynamic module paths when a module mock is genuinely necessary.
- Give every Vitest project config file an explicit
root:fileURLToPath(new URL(".", import.meta.url)). Since Vitest 5.0.4, a project gets its root aftersvelte()has read it. Without one, the plugin starts from the workspace root, leaves Svelte libraries untransformed (Unknown file extension ".svelte") and loads a second Svelte runtime (lifecycle_outside_component). - Name a config that holds only Vitest options
vitest.config.ts, nevervite.config.ts. Since 4.7.7,svelte-checkreads.sveltefiles from symlinked workspace packages at their real path and configures each from the nearestvite.config.*orsvelte.config.*, the Vite one winning within a directory. A Vite config without the Svelte plugin then fails withNo Svelte configuration found in vite config, as uikit'spackages/storybook-configdid. Vitest triesvitest.config.*first, so the rename costs nothing. - Keep
vi.mockscope and hoisting rules visible. Refactor an inseparable module boundary rather than relying on a mock the runtime cannot intercept. - Render DOM, not component instances. Follow Testing Library query priority and guiding principle: tests should resemble real use.
- Use the repository user-interaction helper when present. Reserve low-level event dispatch for the browser primitive being tested.
- Put native lifecycle and teardown races in a browser project, not jsdom. Exercise the real element API and event queue, including events delivered as a component unmounts, and assert the user-visible outcome rather than Svelte internals.
- Name tests as observable behavior in plain language. Group by public function, component, or user journey.
Storybook
- Give every public component stories for meaningful variants and states, including interactive, disabled/error, long-content, and narrow-layout cases.
- Show related variants together. Include the concise text API and one realistic composed example; verify that optional regions can be omitted without leaving empty structure or spacing.
- Render sizes, colors, variants, and persistent/transient state combinations in aligned matrices. Keep docs wrappers interaction-neutral so table or tile hover styles cannot masquerade as component behavior.
- Keep stories deterministic, self-contained, and free of production side effects. Use loaders and decorators only for shared, explicit environment contracts.
- Use realistic interface content in visual examples. Explain controller transitions and keyboard mechanics in docs and tests instead of making them the example's title or body.
- Isolate screens and top-layer content in subdocuments on docs pages. Show desktop/mobile examples together with responsive wrapping; modest scaling helps comparison, but verify geometry and touch targets at the native viewport size. Check the docs page itself as well as individual stories.
- Pin visual-review stories through fixed-state controllers. Clicking, submitting, pressing Escape,
or clicking outside must not change the displayed scenario. Show distinct states as separate
examples; exercise live transitions in controller/component tests. Keep locale, theme, and story
inputs configurable instead of duplicating scenarios per locale. Preserve native focus, scrolling,
and text selection; do not freeze previews
with event-blocking overlays,
inert, orpointer-events: none. - Add a docs page for every public component: intent, composition, accessibility contract, and examples. Use generated controls and ArgTypes for API reference instead of repeating a manual table. Document foundations separately from components.
- Enable accessibility analysis globally and make violations fail automated story tests when the installed Storybook integration supports it. Any exception must identify a documented false positive or intentional antipattern story.
- Run contrast assertions in the real browser against the exact rendered semantic pairs and states, not palette swatches alone. Automated tooling does not credit glow and may not understand every gradient, transparency stack, pseudo-element, or forced-colors result; inspect computed output and visually compare state separation in the supported surface contexts.
- Treat a near-threshold contrast violation as a real failure. Fix the owning semantic token and keep a rendered safety margin; do not disable the rule or add a consumer override merely because a calculated source value appeared to meet the minimum.
- Treat automated accessibility output as a first pass. Manually verify keyboard/focus behavior and relevant browser/assistive-technology combinations for complex widgets.
- Keep stories and docs in a private workbench. Keep reusable Storybook theme, preview, and test configuration in a separately consumable development package; never publish stories or runtime workbench code as part of the component package.
- List each dependency subpath a story imports in Storybook's
optimizeDeps.include(@a-novel-kit/uikit-storybook/ScrollPreview.svelte, not only the package). Vite matches entries exactly; an unlisted subpath is optimized mid-run, which reloads the iframes and fails every story file on a cold cache. CI is always cold, so prove such fixes after deletingnode_modules/.cacheandnode_modules/.vite. - Keep a representative framework or extraction fixture with the shared nodelib preset it validates. A platform tests its product catalogs, screen states, and wiring instead of copying that generic fixture locally.
End-to-end tests and screenshot comparisons
During stage 3 of develop-feature, create or update all affected Playwright tests for client-side
work. Cover the changed journeys and browser contracts, then run the relevant browser suite. Reuse
the existing harness; when one is missing, include the smallest suitable Playwright setup in the
agreed scope, following choose-dependency. Do not silently defer required browser validation.
Separate a journey's phases with blank lines. When a loop wraps test.step, move the step body into
a named function, so the loop reads as the list of cases.
For rendered changes, capture deterministic screenshots of the affected states and supported viewports and compare them with reviewed baselines. Stabilize data, fonts, locale, theme, and motion. Inspect expected, actual, and diff images. Fix unexpected differences; update a baseline only when the new rendering matches the agreed UI, and review initial baselines for new screens. Screenshots complement live app/Storybook review and behavioral assertions. For non-visual client changes, verify relevant existing visual baselines where applicable and state when no rendered surface is affected instead of inventing a screenshot test.
- Test critical journeys and browser contracts, not every visual variant.
- Use accessible locators and observable readiness conditions. Never use fixed sleeps.
- Keep test data isolated and clean it through supported product interfaces.
- Point every URL the server under test reads at a local fixture started in a global setup, never at
a live or production file. When the server caches what it reads, give each state its own
webServerentry: entries start in order, so later ones runnode buildon the first entry's build. platform-studio's downtime journeys follow this pattern. - Make a compose service that a journey stops and starts, as the outage journeys stop
authentication, join a holder's network:network_mode: service:<holder>, where aregistry.k8s.io/pauseholder publishes the ports. A restarted container otherwise gets a new host interface, and Chromium fails the page then loading withnet::ERR_NETWORK_CHANGED. platform-template'sbuilds/compose.e2e.yamlfollows this pattern. - Serve another platform's production image over plain http with
PROTOCOL_HEADER: x-forwarded-protoon its container, and sendX-Forwarded-Proto: httpfrom the journeys' browser (PlaywrightextraHTTPHeaders). adapter-node otherwise assumes https, and SvelteKit then rejects every form post to that platform as cross-site. The account platform also names anhttpsissuer, which its clients refuse. - Run Authentication in a platform's stack with the callers production gives it.
service-authentication's
service-token-issuerimage stands in for the cluster's issuer, which Authentication trusts throughSERVICE_TOKEN_ISSUER,SERVICE_TOKEN_AUDIENCEandSERVICE_TOKEN_CALLERS. A Playwright global setup draws the platform's token from the issuer into the fileSERVICE_TOKEN_PATHnames. Fixtures call Authentication through afetchthat adds a caller's token from the issuer inX-Service-Authorization. - Run the account platform's image in a client's stack, with a token drawn from the issuer at
start, and register the client in
OAUTH_CLIENTSon the address of the journeys' server. The account platform's own stack registers a stub client instead, whose callback the test serves and whose code the test exchanges. platform-studio'sbuilds/compose.e2e.yamlandtests/e2e/service-token.tsfollow this pattern. - A change to a platform's shell or pages can break the sibling journeys that drive its published
image, and they fail only when that image's pin moves. Search every other platform's
tests/e2e/for each accessible name you move or remove, and fix the journeys that reach it in a pull request that also bumps their pin. platform-account v1.2 moved its "Agora apps" list into the rail, and Studio's sign-in journey, still clicking the removed button, broke Renovate's account image bump until platform-studio#439. - A
page.routehandler sees only the first URL of a redirect chain. To alter a later step, walk the chain withpage.request.get(url, { maxRedirects: 0 }), read eachlocation, and open the altered URL withpage.goto. platform-studio's failed-exchange journey forges its code this way. - Capture traces/screenshots on failure where the existing runner supports them; do not commit transient artifacts.
- Run at least the repository browser baseline for compatibility-sensitive behavior.
Before a repository first compares its screenshots against Drive reference batches, read
Subscribe a repository to Drive visual tests for its identities,
folders, variables and seeding order. Read its recovery section when master's test-browser keeps
failing on screenshot changes that merged pull requests already approved.
A Vitest browser project, such as uikit's Storybook stories, compares its screenshots against Drive
reference batches through node-actions/test-playwright with runner: vitest. The workflows repo's
docs/migrations/v1.64.0.md is the adoption guide. Vitest's browser mode adds these rules:
- Capture
expect(page).toMatchScreenshot(). Modal dialogs and popovers render in the top layer, outside every container, so a container capture misses them. In Storybook's Vitest run, the firstbodydiv is the hiddensb-preparing-storywrapper. - Declare each screenshot with a
visual-snapshotannotation inbeforeEachor before the first assertion. Vitest acceptsannotate()only while the test state isrun, and rejects it inafterEachor after a failed soft assertion. - Name each screenshot flat, from
[A-Za-z0-9_-]with single hyphens:`${task.file.name}-${task.name}`.replace(/\W+/g, "-"). Vitest resolves only the base name and strips every other character, so a Storybook story ID or a dotted name stops matching its annotation. - Treat the annotations as the inventory. Vitest records a
toMatchScreenshotartifact only on failure, so the Drive runner lists screenshots from annotations and fails a run that writes an undeclared one. - A style assertion in a play function turns a visual change into a functional failure, which
allow-screenshot-changecannot waive. uikit's Toolbar story asserts that its link keeps the button radius, so a Button radius change fails until the link follows.
Coverage and completion
Treat coverage as a map, not a percentage target; 100% is not required. Missing error, keyboard, security, or state-transition paths matter; uncovered generated glue does not justify a test.
Run focused checks during iteration. After scope approval, complete meaningful coverage and run the applicable suites; after cleanup, rerun checks affected by the final edits:
pnpm lint
a-novel test --type=pnpm -y
a-novel build --type=pnpm -yThe change is complete only when new behavior has a regression test at the truthful layer and all affected existing tests remain green.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

