99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import dotenv from "dotenv";
|
|
import getPool from "../lib/server/db";
|
|
import { createEntry, deleteEntry, listEntries, updateEntry } from "../lib/server/entries";
|
|
import { ensureTagsForGroup } from "../lib/server/tags";
|
|
import { cleanupTestData, uniqueInviteCode } from "./test-helpers";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
const envLoaded = dotenv.config({ path: path.resolve(__dirname, "../../../.env") });
|
|
|
|
const hasDb = Boolean(process.env.DATABASE_URL);
|
|
|
|
test("entries CRUD", async t => {
|
|
if (!hasDb) {
|
|
t.skip("DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
if (envLoaded.error) t.diagnostic(String(envLoaded.error));
|
|
|
|
const pool = getPool();
|
|
const client = await pool.connect();
|
|
let userId: number | null = null;
|
|
let groupId: number | null = null;
|
|
try {
|
|
const userRes = await client.query(
|
|
"insert into users(email, password_hash) values($1,$2) returning id",
|
|
[`entry_${Date.now()}@example.com`, "hash"]
|
|
);
|
|
userId = userRes.rows[0].id as number;
|
|
|
|
const groupRes = await client.query(
|
|
"insert into groups(name, invite_code, created_by) values($1,$2,$3) returning id",
|
|
["Entries Test", uniqueInviteCode("E"), userId]
|
|
);
|
|
groupId = groupRes.rows[0].id as number;
|
|
|
|
await client.query(
|
|
"insert into group_members(group_id, user_id, role) values($1,$2,'GROUP_ADMIN')",
|
|
[groupId, userId]
|
|
);
|
|
|
|
await ensureTagsForGroup({ userId, groupId, tags: ["groceries", "weekly"] });
|
|
|
|
const entry = await createEntry({
|
|
groupId,
|
|
userId,
|
|
entryType: "SPENDING",
|
|
amountDollars: 12.34,
|
|
occurredAt: "2026-02-02",
|
|
necessity: "NECESSARY",
|
|
purchaseType: "Groceries",
|
|
notes: "Test",
|
|
tags: ["groceries", "weekly"],
|
|
isRecurring: false,
|
|
intervalCount: 1
|
|
});
|
|
|
|
const list = await listEntries(groupId);
|
|
assert.equal(list.length, 1);
|
|
assert.equal(list[0].id, entry.id);
|
|
assert.deepEqual(list[0].tags.sort(), ["groceries", "weekly"]);
|
|
assert.equal(list[0].entryType, "SPENDING");
|
|
|
|
const updated = await updateEntry({
|
|
id: entry.id,
|
|
groupId,
|
|
userId,
|
|
entryType: "INCOME",
|
|
amountDollars: 15,
|
|
occurredAt: "2026-02-02",
|
|
necessity: "BOTH",
|
|
purchaseType: "Groceries",
|
|
notes: "Updated",
|
|
tags: ["groceries"],
|
|
isRecurring: true,
|
|
frequency: "MONTHLY",
|
|
intervalCount: 1,
|
|
endCondition: "NEVER",
|
|
nextRunAt: "2026-02-02"
|
|
});
|
|
assert.ok(updated);
|
|
assert.equal(updated?.amountDollars, 15);
|
|
assert.equal(updated?.entryType, "INCOME");
|
|
assert.deepEqual(updated?.tags.sort(), ["groceries"]);
|
|
|
|
await deleteEntry({ id: entry.id, groupId });
|
|
const listAfter = await listEntries(groupId);
|
|
assert.equal(listAfter.length, 0);
|
|
} finally {
|
|
await cleanupTestData(client, { userIds: [userId], groupId });
|
|
client.release();
|
|
}
|
|
});
|