All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 20m17s
- New shared helper findKeyInCacheOrDb(column, value) for DB lookups - Refactored downgradeByCustomer, updateKeyEmail, updateEmailByCustomer, and findKeyByCustomerId to use the shared helper - Eliminated ~60 lines of duplicated SELECT/row-mapping code - 3 TDD tests added (keys-db-fallback-helper.test.ts) - 636 tests passing, 0 tsc errors
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
vi.unmock("../services/keys.js");
|
|
|
|
// The DB mock is set up in setup.ts — we need to control queryWithRetry
|
|
const mockQueryWithRetry = vi.fn();
|
|
vi.mock("../services/db.js", () => ({
|
|
default: { query: vi.fn(), end: vi.fn() },
|
|
pool: { query: vi.fn(), end: vi.fn() },
|
|
queryWithRetry: (...args: unknown[]) => mockQueryWithRetry(...args),
|
|
connectWithRetry: vi.fn(),
|
|
initDatabase: vi.fn(),
|
|
cleanupStaleData: vi.fn(),
|
|
}));
|
|
|
|
import { findKeyInCacheOrDb } from "../services/keys.js";
|
|
|
|
describe("findKeyInCacheOrDb", () => {
|
|
beforeEach(() => {
|
|
mockQueryWithRetry.mockReset();
|
|
});
|
|
|
|
it("returns null when DB finds no row", async () => {
|
|
mockQueryWithRetry.mockResolvedValue({ rows: [] });
|
|
const result = await findKeyInCacheOrDb("stripe_customer_id", "cus_nonexistent");
|
|
expect(result).toBeNull();
|
|
expect(mockQueryWithRetry).toHaveBeenCalledWith(
|
|
expect.stringContaining("WHERE stripe_customer_id = $1"),
|
|
["cus_nonexistent"]
|
|
);
|
|
});
|
|
|
|
it("returns ApiKey when DB finds a row", async () => {
|
|
mockQueryWithRetry.mockResolvedValue({
|
|
rows: [{
|
|
key: "df_pro_abc",
|
|
tier: "pro",
|
|
email: "test@example.com",
|
|
created_at: "2026-01-01T00:00:00.000Z",
|
|
stripe_customer_id: "cus_123",
|
|
}],
|
|
});
|
|
const result = await findKeyInCacheOrDb("stripe_customer_id", "cus_123");
|
|
expect(result).toEqual({
|
|
key: "df_pro_abc",
|
|
tier: "pro",
|
|
email: "test@example.com",
|
|
createdAt: "2026-01-01T00:00:00.000Z",
|
|
stripeCustomerId: "cus_123",
|
|
});
|
|
});
|
|
|
|
it("handles Date objects in created_at", async () => {
|
|
mockQueryWithRetry.mockResolvedValue({
|
|
rows: [{
|
|
key: "df_pro_abc",
|
|
tier: "pro",
|
|
email: "test@example.com",
|
|
created_at: new Date("2026-01-01T00:00:00.000Z"),
|
|
stripe_customer_id: null,
|
|
}],
|
|
});
|
|
const result = await findKeyInCacheOrDb("key", "df_pro_abc");
|
|
expect(result).not.toBeNull();
|
|
expect(result!.createdAt).toBe("2026-01-01T00:00:00.000Z");
|
|
expect(result!.stripeCustomerId).toBeUndefined();
|
|
});
|
|
});
|