Files
TPSchedule/mobile/test/app/school_term_test.dart
T

142 lines
4.8 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:hepan_everyday/app/app_controller.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
import 'package:hepan_everyday/domain/app_settings.dart';
import 'package:hepan_everyday/domain/semester.dart';
import 'package:hepan_everyday/domain/school_term.dart';
import 'package:hepan_everyday/domain/exam_schedule.dart';
import 'package:hepan_everyday/domain/course.dart';
import 'package:hepan_everyday/data/json_schedule_import.dart';
import '../support/fakes.dart';
import '../domain/schedule_engine_test.dart' show course;
void main() {
test('term labels and both query URLs follow the school numbering', () {
expect(SchoolTerm(73).label, '2026-2027年秋');
expect(SchoolTerm(72).label, '2025-2026年春');
expect(SchoolTerm(71).label, '2025-2026年秋');
expect(SchoolTerm(74).label, '2026-2027年春');
expect(SchoolTerm(75).label, '2027-2028年秋');
expect(SchoolTerm(73).timetableUri.path, '/pyxx/pygl/xskbcx/index/73');
expect(SchoolTerm(72).examUri.queryParameters, {'xq': '72'});
});
test('selected school term survives settings copies and restart', () {
final saved = AppSnapshot(schoolTerm: SchoolTerm(72));
final loaded = AppSnapshot.fromJson(
saved
.copyWith(settings: saved.settings.copyWith(reminderMinutes: 30))
.toJson(),
);
expect(loaded.schoolTerm, SchoolTerm(72));
final legacy = saved.toJson()..remove('schoolTerm');
expect(AppSnapshot.fromJson(legacy).schoolTerm, isNull);
expect(() => SchoolTerm(0), throwsArgumentError);
});
test(
'previous app saves recover the actual HTML term for subsequent refresh',
() {
final legacy = AppSnapshot(
examSchedule: ExamSchedule(
semesterLabel: '2026-2027秋',
termId: '73',
records: [],
),
).toJson()..remove('schoolTerm');
expect(AppSnapshot.fromJson(legacy).schoolTerm, SchoolTerm(73));
},
);
for (final exams in [false, true]) {
test(
'successful new term ${exams ? 'exam' : 'course'} import isolates old dates and data',
() async {
final old = AppSnapshot(
schoolTerm: SchoolTerm(73),
courses: [course()],
examSchedule: ExamSchedule(
semesterLabel: 'old',
termId: '73',
records: [],
),
settings: AppSettings(
semester: Semester(startDate: DateTime(2026, 9, 7), totalWeeks: 20),
),
);
final store = MemoryStore(old);
final c = AppController(
store,
FakeNotifications(),
FakeCalendar(),
() => DateTime(2026, 10, 13),
);
await c.initialize();
if (exams) {
await c.applyExams(
ExamSchedule(
semesterLabel: SchoolTerm(72).label,
termId: '72',
records: [],
),
);
expect(c.snapshot.courses, isEmpty);
} else {
await c.applyImport(
ImportDraft(
courses: [course()],
explicitlyEmpty: false,
source: CourseSource.file,
parserVersion: 'test',
schoolTerm: SchoolTerm(72),
),
confirmedEmpty: false,
);
expect(c.snapshot.examSchedule, isNull);
}
expect(c.lastError, isNull);
expect(c.snapshot.schoolTerm, SchoolTerm(72));
expect(c.snapshot.settings.semester, isNull);
c.dispose();
},
);
}
test('same-term refresh keeps date and exams; failed term change keeps all old data', () async {
final old = AppSnapshot(
schoolTerm: SchoolTerm(73),
courses: [course()],
examSchedule: ExamSchedule(
semesterLabel: 'old',
termId: '73',
records: [],
),
settings: AppSettings(
semester: Semester(startDate: DateTime(2026, 9, 7), totalWeeks: 20),
),
);
final store = MemoryStore(old);
final c = AppController(
store,
FakeNotifications(),
FakeCalendar(),
() => DateTime(2026, 10, 13),
);
await c.initialize();
ImportDraft draft(int id) => ImportDraft(
courses: [course()],
explicitlyEmpty: false,
source: CourseSource.file,
parserVersion: 'test',
schoolTerm: SchoolTerm(id),
);
await c.applyImport(draft(73), confirmedEmpty: false);
expect(c.snapshot.settings.semester, old.settings.semester);
expect(c.snapshot.examSchedule, old.examSchedule);
store.failSave = true;
await c.applyImport(draft(72), confirmedEmpty: false);
expect(c.lastError, isNotNull);
expect(c.snapshot.schoolTerm, SchoolTerm(73));
expect(c.snapshot.settings.semester, old.settings.semester);
expect(c.snapshot.examSchedule, old.examSchedule);
c.dispose();
});
}