import 'package:adhd_scheduler_core/scheduler_core.dart'; import 'package:test/test.dart'; void main() { group('Required task action service', () { final now = DateTime(2026, 6, 19, 12); const service = RequiredTaskActionService(); test('done marks inflexible task completed without clearing history', () { final task = requiredTask( id: 'appointment', type: TaskType.inflexible, createdAt: now, start: DateTime(2026, 6, 19, 9), ); final result = service.apply( task: task, action: RequiredTaskAction.done, updatedAt: now, ); expect(result.action, RequiredTaskAction.done); expect(result.task.status, TaskStatus.completed); expect(result.task.scheduledStart, task.scheduledStart); expect(result.task.scheduledEnd, task.scheduledEnd); expect(result.removedFromActivePlan, isFalse); }); test('done marks critical task completed without moving it', () { final task = requiredTask( id: 'meds', type: TaskType.critical, createdAt: now, start: DateTime(2026, 6, 19, 10), ); final result = service.apply( task: task, action: RequiredTaskAction.done, updatedAt: now, ); expect(result.task.status, TaskStatus.completed); expect(result.task.scheduledStart, task.scheduledStart); expect(result.task.scheduledEnd, task.scheduledEnd); }); test('missed critical task moves to backlog and clears schedule', () { final task = requiredTask( id: 'critical', type: TaskType.critical, createdAt: now, start: DateTime(2026, 6, 19, 9), ); final result = service.apply( task: task, action: RequiredTaskAction.missed, updatedAt: now, ); expect(result.task.status, TaskStatus.backlog); expect(result.task.scheduledStart, isNull); expect(result.task.scheduledEnd, isNull); expect(result.task.stats.missedCount, 1); expect(result.task.stats.movedToBacklogCount, 1); expect(result.removedFromActivePlan, isTrue); }); test('missed inflexible task remains scheduled as history', () { final task = requiredTask( id: 'appointment', type: TaskType.inflexible, createdAt: now, start: DateTime(2026, 6, 19, 9), ); final result = service.apply( task: task, action: RequiredTaskAction.missed, updatedAt: now, ); expect(result.task.status, TaskStatus.missed); expect(result.task.scheduledStart, task.scheduledStart); expect(result.task.scheduledEnd, task.scheduledEnd); expect(result.task.stats.missedCount, 1); expect(result.removedFromActivePlan, isFalse); }); test('cancel and no-longer-relevant remain distinct states', () { final task = requiredTask( id: 'appointment', type: TaskType.inflexible, createdAt: now, start: DateTime(2026, 6, 19, 9), ); final cancelled = service.apply( task: task, action: RequiredTaskAction.cancel, updatedAt: now, ); final noLongerRelevant = service.apply( task: task, action: RequiredTaskAction.noLongerRelevant, updatedAt: now, ); expect(cancelled.task.status, TaskStatus.cancelled); expect(cancelled.task.scheduledStart, isNull); expect(cancelled.task.scheduledEnd, isNull); expect(cancelled.task.stats.cancelledCount, 1); expect(cancelled.removedFromActivePlan, isTrue); expect(noLongerRelevant.task.status, TaskStatus.noLongerRelevant); expect(noLongerRelevant.task.scheduledStart, isNull); expect(noLongerRelevant.task.scheduledEnd, isNull); expect(noLongerRelevant.task.stats.cancelledCount, 0); expect(noLongerRelevant.removedFromActivePlan, isTrue); }); test('required action service rejects flexible tasks', () { final task = Task.quickCapture( id: 'flexible', title: 'Flexible', createdAt: now, ).copyWith(status: TaskStatus.planned); expect( () => service.apply( task: task, action: RequiredTaskAction.done, updatedAt: now, ), throwsArgumentError, ); }); test('required action service rejects locked tasks', () { final task = requiredTask( id: 'locked', type: TaskType.locked, createdAt: now, start: DateTime(2026, 6, 19, 9), ); expect( () => service.apply( task: task, action: RequiredTaskAction.missed, updatedAt: now, ), throwsArgumentError, ); }); }); } Task requiredTask({ required String id, required TaskType type, required DateTime createdAt, required DateTime start, }) { return Task( id: id, title: id, projectId: 'required', type: type, status: TaskStatus.planned, priority: PriorityLevel.high, durationMinutes: 30, scheduledStart: start, scheduledEnd: start.add(const Duration(minutes: 30)), createdAt: createdAt, updatedAt: createdAt, ); }