一键导入
test-hardening
Convert passed QA Contract criteria to automated tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Convert passed QA Contract criteria to automated tests
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Connect and verify the Well MCP — authenticate, confirm the tools work, and show what to ask. Use when the user runs /well:connect, just installed the Well plugin, or says the Well connection/MCP "isn't working" / "nothing happened".
Produce an accounts-receivable aging report and surface overdue invoices for a Well workspace. Use when the user asks who owes them money, an AR aging report, overdue invoices, days sales outstanding (DSO), or which customers to chase.
Forecast cash flow and runway for a Well workspace from booked invoices and collected bank transactions. Use when the user asks for a cash-flow forecast, runway, how long until they run out of cash, projected balance, or expected inflows/outflows.
Run a month-end (or period) close checklist against a Well workspace — verify everything is reconciled and posted before the books are closed. Use when the user asks to close the month/period, run a close checklist, check if the books are ready to close, or what's left before closing.
Produce a VAT / sales-tax summary for a period from a Well workspace's posted ledger. Use when the user asks for a VAT return, VAT summary, sales tax owed, output vs input VAT, or tax declaration figures for a period.
Build a balance sheet (bilan) from a Well workspace. Use when the user asks for a balance sheet, bilan, assets/liabilities/equity, or financial position at a point in time.
| name | test-hardening |
| description | Convert passed QA Contract criteria to automated tests |
Convert verified QA Contract criteria (G#N, AC#N) into permanent automated tests. Ensures passing scenarios become regression tests.
From qa-commit's Verification Report:
| Criteria Type | Test Framework | Location |
|---|---|---|
| G#N (Backend) | Jest | apps/api/**/*.test.ts |
| AC#N (UI State) | Storybook | **/*.stories.tsx |
| AC#N (Interaction) | Playwright | tests/e2e/**/*.spec.ts |
Grep: "G#[N]" or "[scenario name]" in test files
Skip if test already exists.
For each passed G#N without existing test:
// apps/api/src/[feature]/__tests__/[feature].test.ts
describe('[Feature Name]', () => {
// G#1: [Scenario name]
it('should [expected behavior]', async () => {
// Arrange
const input = { /* test data */ };
// Act
const response = await request(app)
.[method]('[endpoint]')
.send(input);
// Assert
expect(response.status).toBe([status]);
expect(response.body).toMatchObject({ /* expected */ });
});
// G#2: [Scenario name]
it('should return [error] when [condition]', async () => {
// Test implementation
});
});
npm run test -- --grep "[scenario name]"
For state-based AC#N:
// apps/web/src/[component]/[Component].stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Component } from './Component';
const meta: Meta<typeof Component> = {
title: 'Features/[Feature]/[Component]',
component: Component,
};
export default meta;
type Story = StoryObj<typeof Component>;
// AC#1: Renders without error
export const Default: Story = {
args: { /* default props */ },
};
// AC#2: Shows loading state
export const Loading: Story = {
args: { isLoading: true },
};
// AC#3: Shows error state
export const Error: Story = {
args: { error: 'Something went wrong' },
};
// AC#4: Shows empty state
export const Empty: Story = {
args: { data: [] },
};
npm run storybook -- --smoke-test
For interaction-based AC#N:
// tests/e2e/[feature].spec.ts
import { test, expect } from '@playwright/test';
test.describe('[Feature Name]', () => {
// AC#5: User can submit form
test('should allow form submission', async ({ page }) => {
await page.goto('/[route]');
await page.fill('[name="field"]', 'value');
await page.click('[type="submit"]');
await expect(page.locator('.success')).toBeVisible();
});
// AC#6: Keyboard navigation works
test('should support keyboard navigation', async ({ page }) => {
await page.goto('/[route]');
await page.keyboard.press('Tab');
await expect(page.locator(':focus')).toHaveAttribute('name', 'first-field');
});
});
npx playwright test [feature].spec.ts
Run all generated tests:
# Backend
npm run test
# Storybook
npm run storybook -- --smoke-test
# E2E (if applicable)
npx playwright test
## Test Hardening Report
### Generated Tests
| Criteria | Type | File | Status |
|----------|------|------|--------|
| G#1 | Jest | `[path]` | CREATED/EXISTS |
| G#2 | Jest | `[path]` | CREATED/EXISTS |
| AC#1 | Storybook | `[path]` | CREATED/EXISTS |
| AC#3 | Playwright | `[path]` | CREATED/EXISTS |
### Test Results
| Suite | Total | Passed | Failed |
|-------|-------|--------|--------|
| Jest | [N] | [N] | 0 |
| Storybook | [N] | [N] | 0 |
| Playwright | [N] | [N] | 0 |
### Coverage Update
- Backend: [N]% → [N]%
- Frontend: [N]% → [N]%
When invoked from debug skill Phase 7 (Harden):
// Regression test for [issue description]
// Debug session: [date]
it('should not [bug behavior] when [condition]', async () => {
// Reproduction steps from debug
});
Invoked by:
qa-commit - After GREEN verdictdebug - Phase 7 HardenOr manually with "use test-hardening skill".