一键导入
test-generator
Generates Playwright test code from test plans and exploration data
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Generates Playwright test code from test plans and exploration data
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Manage OpenShift instance deployments: deploy, teardown, list, build images, backup/restore databases, and setup service accounts. Trigger phrases: deploy instance, teardown instance, list instances, build images, backup database, restore database, setup service account, oc deploy, instance management. Do NOT invoke for: local development setup, docker-compose, writing application code, database migrations.
Splits a feature branch into multiple sequential draft PRs targeting develop. Trigger phrases: split branch into PRs, break branch into PRs, create stacked PRs, split into multiple PRs. Do NOT invoke for: creating a single PR, cherry-picking individual commits, or rebasing.
Requirements Refiner: Iteratively questions the user to clarify vague requirements and outputs a single consolidated requirements document in feature-docs.
Implements user stories from a user_stories directory in dependency order using subagents. Reads README.md to find the next unchecked story, spawns Agent tool subagents to implement each one, tracks progress via scenario checkboxes in story files and story checkboxes in README. Trigger phrases: implement stories, implement user stories, story implementer, work on stories, implement next story. Do NOT invoke for: writing user stories (use write-user-stories), general code changes, checklist execution.
User Story Writer: Converts refined requirements into individual User Story files following a strict template, plus a README.md with phase breakdown. Trigger phrases: write user stories, generate user stories, create user stories from requirements.
Converts a user-provided list of issues, bugs, or tasks into a structured markdown checklist file in docs-md/. Trigger phrases: create checklist, make a checklist, turn these into a checklist, create todo file, checklist from these items. Do NOT invoke for: executing/working through checklist items, editing existing checklists, or general markdown file creation.
| name | test-generator |
| description | Generates Playwright test code from test plans and exploration data |
Generate production-ready Playwright tests from test plans and page exploration data.
feature-docs/003-benchmarking-system/){feature-dir}/playwright/test-plans/ directory (all .md files except README.md){feature-dir}/playwright/test-generation/generation-progress.md for already completed test plans*.page-doc.md and *.selectors.md files from {feature-dir}/playwright/exploration/ relevant to that test plantests/e2e/{feature-name}/tests/e2e/pages/{feature-dir}/playwright/test-generation/generation-progress.md (do not add any other information, just mark as complete)CRITICAL: Reset and seed the database before running tests to ensure consistent starting state.
Before running any tests, execute these commands:
# From apps/backend-services directory
cd apps/backend-services
# Reset database (drops all data)
PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION="yes" npx prisma migrate reset --force
# Run migrations
npm run db:migrate
# Seed test data
npm run db:seed
OR use the combined reset command:
cd apps/backend-services && PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION="yes" npx prisma migrate reset --force && npm run db:seed
NOTE: switch back to project root after resetting database.
apps/shared/prisma/seed.ts to understand available test dataseed-project-id, seed-dataset-invoices)apps/shared/prisma/seed.ts to add needed test entitiesseed- prefixnpm run db:seed to populateCreate/update {feature-dir}/playwright/test-generation/generation-progress.md:
# Test Generation Progress
- [x] US-001.md - Completed 2026-02-15
- [x] US-003.md - Completed 2026-02-15
- [ ] US-004.md - In progress
- [ ] US-006.md
- [ ] US-008.md
**Status**: 2/5 test plans generated
**Last Updated**: 2026-02-15 3:42 PM
To run Playwright tests in parallel without interference, you need to ensure test isolation – each test must run independently without sharing state. Playwright creates separate browser contexts for each test by default, but tests can still interact if they share external resources like databases, files, or API state.[^1][^2][^3]
Ensure Complete Test Independence Each test should have its own:
Avoid Shared State Common causes of test interference include:
Control Specific Test Groups For tests that must run sequentially (like database setup/teardown):
// Mark specific files to run sequentially
test.describe.configure({ mode: 'serial' });
test('Test 1', async ({ page }) => { /* ... */ });
test('Test 2', async ({ page }) => { /* ... */ });
afterEach() hooks to remove test data, but prefer starting fresh over cleanup[^3]tests/e2e/pages/{PageName}Page.tsimport { Page, Locator } from '@playwright/test';
export class EventCreationPage {
readonly page: Page;
readonly createButton: Locator;
readonly eventNameInput: Locator;
readonly submitButton: Locator;
readonly successToast: Locator;
constructor(page: Page) {
this.page = page;
this.createButton = page.locator('button:has-text("Create Event")');
this.eventNameInput = page.locator('input[name="eventName"]');
this.submitButton = page.locator('button[type="submit"]');
this.successToast = page.locator('.toast-success');
}
async createEvent(name: string, date: string) {
await this.createButton.click();
await this.eventNameInput.fill(name);
await this.page.locator('[data-testid="date-picker"]').fill(date);
await this.submitButton.click();
await this.successToast.waitFor({ state: 'visible' });
}
}
tests/e2e/{feature-name}/{scenario-name}.spec.tsimport { test, expect } from '@playwright/test';
import { setupAuthenticatedTest } from '../helpers/auth';
import { EventCreationPage } from '../pages/EventCreationPage';
test.describe('Event Creation - Happy Path', () => {
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:3002';
const FRONTEND_URL = process.env.FRONTEND_URL || 'http://localhost:3000';
const TEST_API_KEY = process.env.TEST_API_KEY;
let eventPage: EventCreationPage;
test.beforeAll(() => {
if (!TEST_API_KEY) {
throw new Error('TEST_API_KEY environment variable is not set');
}
});
test.beforeEach(async ({ page }) => {
// Setup authentication (both frontend and backend)
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
eventPage = new EventCreationPage(page);
});
test('should create event with valid data', async ({ page }) => {
// Given: User is on dashboard
await expect(page).toHaveURL(/dashboard/);
// When: User creates an event
await eventPage.createEvent('Team Meeting', '2026-03-15');
// Then: Event is created successfully
await expect(eventPage.successToast).toBeVisible();
await expect(page.locator('[data-testid="event-row"]')).toContainText('Team Meeting');
// Take screenshot for verification
await page.screenshot({
path: 'test-results/event-creation-success.png',
fullPage: true,
});
});
test('should show error for empty event name', async ({ page }) => {
// Given: User is on event creation form
await eventPage.createButton.click();
// When: User submits without entering name
await eventPage.submitButton.click();
// Then: Error message is displayed
await expect(page.locator('.error-message')).toContainText('Event name is required');
});
});
CRITICAL: Every test MUST use the authentication helper:
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
This helper:
x-api-key header for backend API callstest('should load the workflows page', async ({ page }) => {
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
// Click navigation item
await page.getByText('Workflows').click();
await page.waitForLoadState('networkidle');
// Verify page loaded
const heading = page.getByRole('heading', { name: /workflows/i });
await expect(heading).toBeVisible();
});
test('should display workflow list', async ({ page }) => {
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
await page.getByText('Workflows').click();
await page.waitForLoadState('networkidle');
// Verify specific item exists
const workflow = page.getByText('Standard OCR Workflow').first();
await expect(workflow).toBeVisible();
// Or check for multiple items
const workflows = page.getByRole('listitem');
await expect(workflows).toHaveCount(3); // or .toBeGreaterThan(0)
});
test('should navigate from list to detail page', async ({ page }) => {
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
// Go to list page
await page.getByText('HITL Review').click();
await page.waitForLoadState('networkidle');
// Click on an item
await page.getByText('Review Session #1').click();
await page.waitForLoadState('networkidle');
// Verify detail page loaded
const detailHeading = page.getByRole('heading', { name: /review session #1/i });
await expect(detailHeading).toBeVisible();
});
test('should create a new project', async ({ page }) => {
await setupAuthenticatedTest(page, {
apiKey: TEST_API_KEY!,
backendUrl: BACKEND_URL,
frontendUrl: FRONTEND_URL,
});
await page.getByText('Training Labels').click();
await page.waitForLoadState('networkidle');
// Click create button
await page.getByRole('button', { name: /new project/i }).click();
// Fill in form
await page.getByLabel('Project Name').fill('My Test Project');
await page.getByLabel('Description').fill('Test description');
// Submit
await page.getByRole('button', { name: /create/i }).click();
// Verify success
await expect(page.getByText('My Test Project')).toBeVisible();
});
setupAuthenticatedTest helper for consistencynetworkidle after navigation.first() when multiple elements match// REQ-003: User can create events)page.locator('#id') unless necessarytests/e2e/
{feature-name}/
{feature-name}.spec.ts # Main feature test
{feature-name}-details.spec.ts # Detail page test
{feature-name}-forms.spec.ts # Form interactions
Process one test plan at a time:
generation-progress.md*.page-doc.md and *.selectors.md)generation-progress.md (do not add any other information, just mark as complete)After generating tests, ALWAYS verify they work by running them.
# Run specific test file
npx playwright test tests/e2e/{feature-name}/{test-file}.spec.ts
# Run all tests for a feature
npx playwright test tests/e2e/{feature-name}/
# Run with UI mode for debugging
npx playwright test --ui
# Run in headed mode to see browser
npx playwright test --headed
When tests fail, identify the root cause:
data-testid missing, element not rendereddata-testid to source component if neededapps/shared/prisma/seed.ts to add required test datacd apps/backend-services && npm run db:seed{feature-dir}/requirements.md to understand expected behavior{feature-dir}/user-stories/data-testid attributes if missingawait page.waitForLoadState('networkidle')await element.waitFor({ state: 'visible' })page.getByRole() over page.locator()setupAuthenticatedTest not called or not working correctlysetupAuthenticatedTest is called in beforeEachTEST_API_KEY environment variable is setx-api-key headercd apps/backend-services && PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION="yes" npx prisma migrate reset --force && npm run db:seednpx playwright test path/to/test.spec.tsrequirements.md when generating tests to ensure correct expected behavioruser-stories/ folder to verify acceptance criteria are tested// ⚠️ TODO: Verify expected behavior with requirements.md