Skip to content

[package:dash_analytics] Tests for conforming to GA4 Measurement Protocol limitations #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 17, 2023
Merged
117 changes: 79 additions & 38 deletions pkgs/dash_analytics/test/dash_analytics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -651,44 +651,6 @@ $initialToolName=${ConfigHandler.dateStamp},$toolsMessageVersion
reason: 'Each event in the events array needs a params key');
});

test(
'All DashTools labels are made of characters that are letters or underscores',
() {
// Regex pattern to match only letters or underscores
final RegExp toolLabelPattern = RegExp(r'^[a-zA-Z\_]+$');
bool valid = true;
final List<DashTool> invalidTools = <DashTool>[];
for (DashTool tool in DashTool.values) {
if (!toolLabelPattern.hasMatch(tool.label)) {
valid = false;
invalidTools.add(tool);
}
}

expect(valid, true,
reason: 'All tool labels should have letters and underscores '
'as a delimiter if needed; invalid tools below\n$invalidTools');
});

test(
'All DashEvents labels are made of characters that are letters or underscores',
() {
// Regex pattern to match only letters or underscores
final RegExp eventLabelPattern = RegExp(r'^[a-zA-Z\_]+$');
bool valid = true;
final List<DashEvent> invalidEvents = <DashEvent>[];
for (DashEvent event in DashEvent.values) {
if (!eventLabelPattern.hasMatch(event.label)) {
valid = false;
invalidEvents.add(event);
}
}

expect(valid, true,
reason: 'All event labels should have letters and underscores '
'as a delimiter if needed; invalid events below\n$invalidEvents');
});

test('Check that log file is correctly persisting events sent', () {
final int numberOfEvents = max((kLogFileLength * 0.1).floor(), 5);

Expand Down Expand Up @@ -871,4 +833,83 @@ $initialToolName=${ConfigHandler.dateStamp},$toolsMessageVersion
expect(query2.flutterChannelCount, 1,
reason: 'The first instance has flutter information initialized');
});

group('Testing against Google Analytics limitations:', () {
// Link to limitations documentation
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#limitations
//
// Only the limitations specified below have been added, the other
// are not able to be validated because it will vary by each tool
//
// 1. Events can have a maximum of 25 user properties
// 2. User property names must be 24 characters or fewer
// 3. (Only for `tool` name) User property values must be 36 characters or fewer
// 4. Event names must be 40 characters or fewer, may only contain alpha-numeric
// characters and underscores, and must start with an alphabetic character
test('max 25 user properties per event', () {
final Map<String, Object> userPropPayload = userProperty.preparePayload();
const int maxUserPropKeys = 25;

expect(userPropPayload.keys.length < maxUserPropKeys, true,
reason: 'There are too many keys in the UserProperty payload');
});

test('max 24 characters for user prop keys', () {
final Map<String, Object> userPropPayload = userProperty.preparePayload();
const int maxUserPropLength = 24;

bool userPropLengthValid = true;
final List<String> invalidUserProps = <String>[];
for (String key in userPropPayload.keys) {
if (key.length > maxUserPropLength) {
userPropLengthValid = false;
invalidUserProps.add(key);
}
}
expect(userPropLengthValid, true,
reason:
'The max length for each user prop is $maxUserPropLength chars\n'
'The below keys are too long:\n$invalidUserProps');
});

test('max 36 characters for user prop values (only `tool` key)', () {
// Checks item 3
// All dash tools must be under 36 characters (and enforce each tool
// begins with a letter)
final RegExp toolLabelPattern = RegExp(r'^[a-zA-Z][a-zA-Z\_]{0,35}$');
bool dashToolLengthValid = true;
final List<DashTool> invalidTools = <DashTool>[];
for (DashTool tool in DashTool.values) {
if (!toolLabelPattern.hasMatch(tool.label)) {
dashToolLengthValid = false;
invalidTools.add(tool);
}
}

expect(dashToolLengthValid, true,
reason:
'All dash tool labels must be under 36 characters and begin with a letter\n'
'The following are invalid\n$invalidTools');
});

test('max 40 characters for event names', () {
// Check that each event name is less than 40 chars and starts with
// an alphabetic character; the entire string has to be alphanumeric
// and underscores
final RegExp eventLabelPattern =
RegExp(r'^[a-zA-Z]{1}[a-zA-Z0-9\_]{0,39}$');
bool eventValid = true;
final List<DashEvent> invalidEvents = <DashEvent>[];
for (DashEvent event in DashEvent.values) {
if (!eventLabelPattern.hasMatch(event.label)) {
eventValid = false;
invalidEvents.add(event);
}
}

expect(eventValid, true,
reason: 'All event labels should have letters and underscores '
'as a delimiter if needed; invalid events below\n$invalidEvents');
});
});
}