Spaces:
Running
Running
| import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| let mockArgon2VerifyResult = true; | |
| let mockIsVerifiedToken = false; | |
| let mockRateLimiterShouldFail = false; | |
| const mockAddVerifiedToken = vi.fn(); | |
| const mockConsume = vi.fn(); | |
| vi.mock("hash-wasm", () => ({ | |
| argon2Verify: vi.fn(() => Promise.resolve(mockArgon2VerifyResult)), | |
| })); | |
| vi.mock("rate-limiter-flexible", () => ({ | |
| RateLimiterMemory: class { | |
| consume = vi.fn((token: string) => { | |
| mockConsume(token); | |
| if (mockRateLimiterShouldFail) { | |
| return Promise.reject(new Error("Rate limit exceeded")); | |
| } | |
| return Promise.resolve(undefined); | |
| }); | |
| }, | |
| })); | |
| vi.mock("./searchToken", () => ({ | |
| getSearchToken: vi.fn().mockReturnValue("dummy-token"), | |
| })); | |
| vi.mock("./verifiedTokens", () => ({ | |
| addVerifiedToken: vi.fn((token: string) => mockAddVerifiedToken(token)), | |
| isVerifiedToken: vi.fn(() => mockIsVerifiedToken), | |
| })); | |
| describe("verifyTokenAndRateLimit", () => { | |
| beforeEach(() => { | |
| vi.clearAllMocks(); | |
| mockArgon2VerifyResult = true; | |
| mockIsVerifiedToken = false; | |
| mockRateLimiterShouldFail = false; | |
| }); | |
| it("should reject missing token", async () => { | |
| const { verifyTokenAndRateLimit } = await import( | |
| "./verifyTokenAndRateLimit" | |
| ); | |
| const result = await verifyTokenAndRateLimit(null); | |
| expect(result.isAuthorized).toBe(false); | |
| expect(result.statusCode).toBe(400); | |
| expect(result.error).toBe("Missing token."); | |
| }); | |
| it("should reject invalid token", async () => { | |
| mockArgon2VerifyResult = false; | |
| vi.resetModules(); | |
| const { verifyTokenAndRateLimit } = await import( | |
| "./verifyTokenAndRateLimit" | |
| ); | |
| const result = await verifyTokenAndRateLimit("invalid-token"); | |
| expect(result.isAuthorized).toBe(false); | |
| expect(result.statusCode).toBe(401); | |
| expect(result.error).toBe("Invalid token."); | |
| }); | |
| it("should accept valid token and add to verified tokens", async () => { | |
| mockArgon2VerifyResult = true; | |
| vi.resetModules(); | |
| const { verifyTokenAndRateLimit } = await import( | |
| "./verifyTokenAndRateLimit" | |
| ); | |
| const result = await verifyTokenAndRateLimit("valid-token"); | |
| expect(result.isAuthorized).toBe(true); | |
| expect(result).not.toHaveProperty("statusCode"); | |
| expect(mockAddVerifiedToken).toHaveBeenCalledWith("valid-token"); | |
| }); | |
| it("should skip verification for already verified tokens", async () => { | |
| mockIsVerifiedToken = true; | |
| vi.resetModules(); | |
| const { verifyTokenAndRateLimit } = await import( | |
| "./verifyTokenAndRateLimit" | |
| ); | |
| const hashWasm = await import("hash-wasm"); | |
| const result = await verifyTokenAndRateLimit("already-verified-token"); | |
| expect(result.isAuthorized).toBe(true); | |
| expect(hashWasm.argon2Verify).not.toHaveBeenCalled(); | |
| }); | |
| it("should enforce rate limiting", async () => { | |
| mockRateLimiterShouldFail = true; | |
| vi.resetModules(); | |
| const { verifyTokenAndRateLimit } = await import( | |
| "./verifyTokenAndRateLimit" | |
| ); | |
| const result = await verifyTokenAndRateLimit("rate-limit-token"); | |
| expect(result.isAuthorized).toBe(false); | |
| expect(result.statusCode).toBe(429); | |
| expect(result.error).toBe("Too many requests."); | |
| }); | |
| }); | |