blob: 9230fc6ae1cc5189beaa8d78b65d04f78fbd6d94 [file] [log] [blame]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. 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:test/test.dart';
import 'package:unified_analytics/src/asserts.dart';
void main() {
test('Failure if client_id top level key is missing', () {
final body = <String, Object?>{};
final expectedErrorMessage = 'client_id missing from top level keys';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure if events top level key is missing', () {
final body = <String, Object?>{'client_id': 'xxxxxxx'};
final expectedErrorMessage = 'events missing from top level keys';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure if user_properties top level key is missing', () {
final body = <String, Object?>{'client_id': 'xxxxxxx', 'events': []};
final expectedErrorMessage = 'user_properties missing from top level keys';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure if more than 25 events found in events list', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[],
'user_properties': <String, Object?>{}
};
// Add more than the 25 allowed events
for (var i = 0; i < 30; i++) {
(body['events'] as List).add({'name': i});
}
final expectedErrorMessage = '25 is the max number of events';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when event name is greater than 40 chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name':
'hot_reload_timehot_reload_timehot_reload_timehot_reload_time',
'params': {'time_ms': 133, 'count': 1999000}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage = 'Limit event names to 40 chars or less\n'
'Event name: '
'"hot_reload_timehot_reload_timehot_reload_timehot_reload_time"'
' is too long';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when event name has invalid chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time!!',
'params': {'time_ms': 133, 'count': 1999000}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Event name can only have alphanumeric chars and underscores\n'
'Event name: "hot_reload_time!!" contains invalid characters';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when event name does not start with alphabetic char', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': '2hot_reload_time',
'params': {'time_ms': 133, 'count': 1999000}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Event name first char must be alphabetic char\n'
'Event name: "2hot_reload_time" must begin with a valid character';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when an event has more than 25 event params', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
// 'params': {...} SUBBING THIS VALUE OUT 30 Maps
}
],
'user_properties': <String, Object?>{}
};
final params = <String, Object?>{};
for (var i = 0; i < 30; i++) {
params['$i'] = i;
}
// Add the params to the first event in the body
((body['events'] as List).first as Map)['params'] = params;
final expectedErrorMessage = 'Limit params for each event to less than 25\n'
'Event: "hot_reload_time" has too many parameters';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when an value for event params is not a supported type (list)',
() {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {
'time_ms': 133,
// Lists and Maps are not supported
'count': <int>[1999000],
}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Values for event params have to be String, int, double, or bool\n'
'Value for "count" is not a valid type for event: "hot_reload_time"';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when an value for event params is not a supported type (map)',
() {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {
'time_ms': 133,
// Lists and Maps are not supported
'count': <int, int>{5: 20},
}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Values for event params have to be String, int, double, or bool\n'
'Value for "count" is not a valid type for event: "hot_reload_time"';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when event param name is more than 40 chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'time_mstime_mstime_mstime_mstime_mstime_ms': 133}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage = 'Limit event param names to 40 chars or less\n'
'The key: "time_mstime_mstime_mstime_mstime_mstime_ms" '
'under the event: "hot_reload_time" is too long';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure for event param name that has invalid chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'time_ns!': 133}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Event param name can only have alphanumeric chars and underscores\n'
'The key: "time_ns!" under the event: "hot_reload_time" contains '
'invalid characters';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test(
'Failure for event param name that does not start with an alphabetic char',
() {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'22time_ns': 133}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Event param name first char must be alphabetic char\n'
'The key: "22time_ns" under the event: "hot_reload_time" must begin '
'in a valid character';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
},
);
test('Failure for event param values that are greater than 100 chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {
'time_ns': 'dsfjlksdjfajlfdsfjlks'
'djfajlfdsfjlksdjfajlfdsfjlksdjfaj'
'lfdsfjlksdjfajlfdsfjlksdjfajlfdsf'
'jlksdjfajlfdsfjlksdjfajlf'
}
}
],
'user_properties': <String, Object?>{}
};
final expectedErrorMessage =
'Limit characters in event param value to 100 chars or less\n'
'Value for "time_ns" is too long, value="'
'dsfjlksdjfajlfdsfjlks'
'djfajlfdsfjlksdjfajlfdsfjlksdjfaj'
'lfdsfjlksdjfajlfdsfjlksdjfajlfdsf'
'jlksdjfajlfdsfjlksdjfajlf"';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when body has more than 25 user properties', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'time_ns': 123}
}
],
'user_properties': <String, Object?>{}
};
for (var i = 0; i < 30; i++) {
(body['user_properties']! as Map<String, Object?>)['$i'] = i;
}
final expectedErrorMessage = 'Limit user properties to 25 or less';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when user properties names are greater than 24 chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'time_ns': 123}
}
],
'user_properties': <String, Object?>{
'testtesttesttesttesttesttest': <String, Object?>{}, // TOO LONG
}
};
final expectedErrorMessage =
'Limit user property names to 24 chars or less\n'
'The user property key: "testtesttesttesttesttesttest" is too long';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Failure when user properties values are greater than 36 chars', () {
final body = <String, Object?>{
'client_id': 'xxxxxxx',
'events': <Map<String, Object?>>[
{
'name': 'hot_reload_time',
'params': {'time_ns': 123}
}
],
'user_properties': <String, Object?>{
'test': <String, Object?>{
'value': 'testtesttesttesttesttesttesttesttesttest' // TOO LONG
},
}
};
final expectedErrorMessage =
'Limit user property values to 36 chars or less\n'
'For the user property key "test", the value '
'"testtesttesttesttesttesttesttesttesttest" is too long';
expect(
() => checkBody(body),
throwsA(predicate(
(AnalyticsException e) => e.message == expectedErrorMessage,
expectedErrorMessage)));
});
test('Successful body passes all asserts', () {
final body = <String, Object?>{
'client_id': '46cc0ba6-f604-4fd9-aa2f-8a20beb24cd4',
'events': [
{
'name': 'testing',
'params': {'time_ns': 345}
}
],
'user_properties': {
'session_id': {'value': 1673466750423},
'flutter_channel': {'value': 'ey-test-channel'},
'host': {'value': 'macos'},
'flutter_version': {'value': 'Flutter 3.6.0-7.0.pre.47'},
'dart_version': {'value': 'Dart 2.19.0'},
'tool': {'value': 'flutter-tools'},
'local_time': {'value': '2023-01-11 14:53:31.471816 -0500'}
}
};
expect(() => checkBody(body), returnsNormally);
});
}