fix: follow undergraduate login links and capture live history URLs

This commit is contained in:
Codex
2026-10-15 17:17:54 +08:00
parent 79d268fd5e
commit defe7fd50e
14 changed files with 213 additions and 32 deletions
@@ -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 {