import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import express from "express"; import request from "supertest"; import type { Db } from "@paperclipai/db"; import { serverVersion } from "../version.js"; import { healthRoutes } from "../routes/health.js"; const mockReadPersistedDevServerStatus = vi.hoisted(() => vi.fn()); vi.mock("../dev-server-status.js", () => ({ readPersistedDevServerStatus: mockReadPersistedDevServerStatus, toDevServerHealthStatus: vi.fn(), })); function createApp(db?: Db) { const app = express(); app.use("/health", healthRoutes(db)); return app; } describe("GET /health", () => { beforeEach(() => { vi.clearAllMocks(); mockReadPersistedDevServerStatus.mockReturnValue(undefined); }); afterEach(() => { vi.restoreAllMocks(); }); it("returns 200 with status ok", async () => { const app = createApp(); const res = await request(app).get("/health"); expect(res.status).toBe(200); expect(res.body).toEqual({ status: "ok", version: serverVersion }); }); it("returns 200 when the database probe succeeds", async () => { const db = { execute: vi.fn().mockResolvedValue([{ "?column?": 1 }]), } as unknown as Db; const app = createApp(db); const res = await request(app).get("/health"); expect(res.status).toBe(200); expect(res.body).toMatchObject({ status: "ok", version: serverVersion }); }); it("returns 503 when the database probe fails", async () => { const db = { execute: vi.fn().mockRejectedValue(new Error("connect ECONNREFUSED")), } as unknown as Db; const app = createApp(db); const res = await request(app).get("/health"); expect(res.status).toBe(503); expect(res.body).toEqual({ status: "unhealthy", version: serverVersion, error: "database_unreachable", }); }); });