Files
firebase-ios-sdk/Example/Auth/Tests/FIRAuthAPNSTokenManagerTests.m
T

275 lines
9.0 KiB
Objective-C

/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <XCTest/XCTest.h>
#import "FIRAuthAPNSToken.h"
#import "FIRAuthAPNSTokenManager.h"
#import <OCMock/OCMock.h>
NS_ASSUME_NONNULL_BEGIN
/** @var kRegistrationTimeout
@brief The registration timeout used for testing.
*/
static const NSTimeInterval kRegistrationTimeout = .5;
/** @var kExpectationTimeout
@brief The test expectation timeout.
@remarks This must be considerably greater than @c kVerificationTimeout .
*/
static const NSTimeInterval kExpectationTimeout = 2;
/** @class FIRAuthLegacyUIApplication
@brief A fake legacy (< iOS 7) UIApplication class.
@remarks A custom class is needed because `respondsToSelector:` itself cannot be mocked.
*/
@interface FIRAuthLegacyUIApplication : NSObject
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types;
#pragma clang diagnostic pop
@end
@implementation FIRAuthLegacyUIApplication
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types {
}
#pragma clang diagnostic pop
@end
/** @class FIRAuthAPNSTokenManagerTests
@brief Unit tests for @c FIRAuthAPNSTokenManager .
*/
@interface FIRAuthAPNSTokenManagerTests : XCTestCase
@end
@implementation FIRAuthAPNSTokenManagerTests {
/** @var _mockApplication
@brief The mock application for testing.
*/
id _mockApplication;
/** @var _manager
@brief The @c FIRAuthAPNSTokenManager instance under tests.
*/
FIRAuthAPNSTokenManager *_manager;
/** @var _data
@brief One piece of data used for testing.
*/
NSData *_data;
/** @var _otherData
@brief Another piece of data used for testing.
*/
NSData *_otherData;
/** @var _error
@brief The fake error used for testing.
*/
NSError *_error;
}
- (void)setUp {
_mockApplication = OCMClassMock([UIApplication class]);
_manager = [[FIRAuthAPNSTokenManager alloc] initWithApplication:_mockApplication];
_data = [@"qwerty" dataUsingEncoding:NSUTF8StringEncoding];
_otherData = [@"!@#$" dataUsingEncoding:NSUTF8StringEncoding];
}
/** @fn testSetToken
@brief Tests setting and getting the `token` property.
*/
- (void)testSetToken {
XCTAssertNil(_manager.token);
_manager.token = [[FIRAuthAPNSToken alloc] initWithData:_data type:FIRAuthAPNSTokenTypeProd];
XCTAssertEqualObjects(_manager.token.data, _data);
XCTAssertEqual(_manager.token.type, FIRAuthAPNSTokenTypeProd);
_manager.token = nil;
XCTAssertNil(_manager.token);
}
/** @fn testDetectTokenType
@brief Tests automatic detection of token type.
*/
- (void)testDetectTokenType {
XCTAssertNil(_manager.token);
_manager.token = [[FIRAuthAPNSToken alloc] initWithData:_data type:FIRAuthAPNSTokenTypeUnknown];
XCTAssertEqualObjects(_manager.token.data, _data);
XCTAssertNotEqual(_manager.token.type, FIRAuthAPNSTokenTypeUnknown);
}
/** @fn testCallback
@brief Tests callbacks are called.
*/
- (void)testCallback {
// Add first callback, which is yet to be called.
OCMExpect([_mockApplication registerForRemoteNotifications]);
__block BOOL firstCallbackCalled = NO;
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertEqualObjects(token.data, self->_data);
XCTAssertEqual(token.type, FIRAuthAPNSTokenTypeSandbox);
XCTAssertNil(error);
firstCallbackCalled = YES;
}];
XCTAssertFalse(firstCallbackCalled);
// Add second callback, which is yet to be called either.
__block BOOL secondCallbackCalled = NO;
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertEqualObjects(token.data, self->_data);
XCTAssertEqual(token.type, FIRAuthAPNSTokenTypeSandbox);
XCTAssertNil(error);
secondCallbackCalled = YES;
}];
XCTAssertFalse(secondCallbackCalled);
// Setting nil token shouldn't trigger either callbacks.
_manager.token = nil;
XCTAssertFalse(firstCallbackCalled);
XCTAssertFalse(secondCallbackCalled);
XCTAssertNil(_manager.token);
// Setting a real token should trigger both callbacks.
_manager.token = [[FIRAuthAPNSToken alloc] initWithData:_data type:FIRAuthAPNSTokenTypeSandbox];
XCTAssertTrue(firstCallbackCalled);
XCTAssertTrue(secondCallbackCalled);
XCTAssertEqualObjects(_manager.token.data, _data);
XCTAssertEqual(_manager.token.type, FIRAuthAPNSTokenTypeSandbox);
// Add third callback, which should be called back immediately.
__block BOOL thirdCallbackCalled = NO;
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertEqualObjects(token.data, self->_data);
XCTAssertEqual(token.type, FIRAuthAPNSTokenTypeSandbox);
XCTAssertNil(error);
thirdCallbackCalled = YES;
}];
XCTAssertTrue(thirdCallbackCalled);
// Verify the mock in the main thread.
XCTestExpectation *expectation = [self expectationWithDescription:@"verify mock"];
dispatch_async(dispatch_get_main_queue(), ^{
OCMVerifyAll(self->_mockApplication);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
}
/** @fn testTimeout
@brief Tests callbacks can be timed out.
*/
- (void)testTimeout {
// Set up timeout.
XCTAssertGreaterThan(_manager.timeout, 0);
_manager.timeout = kRegistrationTimeout;
// Add callback to time out.
OCMExpect([_mockApplication registerForRemoteNotifications]);
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertNil(token);
XCTAssertNil(error);
[expectation fulfill];
}];
// Time out.
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
OCMVerifyAll(_mockApplication);
// Calling cancel afterwards should have no effect.
[_manager cancelWithError:_error];
}
/** @fn testCancel
@brief Tests cancelling the pending callbacks.
*/
- (void)testCancel {
// Set up timeout.
XCTAssertGreaterThan(_manager.timeout, 0);
_manager.timeout = kRegistrationTimeout;
// Add callback to cancel.
OCMExpect([_mockApplication registerForRemoteNotifications]);
__block BOOL callbackCalled = NO;
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertNil(token);
XCTAssertEqualObjects(error, self->_error);
XCTAssertFalse(callbackCalled); // verify callback is not called twice
callbackCalled = YES;
}];
XCTAssertFalse(callbackCalled);
// Call cancel.
[_manager cancelWithError:_error];
XCTAssertTrue(callbackCalled);
// Add callback to timeout.
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertNil(token);
XCTAssertNil(error);
[expectation fulfill];
}];
// Time out.
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
OCMVerifyAll(_mockApplication);
}
/** @fn testLegacyRegistration
@brief Tests remote notification registration on legacy systems.
*/
- (void)testLegacyRegistration {
// Use a custom class for `respondsToSelector:` to work.
_mockApplication = OCMClassMock([FIRAuthLegacyUIApplication class]);
_manager = [[FIRAuthAPNSTokenManager alloc] initWithApplication:_mockApplication];
// Add callback.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[[_mockApplication expect] ignoringNonObjectArgs] registerForRemoteNotificationTypes:0];
#pragma clang diagnostic pop
__block BOOL callbackCalled = NO;
[_manager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token, NSError *_Nullable error) {
XCTAssertEqualObjects(token.data, self->_data);
XCTAssertNotEqual(token.type, FIRAuthAPNSTokenTypeUnknown);
XCTAssertNil(error);
callbackCalled = YES;
}];
XCTAssertFalse(callbackCalled);
// Set the token.
_manager.token = [[FIRAuthAPNSToken alloc] initWithData:_data type:FIRAuthAPNSTokenTypeUnknown];
XCTAssertTrue(callbackCalled);
// Verify the mock in the main thread.
XCTestExpectation *expectation = [self expectationWithDescription:@"verify mock"];
dispatch_async(dispatch_get_main_queue(), ^{
OCMVerifyAll(self->_mockApplication);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
}
@end
NS_ASSUME_NONNULL_END