import 'package:flutter_test/flutter_test.dart'; import 'package:household_keeper/features/tasks/domain/frequency.dart'; import 'package:household_keeper/features/tasks/domain/relative_date.dart'; import 'package:household_keeper/features/tasks/domain/scheduling.dart'; void main() { group('calculateNextDueDate', () { test('daily adds 1 day', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 3, 15), intervalType: IntervalType.daily, intervalDays: 1, ); expect(result, DateTime(2026, 3, 16)); }); test('everyNDays(3) adds 3 days', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 3, 15), intervalType: IntervalType.everyNDays, intervalDays: 3, ); expect(result, DateTime(2026, 3, 18)); }); test('weekly adds 7 days', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 3, 15), intervalType: IntervalType.weekly, intervalDays: 1, ); expect(result, DateTime(2026, 3, 22)); }); test('biweekly adds 14 days', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 3, 15), intervalType: IntervalType.biweekly, intervalDays: 1, ); expect(result, DateTime(2026, 3, 29)); }); test('monthly from Jan 15 gives Feb 15', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 1, 15), intervalType: IntervalType.monthly, intervalDays: 1, ); expect(result, DateTime(2026, 2, 15)); }); test('monthly from Jan 31 gives Feb 28 (clamping)', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 1, 31), intervalType: IntervalType.monthly, intervalDays: 1, ); expect(result, DateTime(2026, 2, 28)); }); test('monthly from Feb 28 (anchor 31) gives Mar 31 (anchor memory)', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 2, 28), intervalType: IntervalType.monthly, intervalDays: 1, anchorDay: 31, ); expect(result, DateTime(2026, 3, 31)); }); test('quarterly from Jan 15 gives Apr 15', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 1, 15), intervalType: IntervalType.quarterly, intervalDays: 1, ); expect(result, DateTime(2026, 4, 15)); }); test('yearly from 2026-03-15 gives 2027-03-15', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 3, 15), intervalType: IntervalType.yearly, intervalDays: 1, ); expect(result, DateTime(2027, 3, 15)); }); test('everyNMonths(2) adds 2 months', () { final result = calculateNextDueDate( currentDueDate: DateTime(2026, 1, 15), intervalType: IntervalType.everyNMonths, intervalDays: 2, ); expect(result, DateTime(2026, 3, 15)); }); }); group('catchUpToPresent', () { test('skips past occurrences to reach today or future', () { // Task was due Jan 1, weekly interval. Today is Mar 15. // Should advance past all missed weeks to the next week on/after Mar 15. final result = catchUpToPresent( nextDue: DateTime(2026, 1, 1), today: DateTime(2026, 3, 15), intervalType: IntervalType.weekly, intervalDays: 1, ); // Jan 1 + 11 weeks = Mar 19 (first Thursday on/after Mar 15) expect(result.isAfter(DateTime(2026, 3, 14)), isTrue); expect(result.isBefore(DateTime(2026, 3, 22)), isTrue); }); test('returns date unchanged if already in future', () { final futureDate = DateTime(2026, 4, 1); final result = catchUpToPresent( nextDue: futureDate, today: DateTime(2026, 3, 15), intervalType: IntervalType.weekly, intervalDays: 1, ); expect(result, futureDate); }); }); group('formatRelativeDate', () { final today = DateTime(2026, 3, 15); test('today returns "Heute"', () { expect(formatRelativeDate(DateTime(2026, 3, 15), today), 'Heute'); }); test('tomorrow returns "Morgen"', () { expect(formatRelativeDate(DateTime(2026, 3, 16), today), 'Morgen'); }); test('3 days from now returns "in 3 Tagen"', () { expect(formatRelativeDate(DateTime(2026, 3, 18), today), 'in 3 Tagen'); }); test('1 day overdue returns "Uberfaellig seit 1 Tag"', () { expect( formatRelativeDate(DateTime(2026, 3, 14), today), 'Uberfaellig seit 1 Tag', ); }); test('5 days overdue returns "Uberfaellig seit 5 Tagen"', () { expect( formatRelativeDate(DateTime(2026, 3, 10), today), 'Uberfaellig seit 5 Tagen', ); }); }); }