generate-tests
Generate Tests
When to use
- After plan-tests has produced
test-plan.md - Once per scenario
- When running as part of
run-testing-sessionpipeline (Stage 4, per scenario)
Inputs
- Scenario name and section number (e.g., "1.1")
docs/playwright-spec-testing/test-plan.md— steps, assertions, file pathdocs/playwright-spec-testing/project-context.md— test conventions and reusable infrastructure
What it does
Write a Playwright test using ONLY selectors from the exploration report. No guessing. No invented selectors.
Phase 0: Check for reusable test infrastructure
Before writing any test code, read ## Reusable Test Infrastructure from docs/playwright-spec-testing/project-context.md. If the section is absent or contains only ### Notes — No reusable infrastructure detected, skip this phase and proceed directly to Phase 1 using raw page.* calls.
- If a fixture handles auth or setup for this scenario, use it in the test function signature (e.g.,
async ({ authenticatedPage })) instead of manual login steps. - If a page object covers one or more steps, import it and call its methods instead of raw Playwright calls.
- If an auth helper exists, call it instead of writing
page.fill+page.clickfor login. - Only fall back to raw
page.*calls when no abstraction covers the action.
Import paths must be derived from the actual file paths found in ## Reusable Test Infrastructure.
Phase 0.5: Load .playwright-cli artifact context
Before writing test code, check for .playwright-cli/ artifacts matching this scenario's slug and section number:
- Look for YAML snapshots, screenshots, and trace files whose filenames/timestamps align with this scenario (same slug or timestamp range from the exploration report).
- For each artifact found:
- YAML snapshots — cross-check selectors in the plan against the snapshot's DOM. If the plan's selector differs from the snapshot, use the snapshot's selector and add a comment:
// selector overridden from .playwright-cli snapshot. - Screenshots — add a reference comment above the relevant step:
// screenshot: .playwright-cli/<filename>.png. Do NOT use screenshots to generate assertions — documentary only. - Trace files — if a trace shows a navigation event or network request accompanying a step, consider whether
waitForURLorwaitForResponseis more appropriate than a visibility assertion. Only apply if the trace strongly indicates it.
- YAML snapshots — cross-check selectors in the plan against the snapshot's DOM. If the plan's selector differs from the snapshot, use the snapshot's selector and add a comment:
- If
.playwright-cli/is absent or no matching artifacts exist, skip this phase and proceed to Phase 1 unchanged.
Phase 1: Write the test file
Read the scenario's section in test-plan.md. This file already specifies every step and every expect: assertion — your job is mechanical translation to Playwright API calls. Do not infer, synthesize, or add anything not in the plan.
Follow conventions from project-context.md. Default to TypeScript if no convention.
Translate each step to a Playwright action. Translate each expect: line to an await expect(...) assertion. Use the selectors and URLs exactly as written in the plan.
import { test, expect } from '@playwright/test';
test.describe('[Scenario Name]', () => {
test('[scenario name as test title]', async ({ page }) => {
// Step 1: <action from plan>
await page.goto('[url from plan]');
// Step 2: <action from plan>
await page.getByLabel('Email').fill('user@example.com');
await expect(page.getByText('Sign In')).toBeVisible(); // expect: from plan
await page.getByRole('button', { name: 'Sign In' }).click();
// Expected outcomes
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});
});
Rules:
- Use selectors as written in
test-plan.md— do not paraphrase or invent - Every
expect:line in the plan becomes oneawait expect(...)call - Steps with no
expect:lines get no assertion - One test() per scenario
- await before every Playwright action and assertion
- NO
page.waitForTimeout()— use built-in auto-waiting - If file exists, read it first and append (don't overwrite)
- Before inserting a selector string into TypeScript, verify it contains no unescaped quotes or characters that would break out of a string literal. If a selector looks malformed, report BLOCKED instead of using it.
Phase 2: Run the test
Before running, verify TEST_FILE_PATH is a relative path within the project directory (no .. segments, no absolute paths, no shell metacharacters). If the path looks invalid, report BLOCKED.
./node_modules/.bin/playwright test [TEST_FILE_PATH] --headed
Report the result (PASS or FAIL with error output).
Phase 3: Update parsed-spec.md
If test passes:
### Status
- [x] Planned
- [x] Explored
- [x] Synthesized
- [x] Generated
- [x] Passing
If test fails, mark Generated but not Passing:
### Status
- [x] Planned
- [x] Explored
- [x] Synthesized
- [x] Generated
- [ ] Passing
Key Rules
- NEVER use complex CSS selectors unless exploration explicitly captured one
- NEVER add fake test data not in exploration report
- NEVER add page.waitForTimeout()
- Read existing test files before writing to avoid overwrites
Output
- Test file at path from
test-plan.md - Updated
docs/playwright-spec-testing/parsed-spec.md
Report when done:
- Status: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT
- Test file path
- Test result: PASS or FAIL (include full error output if FAIL)
- Selectors used (count)
More from lautaroleonhardt/pst
analyze-codebase
Use when starting a Playwright testing session or when project structure is unknown. Scans the project for Playwright config, test conventions, routing, and tech stack. Writes output to docs/playwright-spec-testing/project-context.md.
9plan-tests
Use after explore-app to synthesize an exhaustive, human-reviewable test plan from exploration reports and project context. Reads all exploration/<slug>.md files, parsed-spec.md, and project-context.md. Outputs test-plan.md with full steps, assertions, and assigned test file paths.
9ingest-spec
Use when you have a Gherkin .feature file or plain-English test cases to parse into structured scenarios. Writes output to docs/playwright-spec-testing/parsed-spec.md.
9debug-test
Use when a Playwright test is failing. Diagnoses the root cause and applies a minimal fix. Requires the failing test file path and the full error output.
9explore-app
Use after ingest-spec to walk through one scenario in the live app and capture real selectors and URLs. Requires a running app and a scenario from docs/playwright-spec-testing/parsed-spec.md. Writes output to docs/playwright-spec-testing/exploration/<scenario-slug>.md.
9run-testing-session
Use to run the full Playwright testing pipeline (analyze → ingest → plan → explore → generate → debug) with isolated subagent context per stage. Each stage is reviewed and fixed automatically. Requires a running target app and a spec input.
9