Skip to content

Commit 02acc2a

Browse files
committed
Unit tests for UserExecutor with identity verification on
1 parent f926109 commit 02acc2a

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

iOS_SDK/OneSignalSDK/OneSignalUserMocks/MockUserDefines.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ public let userB_OSID = "test_user_b_onesignal_id"
55
public let userB_EUID = "test_user_b_external_id"
66

77
public let testPushSubId = "test_push_subscription_id"
8+
9+
public let userA_JwtToken = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMTM5YmQ2Zi00NTFmLTQzOGMtODg4Ni00ZTBmMGZlM2EwODUiLCJleHAiOjE3MjUzOTY3NTksImlkZW50aXR5Ijp7ImV4dGVybmFsX2lkIjoiZWxsaW90MTE0MCJ9LCJzdWJzY3JpcHRpb25zIjpbeyJ0eXBlIjoiRW1haWwiLCJ0b2tlbiI6InRlc3RAZG9tYWluLmNvbSJ9LHsidHlwZSI6IlNNUyIsInRva2VuIjoiKzEyMzQ1Njc4In1dfQ.wmtt8mH7wYpxmUDyx_l8ktfF4Eg-6y_4iOSsIEl3AxuQ5pEriCIRj-3P-NmSPO3jsSAGPeBRZQ-rRS5j-LbN1w"

iOS_SDK/OneSignalSDK/OneSignalUserMocks/MockUserRequests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ public class MockUserRequests: NSObject {
5959
"properties": properties
6060
]
6161
}
62+
63+
public static func testUnauthorizedailureError() -> NSError {
64+
let userInfo = ["returned": [
65+
"errors": [["title":"token has invalid claims: token is expired", "code":"auth-0"]],
66+
"httpStatusCode": 401,
67+
]]
68+
return NSError(domain: "not-important", code: 401, userInfo: userInfo)
69+
}
6270
}
6371

6472
// MARK: - Set Up Default Client Responses
@@ -97,6 +105,16 @@ extension MockUserRequests {
97105
response: userResponse
98106
)
99107
}
108+
109+
public static func setUnauthorizedCreateUserFailureResponses(with client: MockOneSignalClient, externalId: String) {
110+
let error = testUnauthorizedailureError()
111+
client.setMockFailureResponseForRequest(request:"<OSRequestCreateUser with external_id: \(externalId)>", error: error)
112+
}
113+
114+
public static func setUnauthorizedFetchUserFailureResponses(with client: MockOneSignalClient, onesignalId: String) {
115+
let error = testUnauthorizedailureError()
116+
client.setMockFailureResponseForRequest(request:"<OSRequestFetchUser with onesignal_id: \(onesignalId)>", error: error)
117+
}
100118

