88 lines
3.3 KiB
Dart
88 lines
3.3 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kouyu_english/core/courses/course_repository.dart';
|
|
import 'package:kouyu_english/core/courses/courses.dart';
|
|
import 'package:kouyu_english/core/models.dart';
|
|
|
|
/// Every level goes through the same pack structure and the same rules, so
|
|
/// the model answers every pack ships have to pass the rules it ships.
|
|
void main() {
|
|
setUpAll(() => CourseRepository.instance.load());
|
|
tearDownAll(() => CourseRepository.instance.resetForTest());
|
|
|
|
test('each core item and its dictation sentence pass its own rule', () {
|
|
final failures = <String>[];
|
|
for (final pack in CourseRepository.instance.units) {
|
|
for (final item in pack.coreItems) {
|
|
if (item.match.isEmpty) continue;
|
|
// A slot like [place] is filled by the learner, so only a fixed
|
|
// phrase can be checked as written.
|
|
if (!item.en.contains('[') && !matchesRule(item.en, item.match)) {
|
|
failures.add('${item.id} en "${item.en}"');
|
|
}
|
|
if (item.dictationSentence.isNotEmpty &&
|
|
!matchesRule(item.dictationSentence, item.match)) {
|
|
failures.add('${item.id} dictation "${item.dictationSentence}"');
|
|
}
|
|
}
|
|
}
|
|
expect(failures, isEmpty);
|
|
});
|
|
|
|
test('each writing example passes its writing rule', () {
|
|
final failures = [
|
|
for (final MapEntry(key: id, value: activity)
|
|
in segmentActivities.entries)
|
|
if (activity.writingExample.isNotEmpty &&
|
|
activity.writingRequiredTerms.isNotEmpty &&
|
|
!matchesRule(
|
|
activity.writingExample,
|
|
activity.writingRequiredTerms,
|
|
))
|
|
'$id "${activity.writingExample}"',
|
|
];
|
|
expect(failures, isEmpty);
|
|
});
|
|
|
|
test('each dialogue model answer passes its turn', () {
|
|
final failures = <String>[];
|
|
final dialogues = {
|
|
...segmentDialogues,
|
|
for (final scene in allScenes) 'scene ${scene.id}': scene.script,
|
|
};
|
|
for (final MapEntry(key: id, value: script) in dialogues.entries) {
|
|
for (var stage = 0; stage < script.hints.length; stage++) {
|
|
if (!matchesDialogueStage(script, stage, script.hints[stage])) {
|
|
failures.add('$id #${stage + 1} "${script.hints[stage]}"');
|
|
}
|
|
}
|
|
}
|
|
expect(failures, isEmpty);
|
|
});
|
|
|
|
test('assessment tasks are answerable and replacements point home', () {
|
|
final ids = {for (final pack in assessmentPacks) pack.id};
|
|
final failures = <String>[];
|
|
for (final pack in assessmentPacks) {
|
|
if (pack.replaces != null && !ids.contains(pack.replaces)) {
|
|
failures.add('${pack.id} replaces missing ${pack.replaces}');
|
|
}
|
|
for (final task in pack.tasks) {
|
|
final open =
|
|
task.skill == AssessmentSkill.writing ||
|
|
task.skill == AssessmentSkill.speaking;
|
|
if (open) {
|
|
if (task.accept.isEmpty) failures.add('${task.id} has no accept');
|
|
if (task.guide.isEmpty) failures.add('${task.id} has no guide');
|
|
} else {
|
|
final index = task.answerIndex;
|
|
if (index == null || index < 0 || index >= task.choices.length) {
|
|
failures.add('${task.id} answerIndex out of range');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
expect(a0AssessmentPacks, isNotEmpty);
|
|
expect(failures, isEmpty);
|
|
});
|
|
}
|