focus-flow/test/document_mapping_test.dart

165 lines
5.9 KiB
Dart

import 'package:adhd_scheduler_core/scheduler_core.dart';
import 'package:test/test.dart';
void main() {
group('MongoDB document mapping helpers', () {
final createdAt = DateTime.utc(2026, 6, 23, 8);
test('task documents round-trip every scheduling field', () {
final task = scheduledTask(
id: 'task-1',
createdAt: createdAt,
reward: RewardLevel.high,
difficulty: DifficultyLevel.hard,
).copyWith(
stats: const TaskStatistics().incrementManualPush(),
);
final document = task.toDocument();
final restored = TaskDocumentMapping.fromDocument(document);
expect(document[TaskDocumentFields.id], task.id);
expect(document[TaskDocumentFields.type], 'flexible');
expect(document[TaskDocumentFields.status], 'planned');
expect(document[TaskDocumentFields.reward], 'high');
expect(document[TaskDocumentFields.difficulty], 'hard');
expect(document[TaskDocumentFields.scheduledStart],
'2026-06-23T09:00:00.000Z');
expect(restored.id, task.id);
expect(restored.title, task.title);
expect(restored.projectId, task.projectId);
expect(restored.type, task.type);
expect(restored.status, task.status);
expect(restored.priority, task.priority);
expect(restored.reward, task.reward);
expect(restored.difficulty, task.difficulty);
expect(restored.durationMinutes, task.durationMinutes);
expect(restored.scheduledStart, task.scheduledStart);
expect(restored.scheduledEnd, task.scheduledEnd);
expect(restored.actualStart, task.actualStart);
expect(restored.actualEnd, task.actualEnd);
expect(restored.completedAt, task.completedAt);
expect(restored.parentTaskId, task.parentTaskId);
expect(restored.backlogTags, task.backlogTags);
expect(restored.reminderOverride, task.reminderOverride);
expect(restored.createdAt, task.createdAt);
expect(restored.updatedAt, task.updatedAt);
expect(restored.stats.manuallyPushedCount, 1);
});
test('task documents preserve not-set reward distinctly from very low', () {
final noReward = scheduledTask(
id: 'no-reward',
createdAt: createdAt,
reward: RewardLevel.notSet,
);
final veryLowReward = scheduledTask(
id: 'very-low',
createdAt: createdAt,
reward: RewardLevel.veryLow,
);
final noRewardDocument = noReward.toDocument();
final veryLowRewardDocument = veryLowReward.toDocument();
expect(noRewardDocument[TaskDocumentFields.reward], 'notSet');
expect(veryLowRewardDocument[TaskDocumentFields.reward], 'veryLow');
expect(
TaskDocumentMapping.fromDocument(noRewardDocument).reward,
RewardLevel.notSet,
);
expect(
TaskDocumentMapping.fromDocument(veryLowRewardDocument).reward,
RewardLevel.veryLow,
);
});
test('task documents support explicit nullable schedule clearing', () {
final task = scheduledTask(
id: 'scheduled',
createdAt: createdAt,
);
final clearedDocument = task.toDocument(clearSchedule: true);
final restored = TaskDocumentMapping.fromDocument(clearedDocument);
expect(clearedDocument[TaskDocumentFields.scheduledStart], isNull);
expect(clearedDocument[TaskDocumentFields.scheduledEnd], isNull);
expect(restored.scheduledStart, isNull);
expect(restored.scheduledEnd, isNull);
expect(restored.id, task.id);
});
test('task statistics document mapping preserves every counter', () {
const stats = TaskStatistics(
skippedDuringBurnoutCount: 1,
manuallyPushedCount: 2,
autoPushedCount: 3,
movedToBacklogCount: 4,
restoredFromBacklogCount: 5,
missedCount: 6,
cancelledCount: 7,
completedLateCount: 8,
completedDuringLockedHoursCount: 9,
completedDuringLockedHoursMinutes: 10,
completedAfterShieldCount: 11,
completedAfterPushCount: 12,
totalPushesBeforeCompletion: 13,
);
final document = stats.toDocument();
final restored = TaskStatisticsDocumentMapping.fromDocument(document);
expect(document.keys.toSet(), TaskStatisticsDocumentFields.all);
expect(restored.skippedDuringBurnoutCount, 1);
expect(restored.manuallyPushedCount, 2);
expect(restored.autoPushedCount, 3);
expect(restored.movedToBacklogCount, 4);
expect(restored.restoredFromBacklogCount, 5);
expect(restored.missedCount, 6);
expect(restored.cancelledCount, 7);
expect(restored.completedLateCount, 8);
expect(restored.completedDuringLockedHoursCount, 9);
expect(restored.completedDuringLockedHoursMinutes, 10);
expect(restored.completedAfterShieldCount, 11);
expect(restored.completedAfterPushCount, 12);
expect(restored.totalPushesBeforeCompletion, 13);
});
test('enum document mapping rejects unknown persistence names', () {
expect(
() => PersistenceEnumMapping.decodeTaskType('unknown'),
throwsArgumentError,
);
});
});
}
Task scheduledTask({
required String id,
required DateTime createdAt,
RewardLevel reward = RewardLevel.notSet,
DifficultyLevel difficulty = DifficultyLevel.medium,
}) {
return Task(
id: id,
title: 'Scheduled task',
projectId: 'project-1',
type: TaskType.flexible,
status: TaskStatus.planned,
priority: PriorityLevel.medium,
reward: reward,
difficulty: difficulty,
durationMinutes: 30,
scheduledStart: DateTime.utc(2026, 6, 23, 9),
scheduledEnd: DateTime.utc(2026, 6, 23, 9, 30),
actualStart: DateTime.utc(2026, 6, 23, 9, 5),
actualEnd: DateTime.utc(2026, 6, 23, 9, 25),
completedAt: DateTime.utc(2026, 6, 23, 9, 30),
parentTaskId: 'parent-1',
backlogTags: const {BacklogTag.wishlist},
reminderOverride: ReminderProfile.persistent,
createdAt: createdAt,
updatedAt: createdAt.add(const Duration(minutes: 5)),
);
}