agentsclimarketplace

Write tests

Skill lukedj78/dev-flow/write-tests

A filesystem contract (.workflow/meta.json) + 37 agent skills that take a product from idea to production: web (Next.js 16) & mobile (Expo/RN), plus an eve agent engine and Linear/scrum. Runs on Claude Code, Codex, Copilot, Gemini, Cursor.

Install
npx -y skills add lukedj78/dev-flow --skill write-tests

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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", "unit test per il componente Z", "add tests for <file>", or after `screenshot-to-page` / `module-add` runs and the user wants coverage. Not for: scaffolding the test infrastructure (`module-add test`), running QA on a deployed site (`qa`), or methodology guidance (`superpowers:test-driven-development`).

SKILL.md

10.6 KB, as published. Nobody here has run it

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 <root>/.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__/<name>.test.ts for unit, e2e/<name>.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 <project-root>/.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:

PatternClassificationReference
lib/server/<domain>.ts (contains "use server" or exported async functions returning ActionResult)Server actionreferences/test-server-action.md
lib/queries/<domain>.ts (async functions reading from @/lib/db)Queryreferences/test-query.md
app/<route>/page.tsx or app/<route>/[...slug]/page.tsxPage (e2e)references/test-page-e2e.md
components/**/*.tsx containing "use client" and interactive logicComponent (RTL)references/test-component.md
components/ui/*.tsx (shadcn primitives)Skip — primitives are tested upstream
Anything elseAsk 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__/<name>.test.ts
  • Queries: lib/queries/__tests__/<name>.test.ts
  • Components: components/<group>/__tests__/<name>.test.tsx (or co-located: components/<group>/<name>.test.tsx)
  • Pages: e2e/<route-slug>.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 <test-file>          # for unit tests
pnpm playwright test <test-file>     # 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:
    {
      "skill": "write-tests",
      "ran_at": "<now>",
      "inputs": {"source": "lib/server/clienti.ts", "type": "server-action"},
      "outputs": ["lib/server/__tests__/clienti.test.ts"],
      "phase_before": "<unchanged>",
      "phase_after": "<unchanged>"
    }
    

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 <path> or pnpm playwright test <path>.

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.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.