Update Saqel Platform: 2026-09-12 13:38:49
This commit is contained in:
@@ -7,19 +7,19 @@ import 'package:student_app/presentation/screens/virtual_labs/labs_registry.dart
|
||||
import 'package:student_app/presentation/screens/virtual_labs/subject_virtual_labs_view.dart';
|
||||
|
||||
void main() {
|
||||
test('registry covers all Grade-10 labs (44 entries, 14 subjects)', () {
|
||||
expect(Grade10LabsRegistry.all.length, 44);
|
||||
test('registry covers all Grade-10 labs (48 entries, 14 subjects)', () {
|
||||
expect(Grade10LabsRegistry.all.length, 48);
|
||||
expect(Grade10LabsRegistry.subjects.length, 14);
|
||||
final ids = Grade10LabsRegistry.all.map((e) => e.id).toSet();
|
||||
expect(ids.length, 44); // stable unique ids
|
||||
expect(ids.length, 48); // stable unique ids
|
||||
});
|
||||
|
||||
test('bound vs authoring-tool split: 28 lesson-bound, 16 standalone tools',
|
||||
test('bound vs authoring-tool split: 34 lesson-bound, 14 standalone tools',
|
||||
() {
|
||||
final bound = Grade10LabsRegistry.boundEntries;
|
||||
final tools = Grade10LabsRegistry.authoringTools;
|
||||
expect(bound.length, 28);
|
||||
expect(tools.length, 16);
|
||||
expect(bound.length, 34);
|
||||
expect(tools.length, 14);
|
||||
for (final e in bound) {
|
||||
expect(e.identity.isBound, isTrue, reason: '${e.id} should be bound');
|
||||
expect(e.isPublished, isFalse,
|
||||
@@ -50,13 +50,19 @@ void main() {
|
||||
expect(vectors!.identity.curriculumLessonId,
|
||||
'physics_10_semester_1_unit_01_lesson_02');
|
||||
|
||||
final vectorsIntro = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'physics_10_semester_1_unit_01_lesson_01');
|
||||
expect(vectorsIntro, isNotNull);
|
||||
expect(vectorsIntro!.identity.curriculumLessonId,
|
||||
'physics_10_semester_1_unit_01_lesson_01');
|
||||
|
||||
// A same-title keyword/lesson_01 guess must NOT resolve.
|
||||
expect(Grade10LabsRegistry.entryForCurriculumLessonId('lesson_01'), isNull);
|
||||
expect(
|
||||
Grade10LabsRegistry.entryForCurriculumLessonId('physics_10'), isNull);
|
||||
expect(
|
||||
Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'physics_10_semester_1_unit_01_lesson_01'),
|
||||
'physics_10_semester_1_unit_01_lesson_99'),
|
||||
isNull);
|
||||
|
||||
// Unbound authoring tools never resolve through lesson lookup.
|
||||
@@ -150,7 +156,7 @@ void main() {
|
||||
'physics_10_semester_1_unit_01_lesson_02', // vectors (bound)
|
||||
'math_10_semester_1_unit_03_lesson_02', // unit circle (bound)
|
||||
'finance_budget', // budget (tool)
|
||||
'islamic_inheritance', // inheritance (tool, no curriculum anchor)
|
||||
'islamic_10_semester_1_unit_01_lesson_02', // inheritance (bound)
|
||||
]) {
|
||||
final entry = Grade10LabsRegistry.all.firstWhere((e) => e.id == id);
|
||||
await t
|
||||
@@ -654,4 +660,139 @@ void main() {
|
||||
}
|
||||
expect(find.textContaining('توظيفُ النداءِ سليمٌ'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'arabic unit2 insha lab: concept checklist solves activity', (t) async {
|
||||
await t.binding.setSurfaceSize(const Size(900, 2600));
|
||||
addTearDown(() => t.binding.setSurfaceSize(null));
|
||||
final entry = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'arabic_10_semester_1_unit_02_lesson_06')!;
|
||||
await t.pumpWidget(MaterialApp(home: Scaffold(body: entry.builder(null))));
|
||||
await t.pump();
|
||||
// Concept toggles: 0,1,2,3,4,5 are true, 6,7 are false
|
||||
for (var i = 0; i < 6; i++) {
|
||||
await t.tap(find.byType(CupertinoSwitch).at(i));
|
||||
await t.pump();
|
||||
}
|
||||
expect(find.textContaining('مفهومُ الإنشاءِ الطّلبيِّ مثبَّتٌ'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'arabic unit2 insha lab: types selection solves activity', (t) async {
|
||||
await t.binding.setSurfaceSize(const Size(900, 2600));
|
||||
addTearDown(() => t.binding.setSurfaceSize(null));
|
||||
final entry = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'arabic_10_semester_1_unit_02_lesson_06')!;
|
||||
await t.pumpWidget(MaterialApp(home: Scaffold(body: entry.builder(null))));
|
||||
await t.pump();
|
||||
await t.tap(find.text('أنواعُ الإنشاءِ'));
|
||||
await t.pump();
|
||||
expect(find.text('النداءُ'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'physics vectors intro lab: crosswind landing and tab switching render correctly',
|
||||
(t) async {
|
||||
await t.binding.setSurfaceSize(const Size(900, 2600));
|
||||
addTearDown(() => t.binding.setSurfaceSize(null));
|
||||
final entry = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'physics_10_semester_1_unit_01_lesson_01')!;
|
||||
await t.pumpWidget(MaterialApp(home: Scaffold(body: entry.builder(null))));
|
||||
await t.pump();
|
||||
|
||||
// Verify Tab 0: Crosswind Landing
|
||||
expect(find.text('الكميات القياسية والمتجهة وتمثيلها'), findsOneWidget);
|
||||
expect(find.textContaining('السرعة الأرضية |Vg|'), findsOneWidget);
|
||||
expect(find.text('تنفيذ هبوط تجريبي على المدرج 🛬'), findsOneWidget);
|
||||
|
||||
// Tap test landing
|
||||
await t.tap(find.text('تنفيذ هبوط تجريبي على المدرج 🛬'));
|
||||
await t.pump(const Duration(milliseconds: 200));
|
||||
expect(find.text('جاري الهبوط التجريبي...'), findsOneWidget);
|
||||
|
||||
// Switch to Tab 1: Vector properties & scalar multiple
|
||||
await t.tap(find.text('تمثيل وسالب المتجه'));
|
||||
await t.pump();
|
||||
expect(find.textContaining('سالب المتجه'), findsWidgets);
|
||||
expect(find.text('المقدار |A|'), findsOneWidget);
|
||||
|
||||
// Switch to Tab 2: Dot and cross product
|
||||
await t.tap(find.text('الضرب النقطي والتقاطعي'));
|
||||
await t.pump();
|
||||
expect(find.textContaining('الضرب القياسي'), findsWidgets);
|
||||
expect(find.textContaining('الضرب المتجهي'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'physics projectile motion lab: launch, presets and vectors render correctly',
|
||||
(t) async {
|
||||
await t.binding.setSurfaceSize(const Size(900, 2600));
|
||||
addTearDown(() => t.binding.setSurfaceSize(null));
|
||||
final entry = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'physics_10_semester_1_unit_02_lesson_02')!;
|
||||
await t.pumpWidget(MaterialApp(home: Scaffold(body: entry.builder(null))));
|
||||
await t.pump();
|
||||
|
||||
// Verify main components render
|
||||
expect(find.text('حركة المقذوفات في بُعدين'), findsOneWidget);
|
||||
expect(find.textContaining('المدى R ='), findsOneWidget);
|
||||
expect(find.text('إطلاق القذيفة 🚀'), findsOneWidget);
|
||||
|
||||
// Tap angle preset 30°
|
||||
await t.tap(find.text('30°'));
|
||||
await t.pump();
|
||||
expect(find.text('30°'), findsWidgets);
|
||||
|
||||
// Launch projectile
|
||||
await t.tap(find.text('إطلاق القذيفة 🚀'));
|
||||
await t.pump(const Duration(milliseconds: 100));
|
||||
expect(find.text('إيقاف مؤقت'), findsOneWidget);
|
||||
|
||||
// Reset simulation
|
||||
await t.tap(find.text('إعادة'));
|
||||
await t.pump();
|
||||
expect(find.text('إطلاق القذيفة 🚀'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'earth air masses lab: front switching and checkpoint trigger render correctly',
|
||||
(t) async {
|
||||
await t.binding.setSurfaceSize(const Size(900, 2600));
|
||||
addTearDown(() => t.binding.setSurfaceSize(null));
|
||||
final entry = Grade10LabsRegistry.entryForCurriculumLessonId(
|
||||
'earth_sciences_10_semester_2_unit_03_lesson_01')!;
|
||||
var checkpointTriggered = false;
|
||||
await t.pumpWidget(MaterialApp(
|
||||
home: Scaffold(body: entry.builder((q, opts, idx) {
|
||||
checkpointTriggered = true;
|
||||
}))));
|
||||
await t.pump();
|
||||
|
||||
// Verify main title and front options
|
||||
expect(find.textContaining('الكتل والجبهات الهوائية'), findsWidgets);
|
||||
expect(find.text('جبهة باردة ❄️'), findsWidgets);
|
||||
expect(find.text('جبهة دافئة ☀️'), findsWidgets);
|
||||
expect(find.text('مستقرة ⏸️'), findsWidgets);
|
||||
expect(find.text('مقفلة 🌀'), findsWidgets);
|
||||
|
||||
// Tap warm front tab
|
||||
await t.tap(find.text('جبهة دافئة ☀️').first);
|
||||
await t.pump();
|
||||
|
||||
// Tap occluded front tab
|
||||
await t.tap(find.text('مقفلة 🌀').first);
|
||||
await t.pump();
|
||||
|
||||
// Tap air mass chip cT
|
||||
await t.tap(find.text('cT قارية مدارية').first);
|
||||
await t.pump();
|
||||
expect(find.textContaining('مدارية'), findsWidgets);
|
||||
|
||||
// Tap checkpoint trigger button
|
||||
await t.tap(find.text('فحص الفهم والاستيعاب').first);
|
||||
await t.pump();
|
||||
expect(checkpointTriggered, isTrue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user