import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:hepan_everyday/features/school/school_exam_adapter.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
String examHtml({String time = '', String room = '', String seat = ''}) =>
'''
${['id', '序号', '学号', '姓名', '课程代码', '课程名称', '考核方式', '考生编号', '考场顺序号', '考场', '座位号', '考试时间'].map((s) => '| $s | ').join()}
${['1', '1', 'private-id', 'private-name', 'MATH', '矩阵理论', '笔试', '', '', room, seat, time].map((s) => '| $s | ').join()}
''';
void main() {
test(
'unscheduled courses and supplied arrangement fields survive saving',
() {
final draft = SchoolExamAdapter.extract(examHtml());
expect(draft.records.single.name, '矩阵理论');
expect(draft.records.single.time, '');
final arranged = SchoolExamAdapter.extract(
examHtml(time: '2026-12-01 09:00–11:00', room: '品学楼A101', seat: '16'),
);
final saved = AppSnapshot.fromJson(
AppSnapshot(examSchedule: arranged).toJson(),
);
expect(saved.examSchedule!.records.single.room, '品学楼A101');
expect(saved.examSchedule!.records.single.seat, '16');
expect(saved.examSchedule!.records.single.time, '2026-12-01 09:00–11:00');
final text = saved.toJson().toString();
expect(text, isNot(contains('private-id')));
expect(text, isNot(contains('private-name')));
},
);
test('partial exam pages cannot replace previously imported records', () {
final headerOnly = examHtml().replaceAll(
RegExp(r'.*?', dotAll: true),
'',
);
expect(() => SchoolExamAdapter.extract(headerOnly), throwsFormatException);
expect(
() =>
SchoolExamAdapter.extract(examHtml().replaceFirst('16 | ', '')),
returnsNormally,
);
expect(
() => SchoolExamAdapter.extract(
examHtml().replaceFirst('MATH | ', ''),
),
throwsFormatException,
);
expect(
() => SchoolExamAdapter.extract('登录'),
throwsFormatException,
);
});
final actual = Platform.environment['RSCHEDULE_EXAM_FIXTURE'];
if (actual != null) {
test(
'provided exam export has eight courses with no arrangements',
() async {
final draft = SchoolExamAdapter.extract(
await File(actual).readAsString(),
);
expect(draft.records.length, 8);
expect(draft.semesterLabel, '2026-2027秋');
expect(
draft.records.every(
(e) => e.time.isEmpty && e.room.isEmpty && e.seat.isEmpty,
),
isTrue,
);
},
);
}
}