Skip to content

Commit 479c42c

Browse files
Merge pull request #20 from Iterable/feature/itbl-5848-login-logout
[ITBL-5848] - disable/re-register device token when email or userId changes
2 parents 02f7a86 + edc0668 commit 479c42c

File tree

13 files changed

+395
-70
lines changed

13 files changed

+395
-70
lines changed

Tests/swift-sdk-objc-tests/IterableAPIResponseTests.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#import "OHHTTPStubs.h"
1212
#import "OHPathHelpers.h"
1313

14+
#import "swift_sdk_objc_tests-Swift.h"
15+
1416
@import IterableSDK;
1517

1618
static CGFloat const IterableResponseExpectationTimeout = 1.0;

Tests/swift-sdk-swift-tests/IterableAPITests.swift

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,17 @@
77
//
88

99
import XCTest
10+
import UserNotifications
1011

1112
@testable import IterableSDK
1213

13-
extension IterableAPI {
14-
// Internal Only used in unit tests.
15-
static func initialize(apiKey: String,
16-
launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil,
17-
config: IterableConfig = IterableConfig(),
18-
dateProvider: DateProviderProtocol = SystemDateProvider(),
19-
networkSession: @escaping @autoclosure () -> NetworkSessionProtocol = URLSession(configuration: URLSessionConfiguration.default)) {
20-
internalImplementation = IterableAPIInternal.init(apiKey: apiKey, launchOptions: launchOptions, config: config, dateProvider: dateProvider, networkSession: networkSession)
21-
}
22-
}
23-
2414
class IterableAPITests: XCTestCase {
2515
private static let apiKey = "zeeApiKey"
2616
private static let email = "[email protected]"
2717

2818
override func setUp() {
2919
super.setUp()
30-
IterableAPI.email = nil
31-
IterableAPI.userId = nil
32-
// Put setup code here. This method is called before the invocation of each test method in the class.
20+
TestUtils.clearUserDefaults()
3321
}
3422

3523
override func tearDown() {
@@ -62,7 +50,11 @@ class IterableAPITests: XCTestCase {
6250
expectation.fulfill()
6351
}) { (reason, data) in
6452
expectation.fulfill()
65-
XCTFail()
53+
if let reason = reason {
54+
XCTFail("encountered error: \(reason)")
55+
} else {
56+
XCTFail("encountered error")
57+
}
6658
}
6759

6860
wait(for: [expectation], timeout: testExpectationTimeout)
@@ -81,7 +73,7 @@ class IterableAPITests: XCTestCase {
8173
onSuccess:{json in
8274
// fail on success
8375
expectation.fulfill()
84-
XCTFail()
76+
XCTFail("did not expect success")
8577
},
8678
onFailure: {(reason, data) in expectation.fulfill()})
8779

@@ -102,8 +94,12 @@ class IterableAPITests: XCTestCase {
10294
TestUtils.validateElementPresent(withName: ITBL_KEY_MERGE_NESTED, andValue: true, inDictionary: body)
10395
TestUtils.validateElementPresent(withName: ITBL_KEY_DATA_FIELDS, andValue: dataFields, inDictionary: body)
10496
expectation.fulfill()
105-
}) {(error, data) in
106-
XCTFail()
97+
}) {(reason, _) in
98+
if let reason = reason {
99+
XCTFail("encountered error: \(reason)")
100+
} else {
101+
XCTFail("encountered error")
102+
}
107103
expectation.fulfill()
108104
}
109105

@@ -130,9 +126,13 @@ class IterableAPITests: XCTestCase {
130126
XCTAssertEqual(IterableAPI.email, newEmail)
131127
expectation.fulfill()
132128
},
133-
onFailure: {(reason, data) in
129+
onFailure: {(reason, _) in
134130
expectation.fulfill()
135-
XCTFail()
131+
if let reason = reason {
132+
XCTFail("encountered error: \(reason)")
133+
} else {
134+
XCTFail("encountered error")
135+
}
136136
})
137137

