jest.mock("jsonwebtoken", () => ({ verify: jest.fn(), })); jest.mock("../models/session.model", () => ({ getActiveSessionWithUser: jest.fn(), })); jest.mock("../utils/logger", () => ({ logError: jest.fn(), })); const jwt = require("jsonwebtoken"); const Session = require("../models/session.model"); const auth = require("../middleware/auth"); function createResponse() { const res = {}; res.status = jest.fn().mockReturnValue(res); res.json = jest.fn().mockReturnValue(res); return res; } describe("auth middleware", () => { const originalJwtSecret = process.env.JWT_SECRET; beforeEach(() => { process.env.JWT_SECRET = "test-secret"; jest.clearAllMocks(); }); afterAll(() => { if (originalJwtSecret === undefined) { delete process.env.JWT_SECRET; } else { process.env.JWT_SECRET = originalJwtSecret; } }); test("uses a valid bearer token without reading the session cookie", async () => { jwt.verify.mockReturnValue({ id: 5, role: "admin" }); const req = { headers: { authorization: "Bearer valid-token", cookie: "sid=session-id", }, }; const res = createResponse(); const next = jest.fn(); await auth(req, res, next); expect(jwt.verify).toHaveBeenCalledWith("valid-token", "test-secret"); expect(Session.getActiveSessionWithUser).not.toHaveBeenCalled(); expect(req.user).toEqual({ id: 5, role: "admin" }); expect(next).toHaveBeenCalled(); }); test("falls back to a valid session cookie when the bearer token is stale", async () => { jwt.verify.mockImplementation(() => { throw new Error("stale token"); }); Session.getActiveSessionWithUser.mockResolvedValue({ id: "session-id", user_id: 7, role: "user", username: "shopper", }); const req = { headers: { authorization: "Bearer stale-token", cookie: "sid=session-id", }, }; const res = createResponse(); const next = jest.fn(); await auth(req, res, next); expect(Session.getActiveSessionWithUser).toHaveBeenCalledWith("session-id"); expect(req.user).toEqual({ id: 7, role: "user", username: "shopper", }); expect(req.session_id).toBe("session-id"); expect(next).toHaveBeenCalled(); expect(res.status).not.toHaveBeenCalled(); }); test("rejects a stale bearer token when no session cookie is present", async () => { jwt.verify.mockImplementation(() => { throw new Error("stale token"); }); const req = { headers: { authorization: "Bearer stale-token", }, }; const res = createResponse(); const next = jest.fn(); await auth(req, res, next); expect(Session.getActiveSessionWithUser).not.toHaveBeenCalled(); expect(next).not.toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(401); expect(res.json).toHaveBeenCalledWith({ error: { code: "unauthorized", message: "Invalid or expired token", }, }); }); });