import 'package:flutter_test/flutter_test.dart'; import 'package:marianum_mobile/api/marianumconnect/queries/get_capabilities/guardian_child.dart'; import 'package:marianum_mobile/background/widget_background_task.dart'; import 'package:marianum_mobile/session/session.dart'; import 'package:marianum_mobile/state/app/modules/capabilities/bloc/capabilities_state.dart'; import 'package:marianum_mobile/state/app/modules/children/child_selection_cubit.dart'; import 'package:marianum_mobile/state/app/modules/timetable/policy/timetable_policy.dart'; import 'package:marianum_mobile/state/app/modules/timetable/primary/primary_subject_resolver.dart'; import 'package:marianum_mobile/state/app/modules/timetable/subject/timetable_subject.dart'; import 'package:marianum_mobile/view/pages/absence_report/absence_form_policy.dart'; import 'package:marianum_mobile/widget_data/widget_sync.dart'; const _anna = GuardianChild(id: 'a', firstName: 'Anna', lastName: 'X'); const _ben = GuardianChild(id: 'b', firstName: 'Ben', lastName: 'X'); const _guardian = GuardianSession(email: 'e@x.de'); final _student = CredentialSession(username: 'max', password: 'pw'); void main() { group('effectiveChild', () { test('keeps a still-linked selection', () { expect(effectiveChild([_anna, _ben], 'b'), _ben); }); test('falls back to the first child', () { expect(effectiveChild([_anna, _ben], null), _anna); expect(effectiveChild([_anna, _ben], 'gone'), _anna); }); test('is null without children', () { expect(effectiveChild(const [], 'a'), isNull); }); }); group('resolvePrimarySubject', () { test('password accounts see their own plan', () { expect( resolvePrimarySubject( session: _student, children: const [], selectedChildId: null, ), const OwnTimetable(), ); }); test('guardians see the selected child', () { expect( resolvePrimarySubject( session: _guardian, children: const [_anna, _ben], selectedChildId: 'b', ), const ChildTimetable('b'), ); }); test('no plan when signed out or without children', () { expect( resolvePrimarySubject( session: null, children: const [], selectedChildId: null, ), const NoTimetable(), ); expect( resolvePrimarySubject( session: _guardian, children: const [], selectedChildId: null, ), const NoTimetable(), ); }); }); group('child subject', () { test('siblings get separate persistent slots', () { expect( const ChildTimetable('a').storageId, isNot(const ChildTimetable('b').storageId), ); expect(const ChildTimetable('a').persistent, isTrue); expect(const ChildTimetable('a').supportsCustomEvents, isFalse); }); test('child plans offer no custom events', () { final p = TimetablePolicy.resolve( subject: const ChildTimetable('a'), capabilities: const CapabilitiesState(userType: 'PARENT'), ); expect(p.canManageCustomEvents, isFalse); expect(p.canEditSubjectColors, isTrue); expect(p.canOpenForeign, isFalse); }); }); group('AbsenceFormPolicy', () { test('users report for themselves with an editable identity', () { final p = AbsenceFormPolicy.resolve( session: _student, children: const [], selectedChildId: null, )!; expect(p.child, isNull); expect(p.identityEditable, isTrue); }); test('guardians report for the selected child', () { final p = AbsenceFormPolicy.resolve( session: _guardian, children: const [_anna, _ben], selectedChildId: 'b', )!; expect(p.child, _ben); expect(p.identityEditable, isFalse); }); test('guardians without children cannot report', () { expect( AbsenceFormPolicy.resolve( session: _guardian, children: const [], selectedChildId: null, ), isNull, ); }); }); group('widget subject', () { test('round-trips primary subjects', () { for (final subject in const [OwnTimetable(), ChildTimetable('a:b')]) { expect( WidgetSync.decodeSubject(WidgetSync.encodeSubject(subject)), subject, ); } }); test('a missing value is the own plan of older installs', () { expect(WidgetSync.decodeSubject(null), const OwnTimetable()); }); test('foreign and empty plans never back the widget', () { expect(WidgetSync.encodeSubject(const NoTimetable()), isNull); expect(WidgetSync.decodeSubject('child:'), isNull); }); test('background refresh follows the session', () { expect( widgetRefreshSubject(session: _student, stored: null), const OwnTimetable(), ); expect( widgetRefreshSubject( session: _guardian, stored: const ChildTimetable('a'), ), const ChildTimetable('a'), ); // Before the app published a child, a guardian has nothing to fetch. expect( widgetRefreshSubject(session: _guardian, stored: const OwnTimetable()), isNull, ); }); }); }