feat: extend optional HTML feedback to graduate imports in 0.7.8
This commit is contained in:
@@ -2,6 +2,8 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:hepan_everyday/services/diagnostic_log.dart';
|
||||
import 'package:hepan_everyday/services/school_page_diagnostic.dart';
|
||||
import 'package:hepan_everyday/features/school/school_page_adapter.dart';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
|
||||
@@ -29,6 +31,132 @@ void main() {
|
||||
platform.delegate.finished(url);
|
||||
}
|
||||
|
||||
test(
|
||||
'graduate auto read retains HTML after leaving and clears on next query',
|
||||
() async {
|
||||
final cache = SchoolPageDiagnostic.instance;
|
||||
addTearDown(cache.clear);
|
||||
await session.openTimetable(term: SchoolTerm(73));
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: platform.web.url!, html: fixture());
|
||||
navigate(SchoolSession.timetableUrl.toString());
|
||||
await flushSchoolEvents();
|
||||
expect(session.pendingDraft, isNotNull);
|
||||
expect(cache.export(), isNotNull);
|
||||
session.setReadingActive(false);
|
||||
expect(cache.export(), isNotNull);
|
||||
await session.openExams(term: SchoolTerm(73));
|
||||
expect(cache.export(), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'failed graduate manual parse retains HTML and logout clears it',
|
||||
() async {
|
||||
final cache = SchoolPageDiagnostic.instance;
|
||||
addTearDown(cache.clear);
|
||||
await session.openTimetable(term: SchoolTerm(73));
|
||||
platform.web.url = SchoolSession.timetableUrl.toString();
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: fixture().replaceFirst('1-3周', '未知周'),
|
||||
);
|
||||
await expectLater(
|
||||
session.readTimetable(),
|
||||
throwsA(isA<UnsupportedSchoolLayout>()),
|
||||
);
|
||||
expect(cache.export(), isNotNull);
|
||||
expect(utf8.decode(cache.export()!), contains('未知周'));
|
||||
session.invalidateAuthentication();
|
||||
expect(cache.export(), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test('graduate exam read retains the recognized exam fragment', () async {
|
||||
final cache = SchoolPageDiagnostic.instance;
|
||||
addTearDown(cache.clear);
|
||||
await session.openExams(term: SchoolTerm(73));
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: examHtml(),
|
||||
kind: 'exams',
|
||||
);
|
||||
navigate(SchoolSession.examUrl.toString());
|
||||
await flushSchoolEvents();
|
||||
expect(session.pendingExams, isNotNull);
|
||||
expect(cache.export(), isNotNull);
|
||||
expect(
|
||||
SchoolExamAdapter.extract(utf8.decode(cache.export()!))
|
||||
.records
|
||||
.single
|
||||
.name,
|
||||
'矩阵理论',
|
||||
);
|
||||
await session.logout();
|
||||
expect(cache.export(), isNull);
|
||||
});
|
||||
|
||||
test(
|
||||
'stale graduate probe cannot replace the current diagnostic attachment',
|
||||
() async {
|
||||
final cache = SchoolPageDiagnostic.instance;
|
||||
addTearDown(cache.clear);
|
||||
await session.openTimetable(term: SchoolTerm(73));
|
||||
final old = Completer<Object>();
|
||||
platform.web.javascript = (_) => old.future;
|
||||
const home = 'https://yjsjy.uestc.edu.cn/pyxx/home/index';
|
||||
navigate(home);
|
||||
await flushSchoolEvents();
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: fixture().replaceAll('示例楼B212', '当前教室A101'),
|
||||
);
|
||||
navigate(SchoolSession.timetableUrl.toString());
|
||||
await flushSchoolEvents();
|
||||
final current = cache.export();
|
||||
expect(current, isNotNull);
|
||||
old.complete(schoolPageEvidence(topUrl: home, html: fixture()));
|
||||
await flushSchoolEvents();
|
||||
expect(cache.export(), current);
|
||||
expect(utf8.decode(cache.export()!), contains('当前教室A101'));
|
||||
},
|
||||
);
|
||||
|
||||
for (final manual in [false, true]) {
|
||||
test(
|
||||
'logout during final URL check rejects stale ${manual ? 'manual' : 'automatic'} HTML',
|
||||
() async {
|
||||
final cache = SchoolPageDiagnostic.instance;
|
||||
addTearDown(cache.clear);
|
||||
await session.openTimetable(term: SchoolTerm(73));
|
||||
final url = SchoolSession.timetableUrl.toString();
|
||||
platform.web.url = url;
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: url, html: fixture());
|
||||
final waitingUrl = Completer<String?>();
|
||||
var reads = 0;
|
||||
platform.web.readCurrentUrl = () async {
|
||||
reads++;
|
||||
if (reads == (manual ? 2 : 3)) return waitingUrl.future;
|
||||
return platform.web.url;
|
||||
};
|
||||
final operation = manual
|
||||
? expectLater(
|
||||
session.readTimetable(),
|
||||
throwsA(isA<UnsupportedSchoolLayout>()),
|
||||
)
|
||||
: session.readCurrentPage();
|
||||
await flushSchoolEvents();
|
||||
expect(reads, manual ? 2 : 3);
|
||||
session.invalidateAuthentication();
|
||||
waitingUrl.complete(url);
|
||||
await operation;
|
||||
expect(cache.export(), isNull);
|
||||
expect(session.pendingDraft, isNull);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test('login diagnostic breadcrumbs distinguish probe and network failures without raw details', () async {
|
||||
await session.openTimetable(term: SchoolTerm(73));
|
||||
session.setReadingActive(true);
|
||||
|
||||
Reference in New Issue
Block a user