aboutsummaryrefslogtreecommitdiffhomepage
path: root/Example/Messaging/Tests/FIRMessagingTest.m
diff options
context:
space:
mode:
Diffstat (limited to 'Example/Messaging/Tests/FIRMessagingTest.m')
-rw-r--r--Example/Messaging/Tests/FIRMessagingTest.m214
1 files changed, 214 insertions, 0 deletions
diff --git a/Example/Messaging/Tests/FIRMessagingTest.m b/Example/Messaging/Tests/FIRMessagingTest.m
new file mode 100644
index 0000000..3d7c95f
--- /dev/null
+++ b/Example/Messaging/Tests/FIRMessagingTest.m
@@ -0,0 +1,214 @@
+/*
+ * 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;
+
+#import <OCMock/OCMock.h>
+
+#import "FIRMessaging.h"
+#import "FIRMessagingConfig.h"
+#import "FIRMessagingInstanceIDProxy.h"
+
+extern NSString *const kFIRMessagingFCMTokenFetchAPNSOption;
+
+@interface FIRMessaging ()
+
+@property(nonatomic, readwrite, strong) NSString *defaultFcmToken;
+@property(nonatomic, readwrite, strong) NSData *apnsTokenData;
+@property(nonatomic, readwrite, strong) FIRMessagingInstanceIDProxy *instanceIDProxy;
+
+- (instancetype)initWithConfig:(FIRMessagingConfig *)config;
+// Direct Channel Methods
+- (void)updateAutomaticClientConnection;
+- (BOOL)shouldBeConnectedAutomatically;
+
+@end
+
+@interface FIRMessagingTest : XCTestCase
+
+@property(nonatomic, readonly, strong) FIRMessaging *messaging;
+@property(nonatomic, readwrite, strong) id mockMessaging;
+@property(nonatomic, readwrite, strong) id mockInstanceIDProxy;
+
+@end
+
+@implementation FIRMessagingTest
+
+- (void)setUp {
+ [super setUp];
+ FIRMessagingConfig *config = [FIRMessagingConfig defaultConfig];
+ _messaging = [[FIRMessaging alloc] initWithConfig:config];
+ _mockMessaging = OCMPartialMock(self.messaging);
+ _mockInstanceIDProxy = OCMPartialMock(self.messaging.instanceIDProxy);
+ self.messaging.instanceIDProxy = _mockInstanceIDProxy;
+}
+
+- (void)tearDown {
+ _messaging = nil;
+ _mockMessaging = nil;
+ [super tearDown];
+}
+
+#pragma mark - Direct Channel Establishment Testing
+
+// Should connect with valid token and application in foreground
+- (void)testDoesAutomaticallyConnectIfTokenAvailableAndForegrounded {
+ // Disable actually attempting a connection
+ [[[_mockMessaging stub] andDo:^(NSInvocation *invocation) {
+ // Doing nothing on purpose, when -updateAutomaticClientConnection is called
+ }] updateAutomaticClientConnection];
+ // Set direct channel to be established after disabling connection attempt
+ self.messaging.shouldEstablishDirectChannel = YES;
+ // Set a "valid" token (i.e. not nil or empty)
+ self.messaging.defaultFcmToken = @"1234567";
+ // Swizzle application state to return UIApplicationStateActive
+ UIApplication *app = [UIApplication sharedApplication];
+ id mockApp = OCMPartialMock(app);
+ [[[mockApp stub] andReturnValue:@(UIApplicationStateActive)] applicationState];
+ BOOL shouldBeConnected = [_mockMessaging shouldBeConnectedAutomatically];
+ XCTAssertTrue(shouldBeConnected);
+}
+
+// Should not connect if application is active, but token is empty
+- (void)testDoesNotAutomaticallyConnectIfTokenIsEmpty {
+ // Disable actually attempting a connection
+ [[[_mockMessaging stub] andDo:^(NSInvocation *invocation) {
+ // Doing nothing on purpose, when -updateAutomaticClientConnection is called
+ }] updateAutomaticClientConnection];
+ // Set direct channel to be established after disabling connection attempt
+ self.messaging.shouldEstablishDirectChannel = YES;
+ // By default, there should be no fcmToken
+ // Swizzle application state to return UIApplicationStateActive
+ UIApplication *app = [UIApplication sharedApplication];
+ id mockApp = OCMPartialMock(app);
+ [[[mockApp stub] andReturnValue:@(UIApplicationStateActive)] applicationState];
+ BOOL shouldBeConnected = [_mockMessaging shouldBeConnectedAutomatically];
+ XCTAssertFalse(shouldBeConnected);
+}
+
+// Should not connect if token valid but application isn't active
+- (void)testDoesNotAutomaticallyConnectIfApplicationNotActive {
+ // Disable actually attempting a connection
+ [[[_mockMessaging stub] andDo:^(NSInvocation *invocation) {
+ // Doing nothing on purpose, when -updateAutomaticClientConnection is called
+ }] updateAutomaticClientConnection];
+ // Set direct channel to be established after disabling connection attempt
+ self.messaging.shouldEstablishDirectChannel = YES;
+ // Set a "valid" token (i.e. not nil or empty)
+ self.messaging.defaultFcmToken = @"abcd1234";
+ // Swizzle application state to return UIApplicationStateActive
+ UIApplication *app = [UIApplication sharedApplication];
+ id mockApp = OCMPartialMock(app);
+ [[[mockApp stub] andReturnValue:@(UIApplicationStateBackground)] applicationState];
+ BOOL shouldBeConnected = [_mockMessaging shouldBeConnectedAutomatically];
+ XCTAssertFalse(shouldBeConnected);
+}
+
+#pragma mark - FCM Token Fetching and Deleting
+
+#ifdef NEED_WORKAROUND_FOR_PRIVATE_OCMOCK_getArgumentAtIndexAsObject
+- (void)testAPNSTokenIncludedInOptionsIfAvailableDuringTokenFetch {
+ self.messaging.apnsTokenData =
+ [@"PRETENDING_TO_BE_A_DEVICE_TOKEN" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Included APNS Token data in options dict."];
+ // Inspect the 'options' dictionary to tell whether our expectation was fulfilled
+ [[[self.mockInstanceIDProxy stub] andDo:^(NSInvocation *invocation) {
+ // Calling getArgument:atIndex: directly leads to an EXC_BAD_ACCESS; use OCMock's wrapper.
+ NSDictionary *options = [invocation getArgumentAtIndexAsObject:4];
+ if (options[@"apns_token"] != nil) {
+ [expectation fulfill];
+ }
+ }] tokenWithAuthorizedEntity:OCMOCK_ANY scope:OCMOCK_ANY options:OCMOCK_ANY handler:OCMOCK_ANY];
+ [self.messaging retrieveFCMTokenForSenderID:@"123456"
+ completion:^(NSString * _Nullable FCMToken,
+ NSError * _Nullable error) {}];
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+
+- (void)testAPNSTokenNotIncludedIfUnavailableDuringTokenFetch {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Included APNS Token data not included in options dict."];
+ // Inspect the 'options' dictionary to tell whether our expectation was fulfilled
+ [[[self.mockInstanceIDProxy stub] andDo:^(NSInvocation *invocation) {
+ // Calling getArgument:atIndex: directly leads to an EXC_BAD_ACCESS; use OCMock's wrapper.
+ NSDictionary *options = [invocation getArgumentAtIndexAsObject:4];
+ if (options[@"apns_token"] == nil) {
+ [expectation fulfill];
+ }
+ }] tokenWithAuthorizedEntity:OCMOCK_ANY scope:OCMOCK_ANY options:OCMOCK_ANY handler:OCMOCK_ANY];
+ [self.messaging retrieveFCMTokenForSenderID:@"123456"
+ completion:^(NSString * _Nullable FCMToken,
+ NSError * _Nullable error) {}];
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+#endif
+
+- (void)testReturnsErrorWhenFetchingTokenWithoutSenderID {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Returned an error fetching token without Sender ID"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+ [self.messaging retrieveFCMTokenForSenderID:nil
+ completion:
+ ^(NSString * _Nullable FCMToken, NSError * _Nullable error) {
+ if (error != nil) {
+ [expectation fulfill];
+ }
+ }];
+#pragma clang diagnostic pop
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+
+- (void)testReturnsErrorWhenFetchingTokenWithEmptySenderID {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Returned an error fetching token with empty Sender ID"];
+ [self.messaging retrieveFCMTokenForSenderID:@""
+ completion:
+ ^(NSString * _Nullable FCMToken, NSError * _Nullable error) {
+ if (error != nil) {
+ [expectation fulfill];
+ }
+ }];
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+
+- (void)testReturnsErrorWhenDeletingTokenWithoutSenderID {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Returned an error deleting token without Sender ID"];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+ [self.messaging deleteFCMTokenForSenderID:nil completion:^(NSError * _Nullable error) {
+ if (error != nil) {
+ [expectation fulfill];
+ }
+ }];
+#pragma clang diagnostic pop
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+
+- (void)testReturnsErrorWhenDeletingTokenWithEmptySenderID {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Returned an error deleting token with empty Sender ID"];
+ [self.messaging deleteFCMTokenForSenderID:@"" completion:^(NSError * _Nullable error) {
+ if (error != nil) {
+ [expectation fulfill];
+ }
+ }];
+ [self waitForExpectationsWithTimeout:0.1 handler:nil];
+}
+
+@end