import { describe, expect, it } from "vitest"; import { buildApp } from "../src/app.js"; import { loadConfig } from "../src/config.js"; async function authHeaders(app: Awaited>) { const res = await app.inject({ method: "POST", url: "/api/v1/auth/login", payload: { username: "admin", password: "admin" }, }); expect(res.statusCode).toBe(200); const { token } = res.json() as { token: string }; return { authorization: `Bearer ${token}` }; } describe("settings health engine", () => { it("GET /api/v1/settings returns env fallbacks for health fields", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null, healthCheckCron: "*/30 * * * * *", healthDegradedFailures: 3, healthDownFailures: 4, healthLatencyWarnMs: 1500, healthSuccessRecoveries: 5, }, memory: true, }); const headers = await authHeaders(app); const res = await app.inject({ method: "GET", url: "/api/v1/settings", headers, }); expect(res.statusCode).toBe(200); const body = res.json() as { healthCheckCron: string; healthDegradedFailures: number; healthDownFailures: number; healthLatencyWarnMs: number; healthSuccessRecoveries: number; healthWorkerStatus?: string; }; expect(body.healthCheckCron).toBe("*/30 * * * * *"); expect(body.healthDegradedFailures).toBe(3); expect(body.healthDownFailures).toBe(4); expect(body.healthLatencyWarnMs).toBe(1500); expect(body.healthSuccessRecoveries).toBe(5); expect(body.healthWorkerStatus).toBe("missing"); await app.close(); }); it("PATCH persists health engine settings", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const res = await app.inject({ method: "PATCH", url: "/api/v1/settings", headers, payload: { healthCheckCron: "0 */5 * * * *", healthDegradedFailures: 2, healthDownFailures: 4, healthLatencyWarnMs: 800, healthSuccessRecoveries: 3, }, }); expect(res.statusCode).toBe(200); const body = res.json() as { healthCheckCron: string; healthDegradedFailures: number; healthDownFailures: number; healthLatencyWarnMs: number; healthSuccessRecoveries: number; }; expect(body.healthCheckCron).toBe("0 */5 * * * *"); expect(body.healthDegradedFailures).toBe(2); expect(body.healthDownFailures).toBe(4); expect(body.healthLatencyWarnMs).toBe(800); expect(body.healthSuccessRecoveries).toBe(3); const again = await app.inject({ method: "GET", url: "/api/v1/settings", headers, }); expect(again.json()).toMatchObject({ healthCheckCron: "0 */5 * * * *", healthDegradedFailures: 2, healthDownFailures: 4, healthLatencyWarnMs: 800, healthSuccessRecoveries: 3, }); await app.close(); }); it("PATCH rejects invalid cron", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const res = await app.inject({ method: "PATCH", url: "/api/v1/settings", headers, payload: { healthCheckCron: "not-a-cron" }, }); expect(res.statusCode).toBe(400); expect(res.json()).toMatchObject({ error: { code: "VALIDATION_ERROR" }, }); await app.close(); }); it("PATCH rejects down < degraded", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const res = await app.inject({ method: "PATCH", url: "/api/v1/settings", headers, payload: { healthDegradedFailures: 5, healthDownFailures: 2, }, }); expect(res.statusCode).toBe(400); await app.close(); }); it("PATCH worker URL; token is not returned in GET", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const res = await app.inject({ method: "PATCH", url: "/api/v1/settings", headers, payload: { healthWorkerUrl: "https://cfdm-health-probe.example.workers.dev", healthWorkerToken: "super-secret", }, }); expect(res.statusCode).toBe(200); const body = res.json() as { healthWorkerUrl: string; healthWorkerTokenSet: boolean; healthWorkerToken?: string; }; expect(body.healthWorkerUrl).toBe( "https://cfdm-health-probe.example.workers.dev", ); expect(body.healthWorkerTokenSet).toBe(true); expect(body.healthWorkerToken).toBeUndefined(); await app.close(); }); it("GET exposes Globalping flags without the token; PATCH persists locations/limit", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const initial = await app.inject({ method: "GET", url: "/api/v1/settings", headers, }); expect(initial.statusCode).toBe(200); const before = initial.json() as { globalpingTokenSet?: boolean; globalpingLocations?: string; globalpingLimit?: number; globalpingToken?: string; }; expect(before.globalpingTokenSet).toBe(false); expect(before.globalpingLocations).toBe("World"); expect(before.globalpingLimit).toBe(3); expect(before.globalpingToken).toBeUndefined(); const patched = await app.inject({ method: "PATCH", url: "/api/v1/settings", headers, payload: { globalpingToken: "gp_secret", globalpingLocations: "EU,US", globalpingLimit: 5, }, }); expect(patched.statusCode).toBe(200); const body = patched.json() as { globalpingTokenSet: boolean; globalpingLocations: string; globalpingLimit: number; globalpingToken?: string; }; expect(body.globalpingTokenSet).toBe(true); expect(body.globalpingLocations).toBe("EU,US"); expect(body.globalpingLimit).toBe(5); expect(body.globalpingToken).toBeUndefined(); await app.close(); }); });