FIRAuthNotificationManagerTests.m 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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 "FIRAuthAppCredential.h"
  18. #import "FIRAuthAppCredentialManager.h"
  19. #import "FIRAuthNotificationManager.h"
  20. #import <OCMock/OCMock.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
  152. delegate:(FIRAuthFakeForwardingDelegate *)delegate {
  153. delegate.forwardsNotification = forwarding;
  154. OCMStub([_mockApplication delegate]).andReturn(delegate);
  155. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  156. [_notificationManager
  157. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  158. XCTAssertEqual(isNotificationBeingForwarded, forwarding);
  159. [expectation fulfill];
  160. }];
  161. XCTAssertFalse(delegate.notificationReceived);
  162. NSTimeInterval timeout = _notificationManager.timeout * (1.5 - forwarding);
  163. [self waitForExpectationsWithTimeout:timeout handler:nil];
  164. XCTAssertTrue(delegate.notificationReceived);
  165. XCTAssertEqual(delegate.notificationhandled, forwarding);
  166. }
  167. /** @fn testCachedResult
  168. @brief Test notification forwarding is only checked once.
  169. */
  170. - (void)testCachedResult {
  171. FIRAuthFakeForwardingDelegate *delegate = _modernDelegate;
  172. [self verifyForwarding:NO delegate:delegate];
  173. delegate.notificationReceived = NO;
  174. __block BOOL calledBack = NO;
  175. [_notificationManager
  176. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  177. XCTAssertFalse(isNotificationBeingForwarded);
  178. calledBack = YES;
  179. }];
  180. XCTAssertTrue(calledBack);
  181. XCTAssertFalse(delegate.notificationReceived);
  182. }
  183. /** @fn testMultipleCallbacks
  184. @brief Test multiple callbacks are handled correctly.
  185. */
  186. - (void)testMultipleCallbacks {
  187. FIRAuthFakeForwardingDelegate *delegate = _legacyDelegate;
  188. delegate.forwardsNotification = YES;
  189. OCMStub([_mockApplication delegate]).andReturn(delegate);
  190. XCTestExpectation *expectation1 = [self expectationWithDescription:@"callback1"];
  191. [_notificationManager
  192. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  193. XCTAssertTrue(isNotificationBeingForwarded);
  194. [expectation1 fulfill];
  195. }];
  196. XCTestExpectation *expectation2 = [self expectationWithDescription:@"callback2"];
  197. [_notificationManager
  198. checkNotificationForwardingWithCallback:^(BOOL isNotificationBeingForwarded) {
  199. XCTAssertTrue(isNotificationBeingForwarded);
  200. [expectation2 fulfill];
  201. }];
  202. XCTAssertFalse(delegate.notificationReceived);
  203. [self waitForExpectationsWithTimeout:_notificationManager.timeout * .5 handler:nil];
  204. XCTAssertTrue(delegate.notificationReceived);
  205. XCTAssertTrue(delegate.notificationhandled);
  206. }
  207. /** @fn testPassingToCredentialManager
  208. @brief Test notification with the right structure is passed to credential manager.
  209. */
  210. - (void)testPassingToCredentialManager {
  211. NSDictionary *payload = @{ @"receipt" : kReceipt, @"secret" : kSecret };
  212. NSDictionary *notification = @{ @"com.google.firebase.auth" : payload };
  213. OCMExpect([_mockAppCredentialManager canFinishVerificationWithReceipt:kReceipt secret:kSecret])
  214. .andReturn(YES);
  215. XCTAssertTrue([_notificationManager canHandleNotification:notification]);
  216. OCMVerifyAll(_mockAppCredentialManager);
  217. // JSON string form
  218. NSData *data = [NSJSONSerialization dataWithJSONObject:payload options:0 error:NULL];
  219. NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  220. notification = @{ @"com.google.firebase.auth" : string };
  221. OCMExpect([_mockAppCredentialManager canFinishVerificationWithReceipt:kReceipt secret:kSecret])
  222. .andReturn(YES);
  223. XCTAssertTrue([_notificationManager canHandleNotification:notification]);
  224. OCMVerifyAll(_mockAppCredentialManager);
  225. }
  226. /** @fn testNotHandling
  227. @brief Test unrecognized notifications are not handled.
  228. */
  229. - (void)testNotHandling {
  230. XCTAssertFalse([_notificationManager canHandleNotification:@{
  231. @"random" : @"string"
  232. }]);
  233. XCTAssertFalse([_notificationManager canHandleNotification:@{
  234. @"com.google.firebase.auth" : @"something wrong"
  235. }]);
  236. XCTAssertFalse([_notificationManager canHandleNotification:@{
  237. @"com.google.firebase.auth" : @{
  238. @"receipt" : kReceipt
  239. // missing secret
  240. }
  241. }]);
  242. XCTAssertFalse([_notificationManager canHandleNotification:@{
  243. @"com.google.firebase.auth" : @{
  244. // missing receipt
  245. @"secret" : kSecret
  246. }
  247. }]);
  248. XCTAssertFalse([_notificationManager canHandleNotification:@{
  249. @"com.google.firebase.auth" : @{
  250. // probing notification does not belong to this instance
  251. @"warning" : @"asdf"
  252. }
  253. }]);
  254. }
  255. @end
  256. NS_ASSUME_NONNULL_END