Skip to content
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
26 changes: 20 additions & 6 deletions mParticle-Rokt-Swift/MPRoktLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,30 @@ public class MPRoktLayout {
let hashedEmailIdentity = MPKitRokt.getHashedEmailUserIdentityType()

let userEmailIdentity = user.identities[NSNumber(value: MPIdentity.email.rawValue)]
let userHashedEmailIdentity = user.identities[hashedEmailIdentity]

let emailMismatch = email != nil && email != userEmailIdentity
let hashedEmailMismatch = hashedEmail != nil && hashedEmail != userHashedEmailIdentity
let emailMismatch: Bool = {
guard let email = email,
let userEmail = user.identities[NSNumber(value: MPIdentity.email.rawValue)] else {
return false
}
return email != userEmail
}()
let hashedEmailMismatch: Bool = {
guard let hashedEmail = hashedEmail,
let hashedEmailIdentity = hashedEmailIdentity,
let userHashedEmail = user.identities[hashedEmailIdentity] else {
return false
}
return hashedEmail != userHashedEmail
}()

if emailMismatch || hashedEmailMismatch {
// If there is an existing email or hashed email but it doesn't match what was passed in, warn the customer
if emailMismatch {
print("The existing email on the user (\(userEmailIdentity ?? "nil")) does not match the email passed in to `selectPlacements:` (\(email ?? "nil")). Please remember to sync the email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout")
}
if hashedEmailMismatch {
print("The existing hashed email on the user (\(userHashedEmailIdentity ?? "nil")) does not match the email passed in to `selectPlacements:` (\(hashedEmail ?? "nil")). Please remember to sync the email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout")
print("The existing hashed email on the user (\(user.identities[hashedEmailIdentity ?? NSNumber(value: -1)] ?? "nil")) does not match the email passed in to `selectPlacements:` (\(hashedEmail ?? "nil")). Please remember to sync the hashed email identity to mParticle as soon as you receive it. We will now identify the user before creating the layout")
}

syncIdentities(user: user, email: email, hashedEmail: hashedEmail, hashedEmailKey: hashedEmailIdentity, completion: completion)
Expand All @@ -80,12 +92,14 @@ public class MPRoktLayout {
user: MParticleUser,
email: String?,
hashedEmail: String?,
hashedEmailKey: NSNumber,
hashedEmailKey: NSNumber?,
completion: @escaping () -> Void
) {
let identityRequest = MPIdentityApiRequest(user: user)
identityRequest.setIdentity(email, identityType: .email)
identityRequest.setIdentity(hashedEmail, identityType: MPIdentity(rawValue: hashedEmailKey.uintValue) ?? .other)
if let hashedEmailKey = hashedEmailKey {
identityRequest.setIdentity(hashedEmail, identityType: MPIdentity(rawValue: hashedEmailKey.uintValue) ?? .other)
}

mparticle.identity.identify(identityRequest) {apiResult, error in
if let error = error {
Expand Down
2 changes: 1 addition & 1 deletion mParticle-Rokt/MPKitRokt.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
@property (nonatomic, unsafe_unretained, readonly) BOOL started;

+ (NSDictionary<NSString *, NSString *> * _Nonnull)prepareAttributes:(NSDictionary<NSString *, NSString *> * _Nonnull)attributes filteredUser:(FilteredMParticleUser * _Nullable)filteredUser performMapping:(BOOL)performMapping;
+ (NSNumber * _Nonnull)getRoktHashedEmailUserIdentityType;
+ (NSNumber * _Nullable)getRoktHashedEmailUserIdentityType;

@end
4 changes: 2 additions & 2 deletions mParticle-Rokt/MPKitRokt.m
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ + (RoktConfig *)convertMPRoktConfig:(MPRoktConfig *)mpRoktConfig {
+ (NSString *)stringForIdentityType:(MPIdentity)identityType {
NSNumber *hashedEmailIdentity = [MPKitRokt getRoktHashedEmailUserIdentityType];

if (hashedEmailIdentity.unsignedIntValue == identityType) {
if (hashedEmailIdentity && hashedEmailIdentity.unsignedIntValue == identityType) {
return @"emailsha256";
}

Expand Down Expand Up @@ -443,7 +443,7 @@ + (NSNumber *)getRoktHashedEmailUserIdentityType {
NSString *hashedIdentityTypeString = roktKitConfig[kMPHashedEmailUserIdentityType];
NSNumber *hashedIdentityTypeNumber = [MPKitRokt identityTypeForString:hashedIdentityTypeString.lowercaseString];

return hashedIdentityTypeNumber != nil ? hashedIdentityTypeNumber : @(MPIdentityOther);
return hashedIdentityTypeNumber;
}

- (MPKitExecStatus *)purchaseFinalized:(NSString *)placementId catalogItemId:(NSString *)catalogItemId success:(NSNumber *)success {
Expand Down
67 changes: 67 additions & 0 deletions mParticle_RoktTests/mParticle_RoktTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ - (void)testAddIdentityAttributes {
FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init];
id mockfilteredUser = OCMPartialMock(filteredUser);
[[[mockfilteredUser stub] andReturn:testIdentities] userIdentities];
id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]);
[[[mockMPKitRoktClass stub] andReturn:@(MPIdentityOther)] getRoktHashedEmailUserIdentityType];

[MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser];

Expand Down Expand Up @@ -267,6 +269,69 @@ - (void)testAddIdentityAttributes {
XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS");
}

- (void)testAddIdentityAttributesUnassigned {
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
NSDictionary<NSNumber *, NSString *> *testIdentities = @{@(MPIdentityCustomerId): @"testCustomerID",
@(MPIdentityEmail): @"testEmail@gmail.com",
@(MPIdentityFacebook): @"testFacebook",
@(MPIdentityFacebookCustomAudienceId): @"testCustomAudienceID",
@(MPIdentityGoogle): @"testGoogle",
@(MPIdentityMicrosoft): @"testMicrosoft",
@(MPIdentityOther): @"testOther",
@(MPIdentityTwitter): @"testTwitter",
@(MPIdentityYahoo): @"testYahoo",
@(MPIdentityOther2): @"testOther2",
@(MPIdentityOther3): @"testOther3",
@(MPIdentityOther4): @"testOther4",
@(MPIdentityOther5): @"testOther5",
@(MPIdentityOther6): @"testOther6",
@(MPIdentityOther7): @"testOther7",
@(MPIdentityOther8): @"testOther8",
@(MPIdentityOther9): @"testOther9",
@(MPIdentityOther10): @"testOther10",
@(MPIdentityMobileNumber): @"1(234)-567-8910",
@(MPIdentityPhoneNumber2): @"1(234)-567-2222",
@(MPIdentityPhoneNumber3): @"1(234)-567-3333",
@(MPIdentityIOSAdvertiserId): @"testAdvertID",
@(MPIdentityIOSVendorId): @"testVendorID",
@(MPIdentityPushToken): @"testPushToken",
@(MPIdentityDeviceApplicationStamp): @"Test DAS"};

FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init];
id mockfilteredUser = OCMPartialMock(filteredUser);
[[[mockfilteredUser stub] andReturn:testIdentities] userIdentities];
id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]);
[[[mockMPKitRoktClass stub] andReturn:nil] getRoktHashedEmailUserIdentityType];

[MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser];

XCTAssertEqualObjects(passedAttributes[@"customerid"], @"testCustomerID");
XCTAssertEqualObjects(passedAttributes[@"email"], @"testEmail@gmail.com");
XCTAssertEqualObjects(passedAttributes[@"facebook"], @"testFacebook");
XCTAssertEqualObjects(passedAttributes[@"facebookcustomaudienceid"], @"testCustomAudienceID");
XCTAssertEqualObjects(passedAttributes[@"google"], @"testGoogle");
XCTAssertEqualObjects(passedAttributes[@"microsoft"], @"testMicrosoft");
XCTAssertEqualObjects(passedAttributes[@"other"], @"testOther");
XCTAssertEqualObjects(passedAttributes[@"twitter"], @"testTwitter");
XCTAssertEqualObjects(passedAttributes[@"yahoo"], @"testYahoo");
XCTAssertEqualObjects(passedAttributes[@"other2"], @"testOther2");
XCTAssertEqualObjects(passedAttributes[@"other3"], @"testOther3");
XCTAssertEqualObjects(passedAttributes[@"other4"], @"testOther4");
XCTAssertEqualObjects(passedAttributes[@"other5"], @"testOther5");
XCTAssertEqualObjects(passedAttributes[@"other6"], @"testOther6");
XCTAssertEqualObjects(passedAttributes[@"other7"], @"testOther7");
XCTAssertEqualObjects(passedAttributes[@"other8"], @"testOther8");
XCTAssertEqualObjects(passedAttributes[@"other9"], @"testOther9");
XCTAssertEqualObjects(passedAttributes[@"other10"], @"testOther10");
XCTAssertEqualObjects(passedAttributes[@"mobile_number"], @"1(234)-567-8910");
XCTAssertEqualObjects(passedAttributes[@"phone_number_2"], @"1(234)-567-2222");
XCTAssertEqualObjects(passedAttributes[@"phone_number_3"], @"1(234)-567-3333");
XCTAssertEqualObjects(passedAttributes[@"ios_idfa"], @"testAdvertID");
XCTAssertEqualObjects(passedAttributes[@"ios_idfv"], @"testVendorID");
XCTAssertEqualObjects(passedAttributes[@"push_token"], @"testPushToken");
XCTAssertEqualObjects(passedAttributes[@"device_application_stamp"], @"Test DAS");
}

- (void)testAddIdentityAttributesWithExistingAttributes {
NSMutableDictionary<NSString *, NSString *> *passedAttributes = [[NSMutableDictionary alloc] init];
[passedAttributes setObject:@"bar" forKey:@"foo"];
Expand Down Expand Up @@ -299,6 +364,8 @@ - (void)testAddIdentityAttributesWithExistingAttributes {
FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] init];
id mockfilteredUser = OCMPartialMock(filteredUser);
[[[mockfilteredUser stub] andReturn:testIdentities] userIdentities];
id mockMPKitRoktClass = OCMClassMock([MPKitRokt class]);
[[[mockMPKitRoktClass stub] andReturn:@(MPIdentityOther)] getRoktHashedEmailUserIdentityType];

[MPKitRokt addIdentityAttributes:passedAttributes filteredUser:filteredUser];

Expand Down
2 changes: 1 addition & 1 deletion mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
)

// Then
#expect(preparedAttributes != nil, "Prepared attributes should not be nil")

Check warning on line 115 in mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift

View workflow job for this annotation

GitHub Actions / Test

comparing non-optional value of type '[String : String]' to 'nil' always returns true
#expect(preparedAttributes.count >= attributes.count, "Prepared attributes should contain at least the original attributes")
}

Expand All @@ -129,7 +129,7 @@
)

// Then
#expect(preparedAttributes != nil, "Prepared attributes should not be nil")

Check warning on line 132 in mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift

View workflow job for this annotation

GitHub Actions / Test

comparing non-optional value of type '[String : String]' to 'nil' always returns true
#expect(preparedAttributes["sandbox"] != nil, "Sandbox attribute should be added automatically")
}

Expand Down Expand Up @@ -183,7 +183,7 @@
)

// Then
#expect(layout.roktLayout is any View, "MPRoktLayout should conform to SwiftUI View protocol")

Check warning on line 186 in mParticle_RoktTests/mParticle_Rokt_SwiftTests.swift

View workflow job for this annotation

GitHub Actions / Test

checking a value with optional type 'RoktLayout?' against type 'any View' succeeds whenever the value is non-nil; did you mean to use '!= nil'?
}

// MARK: - Parameter Validation Tests
Expand Down Expand Up @@ -273,7 +273,7 @@
)

// Then
#expect(layout.roktLayout == nil, "Layout should attempt to identify user attributes and fail")
#expect(layout.roktLayout != nil, "Layout should attempt to identify user attributes and fail")
}

@MainActor @available(iOS 15, *)
Expand Down
Loading