FIRAuthNotificationManagerTests.m 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <XCTest/XCTest.h>
  17. #import <OCMock/OCMock.h>
  18. #import "FIRAuthAppCredential.h"
  19. #import "FIRAuthAppCredentialManager.h"
  20. #import "FIRAuthNotificationManager.h"
  21. NS_ASSUME_NONNULL_BEGIN
  22. /** @var kReceipt
  23. @brief A fake receipt used for testing.
  24. */
  25. static NSString *const kReceipt = @"FAKE_RECEIPT";
  26. /** @var kSecret
  27. @brief A fake secret used for testing.
  28. */
  29. static NSString *const kSecret = @"FAKE_SECRET";
  30. /** @class FIRAuthFakeForwardingDelegate
  31. @brief The base class for a fake UIApplicationDelegate that forwards remote notifications.
  32. */
  33. @interface FIRAuthFakeForwardingDelegate : NSObject <UIApplicationDelegate>
  34. /** @property notificationManager
  35. @brief The notification manager to forward.
  36. */
  37. @property(nonatomic, strong) FIRAuthNotificationManager *notificationManager;
  38. /** @property forwardsNotification
  39. @brief Whether notifications are being forwarded.
  40. */
  41. @property(nonatomic, assign) BOOL forwardsNotification;
  42. /** @property notificationReceived
  43. @brief Whether a notification has been received.
  44. */
  45. @property(nonatomic, assign) BOOL notificationReceived;
  46. /** @property notificationhandled
  47. @brief Whether a notification has been handled.
  48. */
  49. @property(nonatomic, assign) BOOL notificationhandled;
  50. @end
  51. @implementation FIRAuthFakeForwardingDelegate
  52. @end
  53. /** @class FIRAuthFakeForwardingDelegate
  54. @brief A fake UIApplicationDelegate that implements the modern deegate method to receive
  55. notification.
  56. */
  57. @interface FIRAuthModernForwardingDelegate : FIRAuthFakeForwardingDelegate
  58. @end
  59. @implementation FIRAuthModernForwardingDelegate
  60. - (void)application:(UIApplication *)application
  61. didReceiveRemoteNotification:(NSDictionary *)userInfo
  62. fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  63. self.notificationReceived = YES;
  64. if (self.forwardsNotification) {
  65. self.notificationhandled = [self.notificationManager canHandleNotification:userInfo];
  66. }
  67. }
  68. @end
  69. /** @class FIRAuthLegacyForwardingDelegate
  70. @brief A fake UIApplicationDelegate that implements the legacy deegate method to receive
  71. notification.
  72. */
  73. @interface FIRAuthLegacyForwardingDelegate : FIRAuthFakeForwardingDelegate
  74. @end
  75. @implementation FIRAuthLegacyForwardingDelegate
  76. - (void)application:(UIApplication *)application
  77. didReceiveRemoteNotification:(NSDictionary *)userInfo {
  78. self.notificationReceived = YES;
  79. if (self.forwardsNotification) {
  80. self.notificationhandled = [self.notificationManager canHandleNotification:userInfo];
  81. }
  82. }
  83. @end
  84. /** @class FIRAuthNotificationManagerTests
  85. @brief Unit tests for @c FIRAuthNotificationManager .
  86. */
  87. @interface FIRAuthNotificationManagerTests : XCTestCase
  88. @end
  89. @implementation FIRAuthNotificationManagerTests {
  90. /** @var _mockApplication
  91. @brief The mock UIApplication for testing.
  92. */
  93. id _mockApplication;
  94. /** @var _mockAppCredentialManager
  95. @brief The mock FIRAuthAppCredentialManager for testing.
  96. */
  97. id _mockAppCredentialManager;
  98. /** @var _notificationManager
  99. @brief The FIRAuthNotificationManager to be tested.
  100. */
  101. FIRAuthNotificationManager *_notificationManager;
  102. /** @var _modernDelegate
  103. @brief The modern fake UIApplicationDelegate for testing.
  104. */
  105. FIRAuthModernForwardingDelegate *_modernDelegate;
  106. /** @var _legacyDelegate
  107. @brief The legacy fake UIApplicationDelegate for testing.
  108. */
  109. FIRAuthLegacyForwardingDelegate *_legacyDelegate;
  110. }
  111. - (void)setUp {
  112. _mockApplication = OCMClassMock([UIApplication class]);
  113. _mockAppCredentialManager = OCMClassMock([FIRAuthAppCredentialManager class]);
  114. _notificationManager =
  115. [[FIRAuthNotificationManager alloc] initWithApplication:_mockApplication
  116. appCredentialManager:_mockAppCredentialManager];
  117. _modernDelegate = [[FIRAuthModernForwardingDelegate alloc] init];
  118. _modernDelegate.notificationManager = _notificationManager;
  119. _legacyDelegate = [[FIRAuthLegacyForwardingDelegate alloc] init];
  120. _legacyDelegate.notificationManager = _notificationManager;
  121. }
  122. /** @fn testForwardingModernDelegate
  123. @brief Tests checking notification forwarding on modern fake delegate.
  124. */
  125. - (void)testForwardingModernDelegate {
  126. [self verifyForwarding:YES delegate:_modernDelegate];
  127. }
  128. /** @fn testForwardingLegacyDelegate
  129. @brief Tests checking notification forwarding on legacy fake delegate.
  130. */
  131. - (void)testForwardingLegacyDelegate {
  132. [self verifyForwarding:YES delegate:_legacyDelegate];
  133. }
  134. /** @fn testNotForwardingModernDelegate
  135. @brief Tests checking notification not forwarding on modern fake delegate.
  136. */
  137. - (void)testNotForwardingModernDelegate {
  138. [self verifyForwarding:NO delegate:_modernDelegate];
  139. }
  140. /** @fn testNotForwardingLegacyDelegate
  141. @brief Tests checking notification not forwarding on legacy fake delegate.
  142. */
  143. - (void)testNotForwardingLegacyDelegate {
  144. [self verifyForwarding:NO delegate:_legacyDelegate];
  145. }
  146. /** @fn verifyForwarding:delegate:
  147. @brief Tests checking notification forwarding on a particular delegate.
  148. @param forwarding Whether the notification is being forwarded or not.
  149. @param delegate The fake UIApplicationDelegate used for testing.
  150. */
  151. - (void)verifyForwarding:(BOOL)forwarding delegate:(FIRAuthFakeForwardingDelegate *)delegate {
  152. delegate.forwardsNotification = forwarding;
  153. OCMStub([_mockApplication delegate]).andReturn(delegate);
  154. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  155. [_notificationManager
  156. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  157. XCTAssertEqual(isNotificationBeingForwarded, forwarding);
  158. [expectation fulfill];
  159. }];
  160. XCTAssertFalse(delegate.notificationReceived);
  161. NSTimeInterval timeout = _notificationManager.timeout * (1.5 - forwarding);
  162. [self waitForExpectationsWithTimeout:timeout handler:nil];
  163. XCTAssertTrue(delegate.notificationReceived);
  164. XCTAssertEqual(delegate.notificationhandled, forwarding);
  165. }
  166. /** @fn testCachedResult
  167. @brief Test notification forwarding is only checked once.
  168. */
  169. - (void)testCachedResult {
  170. FIRAuthFakeForwardingDelegate *delegate = _modernDelegate;
  171. [self verifyForwarding:NO delegate:delegate];
  172. delegate.notificationReceived = NO;
  173. __block BOOL calledBack = NO;
  174. [_notificationManager
  175. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  176. XCTAssertFalse(isNotificationBeingForwarded);
  177. calledBack = YES;
  178. }];
  179. XCTAssertTrue(calledBack);
  180. XCTAssertFalse(delegate.notificationReceived);
  181. }
  182. /** @fn testMultipleCallbacks
  183. @brief Test multiple callbacks are handled correctly.
  184. */
  185. - (void)testMultipleCallbacks {
  186. FIRAuthFakeForwardingDelegate *delegate = _legacyDelegate;
  187. delegate.forwardsNotification = YES;
  188. OCMStub([_mockApplication delegate]).andReturn(delegate);
  189. XCTestExpectation *expectation1 = [self expectationWithDescription:@"callback1"];
  190. [_notificationManager
  191. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  192. XCTAssertTrue(isNotificationBeingForwarded);
  193. [expectation1 fulfill];
  194. }];
  195. XCTestExpectation *expectation2 = [self expectationWithDescription:@"callback2"];
  196. [_notificationManager
  197. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  198. XCTAssertTrue(isNotificationBeingForwarded);
  199. [expectation2 fulfill];
  200. }];
  201. XCTAssertFalse(delegate.notificationReceived);
  202. [self waitForExpectationsWithTimeout:_notificationManager.timeout * .5 handler:nil];
  203. XCTAssertTrue(delegate.notificationReceived);
  204. XCTAssertTrue(delegate.notificationhandled);
  205. }
  206. /** @fn testPassingToCredentialManager
  207. @brief Test notification with the right structure is passed to credential manager.
  208. */
  209. - (void)testPassingToCredentialManager {
  210. NSDictionary *payload = @{@"receipt" : kReceipt, @"secret" : kSecret};
  211. NSDictionary *notification = @{@"com.google.firebase.auth" : payload};
  212. OCMExpect([_mockAppCredentialManager canFinishVerificationWithReceipt:kReceipt secret:kSecret])
  213. .andReturn(YES);
  214. XCTAssertTrue([_notificationManager canHandleNotification:notification]);
  215. OCMVerifyAll(_mockAppCredentialManager);
  216. // JSON string form
  217. NSData *data = [NSJSONSerialization dataWithJSONObject:payload options:0 error:NULL];
  218. NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  219. notification = @{@"com.google.firebase.auth" : string};
  220. OCMExpect([_mockAppCredentialManager canFinishVerificationWithReceipt:kReceipt secret:kSecret])
  221. .andReturn(YES);
  222. XCTAssertTrue([_notificationManager canHandleNotification:notification]);
  223. OCMVerifyAll(_mockAppCredentialManager);
  224. }
  225. /** @fn testNotHandling
  226. @brief Test unrecognized notifications are not handled.
  227. */
  228. - (void)testNotHandling {
  229. XCTAssertFalse([_notificationManager canHandleNotification:@{@"random" : @"string"}]);
  230. XCTAssertFalse([_notificationManager
  231. canHandleNotification:@{@"com.google.firebase.auth" : @"something wrong"}]);
  232. XCTAssertFalse([_notificationManager canHandleNotification:@{
  233. @"com.google.firebase.auth" : @{
  234. @"receipt" : kReceipt
  235. // missing secret
  236. }
  237. }]);
  238. XCTAssertFalse([_notificationManager canHandleNotification:@{
  239. @"com.google.firebase.auth" : @{
  240. // missing receipt
  241. @"secret" : kSecret
  242. }
  243. }]);
  244. XCTAssertFalse([_notificationManager canHandleNotification:@{
  245. @"com.google.firebase.auth" : @{
  246. // probing notification does not belong to this instance
  247. @"warning" : @"asdf"
  248. }
  249. }]);
  250. }
  251. @end
  252. NS_ASSUME_NONNULL_END