From da974158f49754af860199b3bea1467c463e55bf Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 22 Dec 2025 14:01:27 -0300 Subject: [PATCH 1/2] Log warning for unsupported configs --- splitio_web/lib/splitio_web.dart | 16 ++++++++++++++++ splitio_web/lib/src/js_interop.dart | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/splitio_web/lib/splitio_web.dart b/splitio_web/lib/splitio_web.dart index 7a3ad91..28e4459 100644 --- a/splitio_web/lib/splitio_web.dart +++ b/splitio_web/lib/splitio_web.dart @@ -66,6 +66,22 @@ class SplitioWeb extends SplitioPlatform { this._impressionListener = sdkConfiguration.configurationMap['impressionListener']; } + + // Log warnings regarding unsupported configs. Not done in _buildConfig to reuse the factory logger + final unsupportedConfigs = [ + 'encryptionEnabled', + 'certificatePinningConfiguration', + 'persistentAttributesEnabled', + 'eventsPerPush' + ]; + for (final configName in unsupportedConfigs) { + if (sdkConfiguration.configurationMap[configName] != null) { + this._factory.settings.log.warn.callAsFunction( + this._factory.settings.log, + 'Config $configName is not supported by the Web package. This config will be ignored.' + .toJS); + } + } } return; diff --git a/splitio_web/lib/src/js_interop.dart b/splitio_web/lib/src/js_interop.dart index 312f50e..fd65946 100644 --- a/splitio_web/lib/src/js_interop.dart +++ b/splitio_web/lib/src/js_interop.dart @@ -1,7 +1,18 @@ import 'dart:js_interop'; +@JS() +extension type JS_Logger._(JSObject _) implements JSObject { + external JSFunction warn; +} + +@JS() +extension type JS_ISettings._(JSObject _) implements JSObject { + external JS_Logger log; +} + @JS() extension type JS_IBrowserSDK._(JSObject _) implements JSObject { + external JS_ISettings settings; } @JS() From eb71ff5047309ebd61a3f0b1c9913191da037df0 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Mon, 22 Dec 2025 16:31:06 -0300 Subject: [PATCH 2/2] Add tests --- splitio_web/lib/splitio_web.dart | 6 +- splitio_web/test/splitio_web_test.dart | 82 ++++++++++++++++++-------- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/splitio_web/lib/splitio_web.dart b/splitio_web/lib/splitio_web.dart index 28e4459..78dfbbe 100644 --- a/splitio_web/lib/splitio_web.dart +++ b/splitio_web/lib/splitio_web.dart @@ -69,10 +69,10 @@ class SplitioWeb extends SplitioPlatform { // Log warnings regarding unsupported configs. Not done in _buildConfig to reuse the factory logger final unsupportedConfigs = [ - 'encryptionEnabled', 'certificatePinningConfiguration', - 'persistentAttributesEnabled', - 'eventsPerPush' + 'encryptionEnabled', + 'eventsPerPush', + 'persistentAttributesEnabled' ]; for (final configName in unsupportedConfigs) { if (sdkConfiguration.configurationMap[configName] != null) { diff --git a/splitio_web/test/splitio_web_test.dart b/splitio_web/test/splitio_web_test.dart index 5c3dafe..c575765 100644 --- a/splitio_web/test/splitio_web_test.dart +++ b/splitio_web/test/splitio_web_test.dart @@ -4,6 +4,7 @@ import 'package:web/web.dart' as web; import 'package:flutter_test/flutter_test.dart'; import 'package:splitio_web/splitio_web.dart'; import 'package:splitio_web/src/js_interop.dart'; +import 'package:splitio_platform_interface/split_certificate_pinning_configuration.dart'; import 'package:splitio_platform_interface/split_configuration.dart'; import 'package:splitio_platform_interface/split_sync_config.dart'; import 'package:splitio_platform_interface/split_rollout_cache_configuration.dart'; @@ -15,19 +16,25 @@ extension on web.Window { } void main() { - String methodName = ''; - dynamic methodArguments; + final List<({String methodName, List methodArguments})> calls = []; - setUp(() { - final mockFactory = JSObject(); + final mockLog = JSObject(); + mockLog['warn'] = (JSAny? arg1) { + calls.add((methodName: 'warn', methodArguments: [arg1])); + }.toJS; + final mockSettings = JSObject(); + mockSettings['log'] = mockLog; + + final mockFactory = JSObject(); + mockFactory['settings'] = mockSettings; - final mockSplitio = JSObject(); - mockSplitio['SplitFactory'] = (JSAny? arg1) { - methodName = 'SplitFactory'; - methodArguments = [arg1]; - return mockFactory; - }.toJS; + final mockSplitio = JSObject(); + mockSplitio['SplitFactory'] = (JSAny? arg1) { + calls.add((methodName: 'SplitFactory', methodArguments: [arg1])); + return mockFactory; + }.toJS; + setUp(() { (web.window as JSObject).setProperty('splitio'.toJS, mockSplitio); }); @@ -38,9 +45,9 @@ void main() { await _platform.init( apiKey: 'api-key', matchingKey: 'matching-key', bucketingKey: null); - expect(methodName, 'SplitFactory'); + expect(calls.last.methodName, 'SplitFactory'); expect( - jsObjectToMap(methodArguments[0]), + jsObjectToMap(calls.last.methodArguments[0]), equals({ 'core': { 'authorizationKey': 'api-key', @@ -57,9 +64,9 @@ void main() { matchingKey: 'matching-key', bucketingKey: 'bucketing-key'); - expect(methodName, 'SplitFactory'); + expect(calls.last.methodName, 'SplitFactory'); expect( - jsObjectToMap(methodArguments[0]), + jsObjectToMap(calls.last.methodArguments[0]), equals({ 'core': { 'authorizationKey': 'api-key', @@ -80,9 +87,9 @@ void main() { bucketingKey: 'bucketing-key', sdkConfiguration: SplitConfiguration()); - expect(methodName, 'SplitFactory'); + expect(calls.last.methodName, 'SplitFactory'); expect( - jsObjectToMap(methodArguments[0]), + jsObjectToMap(calls.last.methodArguments[0]), equals({ 'core': { 'authorizationKey': 'api-key', @@ -101,7 +108,6 @@ void main() { })); }); - // @TODO validate warning for unsupported config options // @TODO validate full config with pluggable Browser SDK modules test('init with config: full config', () async { SplitioWeb _platform = SplitioWeb(); @@ -118,11 +124,11 @@ void main() { eventsQueueSize: 5, impressionsQueueSize: 6, eventFlushInterval: 7, - // eventsPerPush: 8, // unsupported in Web + eventsPerPush: 8, // unsupported in Web trafficType: 'user', enableDebug: false, // deprecated, logLevel has precedence streamingEnabled: false, - // persistentAttributesEnabled: true, // unsupported in Web + persistentAttributesEnabled: true, // unsupported in Web impressionListener: true, sdkEndpoint: 'sdk-endpoint', eventsEndpoint: 'events-endpoint', @@ -134,19 +140,19 @@ void main() { impressionsMode: ImpressionsMode.none, syncEnabled: true, userConsent: UserConsent.granted, - // encryptionEnabled: true, // unsupported in Web + encryptionEnabled: true, // unsupported in Web logLevel: SplitLogLevel.info, readyTimeout: 1, - // certificatePinningConfiguration: - // CertificatePinningConfiguration(), // unsupported in Web + certificatePinningConfiguration: CertificatePinningConfiguration() + .addPin('host', 'pin'), // unsupported in Web rolloutCacheConfiguration: RolloutCacheConfiguration( expirationDays: 100, clearOnInit: true, ))); - expect(methodName, 'SplitFactory'); + expect(calls[calls.length - 5].methodName, 'SplitFactory'); expect( - jsObjectToMap(methodArguments[0]), + jsObjectToMap(calls[calls.length - 5].methodArguments[0]), equals({ 'core': { 'authorizationKey': 'api-key', @@ -197,6 +203,30 @@ void main() { 'clearOnInit': true } })); + + expect(calls[calls.length - 4].methodName, 'warn'); + expect( + jsAnyToDart(calls[calls.length - 4].methodArguments[0]), + equals( + 'Config certificatePinningConfiguration is not supported by the Web package. This config will be ignored.')); + + expect(calls[calls.length - 3].methodName, 'warn'); + expect( + jsAnyToDart(calls[calls.length - 3].methodArguments[0]), + equals( + 'Config encryptionEnabled is not supported by the Web package. This config will be ignored.')); + + expect(calls[calls.length - 2].methodName, 'warn'); + expect( + jsAnyToDart(calls[calls.length - 2].methodArguments[0]), + equals( + 'Config eventsPerPush is not supported by the Web package. This config will be ignored.')); + + expect(calls[calls.length - 1].methodName, 'warn'); + expect( + jsAnyToDart(calls[calls.length - 1].methodArguments[0]), + equals( + 'Config persistentAttributesEnabled is not supported by the Web package. This config will be ignored.')); }); test('init with config: SyncConfig.flagSets', () async { @@ -209,9 +239,9 @@ void main() { sdkConfiguration: SplitConfiguration( syncConfig: SyncConfig.flagSets(['flag_set_1', 'flag_set_2']))); - expect(methodName, 'SplitFactory'); + expect(calls.last.methodName, 'SplitFactory'); expect( - jsObjectToMap(methodArguments[0]), + jsObjectToMap(calls.last.methodArguments[0]), equals({ 'core': { 'authorizationKey': 'api-key',