= settings.authorizationStatus; if (status != UNAuthorizationStatusAuthorized) { NSError *error = [[NSError alloc] initWithDomain:@"UnauthorizedPushError" code:404 userInfo:@{}]; if (self.registrationCompletionHandler) { self.registrationCompletionHandler(nil, error); } // FIXME: Should the `registrationCompletionHandler` be nilled // here, like in all other cases after it has been called? return; } dispatch_async(dispatch_get_main_queue(), ^{ [application registerForRemoteNotifications]; }); }]; 18 — @basthomas
@escaping (Bool, Error?) -> Void ) /// This is expected to be a shim around `getNotificationSettings` that is /// usable from Objective-C. Due to selectors, we can not shadow the name /// with only a different type as a closure parameter. func requestNotificationSettings( completionHandler: @escaping (NotificationSettings) -> Void ) func setNotificationCategories(_ categories: Set<UNNotificationCategory>) } extension UNUserNotificationCenter: NotificationRequester { public func requestNotificationSettings( completionHandler: @escaping (NotificationSettings) -> Void ) { getNotificationSettings(completionHandler: completionHandler) } } 24 — @basthomas
{ case notDetermined case `true` case `false` } var didCallRequestAuthorization = false var didCallHandleNotificationAuthorization = false var didCallRequestAuthorizationViaDeeplink: RequestedViaDeeplink = .notDetermined var didCallHandleNotificationAuthorizationViaDeeplink: RequestedViaDeeplink = .notDetermined // omitting `registerForRemoteNotifications`, as it is not used. 26 — @basthomas
return XCTFail("Expected to have a non-nil delegate.") } XCTAssertNotNil(delegate.requestAuthorization) // given we request notifications with deeplink = true let mockTracker = MockTracker() delegate.requestAuthorization?( viaDeeplink: true, notificationRequester: mockNotificationRequester, tracker: mockTracker, application: mockApplication ) // it SHOULD track let status = UNAuthorizationStatus.authorized let trackAction = UNUserNotificationCenter.description(for: status) XCTAssertTrue(mockTracker.didLog(origin: trackOrigin, action: trackAction)) } 33 — @basthomas
return XCTFail("Expected to have a non-nil delegate.") } XCTAssertNotNil(delegate.requestAuthorization) // given we request notifications with deeplink = true let mockTracker = MockTracker() delegate.requestAuthorization?( viaDeeplink: true, notificationRequester: mockNotificationRequester, tracker: mockTracker, application: mockApplication ) // it SHOULD track let status = UNAuthorizationStatus.authorized let trackAction = UNUserNotificationCenter.description(for: status) XCTAssertTrue(mockTracker.didLog(origin: trackOrigin, action: trackAction)) } 34 — @basthomas
testable code helps with more than tests ▸ Protocols and default expressions are ok ▸ Utilize assertions and preconditions ▸ Keep side effects in check 41 — @basthomas
testable code helps with more than tests ▸ Protocols and default expressions are ok ▸ Utilize assertions and preconditions ▸ Keep side effects in check ▸ Mixing Objective-C & Swift is still difficult 41 — @basthomas