diff --git a/test/features/tasks/data/tasks_dao_test.dart b/test/features/tasks/data/tasks_dao_test.dart index fa13da1..f5729e6 100644 --- a/test/features/tasks/data/tasks_dao_test.dart +++ b/test/features/tasks/data/tasks_dao_test.dart @@ -317,6 +317,79 @@ void main() { expect(overdueCount, 1); }); + test('completeTask on due date preserves rhythm', () async { + // Weekly task due 2026-03-24, completed on 2026-03-24: next due = 2026-03-31 + final id = await db.tasksDao.insertTask( + TasksCompanion.insert( + roomId: roomId, + name: 'Weekly On Due Day', + intervalType: IntervalType.weekly, + effortLevel: EffortLevel.medium, + nextDueDate: DateTime(2026, 3, 24), + ), + ); + + await db.tasksDao.completeTask(id, now: DateTime(2026, 3, 24)); + + final tasks = await db.tasksDao.watchTasksInRoom(roomId).first; + expect(tasks.first.nextDueDate, DateTime(2026, 3, 31)); + }); + + test('completeTask before due date recalculates from today', () async { + // Weekly task due 2026-03-28, completed on 2026-03-24 (Tuesday): next due = 2026-03-31 (7 days from today) + final id = await db.tasksDao.insertTask( + TasksCompanion.insert( + roomId: roomId, + name: 'Weekly Before Due Day', + intervalType: IntervalType.weekly, + effortLevel: EffortLevel.medium, + nextDueDate: DateTime(2026, 3, 28), + ), + ); + + await db.tasksDao.completeTask(id, now: DateTime(2026, 3, 24)); + + final tasks = await db.tasksDao.watchTasksInRoom(roomId).first; + expect(tasks.first.nextDueDate, DateTime(2026, 3, 31)); + }); + + test('completeTask daily task on non-due day recalculates from today', () async { + // Daily task due 2026-03-26, completed on 2026-03-24: next due = 2026-03-25 (tomorrow) + final id = await db.tasksDao.insertTask( + TasksCompanion.insert( + roomId: roomId, + name: 'Daily Non-Due Day', + intervalType: IntervalType.daily, + effortLevel: EffortLevel.low, + nextDueDate: DateTime(2026, 3, 26), + ), + ); + + await db.tasksDao.completeTask(id, now: DateTime(2026, 3, 24)); + + final tasks = await db.tasksDao.watchTasksInRoom(roomId).first; + expect(tasks.first.nextDueDate, DateTime(2026, 3, 25)); + }); + + test('completeTask monthly task early preserves anchor', () async { + // Monthly task due 2026-03-28 anchorDay=28, completed on 2026-03-24: next due = 2026-04-28 + final id = await db.tasksDao.insertTask( + TasksCompanion.insert( + roomId: roomId, + name: 'Monthly Early Completion', + intervalType: IntervalType.monthly, + effortLevel: EffortLevel.high, + nextDueDate: DateTime(2026, 3, 28), + anchorDay: const Value(28), + ), + ); + + await db.tasksDao.completeTask(id, now: DateTime(2026, 3, 24)); + + final tasks = await db.tasksDao.watchTasksInRoom(roomId).first; + expect(tasks.first.nextDueDate, DateTime(2026, 4, 28)); + }); + test('hard deleteTask still removes task and its completions', () async { final id = await db.tasksDao.insertTask( TasksCompanion.insert(