Skip to content
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

feat: match android type support for custom attributes #157

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Example/mParticleExample/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ - (void)logEvent {
MPEvent *event = [[MPEvent alloc] initWithName:@"Event Name" type:MPEventTypeTransaction];

// Add attributes to an event
NSDate *currentDate = [NSDate dateWithTimeIntervalSinceNow:0];
event.customAttributes = @{@"A_String_Key":@"A String Value",
@"A Number Key":@(42),
@"A Date Key":[NSDate date]};
@"A Number Key":@(42),
@"A Date Key":[NSDate date],
@"test Dictionary": @{@"test1": @"test", @"test2": @2, @"test3": currentDate}};

// Custom flags are attributes sent to mParticle, but not forwarded to other providers
[event addCustomFlag:@"Top Secret" withKey:@"Not_forwarded_to_providers"];
Expand Down
81 changes: 77 additions & 4 deletions UnitTests/MPEventTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ - (void)testInstance {
}

NSDictionary *eventInfo = @{@"speed":@25,
@"modality":@"sprinting"};
@"modality":@"sprinting",
@"stats":@{}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question, especially for unit test, maybe we should have an empty dictionary, then another key with a dictionary with one or two k/v pairs, then finally a key with a dictionary that contains a dictionary in one of its values (nested dictionary) for better coverage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test case for dictionary with values and one with dictionary values in the dictionary


event.customAttributes = eventInfo;
event.category = @"Olympic Games";
Expand Down Expand Up @@ -86,8 +87,8 @@ - (void)testInstance {
XCTAssertNotNil(event.customAttributes, @"Should not have been nil.");
XCTAssertNotNil(event.info, @"Should not have been nil.");

XCTAssertEqual(event.customAttributes.count, 2, @"Should have been two values in the customAttributes dictionary.");
XCTAssertEqual(event.info.count, 2, @"Should have been two values in the info dictionary.");
XCTAssertEqual(event.customAttributes.count, 3, @"Should have been three values in the customAttributes dictionary.");
XCTAssertEqual(event.info.count, 3, @"Should have been three values in the info dictionary.");

NSDictionary *copyEventInfo = [eventInfo copy];
event.customAttributes = copyEventInfo;
Expand Down Expand Up @@ -163,7 +164,78 @@ - (void)testDictionaryRepresentation {
MPEvent *event = [[MPEvent alloc] initWithName:@"Dinosaur Run" type:MPEventTypeOther];
event.duration = eventDuration;
event.customAttributes = @{@"speed":@25,
@"modality":@"sprinting"};
@"modality":@"sprinting",
@"stats":@{}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment re: other dictionary test cases

event.category = @"Olympic Games";

[session incrementCounter];
[session incrementCounter];
[session incrementCounter];

NSDictionary *dictionaryRepresentation = [event dictionaryRepresentation];
XCTAssertNotNil(dictionaryRepresentation, @"Dictionary representation should not have been nil.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventNameKey], @"Dinosaur Run", @"Name is not correct.");
XCTAssertNotNil(dictionaryRepresentation[kMPEventStartTimestamp], @"Start timestamp should not have been nil.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventTypeKey], @"Other", @"Type should have been 'Other.'");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventLength], @2, @"Length should have been 2.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventCounterKey], @3, @"Event counter should have been 3.");

NSDictionary *attributes = @{@"speed":@25,
@"modality":@"sprinting",
@"stats":@{},
BrandonStalnaker marked this conversation as resolved.
Show resolved Hide resolved
@"$Category":@"Olympic Games",
@"EventLength":eventDuration};
XCTAssertEqualObjects(dictionaryRepresentation[kMPAttributesKey], attributes, @"Attributes are not being set correctly.");
}

- (void)testDictionaryRepresentationWithDictionaryValues {
MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]];
MPStateMachine *stateMachine = [MParticle sharedInstance].stateMachine;
stateMachine.currentSession = session;

NSNumber *eventDuration = @2;

