docfast/src/__tests__/keys-coverage.test.ts
OpenClaw Subagent 99b67f2584
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 19m37s
test: improve keys.ts coverage — cache-hit paths for createFreeKey, updateKeyEmail, updateEmailByCustomer
2026-03-13 17:10:13 +01:00

155 lines
No EOL
4.8 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
// Override the global setup.ts mock for keys — we need the REAL implementation
vi.unmock("../services/keys.js");
// Keep db mocked (setup.ts already does this, but be explicit about our mock)
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 {
createFreeKey,
updateKeyEmail,
updateEmailByCustomer,
loadKeys,
getAllKeys
} from "../services/keys.js";
const mockQuery = vi.mocked(queryWithRetry);
describe("keys.ts cache-hit coverage", () => {
beforeEach(() => {
vi.clearAllMocks();
// Reset cache by loading empty state
mockQuery.mockResolvedValue({ rows: [], rowCount: 0 } as any);
});
it("createFreeKey returns existing key when email has a free key in cache", async () => {
// Pre-populate cache with a free key
mockQuery.mockResolvedValueOnce({
rows: [
{
key: "df_free_existing123",
tier: "free",
email: "existing@example.com",
created_at: "2026-01-01T00:00:00.000Z",
stripe_customer_id: null,
},
],
rowCount: 1,
} as any);
// Load the cache with our test data
await loadKeys();
// Clear mock calls from loadKeys
mockQuery.mockClear();
// Now call createFreeKey with the same email - should hit cache and return existing
const result = await createFreeKey("existing@example.com");
expect(result.key).toBe("df_free_existing123");
expect(result.tier).toBe("free");
expect(result.email).toBe("existing@example.com");
// Should NOT have called the database INSERT (cache hit path)
const insertCalls = mockQuery.mock.calls.filter((call) =>
(call[0] as string).includes("INSERT")
);
expect(insertCalls).toHaveLength(0);
});
it("updateKeyEmail updates cache and DB when key is found in cache", async () => {
// Pre-populate cache with a key
mockQuery.mockResolvedValueOnce({
rows: [
{
key: "df_pro_test123",
tier: "pro",
email: "old@example.com",
created_at: "2026-01-01T00:00:00.000Z",
stripe_customer_id: "cus_test123",
},
],
rowCount: 1,
} as any);
// Load the cache
await loadKeys();
// Clear mock calls
mockQuery.mockClear();
// Mock the UPDATE query
mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 1 } as any);
// Call updateKeyEmail - should hit cache
const result = await updateKeyEmail("df_pro_test123", "new@example.com");
expect(result).toBe(true);
// Should have called the UPDATE query
expect(mockQuery).toHaveBeenCalledWith(
"UPDATE api_keys SET email = $1 WHERE key = $2",
["new@example.com", "df_pro_test123"]
);
// Verify cache was updated
const keys = getAllKeys();
const updatedKey = keys.find(k => k.key === "df_pro_test123");
expect(updatedKey?.email).toBe("new@example.com");
});
it("updateEmailByCustomer updates cache and DB when stripeCustomerId is found in cache", async () => {
// Pre-populate cache with a key that has stripeCustomerId
mockQuery.mockResolvedValueOnce({
rows: [
{
key: "df_pro_customer123",
tier: "pro",
email: "customer@example.com",
created_at: "2026-01-01T00:00:00.000Z",
stripe_customer_id: "cus_customer123",
},
],
rowCount: 1,
} as any);
// Load the cache
await loadKeys();
// Clear mock calls
mockQuery.mockClear();
// Mock the UPDATE query
mockQuery.mockResolvedValueOnce({ rows: [], rowCount: 1 } as any);
// Call updateEmailByCustomer - should hit cache
const result = await updateEmailByCustomer("cus_customer123", "newemail@example.com");
expect(result).toBe(true);
// Should have called the UPDATE query
expect(mockQuery).toHaveBeenCalledWith(
"UPDATE api_keys SET email = $1 WHERE stripe_customer_id = $2",
["newemail@example.com", "cus_customer123"]
);
// Verify cache was updated
const keys = getAllKeys();
const updatedKey = keys.find(k => k.stripeCustomerId === "cus_customer123");
expect(updatedKey?.email).toBe("newemail@example.com");
});
});