Skip to content

Commit 427d15a

Browse files
committed
🧪 Added tests to validate JWT refresh on 401s
1 parent 298c834 commit 427d15a

File tree

3 files changed

+93
-11
lines changed

3 files changed

+93
-11
lines changed

swift-sdk/Internal/in-app/InAppHelper.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import UIKit
1010
struct InAppHelper {
1111
static func getInAppMessagesFromServer(apiClient: ApiClientProtocol,
1212
authManager: IterableAuthManagerProtocol?,
13-
number: Int) -> Pending<[IterableInAppMessage], SendRequestError> {
13+
number: Int,
14+
successHandler onSuccess: OnSuccessHandler? = nil,
15+
failureHandler onFailure: OnFailureHandler? = nil) -> Pending<[IterableInAppMessage], SendRequestError> {
1416

1517
RequestProcessorUtil.sendRequest(requestProvider: { apiClient.getInAppMessages(NSNumber(value: number)) },
16-
successHandler: nil,
17-
failureHandler: nil,
18+
successHandler: onSuccess,
19+
failureHandler: onFailure,
1820
authManager: authManager,
1921
requestIdentifier: "getInAppMessages")
2022
.map {

tests/common/MockAuthManager.swift

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@ import Foundation
1010

1111
class MockAuthManager: IterableAuthManagerProtocol {
1212

13+
var token = "AuthToken"
14+
1315
var shouldRetry = true
1416
var retryWasRequested = false
17+
var isLastAuthTokenValid = false
18+
var pauseAuthRetries = false
19+
var handleAuthFailureCalled = false
20+
var getNextRetryIntervalCalled = false
21+
var failedAuthCount = 0
1522

1623
func handleAuthFailure(failedAuthToken: String?, reason: IterableSDK.AuthFailureReason) {
17-
24+
failedAuthCount += 1
25+
handleAuthFailureCalled = true
26+
print("AuthManager handleAuthFailure with reason: \(reason.rawValue) and token: \(String(describing: failedAuthToken))")
1827
}
1928

2029
func requestNewAuthToken(hasFailedPriorAuth: Bool, onSuccess: ((String?) -> Void)?, shouldIgnoreRetryPolicy: Bool) {
@@ -31,32 +40,37 @@ class MockAuthManager: IterableAuthManagerProtocol {
3140
}
3241

3342
func scheduleAuthTokenRefreshTimer(interval: TimeInterval, isScheduledRefresh: Bool, successCallback: IterableSDK.AuthTokenRetrievalHandler?) {
34-
requestNewAuthToken(hasFailedPriorAuth: false, onSuccess: successCallback, shouldIgnoreRetryPolicy: true)
43+
requestNewAuthToken(hasFailedPriorAuth: false, onSuccess: { newToken in
44+
guard let newToken else { return }
45+
self.setNewToken(newToken)
46+
successCallback?(newToken)
47+
}, shouldIgnoreRetryPolicy: true)
3548
}
3649

3750
func pauseAuthRetries(_ pauseAuthRetry: Bool) {
38-
51+
pauseAuthRetries = pauseAuthRetry
3952
}
4053

4154
func setIsLastAuthTokenValid(_ isValid: Bool) {
42-
55+
isLastAuthTokenValid = isValid
4356
}
4457

4558
func getNextRetryInterval() -> Double {
59+
getNextRetryIntervalCalled = true
4660
return 0
4761
}
4862

4963

5064
func getAuthToken() -> String? {
51-
return "AuthToken"
65+
token
5266
}
5367

5468
func resetFailedAuthCount() {
55-
69+
failedAuthCount = 0
5670
}
5771

5872
func setNewToken(_ newToken: String) {
59-
73+
token = newToken
6074
}
6175

6276
func logoutUser() {

tests/unit-tests/InAppHelperTests.swift

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ import XCTest
66

77
@testable import IterableSDK
88

9+
private final class RetryingApiClient: BlankApiClient {
10+
var numOfMessages = 3
11+
var callCount = -1
12+
var lastCountRequested: NSNumber?
13+
var failureReason = "jwt token is expired"
14+
weak var authManager: MockAuthManager?
15+
16+
override func getInAppMessages(_ count: NSNumber) -> Pending<SendRequestValue, SendRequestError> {
17+
callCount += 1
18+
lastCountRequested = count
19+
20+
if callCount == 0 {
21+
return Fulfill(value: TestInAppPayloadGenerator.createPayloadWithUrl(numMessages: numOfMessages))
22+
}
23+
24+
if authManager?.retryWasRequested == true {
25+
return Fulfill(value: TestInAppPayloadGenerator.createPayloadWithUrl(numMessages: numOfMessages))
26+
}
27+
return Fulfill(error: SendRequestError(reason: failureReason,
28+
httpStatusCode: 401,
29+
iterableCode: JsonValue.Code.invalidJwtPayload))
30+
}
31+
}
32+
933
class InAppHelperTests: XCTestCase {
1034
func testGetInAppMessagesWithNoError() {
1135
class MyApiClient: BlankApiClient {
@@ -76,7 +100,49 @@ class InAppHelperTests: XCTestCase {
76100

77101
wait(for: [expectation1], timeout: testExpectationTimeout)
78102
}
79-
103+
104+
func testGetInAppMessagesRetriesAfterJWT401() {
105+
let authManager = MockAuthManager()
106+
authManager.shouldRetry = true
107+
108+
let apiClient = RetryingApiClient()
109+
apiClient.authManager = authManager
110+
111+
112+
let initialFailedAuthCount = authManager.failedAuthCount
113+
114+
InAppHelper.getInAppMessagesFromServer(apiClient: apiClient,
115+
authManager: authManager,
116+
number: apiClient.numOfMessages).onSuccess { messages in
117+
print(messages)
118+
}.onError { error in
119+
XCTFail("expected success, got error: \(error)")
120+
}
121+
122+
InAppHelper.getInAppMessagesFromServer(apiClient: apiClient,
123+
authManager: authManager,
124+
number: apiClient.numOfMessages,
125+
successHandler: { data in
126+
XCTAssertTrue(authManager.handleAuthFailureCalled)
127+
XCTAssertTrue(authManager.getNextRetryIntervalCalled)
128+
129+
XCTAssertTrue(authManager.retryWasRequested)
130+
XCTAssertEqual(authManager.getAuthToken(), "newAuthToken")
131+
}).onSuccess { messages in
132+
print(messages)
133+
}.onError { error in
134+
XCTFail("expected success, got error: \(error)")
135+
}
136+
137+
InAppHelper.getInAppMessagesFromServer(apiClient: apiClient,
138+
authManager: authManager,
139+
number: apiClient.numOfMessages).onSuccess { messages in
140+
XCTAssertTrue(authManager.retryWasRequested)
141+
}.onError { error in
142+
XCTFail("expected success, got error: \(error)")
143+
}
144+
}
145+
80146
func testParseURL() {
81147
let urlWithNoScheme = URL(string: "blah")!
82148
XCTAssertNil(InAppHelper.parse(inAppUrl: urlWithNoScheme))

0 commit comments

Comments
 (0)