From 7eee49a4717bd7363304f718c956ce0a475e2dbc Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Thu, 21 Sep 2023 18:28:23 +0200 Subject: [PATCH] [webview_flutter_wkwebview] Adds WKWebView implementation to override console log (#4703) Adds the WKWebView implementation for registering a JavaScript console callback. This will allow developers to receive JavaScript console messages in a Dart callback. This PR contains the `webview_flutter_wkwebview` specific changes from PR #4541. Related issue: flutter/flutter#32908 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* --- .../webview_flutter_wkwebview/CHANGELOG.md | 4 + .../webview_flutter_test.dart | 42 ++++++ .../example/lib/main.dart | 52 ++++++++ .../example/pubspec.yaml | 2 +- .../lib/src/webkit_webview_controller.dart | 106 ++++++++++++++- .../webview_flutter_wkwebview/pubspec.yaml | 4 +- .../web_kit_cookie_manager_test.mocks.dart | 4 +- .../web_kit_webview_widget_test.mocks.dart | 14 +- .../src/foundation/foundation_test.mocks.dart | 4 +- .../test/src/ui_kit/ui_kit_test.mocks.dart | 4 +- .../test/src/web_kit/web_kit_test.mocks.dart | 4 +- .../test/webkit_webview_controller_test.dart | 121 ++++++++++++++++++ .../webkit_webview_controller_test.mocks.dart | 87 ++++++++++++- ...kit_webview_cookie_manager_test.mocks.dart | 4 +- .../webkit_webview_widget_test.mocks.dart | 4 +- 15 files changed, 444 insertions(+), 12 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 384b16b0653..5bb9cb3e6d1 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.0 + +* Adds support to register a callback to receive JavaScript console messages. See `WebKitWebViewController.setOnConsoleMessage`. + ## 3.7.4 * Adds pub topics to package metadata. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 66567accda3..24b96d755c4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -1196,6 +1196,48 @@ Future main() async { await expectLater(controller.currentUrl(), completion(primaryUrl)); }, ); + + group('Logging', () { + testWidgets('can receive console log messages', + (WidgetTester tester) async { + const String testPage = ''' + + + + WebResourceError test + + +

Test page

+ + + '''; + + final Completer debugMessageReceived = Completer(); + final PlatformWebViewController controller = PlatformWebViewController( + const PlatformWebViewControllerCreationParams(), + ); + unawaited(controller.setJavaScriptMode(JavaScriptMode.unrestricted)); + + await controller + .setOnConsoleMessage((JavaScriptConsoleMessage consoleMessage) { + debugMessageReceived + .complete('${consoleMessage.level.name}:${consoleMessage.message}'); + }); + + await controller.loadHtmlString(testPage); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) { + return PlatformWebViewWidget( + PlatformWebViewWidgetCreationParams(controller: controller), + ).build(context); + }, + )); + + await expectLater( + debugMessageReceived.future, completion('debug:Debug message')); + }); + }); } /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index 7367828dbed..4180650574d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -74,6 +74,40 @@ const String kTransparentBackgroundPage = ''' '''; +const String kLogExamplePage = ''' + + + +Load file or HTML string example + + + +

Local demo page

+

+ This page is used to test the forwarding of console logs to Dart. +

+ + + +
+ + + + + +
+ + + +'''; + class WebViewExample extends StatefulWidget { const WebViewExample({super.key, this.cookieManager}); @@ -202,6 +236,7 @@ enum MenuOptions { loadHtmlString, transparentBackground, setCookie, + logExample, } class SampleMenu extends StatelessWidget { @@ -262,6 +297,9 @@ class SampleMenu extends StatelessWidget { case MenuOptions.setCookie: _onSetCookie(); break; + case MenuOptions.logExample: + _onLogExample(); + break; } }, itemBuilder: (BuildContext context) => >[ @@ -318,6 +356,10 @@ class SampleMenu extends StatelessWidget { value: MenuOptions.transparentBackground, child: Text('Transparent background example'), ), + const PopupMenuItem( + value: MenuOptions.logExample, + child: Text('Log example'), + ), ], ); } @@ -466,6 +508,16 @@ class SampleMenu extends StatelessWidget { return indexFile.path; } + + Future _onLogExample() { + webViewController + .setOnConsoleMessage((JavaScriptConsoleMessage consoleMessage) { + debugPrint( + '== JS == ${consoleMessage.level.name}: ${consoleMessage.message}'); + }); + + return webViewController.loadHtmlString(kLogExamplePage); + } } class NavigationControls extends StatelessWidget { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index b214ded210b..11f6bc6092f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter path_provider: ^2.0.6 - webview_flutter_platform_interface: ^2.4.0 + webview_flutter_platform_interface: ^2.6.0 webview_flutter_wkwebview: # When depending on this package from a real application you should use: # webview_flutter: ^x.y.z diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 764ed11d6aa..5162a064b32 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; import 'dart:math'; import 'package:flutter/material.dart'; @@ -269,6 +270,7 @@ class WebKitWebViewController extends PlatformWebViewController { bool _zoomEnabled = true; WebKitNavigationDelegate? _currentNavigationDelegate; + void Function(JavaScriptConsoleMessage)? _onConsoleMessageCallback; void Function(PlatformWebViewPermissionRequest)? _onPermissionRequestCallback; WebKitWebViewControllerCreationParams get _webKitParams => @@ -327,7 +329,8 @@ class WebKitWebViewController extends PlatformWebViewController { javaScriptChannelParams is WebKitJavaScriptChannelParams ? javaScriptChannelParams : WebKitJavaScriptChannelParams.fromJavaScriptChannelParams( - javaScriptChannelParams); + javaScriptChannelParams, + ); _javaScriptChannelParams[webKitParams.name] = webKitParams; @@ -512,6 +515,104 @@ class WebKitWebViewController extends PlatformWebViewController { .addUserScript(userScript); } + /// Sets a callback that notifies the host application of any log messages + /// written to the JavaScript console. + /// + /// Because the iOS WKWebView doesn't provide a built-in way to access the + /// console, setting this callback will inject a custom [WKUserScript] which + /// overrides the JavaScript `console.debug`, `console.error`, `console.info`, + /// `console.log` and `console.warn` methods and forwards the console message + /// via a `JavaScriptChannel` to the host application. + @override + Future setOnConsoleMessage( + void Function(JavaScriptConsoleMessage consoleMessage) onConsoleMessage, + ) { + _onConsoleMessageCallback = onConsoleMessage; + + final JavaScriptChannelParams channelParams = WebKitJavaScriptChannelParams( + name: 'fltConsoleMessage', + webKitProxy: _webKitParams.webKitProxy, + onMessageReceived: (JavaScriptMessage message) { + if (_onConsoleMessageCallback == null) { + return; + } + + final Map consoleLog = + jsonDecode(message.message) as Map; + + JavaScriptLogLevel level; + switch (consoleLog['level']) { + case 'error': + level = JavaScriptLogLevel.error; + break; + case 'warning': + level = JavaScriptLogLevel.warning; + break; + case 'debug': + level = JavaScriptLogLevel.debug; + break; + case 'info': + level = JavaScriptLogLevel.info; + break; + case 'log': + default: + level = JavaScriptLogLevel.log; + break; + } + + _onConsoleMessageCallback!( + JavaScriptConsoleMessage( + level: level, + message: consoleLog['message']! as String, + ), + ); + }); + + addJavaScriptChannel(channelParams); + return _injectConsoleOverride(); + } + + Future _injectConsoleOverride() { + const WKUserScript overrideScript = WKUserScript( + ''' +function log(type, args) { + var message = Object.values(args) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v) : v.toString()) + .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars + .join(", "); + + var log = { + level: type, + message: message + }; + + window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); +} + +let originalLog = console.log; +let originalInfo = console.info; +let originalWarn = console.warn; +let originalError = console.error; +let originalDebug = console.debug; + +console.log = function() { log("log", arguments); originalLog.apply(null, arguments) }; +console.info = function() { log("info", arguments); originalInfo.apply(null, arguments) }; +console.warn = function() { log("warning", arguments); originalWarn.apply(null, arguments) }; +console.error = function() { log("error", arguments); originalError.apply(null, arguments) }; +console.debug = function() { log("debug", arguments); originalDebug.apply(null, arguments) }; + +window.addEventListener("error", function(e) { + log("error", e.message + " at " + e.filename + ":" + e.lineno + ":" + e.colno); +}); + ''', + WKUserScriptInjectionTime.atDocumentStart, + isMainFrameOnly: true, + ); + + return _webView.configuration.userContentController + .addUserScript(overrideScript); + } + // WKWebView does not support removing a single user script, so all user // scripts and all message handlers are removed instead. And the JavaScript // channels that shouldn't be removed are re-registered. Note that this @@ -537,6 +638,9 @@ class WebKitWebViewController extends PlatformWebViewController { // Zoom is disabled with a WKUserScript, so this adds it back if it was // removed above. if (!_zoomEnabled) _disableZoom(), + // Console logs are forwarded with a WKUserScript, so this adds it back + // if a console callback was registered with [setOnConsoleMessage]. + if (_onConsoleMessageCallback != null) _injectConsoleOverride(), ]); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 2c888669fa1..5f99bc9d25f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.7.4 +version: 3.8.0 environment: sdk: ">=2.19.0 <4.0.0" @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter path: ^1.8.0 - webview_flutter_platform_interface: ^2.4.0 + webview_flutter_platform_interface: ^2.6.0 dev_dependencies: build_runner: ^2.1.5 diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart index b88d686b205..5d0eede3b0e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/legacy/web_kit_cookie_manager_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart index 3c4210e8419..b0112709f2b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i5; import 'dart:math' as _i2; @@ -760,6 +762,16 @@ class MockWKWebViewConfiguration extends _i1.Mock returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override + _i5.Future setLimitsNavigationsToAppBoundDomains(bool? limit) => + (super.noSuchMethod( + Invocation.method( + #setLimitsNavigationsToAppBoundDomains, + [limit], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override _i5.Future setMediaTypesRequiringUserActionForPlayback( Set<_i4.WKAudiovisualMediaType>? types) => (super.noSuchMethod( diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart index a648fc65a4d..60cb608302b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/src/foundation/foundation_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:mockito/mockito.dart' as _i1; import 'package:webview_flutter_wkwebview/src/common/web_kit.g.dart' as _i3; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart index 65fdc41b275..515028b1d1e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i4; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart index e92132bdeb2..e46a4ce989b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index 2cd20e0f688..a22e2f6a324 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -28,6 +28,7 @@ import 'webkit_webview_controller_test.mocks.dart'; WKWebsiteDataStore, WKWebView, WKWebViewConfiguration, + WKScriptMessageHandler, ]) void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -98,6 +99,7 @@ void main() { requestMediaCapturePermission: requestMediaCapturePermission, ); }, + createScriptMessageHandler: WKScriptMessageHandler.detached, ), instanceManager: instanceManager, ); @@ -1163,6 +1165,125 @@ void main() { await controller.setInspectable(true); verify(mockWebView.setInspectable(true)); }); + + group('Console logging', () { + test('setConsoleLogCallback should inject the correct JavaScript', + () async { + final MockWKUserContentController mockUserContentController = + MockWKUserContentController(); + final WebKitWebViewController controller = createControllerWithMocks( + mockUserContentController: mockUserContentController, + ); + + await controller + .setOnConsoleMessage((JavaScriptConsoleMessage message) {}); + + final List capturedScripts = + verify(mockUserContentController.addUserScript(captureAny)) + .captured + .toList(); + final WKUserScript messageHandlerScript = + capturedScripts[0] as WKUserScript; + final WKUserScript overrideConsoleScript = + capturedScripts[1] as WKUserScript; + + expect(messageHandlerScript.isMainFrameOnly, isFalse); + expect(messageHandlerScript.injectionTime, + WKUserScriptInjectionTime.atDocumentStart); + expect(messageHandlerScript.source, + 'window.fltConsoleMessage = webkit.messageHandlers.fltConsoleMessage;'); + + expect(overrideConsoleScript.isMainFrameOnly, isTrue); + expect(overrideConsoleScript.injectionTime, + WKUserScriptInjectionTime.atDocumentStart); + expect(overrideConsoleScript.source, ''' +function log(type, args) { + var message = Object.values(args) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v) : v.toString()) + .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars + .join(", "); + + var log = { + level: type, + message: message + }; + + window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); +} + +let originalLog = console.log; +let originalInfo = console.info; +let originalWarn = console.warn; +let originalError = console.error; +let originalDebug = console.debug; + +console.log = function() { log("log", arguments); originalLog.apply(null, arguments) }; +console.info = function() { log("info", arguments); originalInfo.apply(null, arguments) }; +console.warn = function() { log("warning", arguments); originalWarn.apply(null, arguments) }; +console.error = function() { log("error", arguments); originalError.apply(null, arguments) }; +console.debug = function() { log("debug", arguments); originalDebug.apply(null, arguments) }; + +window.addEventListener("error", function(e) { + log("error", e.message + " at " + e.filename + ":" + e.lineno + ":" + e.colno); +}); + '''); + }); + + test('setConsoleLogCallback should parse levels correctly', () async { + final MockWKUserContentController mockUserContentController = + MockWKUserContentController(); + final WebKitWebViewController controller = createControllerWithMocks( + mockUserContentController: mockUserContentController, + ); + + final Map logs = + {}; + await controller.setOnConsoleMessage( + (JavaScriptConsoleMessage message) => + logs[message.level] = message.message); + + final List capturedParameters = verify( + mockUserContentController.addScriptMessageHandler( + captureAny, any)) + .captured + .toList(); + final WKScriptMessageHandler scriptMessageHandler = + capturedParameters[0] as WKScriptMessageHandler; + + scriptMessageHandler.didReceiveScriptMessage( + mockUserContentController, + const WKScriptMessage( + name: 'test', + body: '{"level": "debug", "message": "Debug message"}')); + scriptMessageHandler.didReceiveScriptMessage( + mockUserContentController, + const WKScriptMessage( + name: 'test', + body: '{"level": "error", "message": "Error message"}')); + scriptMessageHandler.didReceiveScriptMessage( + mockUserContentController, + const WKScriptMessage( + name: 'test', + body: '{"level": "info", "message": "Info message"}')); + scriptMessageHandler.didReceiveScriptMessage( + mockUserContentController, + const WKScriptMessage( + name: 'test', + body: '{"level": "log", "message": "Log message"}')); + scriptMessageHandler.didReceiveScriptMessage( + mockUserContentController, + const WKScriptMessage( + name: 'test', + body: '{"level": "warning", "message": "Warning message"}')); + + expect(logs.length, 5); + expect(logs[JavaScriptLogLevel.debug], 'Debug message'); + expect(logs[JavaScriptLogLevel.error], 'Error message'); + expect(logs[JavaScriptLogLevel.info], 'Info message'); + expect(logs[JavaScriptLogLevel.log], 'Log message'); + expect(logs[JavaScriptLogLevel.warning], 'Warning message'); + }); + }); }); group('WebKitJavaScriptChannelParams', () { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart index 84f1587f45a..7624a8724d9 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/webkit_webview_controller_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i6; import 'dart:math' as _i3; @@ -119,6 +121,17 @@ class _FakeWKWebView_8 extends _i1.SmartFake implements _i5.WKWebView { ); } +class _FakeWKScriptMessageHandler_9 extends _i1.SmartFake + implements _i5.WKScriptMessageHandler { + _FakeWKScriptMessageHandler_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [NSUrl]. /// /// See the documentation for Mockito's code generation for more information. @@ -924,3 +937,75 @@ class MockWKWebViewConfiguration extends _i1.Mock returnValueForMissingStub: _i6.Future.value(), ) as _i6.Future); } + +/// A class which mocks [WKScriptMessageHandler]. +/// +/// See the documentation for Mockito's code generation for more information. +// ignore: must_be_immutable +class MockWKScriptMessageHandler extends _i1.Mock + implements _i5.WKScriptMessageHandler { + MockWKScriptMessageHandler() { + _i1.throwOnMissingStub(this); + } + + @override + void Function( + _i5.WKUserContentController, + _i5.WKScriptMessage, + ) get didReceiveScriptMessage => (super.noSuchMethod( + Invocation.getter(#didReceiveScriptMessage), + returnValue: ( + _i5.WKUserContentController userContentController, + _i5.WKScriptMessage message, + ) {}, + ) as void Function( + _i5.WKUserContentController, + _i5.WKScriptMessage, + )); + @override + _i5.WKScriptMessageHandler copy() => (super.noSuchMethod( + Invocation.method( + #copy, + [], + ), + returnValue: _FakeWKScriptMessageHandler_9( + this, + Invocation.method( + #copy, + [], + ), + ), + ) as _i5.WKScriptMessageHandler); + @override + _i6.Future addObserver( + _i2.NSObject? observer, { + required String? keyPath, + required Set<_i2.NSKeyValueObservingOptions>? options, + }) => + (super.noSuchMethod( + Invocation.method( + #addObserver, + [observer], + { + #keyPath: keyPath, + #options: options, + }, + ), + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); + @override + _i6.Future removeObserver( + _i2.NSObject? observer, { + required String? keyPath, + }) => + (super.noSuchMethod( + Invocation.method( + #removeObserver, + [observer], + {#keyPath: keyPath}, + ), + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart index 95818c3cefa..042631982cf 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/webkit_webview_cookie_manager_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart index b171e28a3bf..8d104c1ed79 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.mocks.dart @@ -1,7 +1,9 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.1 from annotations // in webview_flutter_wkwebview/test/webkit_webview_widget_test.dart. // Do not manually edit this file. +// @dart=2.19 + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3;