diff --git a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart index 4e279191f320..cc7dc3e4bad1 100755 --- a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart @@ -104,7 +104,10 @@ class FirebaseAnalytics extends FirebasePluginPlatform { }) async { _logEventNameValidation(name); - _assertParameterTypesAreCorrect(parameters); + _assertParameterTypesAreCorrect( + parameters, + allowItems: true, + ); await _delegate.logEvent( name: name, @@ -1385,14 +1388,37 @@ List>? _marshalItems(List? items) { } void _assertParameterTypesAreCorrect( - Map? parameters, -) => - parameters?.forEach((key, value) { + Map? parameters, { + bool allowItems = false, +}) { + if (parameters == null) { + return; + } + + for (final MapEntry(:key, :value) in parameters.entries) { + if (allowItems && key == _ITEMS) { + assert(value is List, "$_ITEMS must be a 'List'"); + + if (value is List) { + for (final item in value) { + assert( + item is Map, + "item in $_ITEMS must be a 'Map'", + ); + + if (item is Map) { + _assertParameterTypesAreCorrect(item); + } + } + } + } else { assert( value is String || value is num, "'string' OR 'number' must be set as the value of the parameter: $key. $value found instead", ); - }); + } + } +} void _assertItemsParameterTypesAreCorrect(List? items) => items?.forEach((item) { diff --git a/packages/firebase_analytics/firebase_analytics/test/firebase_analytics_test.dart b/packages/firebase_analytics/firebase_analytics/test/firebase_analytics_test.dart index f2f540c449d8..5e7ac926a84c 100755 --- a/packages/firebase_analytics/firebase_analytics/test/firebase_analytics_test.dart +++ b/packages/firebase_analytics/firebase_analytics/test/firebase_analytics_test.dart @@ -136,10 +136,74 @@ void main() { expect(analytics!.logEvent(name: 'firebase_foo'), throwsArgumentError); }); + test('reject events with wrong param value', () async { + expect( + () => analytics!.logEvent( + name: 'test_event', + parameters: { + 'a': true, + }, + ), + throwsAssertionError, + ); + }); + + test('reject events with wrong param items', () async { + expect( + () => analytics!.logEvent( + name: 'test_event', + parameters: { + 'items': true, + }, + ), + throwsAssertionError, + ); + }); + + test('reject events with wrong param items values', () async { + expect( + () => analytics!.logEvent( + name: 'test_event', + parameters: { + 'items': [ + { + 'a': 123, + }, + true, + ], + }, + ), + throwsAssertionError, + ); + }); + + test('reject events with wrong param items items', () async { + expect( + () => analytics!.logEvent( + name: 'test_event', + parameters: { + 'items': [ + { + 'items': [], + }, + ], + }, + ), + throwsAssertionError, + ); + }); + test('custom event with correct parameters', () async { await analytics!.logEvent( name: 'test-event', - parameters: {'a': 'b'}, + parameters: { + 'a': 'b', + 'items': [ + { + 'c': 'd', + }, + ], + }, ); expect( methodCallLog, @@ -148,7 +212,14 @@ void main() { 'Analytics#logEvent', arguments: { 'eventName': 'test-event', - 'parameters': {'a': 'b'}, + 'parameters': { + 'a': 'b', + 'items': [ + { + 'c': 'd', + }, + ], + }, }, ), ],