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

[MOB-6055] callback on setEmail/setUserId #629

Merged
merged 8 commits into from
Jun 1, 2023
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
25 changes: 21 additions & 4 deletions swift-sdk/Internal/InternalIterableAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
_payloadData = data
}

func setEmail(_ email: String?, authToken: String? = nil) {
func setEmail(_ email: String?, authToken: String? = nil, successHandler: OnSuccessHandler? = nil, failureHandler: OnFailureHandler? = nil) {
Copy link
Member

Choose a reason for hiding this comment

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

Had initial thought that we might need additional functions with and without handlers as we do in Android. But looks like having optional parameters makes it modern and lets us have only one signature instead of bloating up the IterableApi class. 👍🏼

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Ayyanchira ok so for this we are good right ?

ITBInfo()

if _email == email && email != nil && authToken != nil {
Expand All @@ -127,13 +127,15 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {

_email = email
_userId = nil
_successCallback = successHandler
_failureCallback = failureHandler

storeIdentifierData()

onLogin(authToken)
}

func setUserId(_ userId: String?, authToken: String? = nil) {
func setUserId(_ userId: String?, authToken: String? = nil, successHandler: OnSuccessHandler? = nil, failureHandler: OnFailureHandler? = nil) {
ITBInfo()

if _userId == userId && userId != nil && authToken != nil {
Expand All @@ -149,6 +151,8 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {

_email = nil
_userId = userId
_successCallback = successHandler
_failureCallback = failureHandler

storeIdentifierData()

Expand All @@ -167,6 +171,7 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
guard let appName = pushIntegrationName else {
let errorMessage = "Not registering device token - appName must not be nil"
ITBError(errorMessage)
_failureCallback?(errorMessage, nil)
onFailure?(errorMessage, nil)
return
}
Expand All @@ -181,8 +186,15 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
sdkVersion: localStorage.sdkVersion)
requestHandler.register(registerTokenInfo: registerTokenInfo,
notificationStateProvider: notificationStateProvider,
onSuccess: onSuccess,
onFailure: onFailure)
onSuccess: { (_ data: [AnyHashable: Any]?) in
self._successCallback?(data)
onSuccess?(data)
},
onFailure: { (_ reason: String?, _ data: Data?) in
self._failureCallback?(reason, data)
onFailure?(reason, data)
}
)
}

@discardableResult
Expand Down Expand Up @@ -428,6 +440,9 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {
private var _email: String?
private var _payloadData: [AnyHashable: Any]?
private var _userId: String?
private var _successCallback: OnSuccessHandler? = nil
Copy link
Member

Choose a reason for hiding this comment

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

If this is going to be global but only used for setting the user credentials, we might have to rename it that way. Because, we will be adding success failure callbacks to other api calls / function calls as well and they will have to pass in success and failure callbacks too. using this global variable to store that and replace whats been stored in that can cause inconsistent behaviors

Copy link
Member

Choose a reason for hiding this comment

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

Like for example, updateEmail also uses success and failure callback handler to notify the state. But by not having it stored globally, it allows for good separation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Ayyanchira yes we can rename it so that is identified differently, but it would be class variable because it is used from the whole different method and that is why we need to hold a reference to it

private var _failureCallback: OnFailureHandler? = nil


/// the hex representation of this device token
private var hexToken: String?
Expand Down Expand Up @@ -537,6 +552,8 @@ final class InternalIterableAPI: NSObject, PushTrackerProtocol, AuthProvider {

if config.autoPushRegistration {
notificationStateProvider.registerForRemoteNotifications()
} else {
_successCallback?([:])
}

_ = inAppManager.scheduleSync()
Expand Down
8 changes: 4 additions & 4 deletions swift-sdk/IterableAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ import UIKit

// MARK: - SDK

public static func setEmail(_ email: String?, _ authToken: String? = nil) {
implementation?.setEmail(email, authToken: authToken)
public static func setEmail(_ email: String?, _ authToken: String? = nil, _ successHandler: OnSuccessHandler? = nil, _ failureHandler: OnFailureHandler? = nil) {
implementation?.setEmail(email, authToken: authToken, successHandler: successHandler, failureHandler: failureHandler)
}

public static func setUserId(_ userId: String?, _ authToken: String? = nil) {
implementation?.setUserId(userId, authToken: authToken)
public static func setUserId(_ userId: String?, _ authToken: String? = nil, _ successHandler: OnSuccessHandler? = nil, _ failureHandler: OnFailureHandler? = nil) {
implementation?.setUserId(userId, authToken: authToken, successHandler: successHandler, failureHandler: failureHandler)
}

/// Handle a Universal Link
Expand Down
72 changes: 72 additions & 0 deletions tests/unit-tests/IterableAPITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,78 @@ class IterableAPITests: XCTestCase {

wait(for: [expectation], timeout: testExpectationTimeout)
}

func testSetEmailWithCallbackSuccess() {
let expectation = XCTestExpectation(description: "Set email with callback success")

let config = IterableConfig()
let networkSession = MockNetworkSession(statusCode: 200)
let internalAPI = InternalIterableAPI.initializeForTesting(apiKey: IterableAPITests.apiKey, config: config, networkSession: networkSession)

internalAPI.setEmail("test@example.com", successHandler: { success in
XCTAssertNotNil(success)
expectation.fulfill()
}, failureHandler: { _, _ in
XCTFail("Failed to set email")
expectation.fulfill()
})

wait(for: [expectation], timeout: testExpectationTimeout)
}

func testSetEmailWithCallbackFailure() {
let expectation = XCTestExpectation(description: "Set email with callback failure")

let config = IterableConfig()
let networkSession = MockNetworkSession(statusCode: 400)
let internalAPI = InternalIterableAPI.initializeForTesting(apiKey: IterableAPITests.apiKey, config: config, networkSession: networkSession)

internalAPI.setEmail("invalid_email", successHandler: { success in
XCTFail("Email should not be set successfully")
expectation.fulfill()
}, failureHandler: { _, error in
XCTAssertNotNil(error)
expectation.fulfill()
})

wait(for: [expectation], timeout: testExpectationTimeout)
}

func testSetUserIdWithCallbackSuccess() {
let expectation = XCTestExpectation(description: "Set user ID with callback success")

let config = IterableConfig()
let networkSession = MockNetworkSession(statusCode: 200)
let internalAPI = InternalIterableAPI.initializeForTesting(apiKey: IterableAPITests.apiKey, config: config, networkSession: networkSession)

internalAPI.setUserId("user123", successHandler: { success in
XCTAssertNil(success)
expectation.fulfill()
}, failureHandler: { _, _ in
XCTFail("Failed to set user ID")
expectation.fulfill()
})

wait(for: [expectation], timeout: testExpectationTimeout)
}

func testSetUserIdWithCallbackFailure() {
let expectation = XCTestExpectation(description: "Set user ID with callback failure")

let config = IterableConfig()
let networkSession = MockNetworkSession(statusCode: 400)
let internalAPI = InternalIterableAPI.initializeForTesting(apiKey: IterableAPITests.apiKey, config: config, networkSession: networkSession)

internalAPI.setUserId("user123", successHandler: { success in
XCTFail("User ID should not be set successfully")
expectation.fulfill()
}, failureHandler: { _, error in
XCTAssertNotNil(error)
expectation.fulfill()
})

wait(for: [expectation], timeout: testExpectationTimeout)
}

func testEmailPersistence() {
let internalAPI = InternalIterableAPI.initializeForTesting()
Expand Down