import { describe, it, expect, beforeEach } from 'vitest'; import { createTestDb } from '$lib/server/db/test-helper'; import { add as addProject } from './projects'; import { add, edit, archive, complete, loadAllVersions, loadProjectDashboard, loadOverview, } from './routines'; const DAY_MS = 24 * 60 * 60 * 1000; describe('routines service', () => { let db: Awaited>['db']; let projectId: number; beforeEach(async () => { const testDb = await createTestDb(); db = testDb.db; const project = await addProject('Household', db); projectId = project.id; }); it('creates a routine with version 1', async () => { const r = await add(projectId, 'clean kitchen', 7, db); expect(r.id).toBe(1); expect(r.version).toBe(1); expect(r.frequencyDays).toBe(7); }); it('edit inserts a new snapshot version and keeps history', async () => { const r = await add(projectId, 'clean kitchen', 7, db); const updated = await edit(r.id, 'clean kitchen deeply', 3, db); expect(updated.version).toBe(2); expect(updated.frequencyDays).toBe(3); const versions = await loadAllVersions(r.id, db); expect(versions).toHaveLength(2); expect(versions[0].frequencyDays).toBe(7); expect(versions[1].frequencyDays).toBe(3); }); it('archive inserts an archived snapshot without removing history', async () => { const r = await add(projectId, 'clean kitchen', 7, db); await archive(r.id, db); const versions = await loadAllVersions(r.id, db); expect(versions).toHaveLength(2); expect(versions[0].archived).toBe(false); expect(versions[1].archived).toBe(true); const dashboard = await loadProjectDashboard(projectId, Date.now(), db); expect(dashboard.routines).toHaveLength(0); expect(dashboard.healthScore).toBe(100); }); it('complete records the snapshot version it was made against', async () => { const r = await add(projectId, 'clean kitchen', 7, db); await edit(r.id, 'clean kitchen', 5, db); const doneAt = new Date().toISOString(); const completion = await complete(r.id, 'with vinegar', doneAt, db); expect(completion.routineVersion).toBe(2); expect(completion.note).toBe('with vinegar'); }); it('dashboard computes urgency and health from completions', async () => { const r = await add(projectId, 'clean kitchen', 7, db); const createdAt = Date.parse(r.createdAt); await complete(r.id, null, new Date(createdAt).toISOString(), db); // 15 days after completion with a 7-day routine => very late const now = createdAt + 15 * DAY_MS; const dashboard = await loadProjectDashboard(projectId, now, db); expect(dashboard.routines).toHaveLength(1); expect(dashboard.routines[0].status).toBe('veryLate'); expect(dashboard.healthScore).toBe(0); }); it('overview aggregates per-project health and a global score', async () => { await add(projectId, 'clean kitchen', 7, db); const growth = await addProject('Personal growth', db); await add(growth.id, 'read 30 minutes', 1, db); const now = Date.now(); const overview = await loadOverview(now, db); expect(overview.projects).toHaveLength(2); expect(overview.globalScore).toBe( Math.round(overview.projects.reduce((s, p) => s + p.healthScore, 0) / 2), ); }); });