import { describe, it, expect, vi, beforeEach } from "vitest"; // Unmock keys service — test the real implementation vi.unmock("../services/keys.js"); vi.mock("../services/db.js", () => ({ default: { query: vi.fn(), connect: vi.fn(), on: vi.fn(), end: vi.fn() }, pool: { query: vi.fn(), connect: vi.fn(), on: vi.fn(), end: vi.fn() }, queryWithRetry: vi.fn().mockResolvedValue({ rows: [], rowCount: 0 }), connectWithRetry: vi.fn().mockResolvedValue(undefined), initDatabase: vi.fn().mockResolvedValue(undefined), cleanupStaleData: vi.fn(), isTransientError: vi.fn(), })); vi.mock("../services/logger.js", () => ({ default: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() }, })); import { queryWithRetry } from "../services/db.js"; import { createProKey, downgradeByCustomer, updateKeyEmail, updateEmailByCustomer } from "../services/keys.js"; const mockQuery = vi.mocked(queryWithRetry); describe("Keys Branch Coverage", () => { beforeEach(() => { vi.clearAllMocks(); }); describe("createProKey - UPSERT conflict path (line 142)", () => { it("should return existing key when stripe_customer_id already exists in DB but NOT in cache", async () => { // Scenario: Another pod created a key for this customer, so it's in DB but not in our cache // The UPSERT will hit ON CONFLICT and return the existing key via RETURNING clause const existingKey = { key: "df_pro_existing_abc", tier: "pro", email: "existing@test.com", created_at: "2026-01-01T00:00:00.000Z", stripe_customer_id: "cus_existing", }; // Mock: UPSERT returns the existing key (ON CONFLICT triggered) mockQuery.mockResolvedValueOnce({ rows: [existingKey], rowCount: 1 } as any); const result = await createProKey("new@test.com", "cus_existing"); // Should return the existing key expect(result.key).toBe("df_pro_existing_abc"); expect(result.email).toBe("existing@test.com"); // Original email, not the new one expect(result.stripeCustomerId).toBe("cus_existing"); expect(result.tier).toBe("pro"); // Verify UPSERT was called const upsertCall = mockQuery.mock.calls.find( (c) => typeof c[0] === "string" && c[0].includes("ON CONFLICT") ); expect(upsertCall).toBeTruthy(); }); it("should handle conflict when inserting new key with existing customer ID", async () => { // First call: load empty cache mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const { loadKeys } = await import("../services/keys.js"); await loadKeys(); vi.clearAllMocks(); const conflictingKey = { key: "df_pro_conflict_xyz", tier: "pro", email: "conflict@test.com", created_at: "2025-12-31T00:00:00.000Z", stripe_customer_id: "cus_conflict", }; // UPSERT returns existing key on conflict mockQuery.mockResolvedValueOnce({ rows: [conflictingKey], rowCount: 1 } as any); const result = await createProKey("different-email@test.com", "cus_conflict"); expect(result.key).toBe("df_pro_conflict_xyz"); expect(result.email).toBe("conflict@test.com"); // Original, not the new email }); }); describe("downgradeByCustomer - customer not found (lines 153-155)", () => { it("should return false when customer is NOT in cache AND NOT in DB", async () => { // Mock: SELECT query returns empty (customer not in DB) mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const result = await downgradeByCustomer("cus_nonexistent"); expect(result).toBe(false); // Verify SELECT was called expect(mockQuery).toHaveBeenCalledWith( expect.stringContaining("SELECT"), expect.arrayContaining(["cus_nonexistent"]) ); // Verify UPDATE was NOT called (no point updating a non-existent key) const updateCalls = mockQuery.mock.calls.filter((c) => (c[0] as string).includes("UPDATE") ); expect(updateCalls).toHaveLength(0); }); it("should return false for completely unknown stripe customer ID", async () => { // Load empty cache first mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const { loadKeys } = await import("../services/keys.js"); await loadKeys(); vi.clearAllMocks(); // Mock: DB also doesn't have this customer mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const result = await downgradeByCustomer("cus_unknown_12345"); expect(result).toBe(false); }); }); describe("updateKeyEmail - DB fallback path (line 175)", () => { it("should return false when key is NOT in cache AND NOT in DB", async () => { // Mock: SELECT query returns empty (key not in DB) mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const result = await updateKeyEmail("df_pro_nonexistent", "new@test.com"); expect(result).toBe(false); // Verify SELECT was called expect(mockQuery).toHaveBeenCalledWith( expect.stringContaining("SELECT"), expect.arrayContaining(["df_pro_nonexistent"]) ); // Verify UPDATE was NOT called const updateCalls = mockQuery.mock.calls.filter((c) => (c[0] as string).includes("UPDATE") ); expect(updateCalls).toHaveLength(0); }); it("should update and cache when key exists in DB but not in cache", async () => { const dbKey = { key: "df_pro_db_only", tier: "pro", email: "old@test.com", created_at: "2026-01-15T00:00:00.000Z", stripe_customer_id: "cus_db_only", }; // Mock: SELECT returns the key from DB mockQuery .mockResolvedValueOnce({ rows: [dbKey], rowCount: 1 } as any) .mockResolvedValueOnce({ rows: [], rowCount: 1 } as any); // UPDATE success const result = await updateKeyEmail("df_pro_db_only", "updated@test.com"); expect(result).toBe(true); // Verify UPDATE was called expect(mockQuery).toHaveBeenCalledWith( expect.stringContaining("UPDATE"), expect.arrayContaining(["updated@test.com", "df_pro_db_only"]) ); }); }); describe("updateEmailByCustomer - DB fallback path (line 175)", () => { it("should return false when customer is NOT in cache AND NOT in DB", async () => { // Mock: SELECT query returns empty mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 0 } as any); const result = await updateEmailByCustomer("cus_nonexistent", "new@test.com"); expect(result).toBe(false); // Verify SELECT was called expect(mockQuery).toHaveBeenCalledWith( expect.stringContaining("SELECT"), expect.arrayContaining(["cus_nonexistent"]) ); // Verify UPDATE was NOT called const updateCalls = mockQuery.mock.calls.filter((c) => (c[0] as string).includes("UPDATE") ); expect(updateCalls).toHaveLength(0); }); it("should update and cache when customer exists in DB but not in cache", async () => { const dbKey = { key: "df_pro_customer_db", tier: "pro", email: "oldcustomer@test.com", created_at: "2026-02-01T00:00:00.000Z", stripe_customer_id: "cus_db_customer", }; // Mock: SELECT returns the key mockQuery .mockResolvedValueOnce({ rows: [dbKey], rowCount: 1 } as any) .mockResolvedValueOnce({ rows: [], rowCount: 1 } as any); // UPDATE success const result = await updateEmailByCustomer("cus_db_customer", "newcustomer@test.com"); expect(result).toBe(true); // Verify UPDATE was called with correct params expect(mockQuery).toHaveBeenCalledWith( expect.stringContaining("UPDATE"), expect.arrayContaining(["newcustomer@test.com", "cus_db_customer"]) ); }); }); });