fix: follow undergraduate login links and capture live history URLs
This commit is contained in:
@@ -6,6 +6,51 @@ import 'package:hepan_everyday/features/school/undergraduate/page_probe.dart';
|
||||
|
||||
void main() {
|
||||
final uri = Uri.parse('https://eams.uestc.edu.cn/eams/');
|
||||
test(
|
||||
'legacy HTTP continuation upgrade is limited to the exact school system',
|
||||
() {
|
||||
expect(
|
||||
UndergraduateNavigationPolicy.secureIdentityRedirect(
|
||||
Uri.parse(
|
||||
'http://eams.uestc.edu.cn/eams/home.action?login=1&next=%2Feams%2F#continue',
|
||||
),
|
||||
).toString(),
|
||||
'https://eams.uestc.edu.cn/eams/home.action?login=1&next=%2Feams%2F#continue',
|
||||
);
|
||||
for (final address in [
|
||||
'http://eams.uestc.edu.cn.attacker.test/eams/home.action',
|
||||
'http://user@eams.uestc.edu.cn/eams/home.action',
|
||||
'http://eams.uestc.edu.cn:8080/eams/home.action',
|
||||
'http://eams.uestc.edu.cn/other/action',
|
||||
]) {
|
||||
expect(
|
||||
UndergraduateNavigationPolicy.secureIdentityRedirect(
|
||||
Uri.parse(address),
|
||||
),
|
||||
isNull,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
test(
|
||||
'decoder still requires captured URL to match the live document URL',
|
||||
() {
|
||||
expect(
|
||||
() => UndergraduatePageEvidence.decode({
|
||||
'topUrl': 'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=523',
|
||||
'authenticated': true,
|
||||
'pages': [
|
||||
{
|
||||
'kind': 'timetable',
|
||||
'url': 'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=523',
|
||||
'html': 'table',
|
||||
},
|
||||
],
|
||||
}, uri),
|
||||
throwsFormatException,
|
||||
);
|
||||
},
|
||||
);
|
||||
test(
|
||||
'navigation and capture distinguish official data from authentication',
|
||||
() {
|
||||
|
||||
@@ -31,6 +31,59 @@ void main() {
|
||||
session = UndergraduateSession();
|
||||
});
|
||||
tearDown(() => session.dispose());
|
||||
test('live URL cannot cross origin or change again during capture', () async {
|
||||
await session.openTimetable();
|
||||
final content = File('test/fixtures/school/undergraduate-timetable.html')
|
||||
.readAsStringSync();
|
||||
platform.web.javascript = (_) async => underEvidence(
|
||||
'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=523',
|
||||
html: content,
|
||||
);
|
||||
for (final address in [
|
||||
'https://other.test/eams/courseTableForStd.action',
|
||||
'https://idas.uestc.edu.cn/authserver/login',
|
||||
'http://eams.uestc.edu.cn/eams/courseTableForStd.action',
|
||||
'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=503',
|
||||
]) {
|
||||
platform.web.documentUrl = address;
|
||||
await session.readCurrentTimetable();
|
||||
expect(session.pendingDraft, isNull);
|
||||
expect(session.message, contains('未完成'));
|
||||
}
|
||||
});
|
||||
test('visible timetable imports after same-document history changes native URL does not follow', () async {
|
||||
await session.openTimetable();
|
||||
platform.web.documentUrl = 'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=523';
|
||||
final content = File('test/fixtures/school/undergraduate-timetable.html')
|
||||
.readAsStringSync();
|
||||
platform.web.javascript = (_) async => underEvidence(
|
||||
'https://eams.uestc.edu.cn/eams/courseTableForStd.action?semester.id=523',
|
||||
html: content,
|
||||
);
|
||||
platform.delegate.finished(platform.web.url!);
|
||||
await flushSchoolEvents();
|
||||
expect(session.statusLabel, '已连接');
|
||||
await session.readCurrentTimetable();
|
||||
expect(session.pendingDraft!.courses, hasLength(18));
|
||||
});
|
||||
test(
|
||||
'duplicate login continuation upgrades exact school HTTP to HTTPS',
|
||||
() async {
|
||||
await session.openTimetable();
|
||||
final decision = await platform.delegate.navigation(
|
||||
NavigationRequest(
|
||||
url: 'http://eams.uestc.edu.cn/eams/home.action?login=1',
|
||||
isMainFrame: true,
|
||||
),
|
||||
);
|
||||
expect(decision, NavigationDecision.prevent);
|
||||
expect(
|
||||
platform.web.loads.last,
|
||||
'https://eams.uestc.edu.cn/eams/home.action?login=1',
|
||||
);
|
||||
expect(session.message, isNot(contains('未完成')));
|
||||
},
|
||||
);
|
||||
test(
|
||||
'page-finished during an old probe is retried on the redirected portal',
|
||||
() async {
|
||||
|
||||
@@ -44,6 +44,7 @@ class FakeSchoolWeb extends PlatformWebViewController {
|
||||
FakeSchoolWeb(super.params) : super.implementation();
|
||||
final loads = <String>[];
|
||||
String? url;
|
||||
String? documentUrl;
|
||||
Future<Object> Function(String)? javascript;
|
||||
Future<void> Function(Uri)? request;
|
||||
@override
|
||||
@@ -63,7 +64,9 @@ class FakeSchoolWeb extends PlatformWebViewController {
|
||||
Future<String?> currentUrl() async => url;
|
||||
@override
|
||||
Future<Object> runJavaScriptReturningResult(String script) =>
|
||||
javascript?.call(script) ?? Future.value(false);
|
||||
script == 'location.href'
|
||||
? Future.value(documentUrl ?? url ?? 'about:blank')
|
||||
: javascript?.call(script) ?? Future.value(false);
|
||||
@override
|
||||
Future<void> clearCache() async {}
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user