focus-flow/test/repositories_test.dart

147 lines
4.5 KiB
Dart

import 'package:adhd_scheduler_core/scheduler_core.dart';
import 'package:test/test.dart';
void main() {
group('Repository interfaces', () {
final createdAt = DateTime(2026, 6, 21, 8);
final window = SchedulingWindow(
start: DateTime(2026, 6, 21, 9),
end: DateTime(2026, 6, 21, 17),
);
test('task repository supports in-memory fakes for domain services',
() async {
final backlogTask = task(
id: 'backlog',
title: 'Backlog task',
status: TaskStatus.backlog,
createdAt: createdAt,
);
final scheduledTask = task(
id: 'scheduled',
title: 'Scheduled task',
status: TaskStatus.planned,
createdAt: createdAt,
scheduledStart: DateTime(2026, 6, 21, 10),
scheduledEnd: DateTime(2026, 6, 21, 10, 30),
);
final repository = InMemoryTaskRepository([backlogTask]);
await repository.save(scheduledTask);
expect(await repository.findById('backlog'), same(backlogTask));
expect(await repository.findByStatus(TaskStatus.backlog), [backlogTask]);
expect(
(await repository.findScheduledInWindow(window)).map((task) => task.id),
['scheduled'],
);
});
test('project repository stores project profiles by stable id', () async {
final project = ProjectProfile(
id: 'home',
name: 'Home',
colorKey: 'project-home',
);
final repository = InMemoryProjectRepository();
await repository.save(project);
expect(await repository.findById('home'), same(project));
expect(await repository.findAll(), [project]);
});
test('locked block repository separates blocks from overrides', () async {
final block = LockedBlock(
id: 'work',
name: 'Work',
startTime: ClockTime(hour: 9, minute: 0),
endTime: ClockTime(hour: 17, minute: 0),
recurrence: LockedBlockRecurrence.weekly(
weekdays: {LockedWeekday.monday},
),
createdAt: createdAt,
updatedAt: createdAt,
);
final override = LockedBlockOverride.remove(
id: 'holiday',
lockedBlockId: block.id,
date: DateTime(2026, 6, 22),
createdAt: createdAt,
);
final repository = InMemoryLockedBlockRepository();
await repository.saveBlock(block);
await repository.saveOverride(override);
expect(await repository.findBlockById('work'), same(block));
expect(await repository.findOverrideById('holiday'), same(override));
expect(await repository.findAllBlocks(), [block]);
expect(await repository.findAllOverrides(), [override]);
});
test('scheduling snapshot repository preserves scheduler input shape',
() async {
final scheduledTask = task(
id: 'scheduled',
title: 'Scheduled task',
status: TaskStatus.planned,
createdAt: createdAt,
scheduledStart: DateTime(2026, 6, 21, 10),
scheduledEnd: DateTime(2026, 6, 21, 10, 30),
);
final lockedInterval = TimeInterval(
start: DateTime(2026, 6, 21, 12),
end: DateTime(2026, 6, 21, 13),
label: 'Lunch',
);
final snapshot = SchedulingStateSnapshot(
id: 'snapshot-1',
capturedAt: DateTime(2026, 6, 21, 8, 30),
window: window,
tasks: [scheduledTask],
lockedIntervals: [lockedInterval],
notices: const [
SchedulingNotice('Saved schedule'),
],
operationName: 'load-day',
);
final repository = InMemorySchedulingSnapshotRepository();
await repository.save(snapshot);
final saved = await repository.findById('snapshot-1');
expect(saved, same(snapshot));
expect(saved!.input.tasks, [scheduledTask]);
expect(saved.input.lockedIntervals, [lockedInterval]);
expect(saved.result.tasks, [scheduledTask]);
expect(saved.result.notices.single.message, 'Saved schedule');
expect(
(await repository.findInWindow(window)).map((snapshot) => snapshot.id),
['snapshot-1'],
);
});
});
}
Task task({
required String id,
required String title,
required TaskStatus status,
required DateTime createdAt,
DateTime? scheduledStart,
DateTime? scheduledEnd,
}) {
return Task(
id: id,
title: title,
projectId: 'inbox',
type: TaskType.flexible,
status: status,
durationMinutes: 30,
scheduledStart: scheduledStart,
scheduledEnd: scheduledEnd,
createdAt: createdAt,
updatedAt: createdAt,
);
}