@@ -549,6 +549,76 @@ - (void)testDefaultToken_validCachedToken {
549
549
XCTAssertEqualObjects ([self .mockInstanceID token ], kToken );
550
550
}
551
551
552
+ /* *
553
+ * Tests that the callback handler will be invoked when the default token is fetched
554
+ * despite the token being unchanged.
555
+ */
556
+ - (void )testDefaultToken_callbackInvokedForUnchangedToken {
557
+ XCTestExpectation *defaultTokenExpectation =
558
+ [self expectationWithDescription: @" Token fetch was successful." ];
559
+
560
+ __block FIRInstanceIDTokenInfo *cachedTokenInfo = nil ;
561
+
562
+ [self stubKeyPairStoreToReturnValidKeypair ];
563
+
564
+ [self mockAuthServiceToAlwaysReturnValidCheckin ];
565
+
566
+ // Mock Token manager to always succeed the token fetch, and return
567
+ // a particular cached value.
568
+
569
+ // Return a dynamic cachedToken variable whenever the cached is checked.
570
+ // This uses an invocation-based mock because the |cachedToken| pointer
571
+ // will change. Normal stubbing will always return the initial pointer,
572
+ // which in this case is 0x0 (nil).
573
+ [[[self .mockTokenManager stub ] andDo: ^(NSInvocation *invocation) {
574
+ [invocation setReturnValue: &cachedTokenInfo];
575
+ }] cachedTokenInfoWithAuthorizedEntity: kAuthorizedEntity scope: kFIRInstanceIDDefaultTokenScope ];
576
+
577
+ [[[self .mockTokenManager stub ] andDo: ^(NSInvocation *invocation) {
578
+ self.newTokenCompletion (kToken , nil );
579
+ }] fetchNewTokenWithAuthorizedEntity: kAuthorizedEntity
580
+ scope: kFIRInstanceIDDefaultTokenScope
581
+ keyPair: [OCMArg any ]
582
+ options: [OCMArg any ]
583
+ handler: [OCMArg checkWithBlock: ^BOOL (id obj) {
584
+ self.newTokenCompletion = obj;
585
+ return obj != nil ;
586
+ }]];
587
+
588
+ __block NSInteger notificationPostCount = 0 ;
589
+ __block NSString *notificationToken = nil ;
590
+
591
+ // Fetch token once to store token state
592
+ NSString *notificationName = kFIRInstanceIDTokenRefreshNotification ;
593
+ self.tokenRefreshNotificationObserver = [[NSNotificationCenter defaultCenter ]
594
+ addObserverForName: notificationName
595
+ object: nil
596
+ queue: nil
597
+ usingBlock: ^(NSNotification *_Nonnull note) {
598
+ // Should have saved token to cache
599
+ cachedTokenInfo = sTokenInfo ;
600
+
601
+ notificationPostCount++;
602
+ notificationToken = [[self .instanceID token ] copy ];
603
+ [defaultTokenExpectation fulfill ];
604
+ }];
605
+ XCTAssertNil ([self .mockInstanceID token ]);
606
+ [self waitForExpectationsWithTimeout: 10.0 handler: nil ];
607
+ [[NSNotificationCenter defaultCenter ] removeObserver: self .tokenRefreshNotificationObserver];
608
+
609
+ XCTAssertEqualObjects (notificationToken, kToken );
610
+
611
+ // Fetch default handler again without any token changes
612
+ XCTestExpectation *tokenCallback = [self expectationWithDescription: @" Callback was invoked." ];
613
+
614
+ [self .mockInstanceID defaultTokenWithHandler: ^(NSString *token, NSError *error) {
615
+ notificationToken = token;
616
+ [tokenCallback fulfill ];
617
+ }];
618
+ [self waitForExpectationsWithTimeout: 10.0 handler: nil ];
619
+ XCTAssertEqualObjects (notificationToken, kToken );
620
+ }
621
+
552
622
/* *
553
623
* Test that when we fetch a new default token and cache it successfully we post a
554
624
* tokenRefresh notification which allows to fetch the cached token.
0 commit comments