import 'dart:async'; import 'package:flutter/widgets.dart'; import 'dart:convert'; import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; class FakeSchoolPlatform extends WebViewPlatform { @override PlatformWebViewWidget createPlatformWebViewWidget( PlatformWebViewWidgetCreationParams params, ) => FakeSchoolWidget(params); int controllerCreations = 0; late FakeSchoolWeb web; late FakeSchoolDelegate delegate; final cookies = FakeSchoolCookies(); @override PlatformWebViewController createPlatformWebViewController( PlatformWebViewControllerCreationParams params, ) { controllerCreations++; return web = FakeSchoolWeb(params); } @override PlatformNavigationDelegate createPlatformNavigationDelegate( PlatformNavigationDelegateCreationParams params, ) => delegate = FakeSchoolDelegate(params); @override PlatformWebViewCookieManager createPlatformCookieManager( PlatformWebViewCookieManagerCreationParams params, ) => cookies; } class FakeSchoolWidget extends PlatformWebViewWidget { FakeSchoolWidget(super.params) : super.implementation(); @override Widget build(BuildContext context) => const SizedBox.expand(key: Key('fake-school-browser')); } class FakeSchoolWeb extends PlatformWebViewController { FakeSchoolWeb(super.params) : super.implementation(); final loads = []; String? url; String? documentUrl; Future Function(String)? javascript; Future Function(Uri)? request; Future Function()? readCurrentUrl; @override Future setJavaScriptMode(JavaScriptMode mode) async {} @override Future setPlatformNavigationDelegate( PlatformNavigationDelegate handler, ) async {} @override Future loadRequest(LoadRequestParams params) async { url = params.uri.toString(); loads.add(url!); await request?.call(params.uri); } @override Future currentUrl() => readCurrentUrl?.call() ?? Future.value(url); @override Future runJavaScriptReturningResult(String script) => script == 'location.href' ? Future.value(documentUrl ?? url ?? 'about:blank') : javascript?.call(script) ?? Future.value(false); @override Future clearCache() async {} @override Future clearLocalStorage() async {} @override Future loadHtmlString(String html, {String? baseUrl}) async { url = 'about:blank'; loads.add('about:blank'); } } class FakeSchoolDelegate extends PlatformNavigationDelegate { FakeSchoolDelegate(super.params) : super.implementation(); late PageEventCallback started, finished; late WebResourceErrorCallback resourceError; late NavigationRequestCallback navigation; @override Future setOnNavigationRequest( NavigationRequestCallback callback, ) async { navigation = callback; } @override Future setOnPageStarted(PageEventCallback callback) async { started = callback; } @override Future setOnPageFinished(PageEventCallback callback) async { finished = callback; } @override Future setOnWebResourceError(WebResourceErrorCallback callback) async { resourceError = callback; } @override Future setOnHttpError(HttpResponseErrorCallback callback) async {} } class FakeSchoolCookies extends PlatformWebViewCookieManager { FakeSchoolCookies() : super.implementation(const PlatformWebViewCookieManagerCreationParams()); Completer? clearing; bool fail = false; @override Future clearCookies() => fail ? Future.error(StateError('native cookies')) : clearing?.future ?? Future.value(true); } Future flushSchoolEvents() async { for (var i = 0; i < 12; i++) { await Future.delayed(Duration.zero); } } String schoolPageEvidence({ required String topUrl, bool authenticated = false, String? html, String? documentUrl, String kind = 'timetable', }) => jsonEncode({ 'topUrl': topUrl, 'authenticated': authenticated, 'pages': [ if (html != null) {'kind': kind, 'url': documentUrl ?? topUrl, 'html': html}, ], });