// e2e coverage for the S4 mock↔coverage-gate interplay (epic #296). // // A mocked worker is still a DECLARED worker (`manifest.workers[].taskType`), so it must not // become a silently-hidden coverage gap. This proves the honest contract: // • a mocked-but-exercised worker counts toward coverage (assertFullCoverage passes) AND is // flagged `SurfaceReport.mocked` so a reader sees the coverage came via a mock, not real code; // • a declared worker that is never exercised at all is still a RED gap (mocking is opt-in and // never hides a genuinely un-driven worker). import { test } from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { bootTestApp } from "./boot-app.ts"; const ORDER_BPMN = ` `; // A real handler that would explode if actually run — proving the mock stood in for it. const HANDLERS = `export const handlers = { "order.pack": async () => { throw new Error("real order.pack must not run when mocked"); }, };`; const MIGRATION = `CREATE TABLE orders (id INTEGER PRIMARY KEY, item TEXT, status TEXT);`; const CREATE_ORDER = `export default async ({ body }, app) => { const item = String((body && body.item) || "").trim(); if (!item) return { status: 400, body: { error: "item is required" } }; await app.data.table("orders", "item").insert({ item, status: "active" }); await app.engine.createInstance({ processDefinitionId: "order", variables: { item } }); return { status: 202, body: { item } }; };`; const OPENAPI = { openapi: "3.0.3", info: { title: "Mock Coverage Fixture", version: "1.0.0" }, paths: { "/orders": { post: { operationId: "createOrder", requestBody: { required: true, content: { "application/json": { schema: { type: "object", properties: { item: { type: "string" } }, required: ["item"] }, }, }, }, responses: { "202": { description: "started" } }, }, }, }, }; /** A minimal app with one operation (`createOrder`) and one worker (`order.pack`). */ async function makeFixture(): Promise { const dir = await mkdtemp(join(tmpdir(), "urban-testkit-mockcov-")); await mkdir(join(dir, "processes"), { recursive: true }); await mkdir(join(dir, "workers"), { recursive: true }); await mkdir(join(dir, "operations"), { recursive: true }); await mkdir(join(dir, "db", "migrations"), { recursive: true }); await writeFile(join(dir, "processes", "order.bpmn"), ORDER_BPMN); await writeFile(join(dir, "workers", "handlers.ts"), HANDLERS); await writeFile(join(dir, "operations", "createOrder.ts"), CREATE_ORDER); await writeFile(join(dir, "db", "migrations", "001_init.sql"), MIGRATION); await writeFile(join(dir, "openapi.json"), JSON.stringify(OPENAPI, null, 2)); const manifest = { schemaVersion: 1, id: "testkit-mockcov-fixture", name: "Testkit Mock Coverage Fixture", models: { processes: ["processes/*.bpmn"] }, data: { default: "app", sources: { app: { driver: "sqlite", url: "file:./db/app.db", migrations: "db/migrations" } }, }, workers: [{ taskType: "order.pack", handler: "workers/handlers.ts" }], api: { spec: "openapi.json", dir: "operations", validateResponses: "never" }, }; await writeFile(join(dir, "nano.app.json"), JSON.stringify(manifest, null, 2)); return dir; } test("mock+coverage: a mocked-but-exercised worker counts toward coverage AND is flagged as mocked", async () => { const dir = await makeFixture(); const app = await bootTestApp(dir, { coverage: true }); try { assert.ok(app.api && app.coverage); // Mock the worker so the (exploding) real handler never runs. app.mockWorker("order.pack").completeWith({ packed: true, via: "mock" }); // Drive createOrder → starts the `order` process → the mocked `order.pack` job is dispatched. const created = await app.api.call<{ item: string }>("createOrder", { body: { item: "widget" } }); assert.equal(created.status, 202, "the real handler would have thrown; the mock stood in"); const report = app.coverage.report(); const workers = report.surfaces.find((s) => s.surface === "workers"); assert.ok(workers); assert.deepEqual(workers.declared, ["order.pack"], "the worker is still a declared surface element"); assert.deepEqual(workers.exercised, ["order.pack"], "a mocked dispatch still counts as exercised — no hidden gap"); assert.deepEqual(workers.missing, [], "nothing declared is un-exercised"); assert.deepEqual(workers.mocked, ["order.pack"], "the coverage is honestly flagged as mock-satisfied"); assert.equal(workers.complete, true); // The gate passes for the workers surface: a mocked, exercised worker is not a gap. app.coverage.assertFullCoverage({ surfaces: ["workers"] }); } finally { await app.stop(); await rm(dir, { recursive: true, force: true }); } }); test("mock+coverage: a declared worker never exercised at all is still a RED gap (mocking hides nothing)", async () => { const dir = await makeFixture(); const app = await bootTestApp(dir, { coverage: true }); try { assert.ok(app.coverage); // Register a mock but never dispatch anything to it — the worker is declared yet never exercised. app.mockWorker("order.pack").completeWith({ packed: true }); const report = app.coverage.report(); const workers = report.surfaces.find((s) => s.surface === "workers"); assert.deepEqual(workers?.exercised, [], "nothing was dispatched"); assert.deepEqual(workers?.missing, ["order.pack"], "the un-driven worker is a genuine gap"); assert.deepEqual(workers?.mocked, [], "a never-dispatched mock does not fabricate coverage"); assert.throws( () => app.coverage?.assertFullCoverage({ surfaces: ["workers"] }), /Coverage incomplete/, "merely registering a mock must not satisfy the gate", ); } finally { await app.stop(); await rm(dir, { recursive: true, force: true }); } });