import 'package:adhd_scheduler_core/scheduler_core.dart'; import 'package:test/test.dart'; void main() { group('Child task ownership', () { final now = DateTime(2026, 6, 19, 12); test('child references parent through parentTaskId', () { final parent = task(id: 'parent', title: 'Clean kitchen', createdAt: now); final child = task( id: 'child', title: 'Clear sink', createdAt: now, parentTaskId: parent.id, ); final view = ChildTaskView(tasks: [parent, child]); expect(child.parentTaskId, parent.id); expect(view.isChildOf(child: child, parent: parent), isTrue); expect(view.parentOf(child), same(parent)); }); test('parent can query and aggregate direct children', () { final parent = task(id: 'parent', title: 'Clean kitchen', createdAt: now); final plannedChild = task( id: 'planned-child', title: 'Clear sink', createdAt: now, parentTaskId: parent.id, ); final completedChild = task( id: 'completed-child', title: 'Wipe counter', createdAt: now, status: TaskStatus.completed, parentTaskId: parent.id, ); final unrelatedChild = task( id: 'unrelated-child', title: 'Sort drawer', createdAt: now, parentTaskId: 'other-parent', ); final view = ChildTaskView( tasks: [parent, plannedChild, unrelatedChild, completedChild], ); expect(view.childrenOf(parent).map((child) => child.id), [ 'planned-child', 'completed-child', ]); final summary = view.summaryFor(parent); expect(summary.totalCount, 2); expect(summary.plannedCount, 1); expect(summary.completedCount, 1); expect(summary.allChildrenCompleted, isFalse); }); test('parent can remain incomplete while children are planned or completed', () { final parent = task(id: 'parent', title: 'Clean kitchen', createdAt: now); final completedChild = task( id: 'completed-child', title: 'Clear sink', createdAt: now, status: TaskStatus.completed, parentTaskId: parent.id, ); final view = ChildTaskView(tasks: [parent, completedChild]); expect(parent.status, TaskStatus.planned); expect(view.summaryFor(parent).allChildrenCompleted, isTrue); expect(view.parentShouldAutoComplete(parent), isFalse); }); test('child ownership does not block normal scheduling behavior', () { const engine = SchedulingEngine(); final parent = task( id: 'parent', title: 'Clean kitchen', createdAt: now, status: TaskStatus.backlog, ); final child = task( id: 'child', title: 'Clear sink', createdAt: now, status: TaskStatus.backlog, durationMinutes: 15, parentTaskId: parent.id, ); final result = engine.insertBacklogTaskIntoNextAvailableSlot( input: SchedulingInput( tasks: [parent, child], window: SchedulingWindow( start: DateTime(2026, 6, 19, 9), end: DateTime(2026, 6, 19, 10), ), ), taskId: child.id, updatedAt: now, ); final scheduledChild = taskById(result.tasks, child.id); final unchangedParent = taskById(result.tasks, parent.id); expect(scheduledChild.status, TaskStatus.planned); expect(scheduledChild.parentTaskId, parent.id); expect(scheduledChild.scheduledStart, DateTime(2026, 6, 19, 9)); expect(unchangedParent.status, TaskStatus.backlog); expect(unchangedParent.scheduledStart, isNull); }); }); } Task task({ required String id, required String title, required DateTime createdAt, TaskStatus status = TaskStatus.planned, int? durationMinutes, String? parentTaskId, }) { return Task( id: id, title: title, projectId: 'home', type: TaskType.flexible, status: status, priority: PriorityLevel.medium, durationMinutes: durationMinutes, parentTaskId: parentTaskId, createdAt: createdAt, updatedAt: createdAt, ); } Task taskById(List tasks, String id) { return tasks.singleWhere((task) => task.id == id); }