import { techStepClassifier } from "../src/lib/recipe-matching/tech-step-matcher.js"; import { resetDatabase } from "./reset-db.js"; /** * Mocha root hook plugin (see `.mocharc.json`'s `require`) — runs once * before every test file's own suites, regardless of load order. * * Warms up `techStepClassifier` here, with its own generous timeout, * instead of leaving it to happen lazily on whichever test file Mocha * happens to load first. In production this one-time cost (a `POST * /v1/train` round-trip per locale to `services/tech-step-intent-service`, * training a real `textcat` on the full `TECH_STEP_TRAINING_DATA` corpus) * is paid by `server.ts`'s own `techStepClassifier.warmUp()` before the * server ever accepts traffic — but this test suite builds its `app` * directly via `createApp()` (see e.g. `tech-step-worker.routes.test.ts`), * never running `server.ts` at all. Without this hook, that cost instead * landed inside whichever test's own call happened to trigger * `_ensureTrained()` first — found the hard way in CI, where training the * full corpus took longer than a single test's default 10s timeout * (`.mocharc.json`) and failed an otherwise-unrelated test purely because * Mocha loaded its file first alphabetically. * * `resetDatabase()` runs first, deliberately: `_train()` * (`tech-step-matcher.ts`) resolves `TechStep.key -> id` from the database * alongside training, and a freshly-migrated (never-seeded) test database * has no `TechStep` rows yet — every per-test `beforeEach` in this suite * already calls `resetDatabase()` again before its own test, which is a * no-op duplication of effort but not a correctness problem: `TRUNCATE ... * RESTART IDENTITY` plus deterministic re-seeding (`seedReferenceData`) * assigns the exact same ids every time, so the `uid -> id` map memoized * here from this first reset stays valid for every reset after it. */ export const mochaHooks = { // biome-ignore lint/suspicious/noExplicitAny: Mocha's root hook `this` (a Context with `.timeout()`) isn't typed without @types/mocha (not a dependency here) — same untyped-`this` shape already used in tech-step-worker.routes.test.ts. async beforeAll(this: any): Promise { this.timeout(60000); await resetDatabase(); await techStepClassifier.warmUp(); }, };