AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Write Tests

skill-lukedj78-dev-flow-write-tests · by lukedj78

Write Vitest unit/integration tests OR Playwright e2e tests for an existing source file (server action, page, component, query). Reads the project''s wired test framework from `.workflow/meta.json#stack.test`, follows the mocking patterns already present in `vitest.setup.ts` and any sibling test files. Use when the user says "scrivi i test per X", "test per la server action Y", "e2e per /clienti"…

No reviews yet
0 installs
28 views
0.0% view→install

Install

$ agentstack add skill-lukedj78-dev-flow-write-tests

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-lukedj78-dev-flow-write-tests)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Write Tests? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

write-tests — generate tests for one file at a time

This skill writes the test file that should sit next to a piece of source code. One invocation = one source file → one test file. It does not install test infrastructure (that's module-add test), does not debug failing tests (that's superpowers:systematic-debugging), and does not run an HTTP-based QA pass (that's qa).

The unit of work is deliberately small because tests rot when they're auto-generated in bulk. A single file at a time forces the user to read what was written and accept it before moving to the next.

When this skill applies

  • The user names a source file: "scrivi i test per lib/server/clienti.ts", "test per app/checkout/page.tsx", "e2e per /scadenze".
  • The orchestrator routes here from module_added (test infrastructure exists) when the user wants per-feature coverage.
  • The project has a wired test stack — meta.json#stack.test is set, OR vitest.config.ts + playwright.config.ts exist at the root.

Contract

This skill follows the dev-flow contract — see references/contracts.md. Key facts:

  • Reads /.workflow/meta.json#stack.test to confirm the test framework is wired.
  • Reads the project's existing vitest.setup.ts, vitest.config.ts, playwright.config.ts, and any sibling test files to learn the mocking style — does not re-prescribe patterns from scratch.
  • Writes a single test file alongside the source (__tests__/.test.ts for unit, e2e/.spec.ts for e2e).
  • Does NOT bump phase — tests are continuous work, not a phase transition.
  • Appends to meta.json#history with the source file path, the test path, and the test type.
  • Idempotent: if the test file already exists, ask the user — either regenerate, append missing cases, or abort. Never silently overwrite.

Workflow

Step 1 — Verify prerequisites

Read /.workflow/meta.json:

  • stack.test must be set (e.g., "vitest+playwright"). If null, stop and tell the user: "Test infrastructure not wired. Run module-add test first, then come back."
  • phase should be module_added or later. If earlier, the project might not have anything testable yet — warn and ask whether to proceed.

If stack.test is unset but vitest.config.ts exists at the project root, the user installed Vitest manually outside the contract. Proceed, but log this in the user-facing summary so they can re-run module-add test to formalize.

Step 2 — Identify the source file + classify it

The user names a file. Classify it by path + content:

| Pattern | Classification | Reference | |---|---|---| | lib/server/.ts (contains "use server" or exported async functions returning ActionResult) | Server action | references/test-server-action.md | | lib/queries/.ts (async functions reading from @/lib/db) | Query | references/test-query.md | | app//page.tsx or app//[...slug]/page.tsx | Page (e2e) | references/test-page-e2e.md | | components/**/*.tsx containing "use client" and interactive logic | Component (RTL) | references/test-component.md | | components/ui/*.tsx (shadcn primitives) | Skip — primitives are tested upstream | — | | Anything else | Ask the user what kind of test they want | — |

If the file matches multiple patterns (e.g., a server action that internally uses a query), test as server action — the action is the public surface, the query is implementation detail.

Step 3 — Read the project's existing test patterns

Before writing anything, read at least one existing test file of the same type in the project. The mocking style, the import order (mocks before imports), the naming convention, and the assertion library are already pinned by what's there. Copy the style. Don't introduce a new pattern.

If no test of that type exists yet:

  • For server actions: read references/test-server-action.md for the canonical pattern.
  • For pages e2e: read references/test-page-e2e.md.
  • For components: read references/test-component.md.
  • For queries: read references/test-query.md.

Also read vitest.setup.ts to see what's globally mocked (typically next/navigation, next/cache). Don't re-mock those in individual tests.

Step 4 — Read the source file

Read the source file end-to-end. Identify:

  • For server actions: the action's input schema (Zod), the success path, every business-error branch (what does it return { ok: false } for?), every system-error branch (what does it throw?), and the auth dependencies (getCurrentTenantId, getCurrentUserId).
  • For queries: the input arguments, the SQL/Drizzle calls, the shape of the return, the not-found / empty-result handling.
  • For pages: the rendered structure (which sections, which interactive elements, which links), the data dependencies (what getX() queries fire), the URL params if dynamic.
  • For components: the prop surface, the interactive states (useState, event handlers), the conditional rendering branches.

Make a list of test cases before writing the test. The list is the spec — the test file is just the encoding.

Step 5 — Check for existing test file

Look for:

  • Server actions: lib/server/__tests__/.test.ts
  • Queries: lib/queries/__tests__/.test.ts
  • Components: components//__tests__/.test.tsx (or co-located: components//.test.tsx)
  • Pages: e2e/.spec.ts

If exists:

  • Ask the user: regenerate from scratch, add only the missing cases, or abort?
  • Default: add only the missing cases. Open the existing file, run the spec list against the existing it("...") blocks, and append the gaps.
  • Never silently overwrite.

Step 6 — Write the test

Apply the relevant reference template (from references/), filling in the project-specific values:

  • Real source paths (resolved from meta.json or by reading the project tree).
  • Real mock shapes (read from existing tests if any).
  • Real assertion patterns (match what's already there for consistency).

The reference templates show the canonical shape for each test type. Adapt — don't paste verbatim.

Step 7 — Run the new test in isolation

After writing:

pnpm vitest run           # for unit tests
pnpm playwright test      # for e2e

If it fails, read the error:

  • Mock missing: a dependency wasn't mocked. Add the mock at the top of the file, re-run.
  • Schema drift: the source file's signature doesn't match what the test assumed. Re-read source, re-write the relevant it() block.
  • Test passes but coverage is wrong: this skill doesn't gate on coverage — leave a comment if a branch wasn't hit and tell the user.

If the failure is in the source code (e.g., the action throws unexpectedly), stop. Tests revealing real bugs is the point — surface the bug to the user, don't paper over it.

Step 8 — Update state and report

Update .workflow/meta.json:

  • Don't bump phase. Tests are continuous.
  • Append history:

``json { "skill": "write-tests", "ran_at": "", "inputs": {"source": "lib/server/clienti.ts", "type": "server-action"}, "outputs": ["lib/server/__tests__/clienti.test.ts"], "phase_before": "", "phase_after": "" } ``

Tell the user:

  • The test file path.
  • The list of cases covered (one bullet per it("...")).
  • The list of cases deliberately not covered (e.g., "auth-mocking pattern requires module-add auth to have run; one test marked it.todo") so they know the gap.
  • The command to run it: pnpm vitest run or pnpm playwright test .

Important constraints

  • One source file per invocation. "Scrivi i test per tutto" is N runs — keep history clean and let the user accept each.
  • Read existing tests first. If lib/server/__tests__/practices.test.ts already exists with a specific mocking style, the new clienti.test.ts matches that style. Consistency over canonical-template-from-this-skill.
  • Don't introduce new test deps. If the project has Vitest + Playwright, work with those. Don't suggest jest, mocha, cypress, vitest-mock-extended, etc.
  • Don't fix the source code. If a test reveals a bug, surface it. Don't silently rewrite the source to make the test pass.
  • Real assertions, not snapshots by default. Snapshot tests rot. Prefer specific assertions (expect(result.ok).toBe(false), expect(page.locator("h1")).toContainText("...")). Snapshots only when the user explicitly asks.
  • Skip what's not testable cheaply. Pages with WebGL canvases, third-party iframes, or external API calls without a mock surface — write a test.skip with a comment explaining why instead of writing a brittle test. Honesty over coverage theater.

Cross-skill dependencies

  • Requires module-add test to have run (the test infrastructure has to exist).
  • Plays nice with module-add db, module-add auth — the smoke tests in module-add test mock these; this skill follows the same pattern.
  • Pre-module-add ci: tests written by this skill run in CI once module-add ci runs (the GHA workflow added there picks up pnpm test:run and pnpm test:e2e).

What this skill does NOT do

  • Does not install test packages. That's module-add test. If vitest isn't in package.json, this skill stops and routes there.
  • Does not run a full test suite. It runs only the new test in isolation to verify it passes. Full suite runs are CI's job.
  • Does not fix failing tests. A failing test is a signal, not a problem. Surface it to the user; the user decides whether to fix the test or fix the source.
  • Does not generate coverage reports. Coverage is a separate concern; the user can wire vitest --coverage themselves once they have enough tests.
  • Does not write tests for shadcn primitives or third-party libs. Test the project's own logic, not the dependencies.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.