154 lines
4.1 KiB
TypeScript
154 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);
|
|
}
|
|
});
|