integratedhub/tests/integration/kv-user-pins-write-through.test.ts
2026-02-14 06:10:15 +00:00

157 lines
4.1 KiB
TypeScript

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<void> {
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<void> {
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);
}
});