import { BadRequestException, UnauthorizedException } from "@nestjs/common"; import { ApiKeyService } from "../src/public-api/api-key.service"; import { createPrismaMock } from "./utils/mock-prisma"; describe("ApiKeyService", () => { it("creates a hashed public API key and returns the raw key once", async () => { const prisma = createPrismaMock(); prisma.apiKey.create.mockImplementation(async ({ data }) => ({ id: "key_1", ...data, createdAt: new Date("2026-01-01T00:00:00.000Z"), })); const service = new ApiKeyService(prisma as any); const result = await service.createKey("user_1", { name: "Power tools" }); expect(result.key).toMatch(/^l1_[A-Za-z0-9_-]+$/); expect(result.prefix).toBe(result.key.slice(0, 10)); expect(result.scopes).toEqual(["transactions:read"]); expect(prisma.apiKey.create).toHaveBeenCalledWith({ data: expect.objectContaining({ userId: "user_1", name: "Power tools", prefix: result.key.slice(0, 10), keyHash: expect.stringMatching(/^[a-f0-9]{64}$/), scopes: ["transactions:read"], }), }); }); it("rejects unsupported scopes", async () => { const service = new ApiKeyService(createPrismaMock() as any); await expect(service.createKey("user_1", { scopes: ["transactions:write"] })).rejects.toBeInstanceOf(BadRequestException); }); it("authenticates a valid API key and updates last used time", async () => { const prisma = createPrismaMock(); prisma.apiKey.findUnique.mockResolvedValue({ id: "key_1", userId: "user_1", scopes: ["transactions:read"], revokedAt: null, expiresAt: null, }); prisma.apiKey.update.mockResolvedValue({}); const service = new ApiKeyService(prisma as any); await expect(service.authenticate("l1_secret")).resolves.toEqual({ userId: "user_1", keyId: "key_1", scopes: ["transactions:read"], }); expect(prisma.apiKey.findUnique).toHaveBeenCalledWith({ where: { keyHash: expect.stringMatching(/^[a-f0-9]{64}$/) }, }); expect(prisma.apiKey.update).toHaveBeenCalledWith({ where: { id: "key_1" }, data: { lastUsedAt: expect.any(Date) }, }); }); it("rejects revoked API keys", async () => { const prisma = createPrismaMock(); prisma.apiKey.findUnique.mockResolvedValue({ id: "key_1", userId: "user_1", scopes: ["transactions:read"], revokedAt: new Date(), expiresAt: null, }); const service = new ApiKeyService(prisma as any); await expect(service.authenticate("l1_secret")).rejects.toBeInstanceOf(UnauthorizedException); }); });