test: add auth, rate-limit, and keys service tests
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 12m13s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 12m13s
This commit is contained in:
parent
1a37765f41
commit
1aea9c872c
3 changed files with 346 additions and 0 deletions
108
src/__tests__/keys.test.ts
Normal file
108
src/__tests__/keys.test.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
// Unmock keys service — we want to test the real implementation
|
||||
vi.unmock("../services/keys.js");
|
||||
|
||||
// DB is still mocked by setup.ts
|
||||
import { queryWithRetry } from "../services/db.js";
|
||||
|
||||
describe("keys service", () => {
|
||||
let keys: typeof import("../services/keys.js");
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
// Re-import to get fresh cache
|
||||
keys = await import("../services/keys.js");
|
||||
});
|
||||
|
||||
describe("after loadKeys", () => {
|
||||
const mockRows = [
|
||||
{ key: "df_free_abc", tier: "free", email: "a@b.com", created_at: "2025-01-01T00:00:00Z", stripe_customer_id: null },
|
||||
{ key: "df_pro_xyz", tier: "pro", email: "pro@b.com", created_at: "2025-01-01T00:00:00Z", stripe_customer_id: "cus_123" },
|
||||
];
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: mockRows, rowCount: 2 } as any);
|
||||
await keys.loadKeys();
|
||||
});
|
||||
|
||||
it("isValidKey returns true for cached keys", () => {
|
||||
expect(keys.isValidKey("df_free_abc")).toBe(true);
|
||||
expect(keys.isValidKey("df_pro_xyz")).toBe(true);
|
||||
});
|
||||
|
||||
it("isValidKey returns false for unknown keys", () => {
|
||||
expect(keys.isValidKey("unknown")).toBe(false);
|
||||
});
|
||||
|
||||
it("isProKey returns true for pro tier, false for free", () => {
|
||||
expect(keys.isProKey("df_pro_xyz")).toBe(true);
|
||||
expect(keys.isProKey("df_free_abc")).toBe(false);
|
||||
});
|
||||
|
||||
it("getKeyInfo returns correct ApiKey object", () => {
|
||||
const info = keys.getKeyInfo("df_pro_xyz");
|
||||
expect(info).toEqual({
|
||||
key: "df_pro_xyz",
|
||||
tier: "pro",
|
||||
email: "pro@b.com",
|
||||
createdAt: "2025-01-01T00:00:00Z",
|
||||
stripeCustomerId: "cus_123",
|
||||
});
|
||||
});
|
||||
|
||||
it("getKeyInfo returns undefined for unknown key", () => {
|
||||
expect(keys.getKeyInfo("nope")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("createFreeKey", () => {
|
||||
beforeEach(async () => {
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: [], rowCount: 0 } as any);
|
||||
await keys.loadKeys();
|
||||
});
|
||||
|
||||
it("creates key with df_free prefix", async () => {
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: [], rowCount: 1 } as any);
|
||||
const result = await keys.createFreeKey("new@test.com");
|
||||
expect(result.key).toMatch(/^df_free_/);
|
||||
expect(result.tier).toBe("free");
|
||||
expect(result.email).toBe("new@test.com");
|
||||
});
|
||||
|
||||
it("returns existing key for same email", async () => {
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: [], rowCount: 1 } as any);
|
||||
const first = await keys.createFreeKey("dup@test.com");
|
||||
const second = await keys.createFreeKey("dup@test.com");
|
||||
expect(second.key).toBe(first.key);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createProKey", () => {
|
||||
beforeEach(async () => {
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: [], rowCount: 0 } as any);
|
||||
await keys.loadKeys();
|
||||
});
|
||||
|
||||
it("uses UPSERT and returns key", async () => {
|
||||
const returnedRow = {
|
||||
key: "df_pro_newkey",
|
||||
tier: "pro",
|
||||
email: "pro@test.com",
|
||||
created_at: "2025-06-01T00:00:00Z",
|
||||
stripe_customer_id: "cus_new",
|
||||
};
|
||||
vi.mocked(queryWithRetry).mockResolvedValueOnce({ rows: [returnedRow], rowCount: 1 } as any);
|
||||
|
||||
const result = await keys.createProKey("pro@test.com", "cus_new");
|
||||
expect(result.tier).toBe("pro");
|
||||
expect(result.stripeCustomerId).toBe("cus_new");
|
||||
|
||||
const call = vi.mocked(queryWithRetry).mock.calls.find(
|
||||
(c) => typeof c[0] === "string" && c[0].includes("ON CONFLICT")
|
||||
);
|
||||
expect(call).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue