MiniSearch / server /validateAccessKeyServerHook.test.ts
github-actions[bot]
Sync from https://github.com/felladrin/MiniSearch
6ace587
Raw
History Blame Contribute Delete
5.68 kB
import { beforeEach, describe, expect, it, vi } from "vitest";
const mockArgon2Verify = vi.fn();
vi.mock("hash-wasm", () => ({
argon2Verify: (...args: unknown[]) => mockArgon2Verify(...args),
}));
beforeEach(() => {
vi.clearAllMocks();
});
function makeMockRequest(
url: string,
method: string,
body?: string,
): {
url: string | undefined;
method: string;
headers: Record<string, string>;
on: ReturnType<typeof vi.fn>;
endCallbacks: Array<() => void>;
} {
const endCallbacks: Array<() => void> = [];
const on = vi.fn((event: string, cb: (chunk: string) => void) => {
if (event === "data" && body) {
cb(body);
}
if (event === "end") {
endCallbacks.push(cb as () => void);
}
});
return { url, method, headers: {}, on, endCallbacks };
}
function makeMockResponse() {
const setHeader = vi.fn();
const end = vi.fn();
const statusCode = 200;
return { setHeader, end, statusCode };
}
describe("validateAccessKeyServerHook", () => {
it("should skip non-matching URLs", async () => {
const { validateAccessKeyServerHook } = await import(
"./validateAccessKeyServerHook"
);
const use = vi.fn();
validateAccessKeyServerHook({
middlewares: { use },
} as never);
const handler = use.mock.calls[0][0] as (
req: { url: string; method: string },
res: unknown,
next: () => void,
) => void;
const next = vi.fn();
handler({ url: "/other", method: "POST" }, {}, next);
expect(next).toHaveBeenCalled();
});
it("should skip non-POST methods", async () => {
const { validateAccessKeyServerHook } = await import(
"./validateAccessKeyServerHook"
);
const use = vi.fn();
validateAccessKeyServerHook({
middlewares: { use },
} as never);
const handler = use.mock.calls[0][0] as (
req: { url: string; method: string },
res: unknown,
next: () => void,
) => void;
const next = vi.fn();
handler({ url: "/api/validate-access-key", method: "GET" }, {}, next);
expect(next).toHaveBeenCalled();
});
it("should return valid: true for a matching access key", async () => {
process.env.ACCESS_KEYS = "test-key";
mockArgon2Verify.mockResolvedValue(true);
const { validateAccessKeyServerHook } = await import(
"./validateAccessKeyServerHook"
);
const use = vi.fn();
validateAccessKeyServerHook({
middlewares: { use },
} as never);
const handler = use.mock.calls[0][0] as (
req: {
url: string;
method: string;
on: (event: string, cb: (chunk: string) => void) => void;
},
res: {
setHeader: ReturnType<typeof vi.fn>;
end: ReturnType<typeof vi.fn>;
},
next: () => void,
) => void;
const res = makeMockResponse();
const req = makeMockRequest(
"/api/validate-access-key",
"POST",
JSON.stringify({ accessKeyHash: "some-hash" }),
);
await new Promise<void>((resolve) => {
handler(req as never, res as never, () => {});
// Trigger the end callback that the handler registered
for (const cb of req.endCallbacks) {
cb();
}
// argon2Verify is async, so we need to wait for it.
setTimeout(resolve, 50);
});
expect(res.end).toHaveBeenCalledWith(JSON.stringify({ valid: true }));
});
it("should return valid: false when no access keys match", async () => {
process.env.ACCESS_KEYS = "test-key";
mockArgon2Verify.mockResolvedValue(false);
const { validateAccessKeyServerHook } = await import(
"./validateAccessKeyServerHook"
);
const use = vi.fn();
validateAccessKeyServerHook({
middlewares: { use },
} as never);
const handler = use.mock.calls[0][0] as (
req: {
url: string;
method: string;
on: (event: string, cb: (chunk: string) => void) => void;
},
res: {
setHeader: ReturnType<typeof vi.fn>;
end: ReturnType<typeof vi.fn>;
},
next: () => void,
) => void;
const res = makeMockResponse();
const req = makeMockRequest(
"/api/validate-access-key",
"POST",
JSON.stringify({ accessKeyHash: "wrong-hash" }),
);
await new Promise<void>((resolve) => {
handler(req as never, res as never, () => {});
for (const cb of req.endCallbacks) {
cb();
}
setTimeout(resolve, 50);
});
expect(res.end).toHaveBeenCalledWith(JSON.stringify({ valid: false }));
});
it("should return 400 for invalid JSON body", async () => {
process.env.ACCESS_KEYS = "test-key";
const { validateAccessKeyServerHook } = await import(
"./validateAccessKeyServerHook"
);
const use = vi.fn();
validateAccessKeyServerHook({
middlewares: { use },
} as never);
const handler = use.mock.calls[0][0] as (
req: {
url: string;
method: string;
on: (event: string, cb: (chunk: string) => void) => void;
},
res: {
setHeader: ReturnType<typeof vi.fn>;
end: ReturnType<typeof vi.fn>;
statusCode: { value: number };
},
next: () => void,
) => void;
const res = makeMockResponse();
const req = makeMockRequest("/api/validate-access-key", "POST", "not-json");
await new Promise<void>((resolve) => {
handler(req as never, res as never, () => {});
for (const cb of req.endCallbacks) {
cb();
}
setTimeout(resolve, 50);
});
expect(res.statusCode).toBe(400);
expect(res.end).toHaveBeenCalledWith(
JSON.stringify({ valid: false, error: "Invalid request" }),
);
});
});