diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart index 22013d2ff0cc..5bf79a675be0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart @@ -283,7 +283,7 @@ class WKWebsiteDataStoreHostApi { } } - Future removeDataOfTypes( + Future removeDataOfTypes( int arg_instanceId, List arg_dataTypes, double arg_secondsModifiedSinceEpoch) async { @@ -308,8 +308,13 @@ class WKWebsiteDataStoreHostApi { message: error['message'] as String?, details: error['details'], ); + } else if (replyMap['result'] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); } else { - return; + return (replyMap['result'] as bool?)!; } } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart index 8aa315aa10ee..1fef81d9dbaa 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart @@ -86,10 +86,85 @@ enum NSKeyValueChangeKey { /// Indicates the value of this key is the value before the attribute was changed. /// - /// https://developer.apple.com/documentation/foundation/nskeyvaluechangeoldkey?language=objc. + /// See https://developer.apple.com/documentation/foundation/nskeyvaluechangeoldkey?language=objc. oldValue, } +/// The supported keys in a cookie attributes dictionary. +/// +/// Wraps [NSHTTPCookiePropertyKey](https://developer.apple.com/documentation/foundation/nshttpcookiepropertykey). +enum NSHttpCookiePropertyKey { + /// A String object containing the comment for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiecomment. + comment, + + /// A String object containing the comment URL for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiecommenturl. + commentUrl, + + /// A String object stating whether the cookie should be discarded at the end of the session. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiediscard. + discard, + + /// A String object specifying the expiration date for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiedomain. + domain, + + /// A String object specifying the expiration date for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookieexpires. + expires, + + /// A String object containing an integer value stating how long in seconds the cookie should be kept, at most. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiemaximumage. + maximumAge, + + /// A String object containing the name of the cookie (required). + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiename. + name, + + /// A String object containing the URL that set this cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookieoriginurl. + originUrl, + + /// A String object containing the path for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiepath. + path, + + /// A String object containing comma-separated integer values specifying the ports for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookieport. + port, + + /// A String indicating the same-site policy for the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiesamesitepolicy. + sameSitePolicy, + + /// A String object indicating that the cookie should be transmitted only over secure channels. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookiesecure. + secure, + + /// A String object containing the value of the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookievalue. + value, + + /// A String object that specifies the version of the cookie. + /// + /// See https://developer.apple.com/documentation/foundation/nshttpcookieversion. + version, +} + /// A URL load request that is independent of protocol or URL scheme. /// /// Wraps [NSUrlRequest](https://developer.apple.com/documentation/foundation/nsurlrequest?language=objc). @@ -142,6 +217,18 @@ class NSError { final String localizedDescription; } +/// A representation of an HTTP cookie. +/// +/// Wraps [NSHTTPCookie](https://developer.apple.com/documentation/foundation/nshttpcookie). +@immutable +class NSHttpCookie { + /// Initializes an HTTP cookie object using the provided properties. + const NSHttpCookie.withProperties(this.properties); + + /// Properties of the new cookie object. + final Map properties; +} + /// The root class of most Objective-C class hierarchies. class NSObject { /// Constructs an [NSObject]. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart index 0703ce1267d9..416e2626fc4a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart @@ -126,6 +126,18 @@ class WKErrorCode { static const int javaScriptResultTypeIsUnsupported = 5; } +/// A record of the data that a particular website stores persistently. +/// +/// Wraps [WKWebsiteDataRecord](https://developer.apple.com/documentation/webkit/wkwebsitedatarecord?language=objc). +@immutable +class WKWebsiteDataRecord { + /// Constructs a [WKWebsiteDataRecord]. + const WKWebsiteDataRecord({required this.displayName}); + + /// Identifying information that you display to users. + final String displayName; +} + /// An object that contains information about an action that causes navigation to occur. /// /// Wraps [WKNavigationAction](https://developer.apple.com/documentation/webkit/wknavigationaction?language=objc). @@ -230,26 +242,51 @@ class WKPreferences { /// /// Wraps [WKWebsiteDataStore](https://developer.apple.com/documentation/webkit/wkwebsitedatastore?language=objc). class WKWebsiteDataStore { - /// Constructs a [WKWebsiteDataStore] that is owned by [configuration]. - @visibleForTesting - WKWebsiteDataStore.fromWebViewConfiguration( - WKWebViewConfiguration configuration, { + WKWebsiteDataStore._({ BinaryMessenger? binaryMessenger, InstanceManager? instanceManager, }) : _websiteDataStoreApi = WKWebsiteDataStoreHostApiImpl( binaryMessenger: binaryMessenger, instanceManager: instanceManager, - ) { - _websiteDataStoreApi.createFromWebViewConfigurationForInstances( - this, + ); + + factory WKWebsiteDataStore._defaultDataStore() { + throw UnimplementedError(); + } + + /// Constructs a [WKWebsiteDataStore] that is owned by [configuration]. + @visibleForTesting + factory WKWebsiteDataStore.fromWebViewConfiguration( + WKWebViewConfiguration configuration, { + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) { + final WKWebsiteDataStore websiteDataStore = WKWebsiteDataStore._( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ); + websiteDataStore._websiteDataStoreApi + .createFromWebViewConfigurationForInstances( + websiteDataStore, configuration, ); + return websiteDataStore; } + /// Default data store that stores data persistently to disk. + static final WKWebsiteDataStore defaultDataStore = + WKWebsiteDataStore._defaultDataStore(); + final WKWebsiteDataStoreHostApiImpl _websiteDataStoreApi; + /// Manages the HTTP cookies associated with a particular web view. + late final WKHttpCookieStore httpCookieStore = + WKHttpCookieStore.fromWebsiteDataStore(this); + /// Removes website data that changed after the specified date. - Future removeDataOfTypes( + /// + /// Returns whether any data was removed. + Future removeDataOfTypes( Set dataTypes, DateTime since, ) { @@ -261,6 +298,26 @@ class WKWebsiteDataStore { } } +/// An object that manages the HTTP cookies associated with a particular web view. +/// +/// Wraps [WKHTTPCookieStore](https://developer.apple.com/documentation/webkit/wkhttpcookiestore?language=objc). +class WKHttpCookieStore { + /// Constructs a [WKHttpCookieStore] that is owned by [dataStore]. + @visibleForTesting + WKHttpCookieStore.fromWebsiteDataStore( + // TODO(bparrishMines): Remove ignore on implementation. + // ignore: avoid_unused_constructor_parameters + WKWebsiteDataStore dataStore, + ) { + throw UnimplementedError(); + } + + /// Adds a cookie to the cookie store. + Future setCookie(NSHttpCookie cookie) { + throw UnimplementedError(); + } +} + /// An interface for receiving messages from JavaScript code running in a webpage. /// /// Wraps [WKScriptMessageHandler](https://developer.apple.com/documentation/webkit/wkscriptmessagehandler?language=objc) @@ -471,7 +528,6 @@ class WKWebViewConfiguration { Future setMediaTypesRequiringUserActionForPlayback( Set types, ) { - assert(types.isNotEmpty); return _webViewConfigurationApi .setMediaTypesRequiringUserActionForPlaybackForInstances( this, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 188f65cbe177..1cda9d4b94c2 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -133,7 +133,7 @@ class WKWebsiteDataStoreHostApiImpl extends WKWebsiteDataStoreHostApi { } /// Calls [removeDataOfTypes] with the ids of the provided object instances. - Future removeDataOfTypesForInstances( + Future removeDataOfTypesForInstances( WKWebsiteDataStore instance, Set dataTypes, { required double secondsModifiedSinceEpoch, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart new file mode 100644 index 000000000000..c73111d73fd0 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit_cookie_manager.dart @@ -0,0 +1,54 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; +import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart'; +import 'package:webview_flutter_wkwebview/src/web_kit/web_kit.dart'; + +/// Handles all cookie operations for the WebView platform. +class WebKitCookieManager extends WebViewCookieManagerPlatform { + /// Constructs a [WebKitCookieManager]. + WebKitCookieManager({WKWebsiteDataStore? websiteDataStore}) + : websiteDataStore = + websiteDataStore ?? WKWebsiteDataStore.defaultDataStore; + + /// Manages stored data for [WKWebView]s. + final WKWebsiteDataStore websiteDataStore; + + @override + Future clearCookies() async { + return websiteDataStore.removeDataOfTypes( + {WKWebsiteDataTypes.cookies}, + DateTime.fromMillisecondsSinceEpoch(0), + ); + } + + @override + Future setCookie(WebViewCookie cookie) { + if (!_isValidPath(cookie.path)) { + throw ArgumentError( + 'The path property for the provided cookie was not given a legal value.'); + } + + return websiteDataStore.httpCookieStore.setCookie( + NSHttpCookie.withProperties( + { + NSHttpCookiePropertyKey.name: cookie.name, + NSHttpCookiePropertyKey.value: cookie.value, + NSHttpCookiePropertyKey.domain: cookie.domain, + NSHttpCookiePropertyKey.path: cookie.path, + }, + ), + ); + } + + bool _isValidPath(String path) { + // Permitted ranges based on RFC6265bis: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + return !path.codeUnits.any( + (int char) { + return (char < 0x20 || char > 0x3A) && (char < 0x3C || char > 0x7E); + }, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index 0d5328dda8d6..370149e638ff 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -179,7 +179,7 @@ abstract class WKWebsiteDataStoreHostApi { ); @async - void removeDataOfTypes( + bool removeDataOfTypes( int instanceId, List dataTypes, double secondsModifiedSinceEpoch, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart index 78e4b9dcfd3d..0e369a351c75 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart @@ -44,7 +44,7 @@ abstract class TestWKWebsiteDataStoreHostApi { void createFromWebViewConfiguration( int instanceId, int configurationInstanceId); - Future removeDataOfTypes( + Future removeDataOfTypes( int instanceId, List dataTypes, double secondsModifiedSinceEpoch); @@ -96,9 +96,9 @@ abstract class TestWKWebsiteDataStoreHostApi { final double? arg_secondsModifiedSinceEpoch = (args[2] as double?); assert(arg_secondsModifiedSinceEpoch != null, 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes was null, expected non-null double.'); - await api.removeDataOfTypes( + final bool output = await api.removeDataOfTypes( arg_instanceId!, arg_dataTypes!, arg_secondsModifiedSinceEpoch!); - return {}; + return {'result': output}; }); } } 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 7bd208eeac05..b8552c5d8157 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,5 +1,5 @@ // Mocks generated by Mockito 5.1.0 from annotations -// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart. +// in webview_flutter_wkwebview/test/src/foundation/foundation_test.dart. // Do not manually edit this file. import 'package:mockito/mockito.dart' as _i1; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart index d51fa9793dd4..aa77157efcf7 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart @@ -70,19 +70,29 @@ void main() { }); test('removeDataOfTypes', () { - websiteDataStore.removeDataOfTypes( - {WKWebsiteDataTypes.cookies}, - DateTime.fromMillisecondsSinceEpoch(5000), + when(mockPlatformHostApi.removeDataOfTypes( + any, + any, + any, + )).thenAnswer((_) => Future.value(true)); + + expect( + websiteDataStore.removeDataOfTypes( + {WKWebsiteDataTypes.cookies}, + DateTime.fromMillisecondsSinceEpoch(5000), + ), + completion(true), ); - final WKWebsiteDataTypesEnumData typeData = + final List typeData = verify(mockPlatformHostApi.removeDataOfTypes( instanceManager.getInstanceId(websiteDataStore), captureAny, 5.0, - )).captured.single.single as WKWebsiteDataTypesEnumData; + )).captured.single.cast() + as List; - expect(typeData.value, WKWebsiteDataTypesEnum.cookies); + expect(typeData.single.value, WKWebsiteDataTypesEnum.cookies); }); }); 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 a2f16317f1fe..9629e2e62636 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,5 +1,5 @@ // Mocks generated by Mockito 5.1.0 from annotations -// in webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. +// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -275,13 +275,12 @@ class MockTestWKWebsiteDataStoreHostApi extends _i1.Mock [instanceId, configurationInstanceId]), returnValueForMissingStub: null); @override - _i4.Future removeDataOfTypes( + _i4.Future removeDataOfTypes( int? instanceId, List<_i3.WKWebsiteDataTypesEnumData?>? dataTypes, double? secondsModifiedSinceEpoch) => (super.noSuchMethod( Invocation.method(#removeDataOfTypes, [instanceId, dataTypes, secondsModifiedSinceEpoch]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i4.Future); + returnValue: Future.value(false)) as _i4.Future); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart new file mode 100644 index 000000000000..4529316d3159 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart @@ -0,0 +1,86 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; +import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart'; +import 'package:webview_flutter_wkwebview/src/web_kit/web_kit.dart'; +import 'package:webview_flutter_wkwebview/src/web_kit_cookie_manager.dart'; +import 'package:webview_flutter_wkwebview/src/web_kit_webview_widget.dart'; + +import 'web_kit_cookie_manager_test.mocks.dart'; + +@GenerateMocks([ + WKHttpCookieStore, + WKWebsiteDataStore, +]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('$WebKitWebViewWidget', () { + late MockWKWebsiteDataStore mockWebsiteDataStore; + late MockWKHttpCookieStore mockWKHttpCookieStore; + + late WebKitCookieManager cookieManager; + + setUp(() { + mockWebsiteDataStore = MockWKWebsiteDataStore(); + mockWKHttpCookieStore = MockWKHttpCookieStore(); + when(mockWebsiteDataStore.httpCookieStore) + .thenReturn(mockWKHttpCookieStore); + + cookieManager = + WebKitCookieManager(websiteDataStore: mockWebsiteDataStore); + }); + + test('clearCookies', () async { + when(mockWebsiteDataStore.removeDataOfTypes( + {WKWebsiteDataTypes.cookies}, any)) + .thenAnswer((_) => Future.value(true)); + expect(cookieManager.clearCookies(), completion(true)); + + when(mockWebsiteDataStore.removeDataOfTypes( + {WKWebsiteDataTypes.cookies}, any)) + .thenAnswer((_) => Future.value(false)); + expect(cookieManager.clearCookies(), completion(false)); + }); + + test('setCookie', () async { + await cookieManager.setCookie( + const WebViewCookie(name: 'a', value: 'b', domain: 'c', path: 'd'), + ); + + final NSHttpCookie cookie = + verify(mockWKHttpCookieStore.setCookie(captureAny)).captured.single + as NSHttpCookie; + expect( + cookie.properties, + { + NSHttpCookiePropertyKey.name: 'a', + NSHttpCookiePropertyKey.value: 'b', + NSHttpCookiePropertyKey.domain: 'c', + NSHttpCookiePropertyKey.path: 'd', + }, + ); + }); + + test('setCookie throws argument error with invalid path', () async { + expect( + () => cookieManager.setCookie( + WebViewCookie( + name: 'a', + value: 'b', + domain: 'c', + path: String.fromCharCode(0x1F), + ), + ), + throwsArgumentError, + ); + }); + }); +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart new file mode 100644 index 000000000000..88025d3d9465 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.mocks.dart @@ -0,0 +1,59 @@ +// Mocks generated by Mockito 5.1.0 from annotations +// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit_cookie_manager_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; + +import 'package:mockito/mockito.dart' as _i1; +import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart' + as _i4; +import 'package:webview_flutter_wkwebview/src/web_kit/web_kit.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +class _FakeWKHttpCookieStore_0 extends _i1.Fake + implements _i2.WKHttpCookieStore {} + +/// A class which mocks [WKHttpCookieStore]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockWKHttpCookieStore extends _i1.Mock implements _i2.WKHttpCookieStore { + MockWKHttpCookieStore() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future setCookie(_i4.NSHttpCookie? cookie) => + (super.noSuchMethod(Invocation.method(#setCookie, [cookie]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); +} + +/// A class which mocks [WKWebsiteDataStore]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockWKWebsiteDataStore extends _i1.Mock + implements _i2.WKWebsiteDataStore { + MockWKWebsiteDataStore() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.WKHttpCookieStore get httpCookieStore => + (super.noSuchMethod(Invocation.getter(#httpCookieStore), + returnValue: _FakeWKHttpCookieStore_0()) as _i2.WKHttpCookieStore); + @override + _i3.Future removeDataOfTypes( + Set<_i2.WKWebsiteDataTypes>? dataTypes, DateTime? since) => + (super.noSuchMethod( + Invocation.method(#removeDataOfTypes, [dataTypes, since]), + returnValue: Future.value(false)) as _i3.Future); +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart index 0c36f6b7de5a..86ee1a99b949 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart @@ -769,17 +769,19 @@ void main() { testWidgets('clearCache', (WidgetTester tester) async { await buildWidget(tester); + when( + mockWebsiteDataStore.removeDataOfTypes( + { + WKWebsiteDataTypes.memoryCache, + WKWebsiteDataTypes.diskCache, + WKWebsiteDataTypes.offlineWebApplicationCache, + WKWebsiteDataTypes.localStroage, + }, + DateTime.fromMillisecondsSinceEpoch(0), + ), + ).thenAnswer((_) => Future.value(false)); - await testController.clearCache(); - verify(mockWebsiteDataStore.removeDataOfTypes( - { - WKWebsiteDataTypes.memoryCache, - WKWebsiteDataTypes.diskCache, - WKWebsiteDataTypes.offlineWebApplicationCache, - WKWebsiteDataTypes.localStroage, - }, - DateTime.fromMillisecondsSinceEpoch(0), - )); + expect(testController.clearCache(), completes); }); testWidgets('addJavascriptChannels', (WidgetTester tester) async { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart index 6c34e0c72004..bc79f656b6e3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.1.0 from annotations -// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart. +// in webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart. // Do not manually edit this file. import 'dart:async' as _i5; @@ -45,14 +45,17 @@ class _FakeWKPreferences_4 extends _i1.Fake implements _i3.WKPreferences {} class _FakeWKWebsiteDataStore_5 extends _i1.Fake implements _i3.WKWebsiteDataStore {} -class _FakeWKWebView_6 extends _i1.Fake implements _i3.WKWebView {} +class _FakeWKHttpCookieStore_6 extends _i1.Fake + implements _i3.WKHttpCookieStore {} -class _FakeWKScriptMessageHandler_7 extends _i1.Fake +class _FakeWKWebView_7 extends _i1.Fake implements _i3.WKWebView {} + +class _FakeWKScriptMessageHandler_8 extends _i1.Fake implements _i3.WKScriptMessageHandler {} -class _FakeWKUIDelegate_8 extends _i1.Fake implements _i3.WKUIDelegate {} +class _FakeWKUIDelegate_9 extends _i1.Fake implements _i3.WKUIDelegate {} -class _FakeWKNavigationDelegate_9 extends _i1.Fake +class _FakeWKNavigationDelegate_10 extends _i1.Fake implements _i3.WKNavigationDelegate {} /// A class which mocks [UIScrollView]. @@ -399,12 +402,15 @@ class MockWKWebsiteDataStore extends _i1.Mock } @override - _i5.Future removeDataOfTypes( + _i3.WKHttpCookieStore get httpCookieStore => + (super.noSuchMethod(Invocation.getter(#httpCookieStore), + returnValue: _FakeWKHttpCookieStore_6()) as _i3.WKHttpCookieStore); + @override + _i5.Future removeDataOfTypes( Set<_i3.WKWebsiteDataTypes>? dataTypes, DateTime? since) => (super.noSuchMethod( Invocation.method(#removeDataOfTypes, [dataTypes, since]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i5.Future); + returnValue: Future.value(false)) as _i5.Future); } /// A class which mocks [WKUIDelegate]. @@ -534,18 +540,18 @@ class MockWebViewWidgetProxy extends _i1.Mock @override _i3.WKWebView createWebView(_i3.WKWebViewConfiguration? configuration) => (super.noSuchMethod(Invocation.method(#createWebView, [configuration]), - returnValue: _FakeWKWebView_6()) as _i3.WKWebView); + returnValue: _FakeWKWebView_7()) as _i3.WKWebView); @override _i3.WKScriptMessageHandler createScriptMessageHandler() => (super.noSuchMethod(Invocation.method(#createScriptMessageHandler, []), - returnValue: _FakeWKScriptMessageHandler_7()) + returnValue: _FakeWKScriptMessageHandler_8()) as _i3.WKScriptMessageHandler); @override _i3.WKUIDelegate createUIDelgate() => (super.noSuchMethod(Invocation.method(#createUIDelgate, []), - returnValue: _FakeWKUIDelegate_8()) as _i3.WKUIDelegate); + returnValue: _FakeWKUIDelegate_9()) as _i3.WKUIDelegate); @override _i3.WKNavigationDelegate createNavigationDelegate() => (super.noSuchMethod( Invocation.method(#createNavigationDelegate, []), - returnValue: _FakeWKNavigationDelegate_9()) as _i3.WKNavigationDelegate); + returnValue: _FakeWKNavigationDelegate_10()) as _i3.WKNavigationDelegate); }