Files
TPSchedule/mobile/test/widgets/undergraduate_auth_test.dart
T

135 lines
4.7 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
import 'package:hepan_everyday/features/school/undergraduate/auth_page.dart';
import 'package:hepan_everyday/features/school/undergraduate/session.dart';
import 'package:hepan_everyday/features/school/undergraduate/page_probe.dart';
import 'package:hepan_everyday/app/app_controller.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
import 'package:hepan_everyday/domain/school_term.dart';
import 'package:hepan_everyday/services/school_page_diagnostic.dart';
import '../support/fake_school_web.dart';
import '../support/fakes.dart';
import '../school/undergraduate_session_test.dart' show underEvidence;
import '../domain/schedule_engine_test.dart' show course;
void main() {
late FakeSchoolPlatform platform;
late UndergraduateSession session;
late AppController controller;
late MemoryStore store;
setUp(() {
platform = FakeSchoolPlatform();
WebViewPlatform.instance = platform;
session = UndergraduateSession();
store = MemoryStore();
});
tearDown(() {
session.dispose();
controller.dispose();
});
Future<void> open(WidgetTester tester) async {
controller = AppController(
store,
FakeNotifications(),
FakeCalendar(),
() => DateTime.utc(2026, 10, 14),
);
await controller.initialize(reconcileServices: false);
await session.openTimetable();
platform.web.javascript = (s) async => underEvidence(
platform.web.url!,
html: s == undergraduateCaptureScript
? File('test/fixtures/school/undergraduate-timetable.html')
.readAsStringSync()
: null,
);
platform.delegate.finished(platform.web.url!);
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (context) => Scaffold(
body: TextButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute<void>(
builder: (_) => UndergraduateAuthPage(
session: session,
controller: controller,
),
),
),
child: const Text('打开'),
),
),
),
),
);
await tester.tap(find.text('打开'));
await tester.pumpAndSettle();
}
testWidgets('manual importer waits for the import button and then saves', (
tester,
) async {
await open(tester);
expect(find.text('导入当前课表'), findsOneWidget);
expect(session.pendingDraft, isNull);
expect(controller.snapshot.courses, isEmpty);
await tester.tap(find.text('导入当前课表'));
await tester.pumpAndSettle();
expect(controller.snapshot.courses, hasLength(18));
expect(find.text('打开'), findsOneWidget);
SchoolPageDiagnostic.instance.clear();
});
testWidgets('cross school replacement can be cancelled without saving', (
tester,
) async {
store.value = AppSnapshot(courses: [course()], schoolTerm: SchoolTerm(73));
await open(tester);
final previous = controller.snapshot.toJson();
await tester.tap(find.text('导入当前课表'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
await tester.pump(const Duration(milliseconds: 400));
expect(find.text('确认你的课表'), findsOneWidget);
await tester.ensureVisible(find.text('取消').last);
await tester.pump();
await tester.tap(find.text('取消').last);
await tester.pumpAndSettle();
expect(controller.snapshot.toJson(), previous);
expect(find.text('导入当前课表'), findsOneWidget);
SchoolPageDiagnostic.instance.clear();
});
testWidgets('failed saving stays on the browser and can be retried', (
tester,
) async {
await open(tester);
store.failSave = true;
await tester.tap(find.text('导入当前课表'));
await tester.pumpAndSettle();
expect(controller.snapshot.courses, isEmpty);
expect(find.text('重试保存'), findsOneWidget);
store.failSave = false;
await tester.tap(find.text('重试保存'));
await tester.pumpAndSettle();
expect(controller.snapshot.courses, hasLength(18));
SchoolPageDiagnostic.instance.clear();
});
testWidgets('an obsolete deferred save does not strand a newer import', (
tester,
) async {
await open(tester);
await tester.tap(find.text('导入当前课表'));
await session.openTimetable();
await session.readCurrentTimetable();
platform.delegate.finished(platform.web.url!);
await tester.pumpAndSettle();
expect(controller.snapshot.courses, hasLength(18));
SchoolPageDiagnostic.instance.clear();
});
}