feat: select school terms and smooth refractive Dock motion
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
|
||||
import 'package:hepan_everyday/features/school/school_session.dart';
|
||||
import 'package:hepan_everyday/features/school/school_page_probe.dart';
|
||||
import 'package:hepan_everyday/domain/school_term.dart';
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import '../support/fake_school_web.dart';
|
||||
import 'recognized_timetable_test.dart' show fixture;
|
||||
import 'exam_adapter_test.dart' show examHtml;
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
test(
|
||||
'first online import waits for an explicit term even on a ready table',
|
||||
() async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
await session.open();
|
||||
const url = 'https://yjsjy.uestc.edu.cn/pyxx/pygl/xskbcx/index/73';
|
||||
platform.web.url = url;
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: url, authenticated: true, html: fixture());
|
||||
platform.delegate.started(url);
|
||||
platform.delegate.finished(url);
|
||||
await flushSchoolEvents();
|
||||
expect(session.pendingDraft, isNull);
|
||||
expect(session.finding, isFalse);
|
||||
expect(session.needsTermSelection, isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
test('signed out change waits for authentication then explicit choice before requesting exams', () async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
await session.openExams(term: SchoolTerm(73), chooseTerm: true);
|
||||
expect(session.needsTermSelection, isFalse);
|
||||
expect(
|
||||
platform.web.loads.single,
|
||||
'https://yjsjy.uestc.edu.cn/pyxx/jzsso/login',
|
||||
);
|
||||
const home = 'https://yjsjy.uestc.edu.cn/pyxx/home/index';
|
||||
platform.web.url = home;
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: platform.web.url!, authenticated: true);
|
||||
platform.delegate.started(home);
|
||||
platform.delegate.finished(home);
|
||||
await flushSchoolEvents();
|
||||
expect(session.needsTermSelection, isTrue);
|
||||
expect(platform.web.loads.length, 1);
|
||||
await session.selectTerm(SchoolTerm(72));
|
||||
expect(
|
||||
platform.web.loads.last,
|
||||
'https://yjsjy.uestc.edu.cn/pyxx/pygl/kskcxx/index?xq=72',
|
||||
);
|
||||
expect(session.needsTermSelection, isFalse);
|
||||
});
|
||||
|
||||
test('connected change prompts immediately without replacing imported data or navigating', () async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
session.connectionState = SchoolConnectionState.connected;
|
||||
await session.openTimetable(term: SchoolTerm(72), chooseTerm: true);
|
||||
expect(session.needsTermSelection, isTrue);
|
||||
expect(platform.web.loads, isEmpty);
|
||||
expect(session.selectedTerm, SchoolTerm(72));
|
||||
expect(session.pendingDraft, isNull);
|
||||
expect(session.termChoices.first.id, 73);
|
||||
expect(session.termChoices.last.id, 1);
|
||||
await session.selectTerm(SchoolTerm(71));
|
||||
expect(
|
||||
platform.web.loads.single,
|
||||
'https://yjsjy.uestc.edu.cn/pyxx/pygl/xskbcx/index/71',
|
||||
);
|
||||
});
|
||||
|
||||
test('timetable selected DOM term must match request before an import can become pending', () async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
session.connectionState = SchoolConnectionState.connected;
|
||||
await session.openTimetable(term: SchoolTerm(72));
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: platform.web.url!, html: fixture());
|
||||
platform.delegate.started(platform.web.url!);
|
||||
platform.delegate.finished(platform.web.url!);
|
||||
await flushSchoolEvents();
|
||||
expect(session.pendingDraft, isNull);
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: fixture().replaceFirst('value="73"', 'value="72"'),
|
||||
);
|
||||
await session.readCurrentPage();
|
||||
expect(session.pendingDraft?.schoolTerm, SchoolTerm(72));
|
||||
});
|
||||
|
||||
test(
|
||||
'exam selected DOM term must match requested query before saving',
|
||||
() async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
session.connectionState = SchoolConnectionState.connected;
|
||||
await session.openExams(term: SchoolTerm(72));
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: examHtml(),
|
||||
kind: 'exams',
|
||||
);
|
||||
platform.delegate.started(platform.web.url!);
|
||||
platform.delegate.finished(platform.web.url!);
|
||||
await flushSchoolEvents();
|
||||
expect(session.pendingExams, isNull);
|
||||
platform.web.javascript = (_) async => schoolPageEvidence(
|
||||
topUrl: platform.web.url!,
|
||||
html: examHtml().replaceFirst('value="73"', 'value="72"'),
|
||||
kind: 'exams',
|
||||
);
|
||||
await session.readCurrentPage();
|
||||
expect(session.pendingExams?.termId, '72');
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
're-authentication retains chosen term and unfinished picker intent',
|
||||
() async {
|
||||
final platform = FakeSchoolPlatform();
|
||||
WebViewPlatform.instance = platform;
|
||||
final session = SchoolSession();
|
||||
addTearDown(session.dispose);
|
||||
session.connectionState = SchoolConnectionState.connected;
|
||||
await session.openExams(term: SchoolTerm(72), chooseTerm: true);
|
||||
await session.openAuthentication();
|
||||
expect(session.needsTermSelection, isFalse);
|
||||
expect(session.selectedTerm, SchoolTerm(72));
|
||||
const home = 'https://yjsjy.uestc.edu.cn/pyxx/home/index';
|
||||
platform.web.url = home;
|
||||
platform.web.javascript = (_) async =>
|
||||
schoolPageEvidence(topUrl: home, authenticated: true);
|
||||
platform.delegate.started(home);
|
||||
platform.delegate.finished(home);
|
||||
await flushSchoolEvents();
|
||||
expect(session.needsTermSelection, isTrue);
|
||||
await session.selectTerm(SchoolTerm(71));
|
||||
await session.openAuthentication();
|
||||
expect(session.selectedTerm, SchoolTerm(71));
|
||||
expect(session.needsTermSelection, isFalse);
|
||||
platform.web.url = home;
|
||||
platform.delegate.started(home);
|
||||
platform.delegate.finished(home);
|
||||
await flushSchoolEvents();
|
||||
expect(
|
||||
platform.web.loads.last,
|
||||
'https://yjsjy.uestc.edu.cn/pyxx/pygl/kskcxx/index?xq=71',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('live dropdown choices are validated, deduplicated and sorted without private fields', () {
|
||||
final uri = Uri.parse('https://yjsjy.uestc.edu.cn/pyxx/home/index');
|
||||
final evidence = SchoolPageEvidence.decode(
|
||||
jsonEncode({
|
||||
'topUrl': uri.toString(),
|
||||
'authenticated': true,
|
||||
'pages': [],
|
||||
'terms': [72, 73, 72, 0, -1, 10000, 'private-value'],
|
||||
}),
|
||||
uri,
|
||||
);
|
||||
expect(evidence.terms.map((term) => term.id), [73, 72]);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user