Add AI-assisted QA test workflow: scenario cards, runner, hooks, API capture

A complete loop for defining, generating, running and gating tests:

- qa/: scenario-card template + examples (API/UI/binding), the Claude
  generation prompt, and a QA runbook tying it together
- e2e/CLAUDE.md: conventions that keep AI-generated tests consistent
- run-tests.ps1: one runner for every layer (backend/api/web/ui/binding),
  logs per run under .testlogs/, JUnit output, evidence report, and a
  re-seed guard against stale demo data
- .githooks/ + scripts/install-hooks.ps1: pre-commit secret scan and
  pre-push unit tests (shift-left before CI)
- evidence report now captures each API call's request, payload and
  response (Authorization redacted); JUnit reporter added for CI
- scripts/db.mjs: db:check freshness guard

Azure DevOps pipeline deferred; the runner already emits JUnit + the
evidence report for any CI to publish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nilesh.p
2026-10-10 13:04:46 +05:30
co-authored by Claude Opus 4.8
parent df9e534e42
commit 45b5b34680
20 changed files with 1054 additions and 11 deletions
+22
View File
@@ -173,6 +173,28 @@ const commands = {
createDatabase(CONFIG.testDatabase);
console.log(`✓ ${CONFIG.testDatabase} ready for go test ./...`);
},
// Freshness guard for the e2e suite. The seed generates flights relative to
// now(), so after ~3 weeks all seeded departures are in the past and the
// browser tests fail on empty search results. Exit non-zero when stale so a
// runner can re-seed before running.
check() {
if (!databaseExists(CONFIG.database)) {
console.error(`✗ ${CONFIG.database} does not exist`);
process.exit(2);
}
const out = run(
['-tAc', 'SELECT count(*) FROM flights WHERE departure_time > now()'],
{ database: CONFIG.database, capture: true },
);
const future = Number((out || '').trim());
if (Number.isFinite(future) && future > 0) {
console.log(`✓ inventory fresh: ${future} future flights`);
process.exit(0);
}
console.error('✗ inventory stale: no future flights — re-seed needed (npm run db:reset)');
process.exit(1);
},
};
const command = process.argv[2];