generated from nhcarrigan/template
d48b53eecd
- Add full test suite for frontend.ts (POST /log and POST /error) - Add error-path tests to all route handlers to cover catch blocks triggered by Prisma rejections - Add non-Error throw tests to cover the `new Error(String(error))` ternary false branch in middleware, services, and route catch handlers - Suppress unreachable outer catch in about.ts with v8 ignore (fetchReleases swallows all errors internally, making the outer catch genuinely dead code)
70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
/* eslint-disable max-lines-per-function -- Test suites naturally have many cases */
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { Hono } from "hono";
|
|
|
|
vi.mock("../../src/services/jwt.js", () => ({
|
|
verifyToken: vi.fn(),
|
|
}));
|
|
|
|
describe("authMiddleware", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
});
|
|
|
|
const makeApp = async () => {
|
|
const { authMiddleware } = await import("../../src/middleware/auth.js");
|
|
const { verifyToken } = await import("../../src/services/jwt.js");
|
|
const app = new Hono<{ Variables: { discordId: string } }>();
|
|
app.use("*", authMiddleware);
|
|
app.get("/test", (c) => c.json({ discordId: c.get("discordId") }));
|
|
return { app, verifyToken };
|
|
};
|
|
|
|
it("returns 401 when Authorization header is missing", async () => {
|
|
const { app } = await makeApp();
|
|
const res = await app.fetch(new Request("http://localhost/test"));
|
|
expect(res.status).toBe(401);
|
|
});
|
|
|
|
it("returns 401 when Authorization header does not start with Bearer", async () => {
|
|
const { app } = await makeApp();
|
|
const res = await app.fetch(new Request("http://localhost/test", {
|
|
headers: { Authorization: "Basic abc123" },
|
|
}));
|
|
expect(res.status).toBe(401);
|
|
});
|
|
|
|
it("sets discordId in context when token is valid", async () => {
|
|
const { app, verifyToken } = await makeApp();
|
|
vi.mocked(verifyToken).mockReturnValueOnce({ discordId: "user_123", iat: 0, exp: 9999999999 });
|
|
const res = await app.fetch(new Request("http://localhost/test", {
|
|
headers: { Authorization: "Bearer valid_token" },
|
|
}));
|
|
expect(res.status).toBe(200);
|
|
const body = await res.json() as { discordId: string };
|
|
expect(body.discordId).toBe("user_123");
|
|
});
|
|
|
|
it("returns 401 when verifyToken throws", async () => {
|
|
const { app, verifyToken } = await makeApp();
|
|
vi.mocked(verifyToken).mockImplementationOnce(() => {
|
|
throw new Error("Invalid token");
|
|
});
|
|
const res = await app.fetch(new Request("http://localhost/test", {
|
|
headers: { Authorization: "Bearer bad_token" },
|
|
}));
|
|
expect(res.status).toBe(401);
|
|
});
|
|
|
|
it("returns 401 when verifyToken throws a non-Error value", async () => {
|
|
const { app, verifyToken } = await makeApp();
|
|
vi.mocked(verifyToken).mockImplementationOnce(() => {
|
|
throw "raw string error";
|
|
});
|
|
const res = await app.fetch(new Request("http://localhost/test", {
|
|
headers: { Authorization: "Bearer bad_token" },
|
|
}));
|
|
expect(res.status).toBe(401);
|
|
});
|
|
});
|