/** * src/services/qa/bdd-test-style-verifier.ts * * BDD test-style verifier. This is the read-only, post-edit companion * to the `scripts/migrate-to-bdd.mjs` AST migrator shipped in Slice A. * * Purpose: * When peaks-qa runs its verification gate, it picks up the git diff * for the slice and asks this module whether the new / modified test * files comply with the BDD given-when-then style. The verdict is * surfaced as either `ok` (and the slice can advance) or one of two * structured failure reasons (`missing-given-when-then` or * `description-no-should-when`) that the caller turns into a * `qa-handoff` rejection back to peaks-rd. * * Why a real AST and not a regex: * The Slice A migrator established the convention: test files have * multi-line `it(...)` calls, nested arrow bodies, and string * literals that often contain words like "when" inside the assertion * message (not in the description). A regex pass on the raw source * would false-positive on string internals. The TypeScript Compiler * API (already a dev dep via vitest) lets us: * 1. Inspect the first `StringLiteral` argument of an `it` / * `test` / `describe` call without scanning comments or * string content inside the body. * 2. Walk only the leading-comment ranges that sit before the * first statement of the callback block, so a `// when:` * inside an `expect(actual).toEqual('when X happens')` is * correctly ignored. * * No new dependencies. The verifier is intentionally synchronous and * pure (input source + path list -> verdict) so peaks-qa can call it * from a deterministic verification step without subprocess overhead. * * Anti-fake-green (CLI silent-catch rule): * This module throws on parse failure. It does NOT swallow parse * errors and return `{ ok: true }` — that would silently green-light * malformed test files. A parse error is a structural problem; the * caller must surface it. */ import { type BddStyleVerdict, type VerifyBddStyleInput } from './bdd-test-style-contract.js'; /** * Verify that every `it(...)` / `test(...)` call in the given test * files follows the BDD given-when-then contract. * * Contract: * 1. The first `StringLiteral` argument of every `it` / `test` call * MUST match `/(\bwhen\b|\bshould\b)/` (word-boundary anchored, * case-insensitive). A regex on the raw description is correct * here because the description itself is a literal — there is * no nested template literal to misread. * 2. The callback body (the second argument when it is an arrow / * function expression with a block) MUST start with the * `// given:` / `// when:` / `// then:` triple, in that order. The * unit is the leading COMMENT, not the source line: a keyword * comment plus any hanging-indented continuation lines counts as * one, so a wrapped `// given:` does not shift `// when:` into a * later slot. Before any executable code the body must hold exactly * those three comments — a fourth leading comment is refused. The * `// arrange:` / `// act:` / `// assert:` AAA legacy is NOT * accepted — the contract is given-when-then only. * * Returns the FIRST failure encountered (file order, then * top-to-bottom line order). A structured `BddStyleFail` is what the * caller maps to `qa-handoff` rejection. */ export declare function verifyBddStyle(input: VerifyBddStyleInput): BddStyleVerdict; export type { BddStyleFailureReason, BddStyleOk, BddStyleFail, BddStyleVerdict, VerifyBddStyleInput } from './bdd-test-style-contract.js';