All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 12m13s
85 lines
3.2 KiB
TypeScript
85 lines
3.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { authMiddleware } from "../middleware/auth.js";
|
|
import { isValidKey, getKeyInfo } from "../services/keys.js";
|
|
|
|
const mockJson = vi.fn();
|
|
const mockStatus = vi.fn(() => ({ json: mockJson }));
|
|
const mockNext = vi.fn();
|
|
|
|
function makeReq(headers: Record<string, string> = {}): any {
|
|
return { headers };
|
|
}
|
|
|
|
function makeRes(): any {
|
|
mockJson.mockClear();
|
|
mockStatus.mockClear();
|
|
return { status: mockStatus, json: mockJson };
|
|
}
|
|
|
|
describe("authMiddleware", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("returns 401 when no auth header and no x-api-key", () => {
|
|
const req = makeReq();
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(mockStatus).toHaveBeenCalledWith(401);
|
|
expect(mockJson).toHaveBeenCalledWith(
|
|
expect.objectContaining({ error: expect.stringContaining("Missing API key") })
|
|
);
|
|
expect(mockNext).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("returns 403 when Bearer token is invalid", () => {
|
|
vi.mocked(isValidKey).mockReturnValueOnce(false);
|
|
const req = makeReq({ authorization: "Bearer bad-key" });
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(mockStatus).toHaveBeenCalledWith(403);
|
|
expect(mockJson).toHaveBeenCalledWith({ error: "Invalid API key" });
|
|
expect(mockNext).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("returns 403 when x-api-key is invalid", () => {
|
|
vi.mocked(isValidKey).mockReturnValueOnce(false);
|
|
const req = makeReq({ "x-api-key": "bad-key" });
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(mockStatus).toHaveBeenCalledWith(403);
|
|
expect(mockNext).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("calls next() and attaches apiKeyInfo when Bearer token is valid", () => {
|
|
const info = { key: "test-key", tier: "pro", email: "t@t.com", createdAt: "2025-01-01" };
|
|
vi.mocked(isValidKey).mockReturnValueOnce(true);
|
|
vi.mocked(getKeyInfo).mockReturnValueOnce(info as any);
|
|
const req = makeReq({ authorization: "Bearer test-key" });
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(mockNext).toHaveBeenCalled();
|
|
expect((req as any).apiKeyInfo).toEqual(info);
|
|
});
|
|
|
|
it("calls next() and attaches apiKeyInfo when x-api-key is valid", () => {
|
|
const info = { key: "xkey", tier: "free", email: "x@t.com", createdAt: "2025-01-01" };
|
|
vi.mocked(isValidKey).mockReturnValueOnce(true);
|
|
vi.mocked(getKeyInfo).mockReturnValueOnce(info as any);
|
|
const req = makeReq({ "x-api-key": "xkey" });
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(mockNext).toHaveBeenCalled();
|
|
expect((req as any).apiKeyInfo).toEqual(info);
|
|
});
|
|
|
|
it("prefers Authorization header over x-api-key when both present", () => {
|
|
vi.mocked(isValidKey).mockReturnValueOnce(true);
|
|
vi.mocked(getKeyInfo).mockReturnValueOnce({ key: "bearer-key" } as any);
|
|
const req = makeReq({ authorization: "Bearer bearer-key", "x-api-key": "header-key" });
|
|
const res = makeRes();
|
|
authMiddleware(req, res, mockNext);
|
|
expect(isValidKey).toHaveBeenCalledWith("bearer-key");
|
|
expect((req as any).apiKeyInfo).toEqual({ key: "bearer-key" });
|
|
});
|
|
});
|