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 5bf79a675be0..6e37826fd085 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 @@ -61,6 +61,23 @@ enum WKNavigationActionPolicyEnum { cancel, } +enum NSHttpCookiePropertyKeyEnum { + comment, + commentUrl, + discard, + domain, + expires, + maximumAge, + name, + originUrl, + path, + port, + sameSitePolicy, + secure, + value, + version, +} + class NSKeyValueObservingOptionsEnumData { NSKeyValueObservingOptionsEnumData({ this.value, @@ -153,6 +170,29 @@ class WKWebsiteDataTypesEnumData { } } +class NSHttpCookiePropertyKeyEnumData { + NSHttpCookiePropertyKeyEnumData({ + this.value, + }); + + NSHttpCookiePropertyKeyEnum? value; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['value'] = value == null ? null : value!.index; + return pigeonMap; + } + + static NSHttpCookiePropertyKeyEnumData decode(Object message) { + final Map pigeonMap = message as Map; + return NSHttpCookiePropertyKeyEnumData( + value: pigeonMap['value'] != null + ? NSHttpCookiePropertyKeyEnum.values[pigeonMap['value']! as int] + : null, + ); + } +} + class NSUrlRequestData { NSUrlRequestData({ required this.url, @@ -221,6 +261,28 @@ class WKUserScriptData { } } +class NSHttpCookieData { + NSHttpCookieData({ + required this.properties, + }); + + Map properties; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['properties'] = properties; + return pigeonMap; + } + + static NSHttpCookieData decode(Object message) { + final Map pigeonMap = message as Map; + return NSHttpCookieData( + properties: (pigeonMap['properties'] as Map?)! + .cast(), + ); + } +} + class _WKWebsiteDataStoreHostApiCodec extends StandardMessageCodec { const _WKWebsiteDataStoreHostApiCodec(); @override @@ -283,6 +345,31 @@ class WKWebsiteDataStoreHostApi { } } + Future createDefaultDataStore(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKWebsiteDataStoreHostApi.createDefaultDataStore', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + Future removeDataOfTypes( int arg_instanceId, List arg_dataTypes, @@ -1686,3 +1773,97 @@ class WKUIDelegateHostApi { } } } + +class _WKHttpCookieStoreHostApiCodec extends StandardMessageCodec { + const _WKHttpCookieStoreHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is NSHttpCookieData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is NSHttpCookiePropertyKeyEnumData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return NSHttpCookieData.decode(readValue(buffer)!); + + case 129: + return NSHttpCookiePropertyKeyEnumData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +class WKHttpCookieStoreHostApi { + /// Constructor for [WKHttpCookieStoreHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WKHttpCookieStoreHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WKHttpCookieStoreHostApiCodec(); + + Future createFromWebsiteDataStore( + int arg_instanceId, int arg_websiteDataStoreInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKHttpCookieStoreHostApi.createFromWebsiteDataStore', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_websiteDataStoreInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setCookie( + int arg_instanceId, NSHttpCookieData arg_cookie) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_cookie]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} 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 416e2626fc4a..23f3d5a6d79d 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 @@ -251,7 +251,11 @@ class WKWebsiteDataStore { ); factory WKWebsiteDataStore._defaultDataStore() { - throw UnimplementedError(); + final WKWebsiteDataStore websiteDataStore = WKWebsiteDataStore._(); + websiteDataStore._websiteDataStoreApi.createDefaultDataStoreForInstances( + websiteDataStore, + ); + return websiteDataStore; } /// Constructs a [WKWebsiteDataStore] that is owned by [configuration]. @@ -301,20 +305,38 @@ 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 { +class WKHttpCookieStore extends NSObject { + WKHttpCookieStore._({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : _httpCookieStoreApi = WKHttpCookieStoreHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ); + /// 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(); + factory WKHttpCookieStore.fromWebsiteDataStore( + WKWebsiteDataStore dataStore, { + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) { + final WKHttpCookieStore cookieStore = WKHttpCookieStore._( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ); + cookieStore._httpCookieStoreApi.createFromWebsiteDataStoreForInstances( + cookieStore, + dataStore, + ); + return cookieStore; } + final WKHttpCookieStoreHostApiImpl _httpCookieStoreApi; + /// Adds a cookie to the cookie store. Future setCookie(NSHttpCookie cookie) { - throw UnimplementedError(); + return _httpCookieStoreApi.setCookieForInsances(this, cookie); } } 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 1cda9d4b94c2..c55325087ac1 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 @@ -44,6 +44,73 @@ Iterable _toWKWebsiteDataTypesEnumData( }); } +extension _NSHttpCookieConverter on NSHttpCookie { + NSHttpCookieData toNSHttpCookieData() { + return NSHttpCookieData( + properties: properties.map( + (NSHttpCookiePropertyKey key, Object value) { + return MapEntry( + key.toNSHttpCookiePropertyKeyEnumData(), + value.toString(), + ); + }, + ), + ); + } +} + +extension _NSHttpCookiePropertyKeyConverter on NSHttpCookiePropertyKey { + NSHttpCookiePropertyKeyEnumData toNSHttpCookiePropertyKeyEnumData() { + late final NSHttpCookiePropertyKeyEnum value; + switch (this) { + case NSHttpCookiePropertyKey.comment: + value = NSHttpCookiePropertyKeyEnum.comment; + break; + case NSHttpCookiePropertyKey.commentUrl: + value = NSHttpCookiePropertyKeyEnum.commentUrl; + break; + case NSHttpCookiePropertyKey.discard: + value = NSHttpCookiePropertyKeyEnum.discard; + break; + case NSHttpCookiePropertyKey.domain: + value = NSHttpCookiePropertyKeyEnum.domain; + break; + case NSHttpCookiePropertyKey.expires: + value = NSHttpCookiePropertyKeyEnum.expires; + break; + case NSHttpCookiePropertyKey.maximumAge: + value = NSHttpCookiePropertyKeyEnum.maximumAge; + break; + case NSHttpCookiePropertyKey.name: + value = NSHttpCookiePropertyKeyEnum.name; + break; + case NSHttpCookiePropertyKey.originUrl: + value = NSHttpCookiePropertyKeyEnum.originUrl; + break; + case NSHttpCookiePropertyKey.path: + value = NSHttpCookiePropertyKeyEnum.path; + break; + case NSHttpCookiePropertyKey.port: + value = NSHttpCookiePropertyKeyEnum.port; + break; + case NSHttpCookiePropertyKey.sameSitePolicy: + value = NSHttpCookiePropertyKeyEnum.sameSitePolicy; + break; + case NSHttpCookiePropertyKey.secure: + value = NSHttpCookiePropertyKeyEnum.secure; + break; + case NSHttpCookiePropertyKey.value: + value = NSHttpCookiePropertyKeyEnum.value; + break; + case NSHttpCookiePropertyKey.version: + value = NSHttpCookiePropertyKeyEnum.version; + break; + } + + return NSHttpCookiePropertyKeyEnumData(value: value); + } +} + extension _WKUserScriptInjectionTimeConverter on WKUserScriptInjectionTime { WKUserScriptInjectionTimeEnumData toWKUserScriptInjectionTimeEnumData() { late final WKUserScriptInjectionTimeEnum value; @@ -132,6 +199,16 @@ class WKWebsiteDataStoreHostApiImpl extends WKWebsiteDataStoreHostApi { } } + /// Calls [createDefaultDataStore] with the ids of the provided object instances. + Future createDefaultDataStoreForInstances( + WKWebsiteDataStore instance, + ) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + await createDefaultDataStore(instanceId); + } + } + /// Calls [removeDataOfTypes] with the ids of the provided object instances. Future removeDataOfTypesForInstances( WKWebsiteDataStore instance, @@ -205,6 +282,44 @@ class WKPreferencesHostApiImpl extends WKPreferencesHostApi { } } +/// Host api implementation for [WKHttpCookieStore]. +class WKHttpCookieStoreHostApiImpl extends WKHttpCookieStoreHostApi { + /// Constructs a [WKHttpCookieStoreHostApiImpl]. + WKHttpCookieStoreHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? InstanceManager.instance, + super(binaryMessenger: binaryMessenger); + + /// Maintains instances stored to communicate with Objective-C objects. + final InstanceManager instanceManager; + + /// Calls [createFromWebsiteDataStore] with the ids of the provided object instances. + Future createFromWebsiteDataStoreForInstances( + WKHttpCookieStore instance, + WKWebsiteDataStore dataStore, + ) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + await createFromWebsiteDataStore( + instanceId, + instanceManager.getInstanceId(dataStore)!, + ); + } + } + + /// Calls [setCookie] with the ids of the provided object instances. + Future setCookieForInsances( + WKHttpCookieStore instance, + NSHttpCookie cookie, + ) { + return setCookie( + instanceManager.getInstanceId(instance)!, + cookie.toNSHttpCookieData(), + ); + } +} + /// Host api implementation for [WKUserContentController]. class WKUserContentControllerHostApiImpl extends WKUserContentControllerHostApi { 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 370149e638ff..39ff20a7743b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -117,6 +117,30 @@ class WKNavigationActionPolicyEnumData { late WKNavigationActionPolicyEnum? value; } +/// Mirror of NSHTTPCookiePropertyKey. +/// +/// See https://developer.apple.com/documentation/foundation/nshttpcookiepropertykey. +enum NSHttpCookiePropertyKeyEnum { + comment, + commentUrl, + discard, + domain, + expires, + maximumAge, + name, + originUrl, + path, + port, + sameSitePolicy, + secure, + value, + version, +} + +class NSHttpCookiePropertyKeyEnumData { + late NSHttpCookiePropertyKeyEnum? value; +} + /// Mirror of NSURLRequest. /// /// See https://developer.apple.com/documentation/foundation/nsurlrequest?language=objc. @@ -168,6 +192,13 @@ class WKScriptMessageData { late Object? body; } +/// Mirror of NSHttpCookieData. +/// +/// See https://developer.apple.com/documentation/foundation/nshttpcookie?language=objc. +class NSHttpCookieData { + late Map properties; +} + /// Mirror of WKWebsiteDataStore. /// /// See https://developer.apple.com/documentation/webkit/wkwebsitedatastore?language=objc. @@ -178,6 +209,8 @@ abstract class WKWebsiteDataStoreHostApi { int configurationInstanceId, ); + void createDefaultDataStore(int instanceId); + @async bool removeDataOfTypes( int instanceId, @@ -350,3 +383,16 @@ abstract class WKWebViewHostApi { abstract class WKUIDelegateHostApi { void create(int instanceId); } + +/// Mirror of WKHttpCookieStore. +/// +/// See https://developer.apple.com/documentation/webkit/wkhttpcookiestore?language=objc. +@HostApi(dartHostTestHandler: 'TestWKHttpCookieStoreHostApi') +abstract class WKHttpCookieStoreHostApi { + void createFromWebsiteDataStore( + int instanceId, + int websiteDataStoreInstanceId, + ); + + void setCookie(int instanceId, NSHttpCookieData cookie); +} 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 0e369a351c75..cf2030cbf893 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,6 +44,7 @@ abstract class TestWKWebsiteDataStoreHostApi { void createFromWebViewConfiguration( int instanceId, int configurationInstanceId); + void createDefaultDataStore(int instanceId); Future removeDataOfTypes( int instanceId, List dataTypes, @@ -74,6 +75,26 @@ abstract class TestWKWebsiteDataStoreHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKWebsiteDataStoreHostApi.createDefaultDataStore', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.createDefaultDataStore was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WKWebsiteDataStoreHostApi.createDefaultDataStore was null, expected non-null int.'); + api.createDefaultDataStore(arg_instanceId!); + return {}; + }); + } + } { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.WKWebsiteDataStoreHostApi.removeDataOfTypes', @@ -1306,3 +1327,91 @@ abstract class TestWKUIDelegateHostApi { } } } + +class _TestWKHttpCookieStoreHostApiCodec extends StandardMessageCodec { + const _TestWKHttpCookieStoreHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is NSHttpCookieData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is NSHttpCookiePropertyKeyEnumData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return NSHttpCookieData.decode(readValue(buffer)!); + + case 129: + return NSHttpCookiePropertyKeyEnumData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class TestWKHttpCookieStoreHostApi { + static const MessageCodec codec = + _TestWKHttpCookieStoreHostApiCodec(); + + void createFromWebsiteDataStore( + int instanceId, int websiteDataStoreInstanceId); + void setCookie(int instanceId, NSHttpCookieData cookie); + static void setup(TestWKHttpCookieStoreHostApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKHttpCookieStoreHostApi.createFromWebsiteDataStore', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.createFromWebsiteDataStore was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.createFromWebsiteDataStore was null, expected non-null int.'); + final int? arg_websiteDataStoreInstanceId = (args[1] as int?); + assert(arg_websiteDataStoreInstanceId != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.createFromWebsiteDataStore was null, expected non-null int.'); + api.createFromWebsiteDataStore( + arg_instanceId!, arg_websiteDataStoreInstanceId!); + return {}; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie was null, expected non-null int.'); + final NSHttpCookieData? arg_cookie = (args[1] as NSHttpCookieData?); + assert(arg_cookie != null, + 'Argument for dev.flutter.pigeon.WKHttpCookieStoreHostApi.setCookie was null, expected non-null NSHttpCookieData.'); + api.setCookie(arg_instanceId!, arg_cookie!); + return {}; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart index a08680940bcc..007c2bc32252 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart @@ -25,7 +25,7 @@ void main() { instanceManager = InstanceManager(); }); - group('$NSObject', () { + group('NSObject', () { late MockTestNSObjectHostApi mockPlatformHostApi; late NSObject object; 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 b8552c5d8157..7bd208eeac05 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/test/src/foundation/foundation_test.dart. +// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/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/ui_kit/ui_kit_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.dart index b6c50609552f..7db190f8192c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/ui_kit/ui_kit_test.dart @@ -31,7 +31,7 @@ void main() { instanceManager = InstanceManager(); }); - group('$UIScrollView', () { + group('UIScrollView', () { late MockTestUIScrollViewHostApi mockPlatformHostApi; late UIScrollView scrollView; @@ -87,7 +87,7 @@ void main() { }); }); - group('$UIView', () { + group('UIView', () { late MockTestUIViewHostApi mockPlatformHostApi; late UIView view; 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 aa77157efcf7..457b0450cf6f 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 @@ -14,6 +14,7 @@ import '../common/test_web_kit.pigeon.dart'; import 'web_kit_test.mocks.dart'; @GenerateMocks([ + TestWKHttpCookieStoreHostApi, TestWKNavigationDelegateHostApi, TestWKPreferencesHostApi, TestWKScriptMessageHandlerHostApi, @@ -33,7 +34,7 @@ void main() { instanceManager = InstanceManager(); }); - group('$WKWebsiteDataStore', () { + group('WKWebsiteDataStore', () { late MockTestWKWebsiteDataStoreHostApi mockPlatformHostApi; late WKWebsiteDataStore websiteDataStore; @@ -69,6 +70,16 @@ void main() { )); }); + test('createDefaultDataStore', () { + final WKWebsiteDataStore defaultDataStore = + WKWebsiteDataStore.defaultDataStore; + verify( + mockPlatformHostApi.createDefaultDataStore( + InstanceManager.instance.getInstanceId(defaultDataStore), + ), + ); + }); + test('removeDataOfTypes', () { when(mockPlatformHostApi.removeDataOfTypes( any, @@ -96,7 +107,70 @@ void main() { }); }); - group('$WKScriptMessageHandler', () { + group('WKHttpCookieStore', () { + late MockTestWKHttpCookieStoreHostApi mockPlatformHostApi; + + late WKHttpCookieStore httpCookieStore; + + late WKWebsiteDataStore websiteDataStore; + + setUp(() { + mockPlatformHostApi = MockTestWKHttpCookieStoreHostApi(); + TestWKHttpCookieStoreHostApi.setup(mockPlatformHostApi); + + TestWKWebViewConfigurationHostApi.setup( + MockTestWKWebViewConfigurationHostApi(), + ); + TestWKWebsiteDataStoreHostApi.setup( + MockTestWKWebsiteDataStoreHostApi(), + ); + + websiteDataStore = WKWebsiteDataStore.fromWebViewConfiguration( + WKWebViewConfiguration(instanceManager: instanceManager), + instanceManager: instanceManager, + ); + + httpCookieStore = WKHttpCookieStore.fromWebsiteDataStore( + websiteDataStore, + instanceManager: instanceManager, + ); + }); + + tearDown(() { + TestWKHttpCookieStoreHostApi.setup(null); + TestWKWebsiteDataStoreHostApi.setup(null); + TestWKWebViewConfigurationHostApi.setup(null); + }); + + test('createFromWebsiteDataStore', () { + verify(mockPlatformHostApi.createFromWebsiteDataStore( + instanceManager.getInstanceId(httpCookieStore), + instanceManager.getInstanceId(websiteDataStore), + )); + }); + + test('setCookie', () async { + await httpCookieStore.setCookie( + const NSHttpCookie.withProperties({ + NSHttpCookiePropertyKey.comment: 'aComment', + })); + + final NSHttpCookieData cookie = verify( + mockPlatformHostApi.setCookie( + instanceManager.getInstanceId(httpCookieStore)!, + captureAny, + ), + ).captured.single as NSHttpCookieData; + + expect( + cookie.properties.entries.single.key!.value, + NSHttpCookiePropertyKeyEnum.comment, + ); + expect(cookie.properties.entries.single.value, 'aComment'); + }); + }); + + group('WKScriptMessageHandler', () { late MockTestWKScriptMessageHandlerHostApi mockPlatformHostApi; late WKScriptMessageHandler scriptMessageHandler; @@ -121,7 +195,7 @@ void main() { }); }); - group('$WKPreferences', () { + group('WKPreferences', () { late MockTestWKPreferencesHostApi mockPlatformHostApi; late WKPreferences preferences; @@ -166,7 +240,7 @@ void main() { }); }); - group('$WKUserContentController', () { + group('WKUserContentController', () { late MockTestWKUserContentControllerHostApi mockPlatformHostApi; late WKUserContentController userContentController; @@ -254,7 +328,7 @@ void main() { }); }); - group('$WKWebViewConfiguration', () { + group('WKWebViewConfiguration', () { late MockTestWKWebViewConfigurationHostApi mockPlatformHostApi; late WKWebViewConfiguration webViewConfiguration; @@ -326,7 +400,7 @@ void main() { }); }); - group('$WKNavigationDelegate', () { + group('WKNavigationDelegate', () { late MockTestWKNavigationDelegateHostApi mockPlatformHostApi; late WKNavigationDelegate navigationDelegate; @@ -351,7 +425,7 @@ void main() { }); }); - group('$WKWebView', () { + group('WKWebView', () { late MockTestWKWebViewHostApi mockPlatformHostApi; late WKWebViewConfiguration webViewConfiguration; @@ -514,7 +588,7 @@ void main() { }); }); - group('$WKUIDelegate', () { + group('WKUIDelegate', () { late MockTestWKUIDelegateHostApi mockPlatformHostApi; late WKUIDelegate uiDelegate; 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 9629e2e62636..c98df38d7b1e 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/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. +// in webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart. // Do not manually edit this file. import 'dart:async' as _i4; @@ -20,6 +20,28 @@ import '../common/test_web_kit.pigeon.dart' as _i2; // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +/// A class which mocks [TestWKHttpCookieStoreHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestWKHttpCookieStoreHostApi extends _i1.Mock + implements _i2.TestWKHttpCookieStoreHostApi { + MockTestWKHttpCookieStoreHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + void createFromWebsiteDataStore( + int? instanceId, int? websiteDataStoreInstanceId) => + super.noSuchMethod( + Invocation.method(#createFromWebsiteDataStore, + [instanceId, websiteDataStoreInstanceId]), + returnValueForMissingStub: null); + @override + void setCookie(int? instanceId, _i3.NSHttpCookieData? cookie) => + super.noSuchMethod(Invocation.method(#setCookie, [instanceId, cookie]), + returnValueForMissingStub: null); +} + /// A class which mocks [TestWKNavigationDelegateHostApi]. /// /// See the documentation for Mockito's code generation for more information. @@ -275,6 +297,10 @@ class MockTestWKWebsiteDataStoreHostApi extends _i1.Mock [instanceId, configurationInstanceId]), returnValueForMissingStub: null); @override + void createDefaultDataStore(int? instanceId) => super.noSuchMethod( + Invocation.method(#createDefaultDataStore, [instanceId]), + returnValueForMissingStub: null); + @override _i4.Future removeDataOfTypes( int? instanceId, List<_i3.WKWebsiteDataTypesEnumData?>? dataTypes, 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 index 4529316d3159..5238c0bb2c56 100644 --- 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 @@ -11,7 +11,6 @@ import 'package:webview_flutter_platform_interface/webview_flutter_platform_inte 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'; @@ -22,7 +21,7 @@ import 'web_kit_cookie_manager_test.mocks.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - group('$WebKitWebViewWidget', () { + group('WebKitWebViewWidget', () { late MockWKWebsiteDataStore mockWebsiteDataStore; late MockWKHttpCookieStore mockWKHttpCookieStore; 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 index 88025d3d9465..a85c57f7bdb3 100644 --- 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 @@ -35,6 +35,33 @@ class MockWKHttpCookieStore extends _i1.Mock implements _i2.WKHttpCookieStore { (super.noSuchMethod(Invocation.method(#setCookie, [cookie]), returnValue: Future.value(), returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future addObserver(_i4.NSObject? observer, + {String? keyPath, Set<_i4.NSKeyValueObservingOptions>? options}) => + (super.noSuchMethod( + Invocation.method( + #addObserver, [observer], {#keyPath: keyPath, #options: options}), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future removeObserver(_i4.NSObject? observer, {String? keyPath}) => + (super.noSuchMethod( + Invocation.method(#removeObserver, [observer], {#keyPath: keyPath}), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future dispose() => + (super.noSuchMethod(Invocation.method(#dispose, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setObserveValue( + void Function( + String, _i4.NSObject, Map<_i4.NSKeyValueChangeKey, Object?>)? + observeValue) => + (super.noSuchMethod(Invocation.method(#setObserveValue, [observeValue]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); } /// A class which mocks [WKWebsiteDataStore]. 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 86ee1a99b949..8c104bdb3ee2 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 @@ -37,7 +37,7 @@ import 'web_kit_webview_widget_test.mocks.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - group('$WebKitWebViewWidget', () { + group('WebKitWebViewWidget', () { late MockWKWebView mockWebView; late MockWebViewWidgetProxy mockWebViewWidgetProxy; late MockWKUserContentController mockUserContentController; @@ -135,7 +135,7 @@ void main() { verify(mockWebView.loadRequest(request)); }); - group('$CreationParams', () { + group('CreationParams', () { testWidgets('initialUrl', (WidgetTester tester) async { await buildWidget( tester, @@ -258,7 +258,7 @@ void main() { expect(javaScriptChannels[3], 'b'); }); - group('$WebSettings', () { + group('WebSettings', () { testWidgets('javascriptMode', (WidgetTester tester) async { await buildWidget( tester, @@ -427,7 +427,7 @@ void main() { }); }); - group('$WebKitWebViewPlatformController', () { + group('WebKitWebViewPlatformController', () { testWidgets('loadFile', (WidgetTester tester) async { await buildWidget(tester); @@ -901,7 +901,7 @@ void main() { }); }); - group('$WebViewPlatformCallbacksHandler', () { + group('WebViewPlatformCallbacksHandler', () { testWidgets('onPageStarted', (WidgetTester tester) async { await buildWidget(tester); @@ -1074,7 +1074,7 @@ void main() { }); }); - group('$JavascriptChannelRegistry', () { + group('JavascriptChannelRegistry', () { testWidgets('onJavascriptChannelMessage', (WidgetTester tester) async { when(mockWebViewWidgetProxy.createScriptMessageHandler()).thenReturn( MockWKScriptMessageHandler(),