From 0de6778f135f963a7ea5ee0e9238eca2217dbf7d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 7 Mar 2026 17:28:00 +0000 Subject: [PATCH] refactor(gateway): dedupe legacy migration validation assertions --- src/gateway/server.legacy-migration.test.ts | 99 ++++++++------------- 1 file changed, 37 insertions(+), 62 deletions(-) diff --git a/src/gateway/server.legacy-migration.test.ts b/src/gateway/server.legacy-migration.test.ts index 0522f8a85..713213908 100644 --- a/src/gateway/server.legacy-migration.test.ts +++ b/src/gateway/server.legacy-migration.test.ts @@ -8,76 +8,51 @@ import { installGatewayTestHooks({ scope: "suite" }); +async function expectHeartbeatValidationError(legacyParsed: Record) { + testState.legacyIssues = [ + { + path: "heartbeat", + message: + "top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", + }, + ]; + testState.legacyParsed = legacyParsed; + testState.migrationConfig = null; + testState.migrationChanges = []; + + let server: Awaited> | undefined; + let thrown: unknown; + try { + server = await startGatewayServer(await getFreePort()); + } catch (err) { + thrown = err; + } + + if (server) { + await server.close(); + } + + expect(thrown).toBeInstanceOf(Error); + const message = String((thrown as Error).message); + expect(message).toContain("Invalid config at"); + expect(message).toContain( + "heartbeat: top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", + ); + expect(message).not.toContain("Legacy config entries detected but auto-migration failed."); +} + describe("gateway startup legacy migration fallback", () => { test("surfaces detailed validation errors when legacy entries have no migration output", async () => { - testState.legacyIssues = [ - { - path: "heartbeat", - message: - "top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", - }, - ]; - testState.legacyParsed = { + await expectHeartbeatValidationError({ heartbeat: { model: "anthropic/claude-3-5-haiku-20241022", every: "30m" }, - }; - testState.migrationConfig = null; - testState.migrationChanges = []; - - let server: Awaited> | undefined; - let thrown: unknown; - try { - server = await startGatewayServer(await getFreePort()); - } catch (err) { - thrown = err; - } - - if (server) { - await server.close(); - } - - expect(thrown).toBeInstanceOf(Error); - const message = String((thrown as Error).message); - expect(message).toContain("Invalid config at"); - expect(message).toContain( - "heartbeat: top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", - ); - expect(message).not.toContain("Legacy config entries detected but auto-migration failed."); + }); }); test("keeps detailed validation errors when heartbeat comes from include-resolved config", async () => { - testState.legacyIssues = [ - { - path: "heartbeat", - message: - "top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", - }, - ]; // Simulate a parsed source that only contains include directives, while // legacy heartbeat is surfaced from the resolved config. - testState.legacyParsed = { + await expectHeartbeatValidationError({ $include: ["heartbeat.defaults.json"], - }; - testState.migrationConfig = null; - testState.migrationChanges = []; - - let server: Awaited> | undefined; - let thrown: unknown; - try { - server = await startGatewayServer(await getFreePort()); - } catch (err) { - thrown = err; - } - - if (server) { - await server.close(); - } - - expect(thrown).toBeInstanceOf(Error); - const message = String((thrown as Error).message); - expect(message).toContain("Invalid config at"); - expect(message).toContain( - "heartbeat: top-level heartbeat is not a valid config path; use agents.defaults.heartbeat (cadence/target/model settings) or channels.defaults.heartbeat (showOk/showAlerts/useIndicator).", - ); - expect(message).not.toContain("Legacy config entries detected but auto-migration failed."); + }); }); });