import { Hono } from "hono"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { cronAuth } from "../../src/middleware/cron-auth"; describe("cronAuth middleware", () => { let app: Hono; const originalEnv = process.env.CRON_SECRET; beforeEach(() => { app = new Hono(); app.use("/cron/*", cronAuth); app.get("/cron/test", (c) => c.json({ success: true })); }); afterEach(() => { // Restore original env if (originalEnv !== undefined) { process.env.CRON_SECRET = originalEnv; } else { delete process.env.CRON_SECRET; } vi.restoreAllMocks(); }); it("allows request with correct secret", async () => { process.env.CRON_SECRET = "test-secret-123"; const res = await app.request("/cron/test", { headers: { Authorization: "Bearer test-secret-123" }, }); expect(res.status).toBe(200); const body = await res.json(); expect(body).toEqual({ success: true }); }); it("rejects request with wrong secret", async () => { process.env.CRON_SECRET = "test-secret-123"; const res = await app.request("/cron/test", { headers: { Authorization: "Bearer wrong-secret" }, }); expect(res.status).toBe(401); const body = await res.json(); expect(body).toHaveProperty("error", "Unauthorized"); }); it("rejects request with missing Authorization header", async () => { process.env.CRON_SECRET = "test-secret-123"; const res = await app.request("/cron/test"); expect(res.status).toBe(401); const body = await res.json(); expect(body).toHaveProperty("error", "Missing Authorization header"); }); it("rejects request with invalid Authorization header format", async () => { process.env.CRON_SECRET = "test-secret-123"; const res = await app.request("/cron/test", { headers: { Authorization: "InvalidFormat" }, }); expect(res.status).toBe(401); const body = await res.json(); expect(body).toHaveProperty("error", "Invalid Authorization header format"); }); it("rejects request with different length secret (timing attack protection)", async () => { process.env.CRON_SECRET = "short"; const res = await app.request("/cron/test", { headers: { Authorization: "Bearer verylongsecret" }, }); expect(res.status).toBe(401); const body = await res.json(); expect(body).toHaveProperty("error", "Unauthorized"); }); it("allows request when CRON_SECRET is not set (dev mode)", async () => { delete process.env.CRON_SECRET; const consoleWarnSpy = vi .spyOn(console, "warn") .mockImplementation(() => {}); const res = await app.request("/cron/test"); expect(res.status).toBe(200); const body = await res.json(); expect(body).toEqual({ success: true }); expect(consoleWarnSpy).toHaveBeenCalledWith( "[cronAuth] CRON_SECRET not set - allowing request (dev mode)", ); }); });