101119
public static func setDefaultIdentifyUserResponses(with client: MockOneSignalClient, externalId: String, conflicted: Bool = false) {
102120
var osid: String

iOS_SDK/OneSignalSDK/OneSignalUserTests/Executors/UserExecutorTests.swift

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,131 @@ final class UserExecutorTests: XCTestCase {
207207
XCTAssertTrue(mocks.client.hasExecutedRequestOfType(OSRequestCreateUser.self))
208208
XCTAssertTrue(mocks.newRecordsState.records.isEmpty)
209209
}
210+
211+
func testCreateUser_IdentityVerificationRequired_butNoToken() {
212+
/* Setup */
213+
let mocks = Mocks()
214+
mocks.setAuthRequired(true)
215+
216+
let _ = mocks.setUserManagerInternalUser(externalId: "")
217+
let newIdentityModel = OSIdentityModel(aliases: [OS_EXTERNAL_ID: userA_EUID], changeNotifier: OSEventProducer())
218+
MockUserRequests.setDefaultCreateUserResponses(with: mocks.client, externalId: userA_EUID)
219+
220+
/* When */
221+
mocks.userExecutor.createUser(aliasLabel: OS_EXTERNAL_ID, aliasId: userA_EUID, identityModel: newIdentityModel)
222+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
223+
224+
/* Then */
225+
// The executor should not execute this request since identity verification is required, but no token was set
226+
XCTAssertFalse(mocks.client.hasExecutedRequestOfType(OSRequestCreateUser.self))
227+
XCTAssertEqual(mocks.newRecordsState.records.count, 0)
228+
}
229+
230+
func testCreateUser_IdentityVerificationRequired_withToken() {
231+
/* Setup */
232+
let mocks = Mocks()
233+
mocks.setAuthRequired(true)
234+
235+
let _ = mocks.setUserManagerInternalUser(externalId: "")
236+
let newIdentityModel = OSIdentityModel(aliases: [OS_EXTERNAL_ID: userA_EUID], changeNotifier: OSEventProducer())
237+
newIdentityModel.jwtBearerToken = userA_JwtToken
238+
MockUserRequests.setDefaultCreateUserResponses(with: mocks.client, externalId: userA_EUID)
239+
240+
/* When */
241+
mocks.userExecutor.createUser(aliasLabel: OS_EXTERNAL_ID, aliasId: userA_EUID, identityModel: newIdentityModel)
242+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
243+
244+
/* Then */
245+
// The executor should execute this request since identity verification is required and the token was set
246+
XCTAssertTrue(mocks.client.hasExecutedRequestOfType(OSRequestCreateUser.self))
247+
}
248+
249+
func testCreateUser_IdentityVerificationRequired_withInvalidToken() {
250+
/* Setup */
251+
let mocks = Mocks()
252+
mocks.setAuthRequired(true)
253+
254+
let _ = mocks.setUserManagerInternalUser(externalId: userA_EUID)
255+
let newIdentityModel = OSIdentityModel(aliases: [OS_EXTERNAL_ID: userA_EUID], changeNotifier: OSEventProducer())
256+
newIdentityModel.jwtBearerToken = userA_JwtToken
257+
MockUserRequests.setUnauthorizedCreateUserFailureResponses(with: mocks.client, externalId: userA_EUID)
258+
259+
var invalidatedCallbackWasCalled = false
260+
OneSignalUserManagerImpl.sharedInstance.User.onJwtInvalidated { event in
261+
XCTAssertTrue(event.message == "token has invalid claims: token is expired")
262+
invalidatedCallbackWasCalled = true
263+
}
264+
265+
/* When */
266+
mocks.userExecutor.createUser(aliasLabel: OS_EXTERNAL_ID, aliasId: userA_EUID, identityModel: newIdentityModel)
267+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
268+
269+
/* Then */
270+
// The executor should execute this request since identity verification is required and the token was set
271+
XCTAssertTrue(mocks.client.hasExecutedRequestOfType(OSRequestCreateUser.self))
272+
XCTAssertTrue(invalidatedCallbackWasCalled)
273+
}
274+
275+
func testFetchUser_IdentityVerificationRequired_butNoToken() {
276+
/* Setup */
277+
let mocks = Mocks()
278+
mocks.setAuthRequired(true)
279+
280+
let _ = mocks.setUserManagerInternalUser(externalId: "")
281+
let newIdentityModel = OSIdentityModel(aliases: [OS_ONESIGNAL_ID: userA_OSID], changeNotifier: OSEventProducer())
282+
MockUserRequests.setDefaultFetchUserResponseForHydration(with: mocks.client, externalId: userA_EUID)
283+
284+
/* When */
285+
mocks.userExecutor.fetchUser(onesignalId: userA_OSID, identityModel: newIdentityModel)
286+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
287+
288+
/* Then */
289+
// The executor should not execute this request since identity verification is required, but no token was set
290+
XCTAssertFalse(mocks.client.hasExecutedRequestOfType(OSRequestFetchUser.self))
291+
}
292+
293+
func testFetchUser_IdentityVerificationRequired_withToken() {
294+
/* Setup */
295+
let mocks = Mocks()
296+
mocks.setAuthRequired(true)
297+
298+
let _ = mocks.setUserManagerInternalUser(externalId: "")
299+
let newIdentityModel = OSIdentityModel(aliases: [OS_ONESIGNAL_ID: userA_OSID, OS_EXTERNAL_ID: userA_EUID], changeNotifier: OSEventProducer())
300+
newIdentityModel.jwtBearerToken = userA_JwtToken
301+
MockUserRequests.setDefaultFetchUserResponseForHydration(with: mocks.client, externalId: userA_EUID)
302+
303+
/* When */
304+
mocks.userExecutor.fetchUser(onesignalId: userA_OSID, identityModel: newIdentityModel)
305+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
306+
307+
/* Then */
308+
// The executor should not execute this request since identity verification is required, but no token was set
309+
XCTAssertTrue(mocks.client.hasExecutedRequestOfType(OSRequestFetchUser.self))
310+
}
311+
312+
func testFetchUser_IdentityVerificationRequired_withInvalidToken() {
313+
/* Setup */
314+
let mocks = Mocks()
315+
mocks.setAuthRequired(true)
316+
317+
let _ = mocks.setUserManagerInternalUser(externalId: userA_EUID)
318+
let newIdentityModel = OSIdentityModel(aliases: [OS_ONESIGNAL_ID: userA_OSID, OS_EXTERNAL_ID: userA_EUID], changeNotifier: OSEventProducer())
319+
newIdentityModel.jwtBearerToken = userA_JwtToken
320+
MockUserRequests.setUnauthorizedFetchUserFailureResponses(with: mocks.client, onesignalId: userA_OSID)
321+
322+
var invalidatedCallbackWasCalled = false
323+
OneSignalUserManagerImpl.sharedInstance.User.onJwtInvalidated { event in
324+
XCTAssertTrue(event.message == "token has invalid claims: token is expired")
325+
invalidatedCallbackWasCalled = true
326+
}
327+
328+
/* When */
329+
mocks.userExecutor.fetchUser(onesignalId: userA_OSID, identityModel: newIdentityModel)
330+
OneSignalCoreMocks.waitForBackgroundThreads(seconds: 0.5)
331+
332+
/* Then */
333+
// The executor should execute this request since identity verification is required and the token was set
334+
XCTAssertTrue(mocks.client.hasExecutedRequestOfType(OSRequestFetchUser.self))
335+
XCTAssertTrue(invalidatedCallbackWasCalled)
336+
}
210337
}

0 commit comments

Comments
 (0)