import 'package:flutter_test/flutter_test.dart'; import 'package:marianum_mobile/api/marianumconnect/queries/parent_letters/parent_letter_models.dart'; import 'package:marianum_mobile/state/app/modules/parent_letters/bloc/parent_letters_state.dart'; import 'package:marianum_mobile/state/app/modules/parent_letters/parent_letters_logic.dart'; ParentLetterSummary _letter( String id, { bool read = true, List childIds = const ['c1'], }) => ParentLetterSummary( id: id, sentAt: DateTime(2026, 9, 20), read: read, childIds: childIds, ); void main() { test('firstPageState takes over list and counters', () { final state = firstPageState( ParentLetterListResponse( items: [_letter('a')], hasMore: true, unreadCount: 2, openCount: 1, ), ); expect(state.letters.single.id, 'a'); expect(state.hasMore, isTrue); expect(state.unreadCount, 2); expect(state.openCount, 1); }); test('appendOlderPage appends without duplicating known letters', () { final state = ParentLettersState( letters: [_letter('a'), _letter('b')], hasMore: true, ); final next = appendOlderPage( state, ParentLetterListResponse(items: [_letter('b'), _letter('c')]), ); expect(next.letters.map((l) => l.id), ['a', 'b', 'c']); expect(next.hasMore, isFalse); }); group('withLetterRead', () { final state = ParentLettersState( letters: [_letter('a', read: false), _letter('b')], unreadCount: 1, ); test('marks the letter and lowers the counter', () { final next = withLetterRead(state, 'a'); expect(next.letters.first.read, isTrue); expect(next.unreadCount, 0); }); test('returns the same state for read or unknown letters', () { expect(identical(withLetterRead(state, 'b'), state), isTrue); expect(identical(withLetterRead(state, 'x'), state), isTrue); }); test('never drops the counter below zero', () { final drifted = state.copyWith(unreadCount: 0); expect(withLetterRead(drifted, 'a').unreadCount, 0); }); }); group('withSummary', () { final open = _letter('b').copyWith(status: ParentLetterStatus.open); final state = ParentLettersState( letters: [_letter('a'), open], openCount: 3, ); test('replaces the letter in place and lowers the open counter', () { final next = withSummary( state, open.copyWith(status: ParentLetterStatus.done), ); expect(next.letters.map((l) => l.id), ['a', 'b']); expect(next.letters.last.status, ParentLetterStatus.done); expect(next.openCount, 2); }); test('keeps the counter while the letter stays open', () { expect(withSummary(state, open.copyWith(read: false)).openCount, 3); }); test('ignores letters the inbox does not hold', () { expect(identical(withSummary(state, _letter('x')), state), isTrue); }); }); test('filterLettersByChild keeps letters that concern the child', () { final letters = [ _letter('a', childIds: ['c1']), _letter('b', childIds: ['c2']), _letter('c', childIds: ['c1', 'c2']), ]; expect(filterLettersByChild(letters, null), letters); expect(filterLettersByChild(letters, 'c2').map((l) => l.id), ['b', 'c']); }); }