aboutsummaryrefslogtreecommitdiff
path: root/src/lib/server/services/groceries.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/server/services/groceries.test.ts')
-rw-r--r--src/lib/server/services/groceries.test.ts98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/lib/server/services/groceries.test.ts b/src/lib/server/services/groceries.test.ts
new file mode 100644
index 0000000..83f8d95
--- /dev/null
+++ b/src/lib/server/services/groceries.test.ts
@@ -0,0 +1,98 @@
+import { describe, it, expect, beforeEach } from 'vitest';
+import { groceries, categories, references } from '$lib/server/db/schema';
+import { eq } from 'drizzle-orm';
+import { createTestDb } from '$lib/server/db/test-helper';
+import {
+ loadUnchecked,
+ loadAll,
+ toggle,
+ addOrUncheck,
+ deleteGrocery,
+} from './groceries';
+
+describe('groceries service', () => {
+ let db: Awaited<ReturnType<typeof createTestDb>>['db'];
+
+ beforeEach(async () => {
+ const testDb = await createTestDb();
+ db = testDb.db;
+ });
+
+ it('loadUnchecked returns only unchecked items', async () => {
+ const now = new Date().toISOString();
+ await db.insert(groceries).values([
+ { name: 'milk', checked: false, createdAt: now },
+ { name: 'bread', checked: true, createdAt: now },
+ ]);
+
+ const result = await loadUnchecked(db);
+ expect(result.items).toHaveLength(1);
+ expect(result.items[0].name).toBe('milk');
+ });
+
+ it('loadAll returns all items', async () => {
+ const now = new Date().toISOString();
+ await db.insert(groceries).values([
+ { name: 'milk', checked: false, createdAt: now },
+ { name: 'bread', checked: true, createdAt: now },
+ ]);
+
+ const result = await loadAll(db);
+ expect(result.items).toHaveLength(2);
+ });
+
+ it('toggle flips checked state', async () => {
+ const now = new Date().toISOString();
+ await db
+ .insert(groceries)
+ .values({ name: 'milk', checked: false, createdAt: now });
+ const [item] = await db.select().from(groceries);
+
+ await toggle(item.id, db);
+
+ const [updated] = await db
+ .select()
+ .from(groceries)
+ .where(eq(groceries.id, item.id));
+ expect(updated.checked).toBe(true);
+ });
+
+ it('addOrUncheck creates a new grocery', async () => {
+ const { item, created } = await addOrUncheck('eggs', null, db);
+
+ expect(created).toBe(true);
+ expect(item.name).toBe('eggs');
+
+ const rows = await db.select().from(groceries);
+ expect(rows).toHaveLength(1);
+ });
+
+ it('addOrUncheck unchecks an existing checked item', async () => {
+ const now = new Date().toISOString();
+ await db
+ .insert(groceries)
+ .values({ name: 'milk', checked: true, createdAt: now });
+
+ const { item, created } = await addOrUncheck('milk', null, db);
+
+ expect(created).toBe(false);
+ expect(item.checked).toBe(false);
+
+ const rows = await db.select().from(groceries);
+ expect(rows).toHaveLength(1);
+ expect(rows[0].checked).toBe(false);
+ });
+
+ it('deleteGrocery removes the item', async () => {
+ const now = new Date().toISOString();
+ await db
+ .insert(groceries)
+ .values({ name: 'milk', checked: false, createdAt: now });
+ const [item] = await db.select().from(groceries);
+
+ await deleteGrocery(item.id, db);
+
+ const rows = await db.select().from(groceries);
+ expect(rows).toHaveLength(0);
+ });
+});