Skip to content

Commit

Permalink
fix(Analytics): Making PinpointEndpointProfile a struct. (#3457)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruisebas authored Jan 9, 2024
1 parent 4b9d9c9 commit c11781f
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension AWSPinpointAnalyticsPlugin {
}

Task {
let currentEndpointProfile = await pinpoint.currentEndpointProfile()
var currentEndpointProfile = await pinpoint.currentEndpointProfile()
currentEndpointProfile.addUserId(userId)
if let userProfile = userProfile {
currentEndpointProfile.addUserProfile(userProfile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT
plan: testPlan,
location: testLocation,
properties: testProperties)
let expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId",
var expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId",
endpointId: "endpointId")
expectedEndpointProfile.addUserId(testIdentityId)
expectedEndpointProfile.addUserProfile(userProfile)
Expand Down Expand Up @@ -108,7 +108,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT
plan: testPlan,
location: testLocation,
properties: testProperties)
let expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId",
var expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId",
endpointId: "endpointId")
expectedEndpointProfile.addUserId(testIdentityId)
expectedEndpointProfile.addUserProfile(userProfile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase {

// Remove userId from the current endpoint
let endpointClient = endpointClient()
let currentProfile = await endpointClient.currentEndpointProfile()
var currentProfile = await endpointClient.currentEndpointProfile()
currentProfile.addUserId("")
try await endpointClient.updateEndpointProfile(with: currentProfile)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ actor EndpointClient: EndpointClientBehaviour {
}

private func configure(endpointProfile: PinpointEndpointProfile) async -> PinpointEndpointProfile {
var endpointProfile = endpointProfile
var deviceToken: PinpointEndpointProfile.DeviceToken?
if let tokenData = Self.getStoredData(from: keychain, forKey: Constants.deviceTokenKey, fallbackTo: userDefaults) {
deviceToken = tokenData.asHexString()
Expand All @@ -109,6 +110,7 @@ actor EndpointClient: EndpointClientBehaviour {
}

private func updateEndpoint(with endpointProfile: PinpointEndpointProfile) async throws {
var endpointProfile = endpointProfile
endpointProfile.effectiveDate = Date()
let input = createUpdateInput(from: endpointProfile)
log.verbose("UpdateEndpointInput: \(input)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import AWSPinpoint
import Foundation

@_spi(InternalAWSPinpoint)
public class PinpointEndpointProfile: Codable {
public struct PinpointEndpointProfile: Codable, Equatable {
typealias DeviceToken = String

var applicationId: String
Expand Down Expand Up @@ -45,11 +45,11 @@ public class PinpointEndpointProfile: Codable {
self.user = user
}

public func addUserId(_ userId: String) {
public mutating func addUserId(_ userId: String) {
user.userId = userId
}

public func addUserProfile(_ userProfile: UserProfile) {
public mutating func addUserProfile(_ userProfile: UserProfile) {
if let email = userProfile.email {
setCustomProperty(email, forKey: Constants.AttributeKeys.email)
}
Expand All @@ -75,18 +75,18 @@ public class PinpointEndpointProfile: Codable {
}
}

public func setAPNsToken(_ apnsToken: Data) {
public mutating func setAPNsToken(_ apnsToken: Data) {
deviceToken = apnsToken.asHexString()
}

private func addCustomProperties(_ properties: [String: UserProfilePropertyValue]?) {
private mutating func addCustomProperties(_ properties: [String: UserProfilePropertyValue]?) {
guard let properties = properties else { return }
for (key, value) in properties {
setCustomProperty(value, forKey: key)
}
}

private func addUserAttributes(_ attributes: [String: [String]]?) {
private mutating func addUserAttributes(_ attributes: [String: [String]]?) {
guard let attributes = attributes else { return }
let userAttributes = user.userAttributes ?? [:]
user.userAttributes = userAttributes.merging(
Expand All @@ -95,7 +95,7 @@ public class PinpointEndpointProfile: Codable {
)
}

private func setCustomProperty(_ value: UserProfilePropertyValue,
private mutating func setCustomProperty(_ value: UserProfilePropertyValue,
forKey key: String) {
if let value = value as? String {
attributes[key] = [value]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class EndpointClientTests: XCTestCase {
XCTAssertNotNil(keychain.dataValues[EndpointClient.Constants.endpointProfileKey])
XCTAssertNotNil(keychain.dataValues[EndpointClient.Constants.deviceTokenKey])
XCTAssertEqual(archiver.decodeCount, 1)
XCTAssertTrue(endpointProfile === storedEndpointProfile, "Expected stored PinpointEndpointProfile object")
XCTAssertNotEqual(endpointProfile, storedEndpointProfile, "Expected updated PinpointEndpointProfile object")
XCTAssertEqual(endpointProfile.applicationId, currentApplicationId)
XCTAssertEqual(endpointProfile.endpointId, currentEndpointId)
XCTAssertEqual(endpointProfile.deviceToken, newToken.asHexString())
Expand Down Expand Up @@ -104,7 +104,7 @@ class EndpointClientTests: XCTestCase {
XCTAssertEqual(keychain.dataForKeyCountMap[EndpointClient.Constants.endpointProfileKey], 1)
XCTAssertEqual(keychain.dataForKeyCountMap[EndpointClient.Constants.deviceTokenKey], 1)
XCTAssertEqual(archiver.decodeCount, 0)
XCTAssertFalse(endpointProfile === storedEndpointProfile, "Expected new PinpointEndpointProfile object")
XCTAssertNotEqual(endpointProfile, storedEndpointProfile, "Expected new PinpointEndpointProfile object")
XCTAssertEqual(endpointProfile.applicationId, currentApplicationId)
XCTAssertEqual(endpointProfile.endpointId, currentEndpointId)
XCTAssertEqual(endpointProfile.deviceToken, newToken?.asHexString())
Expand All @@ -128,7 +128,7 @@ class EndpointClientTests: XCTestCase {
func testUpdateEndpointProfile_withAPNsToken_withoutStoredToken_shouldSaveToken() async {
keychain.resetCounters()

let endpoint = PinpointEndpointProfile(applicationId: "applicationId",
var endpoint = PinpointEndpointProfile(applicationId: "applicationId",
endpointId: "endpointId")
endpoint.setAPNsToken(Data(hexString: newTokenHex)!)
try? await endpointClient.updateEndpointProfile(with: endpoint)
Expand All @@ -142,7 +142,7 @@ class EndpointClientTests: XCTestCase {
storeToken("oldToken")
keychain.resetCounters()

let endpoint = PinpointEndpointProfile(applicationId: "applicationId",
var endpoint = PinpointEndpointProfile(applicationId: "applicationId",
endpointId: "endpointId")
endpoint.setAPNsToken(Data(hexString: newTokenHex)!)
try? await endpointClient.updateEndpointProfile(with: endpoint)
Expand All @@ -156,7 +156,7 @@ class EndpointClientTests: XCTestCase {
storeToken(newTokenHex)
keychain.resetCounters()

let endpoint = PinpointEndpointProfile(applicationId: "applicationId",
var endpoint = PinpointEndpointProfile(applicationId: "applicationId",
endpointId: "endpointId")
endpoint.setAPNsToken(Data(hexString: newTokenHex)!)
try? await endpointClient.updateEndpointProfile(with: endpoint)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import AppKit

extension AWSPinpointPushNotificationsPlugin {
public func identifyUser(userId: String, userProfile: UserProfile?) async throws {
let currentEndpointProfile = await pinpoint.currentEndpointProfile()
var currentEndpointProfile = await pinpoint.currentEndpointProfile()
currentEndpointProfile.addUserId(userId)
if let userProfile = userProfile {
currentEndpointProfile.addUserProfile(userProfile)
Expand All @@ -30,7 +30,7 @@ extension AWSPinpointPushNotificationsPlugin {
}

public func registerDevice(apnsToken: Data) async throws {
let currentEndpointProfile = await pinpoint.currentEndpointProfile()
var currentEndpointProfile = await pinpoint.currentEndpointProfile()
currentEndpointProfile.setAPNsToken(apnsToken)
do {
try await pinpoint.updateEndpoint(with: currentEndpointProfile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userId, "newUserId")
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.user.userId, "newUserId")
}

func testIdentifyUser_withProfile_shouldUpdateUserProfile() async throws {
Expand All @@ -38,13 +39,14 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userId, "newUserId")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes.count, 3)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["name"]?.first, "Name")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["email"]?.first, "Email")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["plan"]?.first, "Plan")
XCTAssertTrue(mockPinpoint.mockedPinpointEndpointProfile.metrics.isEmpty)
XCTAssertNil(mockPinpoint.mockedPinpointEndpointProfile.user.userAttributes)
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.user.userId, "newUserId")
XCTAssertEqual(updatedEndpoint.attributes.count, 3)
XCTAssertEqual(updatedEndpoint.attributes["name"]?.first, "Name")
XCTAssertEqual(updatedEndpoint.attributes["email"]?.first, "Email")
XCTAssertEqual(updatedEndpoint.attributes["plan"]?.first, "Plan")
XCTAssertTrue(updatedEndpoint.metrics.isEmpty)
XCTAssertNil(updatedEndpoint.user.userAttributes)
}

func testIdentifyUser_withAnalyticsProfile_shouldUpdateUserProfile() async throws {
Expand All @@ -60,14 +62,15 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userId, "newUserId")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes.count, 2)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["attribute"]?.first, "string")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["metric"], 2.0)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["intMetric"], 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics.count, 2)
XCTAssertNil(mockPinpoint.mockedPinpointEndpointProfile.user.userAttributes)
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.user.userId, "newUserId")
XCTAssertEqual(updatedEndpoint.attributes.count, 2)
XCTAssertEqual(updatedEndpoint.attributes["attribute"]?.first, "string")
XCTAssertEqual(updatedEndpoint.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(updatedEndpoint.metrics["metric"], 2.0)
XCTAssertEqual(updatedEndpoint.metrics["intMetric"], 1)
XCTAssertEqual(updatedEndpoint.metrics.count, 2)
XCTAssertNil(updatedEndpoint.user.userAttributes)
}

func testIdentifyUser_withBasicProfile_shouldUpdateUserProfile() async throws {
Expand All @@ -83,14 +86,15 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userId, "newUserId")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes.count, 2)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["attribute"]?.first, "string")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["metric"], 2.0)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["intMetric"], 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics.count, 2)
XCTAssertNil(mockPinpoint.mockedPinpointEndpointProfile.user.userAttributes)
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.user.userId, "newUserId")
XCTAssertEqual(updatedEndpoint.attributes.count, 2)
XCTAssertEqual(updatedEndpoint.attributes["attribute"]?.first, "string")
XCTAssertEqual(updatedEndpoint.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(updatedEndpoint.metrics["metric"], 2.0)
XCTAssertEqual(updatedEndpoint.metrics["intMetric"], 1)
XCTAssertEqual(updatedEndpoint.metrics.count, 2)
XCTAssertNil(updatedEndpoint.user.userAttributes)
}

func testIdentifyUser_withPinpointProfile_shouldUpdateUserProfile() async throws {
Expand All @@ -110,26 +114,29 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["attribute"]?.first, "string")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["attributes"]?.count, 2)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["attributes"]?.first, "string")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["metric"], 2)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.metrics["intMetric"], 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userId, "newUserId")
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userAttributes?["roles"]?.count, 2)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.user.userAttributes?["roles"]?.first, "Test")
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.attributes["attribute"]?.first, "string")
XCTAssertEqual(updatedEndpoint.attributes["attributes"]?.count, 2)
XCTAssertEqual(updatedEndpoint.attributes["attributes"]?.first, "string")
XCTAssertEqual(updatedEndpoint.attributes["boolAttribute"]?.first, "true")
XCTAssertEqual(updatedEndpoint.metrics["metric"], 2)
XCTAssertEqual(updatedEndpoint.metrics["intMetric"], 1)
XCTAssertEqual(updatedEndpoint.user.userId, "newUserId")
XCTAssertEqual(updatedEndpoint.user.userAttributes?["roles"]?.count, 2)
XCTAssertEqual(updatedEndpoint.user.userAttributes?["roles"]?.first, "Test")
}

func testIdentifyUser_withPinpointProfileOptedOutOfMessages_shouldUpdateUserProfileOptOutValue() async throws {
try await plugin.identifyUser(userId: "newUserId", userProfile: nil)
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
var updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertFalse(updatedEndpoint.isOptOut)

try await plugin.identifyUser(userId: "newUserId", userProfile: PinpointUserProfile(optedOutOfMessages: true))
updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertTrue(updatedEndpoint.isOptOut)

try await plugin.identifyUser(userId: "newUserId", userProfile: PinpointUserProfile(name: "User"))
updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertTrue(updatedEndpoint.isOptOut)
}

Expand All @@ -140,7 +147,8 @@ class AWSPinpointPushNotificationsPluginClientBehaviourTests: AWSPinpointPushNot

XCTAssertEqual(mockPinpoint.currentEndpointProfileCount, 1)
XCTAssertEqual(mockPinpoint.updateEndpointCount, 1)
XCTAssertEqual(mockPinpoint.mockedPinpointEndpointProfile.deviceToken, apnsToken.asHexString())
let updatedEndpoint = try XCTUnwrap(mockPinpoint.updatedPinpointEndpointProfile)
XCTAssertEqual(updatedEndpoint.deviceToken, apnsToken.asHexString())
}

// MARK: - Record Notification received tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class MockAWSPinpoint: AWSPinpointBehavior {
)
func currentEndpointProfile() async -> PinpointEndpointProfile {
currentEndpointProfileCount += 1
return mockedPinpointEndpointProfile
return updatedPinpointEndpointProfile ?? mockedPinpointEndpointProfile
}

var updateEndpointCount = 0
Expand Down

0 comments on commit c11781f

Please sign in to comment.