138138
wait(for: [expectation], timeout: testExpectationTimeout)
@@ -145,7 +145,7 @@ class IterableAPITests: XCTestCase {
145145
IterableAPI.initialize(apiKey: IterableAPITests.apiKey, networkSession: networkSession)
146146

147147
IterableAPI.register(token: "zeeToken".data(using: .utf8)!, onSuccess: { (dict) in
148-
XCTFail()
148+
XCTFail("did not expect success here")
149149
}) {(_,_) in
150150
// failure
151151
expectation.fulfill()
@@ -166,7 +166,7 @@ class IterableAPITests: XCTestCase {
166166
IterableAPI.userId = nil
167167

168168
IterableAPI.register(token: "zeeToken".data(using: .utf8)!, onSuccess: { (dict) in
169-
XCTFail()
169+
XCTFail("did not expect success here")
170170
}) {(_,_) in
171171
// failure
172172
expectation.fulfill()
@@ -193,9 +193,13 @@ class IterableAPITests: XCTestCase {
193193
TestUtils.validateMatch(keyPath: KeyPath("device.token"), value: (token as NSData).iteHexadecimalString(), inDictionary: body)
194194

195195
expectation.fulfill()
196-
}) {(_,_) in
196+
}) {(reason, _) in
197197
// failure
198-
XCTFail()
198+
if let reason = reason {
199+
XCTFail("encountered error: \(reason)")
200+
} else {
201+
XCTFail("encountered error")
202+
}
199203
}
200204

201205
// only wait for small time, supposed to error out
@@ -212,7 +216,7 @@ class IterableAPITests: XCTestCase {
212216
IterableAPI.email = "[email protected]"
213217

214218
IterableAPI.disableDeviceForCurrentUser(withOnSuccess: { (json) in
215-
XCTFail()
219+
XCTFail("did not expect success here")
216220
}) { (errorMessage, data) in
217221
expectation.fulfill()
218222
}
@@ -256,9 +260,7 @@ class IterableAPITests: XCTestCase {
256260
config.pushIntegrationName = "my-push-integration"
257261
IterableAPI.initialize(apiKey: IterableAPITests.apiKey, config:config, networkSession: networkSession)
258262
IterableAPI.email = "[email protected]"
259-
IterableAPI.userId = "zeeUserId"
260263
let token = "zeeToken".data(using: .utf8)!
261-
IterableAPI.register(token: token)
262264
networkSession.callback = {(data, response, error) in
263265
networkSession.callback = nil
264266
IterableAPI.disableDeviceForAllUsers(withOnSuccess: { (json) in
@@ -272,6 +274,7 @@ class IterableAPITests: XCTestCase {
272274
expectation.fulfill()
273275
}
274276
}
277+
IterableAPI.register(token: token)
275278

276279
// only wait for small time, supposed to error out
277280
wait(for: [expectation], timeout: testExpectationTimeout)
@@ -287,7 +290,7 @@ class IterableAPITests: XCTestCase {
287290

288291
IterableAPI.track(purchase: 10.0, items: [], dataFields: nil, onSuccess: { (json) in
289292
// no userid or email should fail
290-
XCTFail()
293+
XCTFail("did not expect success here")
291294
}) { (errorMessage, data) in
292295
expectation.fulfill()
293296
}
@@ -312,8 +315,12 @@ class IterableAPITests: XCTestCase {
312315
TestUtils.validateElementPresent(withName: ITBL_KEY_TOTAL, andValue: 10.55, inDictionary: body)
313316

314317
expectation.fulfill()
315-
}) { (errorMessage, data) in
316-
XCTFail()
318+
}) { (reason, _) in
319+
if let reason = reason {
320+
XCTFail("encountered error: \(reason)")
321+
} else {
322+
XCTFail("encountered error")
323+
}
317324
}
318325

319326
// only wait for small time, supposed to error out
@@ -344,11 +351,14 @@ class IterableAPITests: XCTestCase {
344351
TestUtils.validateElementPresent(withName: "price", andValue: 5.0, inDictionary: firstElement)
345352
TestUtils.validateElementPresent(withName: "quantity", andValue: 2, inDictionary: firstElement)
346353
expectation.fulfill()
347-
}) { (errorMessage, data) in
348-
XCTFail()
354+
}) { (reason, _) in
355+
if let reason = reason {
356+
XCTFail("encountered error: \(reason)")
357+
} else {
358+
XCTFail("encountered error")
359+
}
349360
}
350361

351-
// only wait for small time, supposed to error out
352362
wait(for: [expectation], timeout: testExpectationTimeout)
353363
}
354364
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//
2+
//
3+
// Created by Tapash Majumder on 8/15/18.
4+
// Copyright © 2018 Iterable. All rights reserved.
5+
//
6+
7+
import XCTest
8+
9+
@testable import IterableSDK
10+
11+
class IterableAutoRegistrationTests: XCTestCase {
12+
private static let apiKey = "zeeApiKey"
13+
14+
override func setUp() {
15+
super.setUp()
16+
17+
TestUtils.clearUserDefaults()
18+
}
19+
20+
override func tearDown() {
21+
// Put teardown code here. This method is called after the invocation of each test method in the class.
22+
super.tearDown()
23+
}
24+
25+
func testCallDisableAndEnable() {
26+
let expectation1 = expectation(description: "call register device API")
27+
let expectation2 = expectation(description: "call registerForRemoteNotifications twice")
28+
expectation2.expectedFulfillmentCount = 2
29+
let expectation3 = expectation(description: "call disable on [email protected]")
30+
31+
let networkSession = MockNetworkSession(statusCode: 200)
32+
let config = IterableConfig()
33+
config.pushIntegrationName = "my-push-integration"
34+
config.autoPushRegistration = true
35+
36+
let notificationStateProvider = MockNotificationStateProvider(enabled: true, expectation: expectation2)
37+
38+
IterableAPI.initialize(apiKey: IterableAutoRegistrationTests.apiKey, config:config, networkSession: networkSession, notificationStateProvider: notificationStateProvider)
39+
IterableAPI.email = "[email protected]"
40+
let token = "zeeToken".data(using: .utf8)!
41+
networkSession.callback = {(_, _, _) in
42+
// First call, API call to register endpoint
43+
expectation1.fulfill()
44+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_REGISTER_DEVICE_TOKEN, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
45+
networkSession.callback = {(_, _, _)in
46+
// Second call, API call to disable endpoint
47+
expectation3.fulfill()
48+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_DISABLE_DEVICE, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
49+
let body = networkSession.getRequestBody() as! [String : Any]
50+
TestUtils.validateElementPresent(withName: ITBL_KEY_TOKEN, andValue: (token as NSData).iteHexadecimalString(), inDictionary: body)
51+
TestUtils.validateElementPresent(withName: ITBL_KEY_EMAIL, andValue: "[email protected]", inDictionary: body)
52+
}
53+
54+
IterableAPI.email = "[email protected]"
55+
}
56+
IterableAPI.register(token: token)
57+
58+
// only wait for small time, supposed to error out
59+
wait(for: [expectation1, expectation2, expectation3], timeout: testExpectationTimeout)
60+
}
61+
62+
func testDoNotCallDisableAndEnableWhenSameValue() {
63+
let expectation1 = expectation(description: "registerForRemoteNotifications")
64+
65+
let networkSession = MockNetworkSession(statusCode: 200)
66+
let config = IterableConfig()
67+
config.pushIntegrationName = "my-push-integration"
68+
config.autoPushRegistration = true
69+
// notifications are enabled
70+
let notificationStateProvider = MockNotificationStateProvider(enabled: true, expectation: expectation1)
71+
72+
IterableAPI.initialize(apiKey: IterableAutoRegistrationTests.apiKey, config:config, networkSession: networkSession, notificationStateProvider: notificationStateProvider)
73+
let email = "[email protected]"
74+
IterableAPI.email = email
75+
let token = "zeeToken".data(using: .utf8)!
76+
networkSession.callback = {(_, _, _) in
77+
// first call back will be called on register
78+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_REGISTER_DEVICE_TOKEN, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
79+
networkSession.callback = {(_, _, _)in
80+
// Second callback should not happen
81+
XCTFail("Should not call disable")
82+
}
83+
// set same value
84+
IterableAPI.email = email
85+
}
86+
IterableAPI.register(token: token)
87+
88+
// only wait for small time, supposed to error out
89+
wait(for: [expectation1], timeout: testExpectationTimeout)
90+
}
91+
92+
func testDoNotCallRegisterForRemoteNotificationsWhenNotificationsAreDisabled() {
93+
let expectation1 = expectation(description: "Call registerToken API endpoint")
94+
let expectation2 = expectation(description: "Disable API endpoint called")
95+
let expectation3 = expectation(description: "do not call registerForRemoteNotifications")
96+
expectation3.isInverted = true
97+
98+
let networkSession = MockNetworkSession(statusCode: 200)
99+
let config = IterableConfig()
100+
config.pushIntegrationName = "my-push-integration"
101+
let notificationStateProvider = MockNotificationStateProvider(enabled: false, expectation: expectation3) // Notifications are disabled
102+
103+
IterableAPI.initialize(apiKey: IterableAutoRegistrationTests.apiKey,
104+
config: config,
105+
networkSession: networkSession,
106+
notificationStateProvider: notificationStateProvider)
107+
IterableAPI.userId = "userId1"
108+
let token = "zeeToken".data(using: .utf8)!
109+
networkSession.callback = {(_, _, _) in
110+
// first call back will be called on register
111+
expectation1.fulfill()
112+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_REGISTER_DEVICE_TOKEN, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
113+
networkSession.callback = {(_, _, _) in
114+
// second call back is for disable when we set new user id
115+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_DISABLE_DEVICE, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
116+
let body = networkSession.getRequestBody() as! [String : Any]
117+
TestUtils.validateElementPresent(withName: ITBL_KEY_TOKEN, andValue: (token as NSData).iteHexadecimalString(), inDictionary: body)
118+
TestUtils.validateElementPresent(withName: ITBL_KEY_USER_ID, andValue: "userId1", inDictionary: body)
119+
expectation2.fulfill()
120+
}
121+
IterableAPI.userId = "userId2"
122+
}
123+
IterableAPI.register(token: token)
124+
125+
// only wait for small time, supposed to error out
126+
wait(for: [expectation1, expectation2, expectation3], timeout: 1.0)
127+
}
128+
129+
func testDoNotCallDisableOrEnableWhenAutoPushIsOff() {
130+
let expectation1 = expectation(description: "do not call register for remote")
131+
expectation1.isInverted = true
132+
133+
let networkSession = MockNetworkSession(statusCode: 200)
134+
let config = IterableConfig()
135+
config.pushIntegrationName = "my-push-integration"
136+
config.autoPushRegistration = false
137+
let notificationStateProvider = MockNotificationStateProvider(enabled: true, expectation: expectation1)
138+
139+
IterableAPI.initialize(apiKey: IterableAutoRegistrationTests.apiKey, config:config, networkSession: networkSession, notificationStateProvider: notificationStateProvider)
140+
IterableAPI.email = "[email protected]"
141+
let token = "zeeToken".data(using: .utf8)!
142+
networkSession.callback = {(_, _, _) in
143+
// first call back will be called on register
144+
TestUtils.validate(request: networkSession.request!, requestType: .post, apiEndPoint: ITBConsts.apiEndpoint, path: ENDPOINT_REGISTER_DEVICE_TOKEN, queryParams: [(name: ITBL_KEY_API_KEY, value: IterableAutoRegistrationTests.apiKey)])
145+
networkSession.callback = {(_, _, _)in
146+
// Second callback should not happen
147+
XCTFail("should not call disable")
148+
}
149+
IterableAPI.email = "[email protected]"
150+
}
151+
IterableAPI.register(token: token)
152+
153+
// only wait for small time, supposed to error out
154+
wait(for: [expectation1], timeout: 1.0)
155+
}
156+
157+
func testAutomaticPushRegistrationOnInit() {
158+
let expectation1 = expectation(description: "call register for remote")
159+
160+
let networkSession = MockNetworkSession(statusCode: 200)
161+
let config = IterableConfig()
162+
config.pushIntegrationName = "my-push-integration"
163+
config.autoPushRegistration = true
164+
let notificationStateProvider = MockNotificationStateProvider(enabled: true, expectation: expectation1)
165+
166+
UserDefaults.standard.set("[email protected]", forKey:ITBConsts.UserDefaults.emailKey)
167+
IterableAPI.initialize(apiKey: IterableAutoRegistrationTests.apiKey, config:config, networkSession: networkSession, notificationStateProvider: notificationStateProvider)
168+
169+
// only wait for small time, supposed to error out
170+
wait(for: [expectation1], timeout: testExpectationTimeout)
171+
}
172+
173+
}

0 commit comments

Comments
 (0)