feat: add validated semester and lesson calculations
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:timezone/data/latest.dart' as tzdata;
|
||||
import 'package:hepan_everyday/domain/schedule_engine.dart';
|
||||
|
||||
Course course({
|
||||
String id = 'math',
|
||||
int day = 3,
|
||||
int first = 1,
|
||||
int last = 1,
|
||||
Set<int> weeks = const {1},
|
||||
}) => Course(
|
||||
id: id,
|
||||
name: '矩阵论',
|
||||
teacher: '示例教师',
|
||||
room: '示例教室',
|
||||
weekday: day,
|
||||
startPeriod: first,
|
||||
endPeriod: last,
|
||||
weeks: weeks,
|
||||
source: CourseSource.file,
|
||||
);
|
||||
|
||||
void main() {
|
||||
setUpAll(tzdata.initializeTimeZones);
|
||||
final term = Semester(startDate: DateTime(2026, 9, 9), totalWeeks: 5);
|
||||
test(
|
||||
'all eleven lessons produce the specified Shanghai start and end times',
|
||||
() {
|
||||
const starts = [
|
||||
510,
|
||||
560,
|
||||
620,
|
||||
670,
|
||||
870,
|
||||
920,
|
||||
980,
|
||||
1030,
|
||||
1170,
|
||||
1220,
|
||||
1270,
|
||||
];
|
||||
const ends = [555, 605, 665, 715, 915, 965, 1025, 1075, 1215, 1265, 1315];
|
||||
for (var p = 1; p <= 11; p++) {
|
||||
final result = ScheduleEngine.occurrences([
|
||||
course(first: p, last: p),
|
||||
], term);
|
||||
expect(result, hasLength(1));
|
||||
expect(
|
||||
result.single.start.hour * 60 + result.single.start.minute,
|
||||
starts[p - 1],
|
||||
);
|
||||
expect(
|
||||
result.single.end.hour * 60 + result.single.end.minute,
|
||||
ends[p - 1],
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
test('term beginning Wednesday suppresses earlier Monday', () {
|
||||
expect(
|
||||
ScheduleEngine.occurrences([
|
||||
course(day: 1, weeks: {1, 2}),
|
||||
], term).map((e) => e.start.day).toList(),
|
||||
[14],
|
||||
);
|
||||
expect(ScheduleEngine.weekNumber(term, DateTime(2026, 9, 9)), 1);
|
||||
expect(ScheduleEngine.weekNumber(term, DateTime(2026, 9, 14)), 2);
|
||||
expect(ScheduleEngine.weekNumber(term, DateTime(2026, 10, 12)), isNull);
|
||||
});
|
||||
test('odd and nonconsecutive weeks create only matching dates', () {
|
||||
expect(
|
||||
ScheduleEngine.occurrences([
|
||||
course(weeks: {1, 3, 5}),
|
||||
], term).map((e) => '${e.start.month}/${e.start.day}').toList(),
|
||||
['9/9', '9/23', '10/7'],
|
||||
);
|
||||
});
|
||||
test('Sunday and consecutive periods use one correct occurrence', () {
|
||||
final events = ScheduleEngine.occurrences([
|
||||
course(day: 7, first: 2, last: 3),
|
||||
], term);
|
||||
expect(events, hasLength(1));
|
||||
expect(events.single.start.day, 13);
|
||||
expect(events.single.start.hour, 9);
|
||||
expect(events.single.start.minute, 20);
|
||||
expect(events.single.end.hour, 11);
|
||||
expect(events.single.end.minute, 5);
|
||||
});
|
||||
test(
|
||||
'school lesson time has a fixed UTC instant regardless of device zone',
|
||||
() {
|
||||
final events = ScheduleEngine.occurrences([course()], term);
|
||||
expect(events, hasLength(1));
|
||||
expect(events.single.start.toUtc(), DateTime.utc(2026, 9, 9, 0, 30));
|
||||
},
|
||||
);
|
||||
test('overlap keeps simultaneous courses but excludes adjacent courses', () {
|
||||
final events = ScheduleEngine.occurrences([
|
||||
course(id: 'a', first: 1, last: 2),
|
||||
course(id: 'b', first: 2, last: 3),
|
||||
course(id: 'c', first: 4, last: 4),
|
||||
], term);
|
||||
expect(events, hasLength(3));
|
||||
expect(ScheduleEngine.overlaps(events[0], events[1]), isTrue);
|
||||
expect(ScheduleEngine.overlaps(events[1], events[2]), isFalse);
|
||||
});
|
||||
test('invalid lesson, weekday and week values are rejected', () {
|
||||
expect(() => course(first: 0), throwsArgumentError);
|
||||
expect(() => course(last: 12), throwsArgumentError);
|
||||
expect(() => course(day: 8), throwsArgumentError);
|
||||
expect(() => course(weeks: {0}), throwsArgumentError);
|
||||
expect(
|
||||
() => Semester(startDate: DateTime(2026), totalWeeks: 31),
|
||||
throwsArgumentError,
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user