MPEvent *event = [[MPEvent alloc] initWithName:@"Dinosaur Run" type:MPEventTypeOther];
event.duration = eventDuration;
NSDate *currentDate = [NSDate dateWithTimeIntervalSinceNow:0];
event.customAttributes = @{@"speed":@25,
@"modality":@"sprinting",
@"stats":@{@"test1": @"test", @"test2": @2, @"test3": currentDate}};
event.category = @"Olympic Games";

[session incrementCounter];
[session incrementCounter];
[session incrementCounter];

NSDictionary *dictionaryRepresentation = [event dictionaryRepresentation];
XCTAssertNotNil(dictionaryRepresentation, @"Dictionary representation should not have been nil.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventNameKey], @"Dinosaur Run", @"Name is not correct.");
XCTAssertNotNil(dictionaryRepresentation[kMPEventStartTimestamp], @"Start timestamp should not have been nil.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventTypeKey], @"Other", @"Type should have been 'Other.'");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventLength], @2, @"Length should have been 2.");
XCTAssertEqualObjects(dictionaryRepresentation[kMPEventCounterKey], @3, @"Event counter should have been 3.");

NSDictionary *attributes = @{@"speed":@25,
@"modality":@"sprinting",
@"stats":@{@"test1": @"test", @"test2": @2, @"test3": currentDate},
@"$Category":@"Olympic Games",
@"EventLength":eventDuration};
XCTAssertEqualObjects(dictionaryRepresentation[kMPAttributesKey], attributes, @"Attributes are not being set correctly.");
}

- (void)testDictionaryRepresentationWithDictionaryValuesContainingDictionary {
MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]];
MPStateMachine *stateMachine = [MParticle sharedInstance].stateMachine;
stateMachine.currentSession = session;

NSNumber *eventDuration = @2;

MPEvent *event = [[MPEvent alloc] initWithName:@"Dinosaur Run" type:MPEventTypeOther];
event.duration = eventDuration;
NSDate *currentDate = [NSDate dateWithTimeIntervalSinceNow:0];
event.customAttributes = @{@"speed":@25,
@"modality":@"sprinting",
@"stats":@{@"test1": @"test", @"test2": @2, @"test3": currentDate}, @"test3": @{@"test1": @"test", @"test2": @2}};
event.category = @"Olympic Games";

[session incrementCounter];
Expand All @@ -180,6 +252,7 @@ - (void)testDictionaryRepresentation {

NSDictionary *attributes = @{@"speed":@25,
@"modality":@"sprinting",
@"stats":@{@"test1": @"test", @"test2": @2, @"test3": currentDate}, @"test3": @{@"test1": @"test", @"test2": @2},
@"$Category":@"Olympic Games",
@"EventLength":eventDuration};
XCTAssertEqualObjects(dictionaryRepresentation[kMPAttributesKey], attributes, @"Attributes are not being set correctly.");
Expand Down
8 changes: 8 additions & 0 deletions mParticle-Apple-SDK/Utils/NSDictionary+MPCaseInsensitive.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ - (id)valueForCaseInsensitiveKey:(NSString *)key {
transformedDictionary[key] = [MPDateFormatter stringFromDateRFC3339:obj];
} else if ([obj isKindOfClass:[NSData class]] && [(NSData *)obj length] > 0) {
transformedDictionary[key] = [[NSString alloc] initWithData:obj encoding:NSUTF8StringEncoding];
} else if ([obj isKindOfClass:[NSDictionary class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSMutableDictionary class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSArray class]]) {
transformedDictionary[key] = [obj description];
} else if ([obj isKindOfClass:[NSMutableArray class]]) {
transformedDictionary[key] = [obj description];
} else {
MPILogError(@"Data type is not supported as an attribute value: %@ - %@", obj, [[obj class] description]);
BrandonStalnaker marked this conversation as resolved.
Show resolved Hide resolved
NSAssert([obj isKindOfClass:[NSString class]], @"Data type is not supported as an attribute value");
Expand Down