import { load } from "$std/dotenv/mod.ts"; import { assert, assertEquals } from "$std/assert/mod.ts"; import { eq } from "drizzle-orm"; import { checkDatabaseConnection, db } from "../../db/db.ts"; import { user_pins, users } from "../../db/schema.ts"; import { kvStore } from "../../modules/KvCacheStore.ts"; import type { User } from "../../services/userService.ts"; await load({ export: true, allowEmptyValues: true }); const REQUIRED_ENV_KEYS = [ "POSTGRES_OPTIONS", ] as const; async function cleanup(userId: string): Promise { await db.delete(user_pins).where(eq(user_pins.user_id, userId)); await db.delete(users).where(eq(users.id, userId)); await kvStore.delete(["user_pins", userId]); await kvStore.delete(["users", userId]); } async function assertDbAvailable(): Promise { const isConnected = await checkDatabaseConnection(); assert( isConnected, "Database is unreachable (POSTGRES_OPTIONS). Start PostgreSQL before running this integration test.", ); } Deno.test("kvStore user_pins write-through creates SQL row even when user only exists in KV", async () => { for (const key of REQUIRED_ENV_KEYS) { assert( Deno.env.get(key), `${key} must be set for KV user_pins write-through integration test`, ); } await assertDbAvailable(); const userId = `kv-user-pin-${crypto.randomUUID()}`; const now = Date.now(); const cachedUser: User = { id: userId, name: "KV Only User", email: "kv-only-user@example.com", phone: "", address_1: "", address_2: "", city: "", state: "", zip: "", country: "", user_type: "tenant", onboarded_landlord: false, onboarded_tenant: false, email_verified: null, banking_setup_complete: null, onboarding_step: null, encrypted_data: null, started_on: now, updated_on: now, }; try { await cleanup(userId); // Seed KV only, intentionally no SQL user row. await kvStore.set(["users", userId], cachedUser); await db.delete(users).where(eq(users.id, userId)); const prePinRows = await db.select().from(user_pins).where( eq(user_pins.user_id, userId), ); assertEquals(prePinRows.length, 0); await kvStore.set(["user_pins", userId], { user_id: userId, pin: "1234", created_on: now, modified_on: now, }); const pinRows = await db.select().from(user_pins).where( eq(user_pins.user_id, userId), ); assertEquals(pinRows.length, 1); assertEquals(pinRows[0].pin, "1234"); const userRows = await db.select().from(users).where(eq(users.id, userId)); assertEquals(userRows.length, 1); } finally { await cleanup(userId); } }); Deno.test("kvStore user_pins write-through updates existing SQL row", async () => { for (const key of REQUIRED_ENV_KEYS) { assert( Deno.env.get(key), `${key} must be set for KV user_pins write-through integration test`, ); } await assertDbAvailable(); const userId = `kv-user-pin-update-${crypto.randomUUID()}`; const now = Date.now(); try { await cleanup(userId); await kvStore.set( ["users", userId], { id: userId, name: "Update User", email: "update-user@example.com", phone: "", address_1: "", address_2: "", city: "", state: "", zip: "", country: "", user_type: "tenant", onboarded_landlord: false, onboarded_tenant: false, email_verified: null, banking_setup_complete: null, onboarding_step: null, encrypted_data: null, started_on: now, updated_on: now, } satisfies User, ); await kvStore.set(["user_pins", userId], { user_id: userId, pin: "1111", created_on: now, modified_on: now, }); await kvStore.set(["user_pins", userId], { user_id: userId, pin: "2222", created_on: now, modified_on: now + 1, }); const pinRows = await db.select().from(user_pins).where( eq(user_pins.user_id, userId), ); assertEquals(pinRows.length, 1); assertEquals(pinRows[0].pin, "2222"); } finally { await cleanup(userId); } });