aboutsummaryrefslogtreecommitdiff
path: root/src/lib/server/services/routines.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/server/services/routines.test.ts')
-rw-r--r--src/lib/server/services/routines.test.ts104
1 files changed, 49 insertions, 55 deletions
diff --git a/src/lib/server/services/routines.test.ts b/src/lib/server/services/routines.test.ts
index 2ad409a..b92db25 100644
--- a/src/lib/server/services/routines.test.ts
+++ b/src/lib/server/services/routines.test.ts
@@ -1,108 +1,103 @@
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,
- loadArchived,
- loadProjectDashboard,
- loadOverview,
-} from './routines';
+import { createTestDb, type TestDb } from '$lib/server/db/test-helper';
+import { ProjectsService } from './projects';
+import { RoutinesService } from './routines';
describe('routines service', () => {
- let db: Awaited<ReturnType<typeof createTestDb>>['db'];
+ let db: TestDb['db'];
+ let service: RoutinesService;
let projectId: number;
beforeEach(async () => {
const testDb = await createTestDb();
db = testDb.db;
- const project = await addProject('Household', db);
+ service = new RoutinesService(db);
+ const project = await new ProjectsService(db).add('Household');
projectId = project.id;
});
it('creates a routine with version 1', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
expect(r.id).toBe(1);
expect(r.version).toBe(1);
expect(r.frequency).toBe('7d');
});
it('edit inserts a new snapshot version and keeps history', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
- const updated = await edit(
- r.id,
- { name: 'clean kitchen deeply', frequency: '3d' },
- db,
- );
+ const r = await service.add(projectId, 'clean kitchen', '7d');
+ const updated = await service.edit(r.id, {
+ name: 'clean kitchen deeply',
+ frequency: '3d',
+ });
expect(updated.version).toBe(2);
expect(updated.frequency).toBe('3d');
- const versions = await loadAllVersions(r.id, db);
+ const versions = await service.loadAllVersions(r.id);
expect(versions).toHaveLength(2);
expect(versions[0].frequency).toBe('7d');
expect(versions[1].frequency).toBe('3d');
});
it('new routines start with an empty description', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
expect(r.description).toBe('');
});
it('edit is partial: name/frequency edits keep the description and vice-versa', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
- const described = await edit(r.id, { description: 'wax on, wax off' }, db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
+ const described = await service.edit(r.id, {
+ description: 'wax on, wax off',
+ });
expect(described.name).toBe('clean kitchen');
expect(described.frequency).toBe('7d');
expect(described.description).toBe('wax on, wax off');
- const renamed = await edit(r.id, { name: 'clean the whole kitchen' }, db);
+ const renamed = await service.edit(r.id, {
+ name: 'clean the whole kitchen',
+ });
expect(renamed.version).toBe(3);
expect(renamed.description).toBe('wax on, wax off');
expect(renamed.frequency).toBe('7d');
- const refreq = await edit(r.id, { frequency: '14d' }, db);
+ const refreq = await service.edit(r.id, { frequency: '14d' });
expect(refreq.version).toBe(4);
expect(refreq.name).toBe('clean the whole kitchen');
expect(refreq.description).toBe('wax on, wax off');
- const cleared = await edit(r.id, { description: '' }, db);
+ const cleared = await service.edit(r.id, { description: '' });
expect(cleared.version).toBe(5);
expect(cleared.description).toBe('');
expect(cleared.name).toBe('clean the whole kitchen');
});
it('archive inserts an archived snapshot without removing history', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
- await archive(r.id, db);
- const versions = await loadAllVersions(r.id, db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
+ await service.archive(r.id);
+ const versions = await service.loadAllVersions(r.id);
expect(versions).toHaveLength(2);
expect(versions[0].archived).toBe(false);
expect(versions[1].archived).toBe(true);
- const dashboard = await loadProjectDashboard(
+ const dashboard = await service.loadProjectDashboard(
projectId,
Temporal.Now.instant(),
- db,
);
expect(dashboard.routines).toHaveLength(0);
expect(dashboard.healthScore).toBe(100);
});
it('loadArchived lists archived routines; edits keep the archive date', async () => {
- const a = await add(projectId, 'clean kitchen', '7d', db);
- await add(projectId, 'water plants', '3d', db);
- await archive(a.id, db);
- const stamped = (await loadAllVersions(a.id, db))[1].archivedAt;
+ const a = await service.add(projectId, 'clean kitchen', '7d');
+ await service.add(projectId, 'water plants', '3d');
+ await service.archive(a.id);
+ const stamped = (await service.loadAllVersions(a.id))[1].archivedAt;
expect(stamped).toBeTruthy();
- const edited = await edit(a.id, { name: 'clean kitchen deeply' }, db);
+ const edited = await service.edit(a.id, { name: 'clean kitchen deeply' });
expect(edited.archived).toBe(true);
expect(edited.archivedAt).toBe(stamped);
- const archived = await loadArchived(projectId, db);
+ const archived = await service.loadArchived(projectId);
expect(archived.map((r) => r.id)).toEqual([a.id]);
expect(archived[0].name).toBe('clean kitchen deeply');
expect(archived[0].frequency).toBe('7d');
@@ -110,12 +105,12 @@ describe('routines service', () => {
});
it('loadArchived sorts most recently archived first', async () => {
- const a = await add(projectId, 'first', '1d', db);
- const b = await add(projectId, 'second', '1d', db);
- await archive(a.id, db);
- await archive(b.id, db);
+ const a = await service.add(projectId, 'first', '1d');
+ const b = await service.add(projectId, 'second', '1d');
+ await service.archive(a.id);
+ await service.archive(b.id);
- const archived = await loadArchived(projectId, db);
+ const archived = await service.loadArchived(projectId);
expect(archived).toHaveLength(2);
// Descending archive date; equal timestamps keep insertion order.
expect(
@@ -126,28 +121,27 @@ describe('routines service', () => {
});
it('complete records the snapshot version it was made against', async () => {
- const r = await add(projectId, 'clean kitchen', '7d', db);
- await edit(r.id, { frequency: '5d' }, db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
+ await service.edit(r.id, { frequency: '5d' });
const doneAt = Temporal.Now.instant().toString({
smallestUnit: 'millisecond',
});
- const completion = await complete(r.id, 'with vinegar', doneAt, db);
+ const completion = await service.complete(r.id, 'with vinegar', doneAt);
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', '7d', db);
+ const r = await service.add(projectId, 'clean kitchen', '7d');
const created = Temporal.Instant.from(r.createdAt);
- await complete(
+ await service.complete(
r.id,
null,
created.toString({ smallestUnit: 'millisecond' }),
- db,
);
// 22 days after completion with a 7-day routine => two periods overdue
const now = created.toZonedDateTimeISO('UTC').add({ days: 22 }).toInstant();
- const dashboard = await loadProjectDashboard(projectId, now, db);
+ const dashboard = await service.loadProjectDashboard(projectId, now);
expect(dashboard.routines).toHaveLength(1);
expect(dashboard.routines[0].status).toBe('veryLate');
expect(dashboard.healthScore).toBe(0);
@@ -157,12 +151,12 @@ describe('routines service', () => {
});
it('overview aggregates per-project health and a global score', async () => {
- await add(projectId, 'clean kitchen', '7d', db);
- const growth = await addProject('Personal growth', db);
- await add(growth.id, 'read 30 minutes', '1d', db);
+ await service.add(projectId, 'clean kitchen', '7d');
+ const growth = await new ProjectsService(db).add('Personal growth');
+ await service.add(growth.id, 'read 30 minutes', '1d');
const now = Temporal.Now.instant();
- const overview = await loadOverview(now, db);
+ const overview = await service.loadOverview(now);
expect(overview.projects).toHaveLength(2);
expect(overview.globalScore).toBe(
Math.round(overview.projects.reduce((s, p) => s + p.healthScore, 0) / 2),