170 lines
5.2 KiB
Dart
170 lines
5.2 KiB
Dart
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,
|
|
);
|
|
});
|
|
});
|
|
}
|