FIRUserTests.m 118 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366
  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 <Foundation/Foundation.h>
  17. #import <XCTest/XCTest.h>
  18. #import <FirebaseAuth/FIRUser.h>
  19. #import <FirebaseAuth/FIREmailAuthProvider.h>
  20. #import <FirebaseAuth/FIRFacebookAuthProvider.h>
  21. #import <FirebaseAuth/FIRGoogleAuthProvider.h>
  22. #import <FirebaseAuth/FIRAdditionalUserInfo.h>
  23. #import "FIRAuth_Internal.h"
  24. #import "FIRAuthErrorUtils.h"
  25. #import "FIRAuthBackend.h"
  26. #import "FIRAuthGlobalWorkQueue.h"
  27. #import "FIRAuthOperationType.h"
  28. #import "FIRAuthTokenResult.h"
  29. #import "FIRSecureTokenService.h"
  30. #import "FIRSecureTokenRequest.h"
  31. #import "FIRSecureTokenResponse.h"
  32. #import "FIRGetAccountInfoRequest.h"
  33. #import "FIRGetAccountInfoResponse.h"
  34. #import "FIRSetAccountInfoRequest.h"
  35. #import "FIRSetAccountInfoResponse.h"
  36. #import "FIRUser_Internal.h"
  37. #import "FIRUserInfo.h"
  38. #import "FIRUserMetadata.h"
  39. #import "FIRVerifyAssertionResponse.h"
  40. #import "FIRVerifyAssertionRequest.h"
  41. #import "FIRVerifyPasswordRequest.h"
  42. #import "FIRVerifyPasswordResponse.h"
  43. #import "FIRVerifyPhoneNumberRequest.h"
  44. #import "FIRVerifyPhoneNumberResponse.h"
  45. #import "FIRApp+FIRAuthUnitTests.h"
  46. #import "OCMStubRecorder+FIRAuthUnitTests.h"
  47. #import <OCMock/OCMock.h>
  48. #if TARGET_OS_IOS
  49. #import "Phone/FIRPhoneAuthCredential_Internal.h"
  50. #import "FIRPhoneAuthProvider.h"
  51. #endif
  52. NS_ASSUME_NONNULL_BEGIN
  53. /** @var kAPIKey
  54. @brief The fake API key.
  55. */
  56. static NSString *const kAPIKey = @"FAKE_API_KEY";
  57. /** @var kAccessToken
  58. @brief The fake access token.
  59. */
  60. static NSString *const kAccessToken = @"eyJhbGciOimnuzI1NiIsImtpZCI6ImY1YjE4Mjc2YTQ4NjYxZDBhODBiYzh"
  61. "jM2U5NDM0OTc0ZDFmMWRiNTEifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZmItc2EtdXBncm"
  62. "FkZWQiLCJhdWQiOiJ0ZXN0X2F1ZCIsImF1dGhfdGltZSI6MTUyMjM2MDU0OSwidXNlcl9pZCI6InRlc3RfdXNlcl9pZCIs"
  63. "InN1YiI6InRlc3Rfc3ViIiwiaWF0IjoxNTIyMzYwNTU3LCJleHAiOjE1MjIzNjQxNTcsImVtYWlsIjoiYXVuaXRlc3R1c2"
  64. "VyQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6"
  65. "WyJhdW5pdGVzdHVzZXJAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoicGFzc3dvcmQifX0=.WFQqSrpVnxx7m"
  66. "UrdKZA517Sp4ZBt-l2xQzGKNMVE90JB3vuNa-NyWZC-aTYMvND3-4aS3qRnN2kvk9KJAaF3eI_BKkcbZuq8O7iDVpOvqKC"
  67. "3QcW0PnwqSPChL3XqoDF322FcBEgemwwgaEVZMuo7GhJvHw-XtBt1KRXOoGHcr3P6RsvoulUouKQmqt6TP27eZtrgH7jjN"
  68. "hHm7gjX_WaRmgTOvYsuDbBBGdE15yIVZ3acI4cFUgwMRhaW-dDV7jTOqZGYJlTsI5oRMehphoVnYnEedJga28r4mqVkPbW"
  69. "lddL4dVVm85FYmQcRc0b2CLMnSevBDlwu754ZUZmRgnuvDA";
  70. /** @var kAccessTokenLength415
  71. @brief The fake access token with 415 characters in the claims potion of the token.
  72. */
  73. static NSString *const kAccessTokenLength415 = @"eyJhbGciOimnuzI1NiIsImtpZCI6ImY1YjE4Mjc2YTQ4NjYxZD"
  74. "BhODBiYzhjM2U5NDM0OTc0ZDFmMWRiNTEifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vdGVzd"
  75. "CIsImF1ZCI6InRlc3RfYXVkIiwiYXV0aF90aW1lIjoxNTIyMzYwNTQ5LCJ1c2VyX2lkIjoidGVzdF91c2VyX2lkIiwic3V"
  76. "iIjoidGVzdF9zdWIiLCJpYXQiOjE1MjIzNjA1NTcsImV4cCI6MTUyMjM2NDE1NywiZW1haWwiOiJhdW5pdGVzdHVzZXJAZ"
  77. "21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7ImVtYWlsIjpbImF"
  78. "1bml0ZXN0dXNlckBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ=.WFQqSrpVnxx7m"
  79. "UrdKZA517Sp4ZBt-l2xQzGKNMVE90JB3vuNa-NyWZC-aTYMvND3-4aS3qRnN2kvk9KJAaF3eI_BKkcbZuq8O7iDVpOvqKC"
  80. "3QcW0PnwqSPChL3XqoDF322FcBEgemwwgaEVZMuo7GhJvHw-XtBt1KRXOoGHcr3P6RsvoulUouKQmqt6TP27eZtrgH7jjN"
  81. "hHm7gjX_WaRmgTOvYsuDbBBGdE15yIVZ3acI4cFUgwMRhaW-dDV7jTOqZGYJlTsI5oRMehphoVnYnEedJga28r4mqVkPbW"
  82. "lddL4dVVm85FYmQcRc0b2CLMnSevBDlwu754ZUZmRgnuvDA";
  83. /** @var kAccessTokenLength416
  84. @brief The fake access token with 416 characters in the claims potion of the token.
  85. */
  86. static NSString *const kAccessTokenLength416 = @"eyJhbGciOimnuzI1NiIsImtpZCI6ImY1YjE4Mjc2YTQ4NjYxZD"
  87. "BhODBiYzhjM2U5NDM0OTc0ZDFmMWRiNTEifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vdGVzd"
  88. "DIiLCJhdWQiOiJ0ZXN0X2F1ZCIsImF1dGhfdGltZSI6MTUyMjM2MDU0OSwidXNlcl9pZCI6InRlc3RfdXNlcl9pZCIsInN"
  89. "1YiI6InRlc3Rfc3ViIiwiaWF0IjoxNTIyMzYwNTU3LCJleHAiOjE1MjIzNjQxNTcsImVtYWlsIjoiYXVuaXRlc3R1c2VyQ"
  90. "GdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ"
  91. "hdW5pdGVzdHVzZXJAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoicGFzc3dvcmQifX0=.WFQqSrpVnxx7m"
  92. "UrdKZA517Sp4ZBt-l2xQzGKNMVE90JB3vuNa-NyWZC-aTYMvND3-4aS3qRnN2kvk9KJAaF3eI_BKkcbZuq8O7iDVpOvqKC"
  93. "3QcW0PnwqSPChL3XqoDF322FcBEgemwwgaEVZMuo7GhJvHw-XtBt1KRXOoGHcr3P6RsvoulUouKQmqt6TP27eZtrgH7jjN"
  94. "hHm7gjX_WaRmgTOvYsuDbBBGdE15yIVZ3acI4cFUgwMRhaW-dDV7jTOqZGYJlTsI5oRMehphoVnYnEedJga28r4mqVkPbW"
  95. "lddL4dVVm85FYmQcRc0b2CLMnSevBDlwu754ZUZmRgnuvDA";
  96. /** @var kAccessTokenLength4523
  97. @brief The fake access token with 523 characters in the claims potion of the token.
  98. */
  99. static NSString *const kAccessTokenLength523 = @"eyJhbGciOimnuzI1NiIsImtpZCI6ImY1YjE4Mjc2YTQ4NjYxZD"
  100. "BhODBiYzhjM2U5NDM0OTc0ZDFmMWRiNTEifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vdGVzd"
  101. "DQiLCJhdWQiOiJ0ZXN0X2F1ZCIsImF1dGhfdGltZSI6MTUyMjM2MDU0OSwidXNlcl9pZCI6InRlc3RfdXNlcl9pZF81NDM"
  102. "yIiwic3ViIjoidGVzdF9zdWIiLCJpYXQiOjE1MjIzNjA1NTcsImV4cCI6MTUyMjM2NDE1OSwiZW1haWwiOiJhdW5pdGVzd"
  103. "HVzZXI0QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7ImVtYWl"
  104. "sIjpbImF1bml0ZXN0dXNlckBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ=.WFQqSrpVn"
  105. "xx7mUrdKZA517Sp4ZBt-l2xQzGKNMVE90JB3vuNa-NyWZC-aTYMvND3-4aS3qRnN2kvk9KJAaF3eI_BKkcbZuq8O7iDVpO"
  106. "vqKC3QcW0PnwqSPChL3XqoDF322FcBEgemwwgaEVZMuo7GhJvHw-XtBt1KRXOoGHcr3P6RsvoulUouKQmqt6TP27eZtrgH"
  107. "7jjNhHm7gjX_WaRmgTOvYsuDbBBGdE15yIVZ3acI4cFUgwMRhaW-dDV7jTOqZGYJlTsI5oRMehphoVnYnEedJga28r4mqV"
  108. "kPbWlddL4dVVm85FYmQcRc0b2CLMnSevBDlwu754ZUZmRgnuvDA";
  109. /** @var kNewAccessToken
  110. @brief A new value for the fake access token.
  111. */
  112. static NSString *const kNewAccessToken = @"NEW_ACCESS_TOKEN";
  113. /** @var kAccessTokenValidInterval
  114. @brief The time to live for the fake access token.
  115. */
  116. static const NSTimeInterval kAccessTokenTimeToLive = 60 * 60;
  117. /** @var kRefreshToken
  118. @brief The fake refresh token.
  119. */
  120. static NSString *const kRefreshToken = @"REFRESH_TOKEN";
  121. /** @var kLocalID
  122. @brief The fake local user ID.
  123. */
  124. static NSString *const kLocalID = @"LOCAL_ID";
  125. /** @var kAnotherLocalID
  126. @brief The fake local ID of another user.
  127. */
  128. static NSString *const kAnotherLocalID = @"ANOTHER_LOCAL_ID";
  129. /** @var kGoogleIDToken
  130. @brief The fake ID token from Google Sign-In.
  131. */
  132. static NSString *const kGoogleIDToken = @"GOOGLE_ID_TOKEN";
  133. /** @var kFacebookIDToken
  134. @brief The fake ID token from Facebook Sign-In. Facebook provider ID token is always nil.
  135. */
  136. static NSString *const kFacebookIDToken = nil;
  137. /** @var kGoogleAccessToken
  138. @brief The fake access token from Google Sign-In.
  139. */
  140. static NSString *const kGoogleAccessToken = @"GOOGLE_ACCESS_TOKEN";
  141. /** @var kFacebookAccessToken
  142. @brief The fake access token from Facebook Sign-In.
  143. */
  144. static NSString *const kFacebookAccessToken = @"FACEBOOK_ACCESS_TOKEN";
  145. /** @var kEmail
  146. @brief The fake user email.
  147. */
  148. static NSString *const kEmail = @"user@company.com";
  149. /** @var kPhoneNumber
  150. @brief The fake user phone number.
  151. */
  152. static NSString *const kPhoneNumber = @"12345658";
  153. /** @var kTemporaryProof
  154. @brief The fake temporary proof.
  155. */
  156. static NSString *const kTemporaryProof = @"12345658";
  157. /** @var kNewEmail
  158. @brief A new value for the fake user email.
  159. */
  160. static NSString *const kNewEmail = @"newuser@company.com";
  161. /** @var kUserName
  162. @brief The fake user name.
  163. */
  164. static NSString *const kUserName = @"User Doe";
  165. /** @var kNewDisplayName
  166. @brief A new value for the fake user display name.
  167. */
  168. static NSString *const kNewDisplayName = @"New User Doe";
  169. /** @var kPhotoURL
  170. @brief The fake user profile image URL string.
  171. */
  172. static NSString *const kPhotoURL = @"https://host.domain/image";
  173. /** @var kNewPhotoURL
  174. @brief A new value for the fake user profile image URL string..
  175. */
  176. static NSString *const kNewPhotoURL = @"https://host.domain/new/image";
  177. /** @var kFakePassword
  178. @brief The fake user password.
  179. */
  180. static NSString *const kFakePassword = @"123456";
  181. /** @var kNewPassword
  182. @brief The fake new user password.
  183. */
  184. static NSString *const kNewPassword = @"1234567";
  185. /** @var kPasswordHash
  186. @brief The fake user password hash.
  187. */
  188. static NSString *const kPasswordHash = @"UkVEQUNURUQ=";
  189. /** @var kGoogleUD
  190. @brief The fake user ID under Google Sign-In.
  191. */
  192. static NSString *const kGoogleID = @"GOOGLE_ID";
  193. /** @var kGoogleEmail
  194. @brief The fake user email under Google Sign-In.
  195. */
  196. static NSString *const kGoogleEmail = @"user@gmail.com";
  197. /** @var kGoogleDisplayName
  198. @brief The fake user display name under Google Sign-In.
  199. */
  200. static NSString *const kGoogleDisplayName = @"Google Doe";
  201. /** @var kEmailDisplayName
  202. @brief The fake user display name for email password user.
  203. */
  204. static NSString *const kEmailDisplayName = @"Email Doe";
  205. /** @var kFacebookDisplayName
  206. @brief The fake user display name under Facebook Sign-In.
  207. */
  208. static NSString *const kFacebookDisplayName = @"Facebook Doe";
  209. /** @var kGooglePhotoURL
  210. @brief The fake user profile image URL string under Google Sign-In.
  211. */
  212. static NSString *const kGooglePhotoURL = @"https://googleusercontents.com/user/profile";
  213. /** @var kFacebookID
  214. @brief The fake user ID under Facebook Login.
  215. */
  216. static NSString *const kFacebookID = @"FACEBOOK_ID";
  217. /** @var kFacebookEmail
  218. @brief The fake user email under Facebook Login.
  219. */
  220. static NSString *const kFacebookEmail = @"user@facebook.com";
  221. /** @var kVerificationCode
  222. @brief Fake verification code used for testing.
  223. */
  224. static NSString *const kVerificationCode = @"12345678";
  225. /** @var kVerificationID
  226. @brief Fake verification ID for testing.
  227. */
  228. static NSString *const kVerificationID = @"55432";
  229. /** @var kUserArchiverKey
  230. @brief The key used to archive and unarchive the user object for test NSSecureCoding.
  231. */
  232. static NSString *const kUserArchiverKey = @"userArchiverKey";
  233. /** @var kCreationDateInSeconds
  234. @brief The fake creation date.
  235. */
  236. static NSTimeInterval const kCreationDateTimeIntervalInSeconds = 1505858500;
  237. /** @var kLastSignInDateTimeIntervalInSeconds
  238. @brief The fake last sign in date date.
  239. */
  240. static NSTimeInterval const kLastSignInDateTimeIntervalInSeconds = 1505858583;
  241. /** @var kExpectationTimeout
  242. @brief The maximum time waiting for expectations to fulfill.
  243. */
  244. static const NSTimeInterval kExpectationTimeout = 2;
  245. /** @extention FIRSecureTokenService
  246. @brief Extends the FIRSecureTokenService class to expose one private method for testing only.
  247. */
  248. @interface FIRSecureTokenService ()
  249. /** @fn hasValidAccessToken
  250. @brief private method exposed so it can be mocked to prevent the fake expiration date from
  251. affecting the the unit tests.
  252. */
  253. - (BOOL)hasValidAccessToken;
  254. @end
  255. /** @class FIRUserTests
  256. @brief Tests for @c FIRUser .
  257. */
  258. @interface FIRUserTests : XCTestCase
  259. @end
  260. @implementation FIRUserTests {
  261. /** @var _mockBackend
  262. @brief The mock @c FIRAuthBackendImplementation .
  263. */
  264. id _mockBackend;
  265. }
  266. /** @fn googleProfile
  267. @brief The fake user profile under additional user data in @c FIRVerifyAssertionResponse.
  268. */
  269. + (NSDictionary *)googleProfile {
  270. static NSDictionary *kGoogleProfile = nil;
  271. static dispatch_once_t onceToken;
  272. dispatch_once(&onceToken, ^{
  273. kGoogleProfile = @{
  274. @"email": kGoogleEmail,
  275. @"given_name": @"User",
  276. @"family_name": @"Doe"
  277. };
  278. });
  279. return kGoogleProfile;
  280. }
  281. - (void)setUp {
  282. [super setUp];
  283. _mockBackend = OCMProtocolMock(@protocol(FIRAuthBackendImplementation));
  284. [FIRAuthBackend setBackendImplementation:_mockBackend];
  285. [FIRApp resetAppForAuthUnitTests];
  286. }
  287. - (void)tearDown {
  288. [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:nil];
  289. [super tearDown];
  290. }
  291. #pragma mark - Tests
  292. /** @fn testUserPropertiesAndNSSecureCoding
  293. @brief Tests properties of the @c FIRUser instance before and after being
  294. serialized/deserialized.
  295. */
  296. - (void)testUserPropertiesAndNSSecureCoding {
  297. // Mock auth provider user info for email/password for GetAccountInfo.
  298. id mockPasswordUserInfo = OCMClassMock([FIRGetAccountInfoResponseProviderUserInfo class]);
  299. OCMStub([mockPasswordUserInfo providerID]).andReturn(FIREmailAuthProviderID);
  300. OCMStub([mockPasswordUserInfo federatedID]).andReturn(kEmail);
  301. OCMStub([mockPasswordUserInfo email]).andReturn(kEmail);
  302. // Mock auth provider user info from Google for GetAccountInfo.
  303. id mockGoogleUserInfo = OCMClassMock([FIRGetAccountInfoResponseProviderUserInfo class]);
  304. OCMStub([mockGoogleUserInfo providerID]).andReturn(FIRGoogleAuthProviderID);
  305. OCMStub([mockGoogleUserInfo displayName]).andReturn(kGoogleDisplayName);
  306. OCMStub([mockGoogleUserInfo photoURL]).andReturn([NSURL URLWithString:kGooglePhotoURL]);
  307. OCMStub([mockGoogleUserInfo federatedID]).andReturn(kGoogleID);
  308. OCMStub([mockGoogleUserInfo email]).andReturn(kGoogleEmail);
  309. // Mock auth provider user info from Facebook for GetAccountInfo.
  310. id mockFacebookUserInfo = OCMClassMock([FIRGetAccountInfoResponseProviderUserInfo class]);
  311. OCMStub([mockFacebookUserInfo providerID]).andReturn(FIRFacebookAuthProviderID);
  312. OCMStub([mockFacebookUserInfo federatedID]).andReturn(kFacebookID);
  313. OCMStub([mockFacebookUserInfo email]).andReturn(kFacebookEmail);
  314. #if TARGET_OS_IOS
  315. // Mock auth provider user info from Phone auth provider for GetAccountInfo.
  316. id mockPhoneUserInfo = OCMClassMock([FIRGetAccountInfoResponseProviderUserInfo class]);
  317. OCMStub([mockPhoneUserInfo providerID]).andReturn(FIRPhoneAuthProviderID);
  318. OCMStub([mockPhoneUserInfo phoneNumber]).andReturn(kPhoneNumber);
  319. #endif
  320. // Mock the root user info object for GetAccountInfo.
  321. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  322. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  323. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  324. OCMStub([mockGetAccountInfoResponseUser emailVerified]).andReturn(YES);
  325. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  326. OCMStub([mockGetAccountInfoResponseUser photoURL]).andReturn([NSURL URLWithString:kPhotoURL]);
  327. OCMStub([mockGetAccountInfoResponseUser creationDate]).
  328. andReturn([NSDate dateWithTimeIntervalSince1970:kCreationDateTimeIntervalInSeconds]);
  329. OCMStub([mockGetAccountInfoResponseUser lastLoginDate]).
  330. andReturn([NSDate dateWithTimeIntervalSince1970:kLastSignInDateTimeIntervalInSeconds]);
  331. NSArray *providerUserInfos = @[
  332. #if TARGET_OS_IOS
  333. mockPhoneUserInfo,
  334. #endif
  335. mockPasswordUserInfo,
  336. mockGoogleUserInfo,
  337. mockFacebookUserInfo
  338. ];
  339. OCMStub([mockGetAccountInfoResponseUser providerUserInfo]).andReturn(providerUserInfos);
  340. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  341. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  342. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  343. completion:^(FIRUser *user) {
  344. // Verify FIRUserInfo properties on FIRUser itself.
  345. XCTAssertEqualObjects(user.providerID, @"Firebase");
  346. XCTAssertEqualObjects(user.uid, kLocalID);
  347. XCTAssertEqualObjects(user.displayName, kGoogleDisplayName);
  348. XCTAssertEqualObjects(user.photoURL, [NSURL URLWithString:kPhotoURL]);
  349. XCTAssertEqualObjects(user.email, kEmail);
  350. XCTAssertEqualObjects(user.metadata.creationDate,
  351. [NSDate dateWithTimeIntervalSince1970:kCreationDateTimeIntervalInSeconds]);
  352. XCTAssertEqualObjects(user.metadata.lastSignInDate,
  353. [NSDate dateWithTimeIntervalSince1970:kLastSignInDateTimeIntervalInSeconds]);
  354. // Verify FIRUser properties besides providerData contents.
  355. XCTAssertFalse(user.anonymous);
  356. XCTAssertTrue(user.emailVerified);
  357. XCTAssertEqualObjects(user.refreshToken, kRefreshToken);
  358. XCTAssertEqual(user.providerData.count, providerUserInfos.count);
  359. NSDictionary<NSString *, id<FIRUserInfo>> *providerMap =
  360. [self dictionaryWithUserInfoArray:user.providerData];
  361. // Verify FIRUserInfo properties from email/password.
  362. id<FIRUserInfo> passwordUserInfo = providerMap[FIREmailAuthProviderID];
  363. XCTAssertEqualObjects(passwordUserInfo.uid, kEmail);
  364. XCTAssertNil(passwordUserInfo.displayName);
  365. XCTAssertNil(passwordUserInfo.photoURL);
  366. XCTAssertEqualObjects(passwordUserInfo.email, kEmail);
  367. // Verify FIRUserInfo properties from the Google auth provider.
  368. id<FIRUserInfo> googleUserInfo = providerMap[FIRGoogleAuthProviderID];
  369. XCTAssertEqualObjects(googleUserInfo.uid, kGoogleID);
  370. XCTAssertEqualObjects(googleUserInfo.displayName, kGoogleDisplayName);
  371. XCTAssertEqualObjects(googleUserInfo.photoURL, [NSURL URLWithString:kGooglePhotoURL]);
  372. XCTAssertEqualObjects(googleUserInfo.email, kGoogleEmail);
  373. // Verify FIRUserInfo properties from the Facebook auth provider.
  374. id<FIRUserInfo> facebookUserInfo = providerMap[FIRFacebookAuthProviderID];
  375. XCTAssertEqualObjects(facebookUserInfo.uid, kFacebookID);
  376. XCTAssertNil(facebookUserInfo.displayName);
  377. XCTAssertNil(facebookUserInfo.photoURL);
  378. XCTAssertEqualObjects(facebookUserInfo.email, kFacebookEmail);
  379. #if TARGET_OS_IOS
  380. // Verify FIRUserInfo properties from the phone auth provider.
  381. id<FIRUserInfo> phoneUserInfo = providerMap[FIRPhoneAuthProviderID];
  382. XCTAssertEqualObjects(phoneUserInfo.phoneNumber, kPhoneNumber);
  383. #endif
  384. // Test NSSecureCoding
  385. XCTAssertTrue([FIRUser supportsSecureCoding]);
  386. NSMutableData *data = [NSMutableData data];
  387. NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
  388. [archiver encodeObject:user forKey:kUserArchiverKey];
  389. [archiver finishEncoding];
  390. NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
  391. FIRUser *unarchivedUser = [unarchiver decodeObjectForKey:kUserArchiverKey];
  392. // Verify NSSecureCoding for FIRUser
  393. XCTAssertEqualObjects(unarchivedUser.providerID, user.providerID);
  394. XCTAssertEqualObjects(unarchivedUser.uid, user.uid);
  395. XCTAssertEqualObjects(unarchivedUser.email, user.email);
  396. XCTAssertEqualObjects(unarchivedUser.photoURL, user.photoURL);
  397. XCTAssertEqualObjects(unarchivedUser.displayName, user.displayName);
  398. // Verify NSSecureCoding properties besides providerData contents.
  399. XCTAssertEqual(unarchivedUser.anonymous, user.anonymous);
  400. XCTAssertEqual(unarchivedUser.emailVerified, user.emailVerified);
  401. XCTAssertEqualObjects(unarchivedUser.refreshToken, user.refreshToken);
  402. XCTAssertEqualObjects(unarchivedUser.metadata.creationDate, user.metadata.creationDate);
  403. XCTAssertEqualObjects(unarchivedUser.metadata.lastSignInDate, user.metadata.lastSignInDate);
  404. XCTAssertEqual(unarchivedUser.providerData.count, user.providerData.count);
  405. NSDictionary<NSString *, id<FIRUserInfo>> *unarchivedProviderMap =
  406. [self dictionaryWithUserInfoArray:unarchivedUser.providerData];
  407. // Verify NSSecureCoding properties from email/password.
  408. id<FIRUserInfo> unarchivedPasswordUserInfo = unarchivedProviderMap[FIREmailAuthProviderID];
  409. XCTAssertEqualObjects(unarchivedPasswordUserInfo.uid, passwordUserInfo.uid);
  410. XCTAssertEqualObjects(unarchivedPasswordUserInfo.displayName, passwordUserInfo.displayName);
  411. XCTAssertEqualObjects(unarchivedPasswordUserInfo.photoURL, passwordUserInfo.photoURL);
  412. XCTAssertEqualObjects(unarchivedPasswordUserInfo.email, passwordUserInfo.email);
  413. // Verify NSSecureCoding properties from the Google auth provider.
  414. id<FIRUserInfo> unarchivedGoogleUserInfo = unarchivedProviderMap[FIRGoogleAuthProviderID];
  415. XCTAssertEqualObjects(unarchivedGoogleUserInfo.uid, googleUserInfo.uid);
  416. XCTAssertEqualObjects(unarchivedGoogleUserInfo.displayName, googleUserInfo.displayName);
  417. XCTAssertEqualObjects(unarchivedGoogleUserInfo.photoURL, googleUserInfo.photoURL);
  418. XCTAssertEqualObjects(unarchivedGoogleUserInfo.email, googleUserInfo.email);
  419. // Verify NSSecureCoding properties from the Facebook auth provider.
  420. id<FIRUserInfo> unarchivedFacebookUserInfo = unarchivedProviderMap[FIRFacebookAuthProviderID];
  421. XCTAssertEqualObjects(unarchivedFacebookUserInfo.uid, facebookUserInfo.uid);
  422. XCTAssertEqualObjects(unarchivedFacebookUserInfo.displayName, facebookUserInfo.displayName);
  423. XCTAssertEqualObjects(unarchivedFacebookUserInfo.photoURL, facebookUserInfo.photoURL);
  424. XCTAssertEqualObjects(unarchivedFacebookUserInfo.email, facebookUserInfo.email);
  425. #if TARGET_OS_IOS
  426. // Verify FIRUserInfo properties from the phone auth provider.
  427. id<FIRUserInfo> unarchivedPhoneUserInfo = unarchivedProviderMap[FIRPhoneAuthProviderID];
  428. XCTAssertEqualObjects(unarchivedPhoneUserInfo.phoneNumber, phoneUserInfo.phoneNumber);
  429. #endif
  430. [expectation fulfill];
  431. }];
  432. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  433. OCMVerifyAll(_mockBackend);
  434. }
  435. /** @fn testUpdateEmailSuccess
  436. @brief Tests the flow of a successful @c updateEmail:completion: call.
  437. */
  438. - (void)testUpdateEmailSuccess {
  439. id (^mockUserInfoWithDisplayName)(NSString *) = ^(NSString *displayName) {
  440. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  441. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  442. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  443. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(displayName);
  444. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  445. return mockGetAccountInfoResponseUser;
  446. };
  447. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  448. id userInfoResponse = mockUserInfoWithDisplayName(kGoogleDisplayName);
  449. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  450. completion:^(FIRUser *user) {
  451. // Pretend that the display name on the server has been changed since last request.
  452. [self
  453. expectGetAccountInfoWithMockUserInfoResponse:mockUserInfoWithDisplayName(kNewDisplayName)];
  454. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  455. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  456. FIRSetAccountInfoResponseCallback callback) {
  457. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  458. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  459. XCTAssertEqualObjects(request.email, kNewEmail);
  460. XCTAssertNil(request.localID);
  461. XCTAssertNil(request.displayName);
  462. XCTAssertNil(request.photoURL);
  463. XCTAssertNil(request.password);
  464. XCTAssertNil(request.providers);
  465. XCTAssertNil(request.deleteAttributes);
  466. XCTAssertNil(request.deleteProviders);
  467. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  468. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  469. OCMStub([mockSetAccountInfoResponse email]).andReturn(kNewEmail);
  470. OCMStub([mockSetAccountInfoResponse displayName]).andReturn(kNewDisplayName);
  471. callback(mockSetAccountInfoResponse, nil);
  472. });
  473. });
  474. [user updateEmail:kNewEmail completion:^(NSError *_Nullable error) {
  475. XCTAssertNil(error);
  476. XCTAssertEqualObjects(user.email, kNewEmail);
  477. XCTAssertEqualObjects(user.displayName, kNewDisplayName);
  478. [expectation fulfill];
  479. }];
  480. }];
  481. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  482. OCMVerifyAll(_mockBackend);
  483. }
  484. /** @fn testUpdateEmailFailure
  485. @brief Tests the flow of a failed @c updateEmail:completion: call.
  486. */
  487. - (void)testUpdateEmailFailure {
  488. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  489. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  490. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  491. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  492. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  493. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  494. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  495. completion:^(FIRUser *user) {
  496. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  497. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  498. .andDispatchError2([FIRAuthErrorUtils invalidEmailErrorWithMessage:nil]);
  499. [user updateEmail:kNewEmail completion:^(NSError *_Nullable error) {
  500. XCTAssertTrue([NSThread isMainThread]);
  501. XCTAssertEqual(error.code, FIRAuthErrorCodeInvalidEmail);
  502. // Email should not have changed on the client side.
  503. XCTAssertEqualObjects(user.email, kEmail);
  504. // User is still signed in.
  505. XCTAssertEqual([FIRAuth auth].currentUser, user);
  506. [expectation fulfill];
  507. }];
  508. }];
  509. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  510. OCMVerifyAll(_mockBackend);
  511. }
  512. /** @fn testUpdateEmailAutoSignOut
  513. @brief Tests the flow of a failed @c updateEmail:completion: call that automatically signs out.
  514. */
  515. - (void)testUpdateEmailAutoSignOut {
  516. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  517. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  518. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  519. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  520. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  521. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  522. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  523. completion:^(FIRUser *user) {
  524. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  525. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  526. .andDispatchError2([FIRAuthErrorUtils invalidUserTokenErrorWithMessage:nil]);
  527. [user updateEmail:kNewEmail completion:^(NSError *_Nullable error) {
  528. XCTAssertTrue([NSThread isMainThread]);
  529. XCTAssertEqual(error.code, FIRAuthErrorCodeInvalidUserToken);
  530. // Email should not have changed on the client side.
  531. XCTAssertEqualObjects(user.email, kEmail);
  532. // User is no longer signed in.
  533. XCTAssertNil([FIRAuth auth].currentUser);
  534. [expectation fulfill];
  535. }];
  536. }];
  537. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  538. OCMVerifyAll(_mockBackend);
  539. }
  540. #if TARGET_OS_IOS
  541. /** @fn testUpdatePhoneSuccess
  542. @brief Tests the flow of a successful @c updatePhoneNumberCredential:completion: call.
  543. */
  544. - (void)testUpdatePhoneSuccess {
  545. id (^mockUserInfoWithPhoneNumber)(NSString *) = ^(NSString *phoneNumber) {
  546. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  547. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  548. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  549. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  550. if (phoneNumber.length) {
  551. OCMStub([mockGetAccountInfoResponseUser phoneNumber]).andReturn(phoneNumber);
  552. }
  553. return mockGetAccountInfoResponseUser;
  554. };
  555. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  556. id userInfoResponse = mockUserInfoWithPhoneNumber(nil);
  557. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  558. completion:^(FIRUser *user) {
  559. [self expectVerifyPhoneNumberRequestWithPhoneNumber:kPhoneNumber isLinkOperation:NO error:nil];
  560. id userInfoResponseUpdate = mockUserInfoWithPhoneNumber(kPhoneNumber);
  561. [self expectGetAccountInfoWithMockUserInfoResponse:userInfoResponseUpdate];
  562. FIRPhoneAuthCredential *credential =
  563. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  564. verificationCode:kVerificationCode];
  565. [user updatePhoneNumberCredential:credential
  566. completion:^(NSError * _Nullable error) {
  567. XCTAssertTrue([NSThread isMainThread]);
  568. XCTAssertNil(error);
  569. XCTAssertEqualObjects([FIRAuth auth].currentUser.phoneNumber, kPhoneNumber);
  570. [expectation fulfill];
  571. }];
  572. }];
  573. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  574. OCMVerifyAll(_mockBackend);
  575. }
  576. /** @fn testUpdatePhoneNumberFailure
  577. @brief Tests the flow of a failed @c updatePhoneNumberCredential:completion: call.
  578. */
  579. - (void)testUpdatePhoneNumberFailure {
  580. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  581. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  582. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  583. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  584. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  585. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  586. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  587. completion:^(FIRUser *user) {
  588. OCMExpect([_mockBackend verifyPhoneNumber:[OCMArg any] callback:[OCMArg any]])
  589. .andDispatchError2([FIRAuthErrorUtils invalidPhoneNumberErrorWithMessage:nil]);
  590. FIRPhoneAuthCredential *credential =
  591. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  592. verificationCode:kVerificationCode];
  593. [user updatePhoneNumberCredential:credential completion:^(NSError *_Nullable error) {
  594. XCTAssertTrue([NSThread isMainThread]);
  595. XCTAssertEqual(error.code, FIRAuthErrorCodeInvalidPhoneNumber);
  596. XCTAssertEqual([FIRAuth auth].currentUser, user);
  597. [expectation fulfill];
  598. }];
  599. }];
  600. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  601. OCMVerifyAll(_mockBackend);
  602. }
  603. /** @fn testUpdatePhoneNumberFailureAutoSignOut
  604. @brief Tests the flow of a failed @c updatePhoneNumberCredential:completion: call that
  605. automatically signs out.
  606. */
  607. - (void)testUpdatePhoneNumberFailureAutoSignOut {
  608. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  609. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  610. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  611. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  612. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  613. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  614. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  615. completion:^(FIRUser *user) {
  616. OCMExpect([_mockBackend verifyPhoneNumber:[OCMArg any] callback:[OCMArg any]])
  617. .andDispatchError2([FIRAuthErrorUtils userTokenExpiredErrorWithMessage:nil]);
  618. FIRPhoneAuthCredential *credential =
  619. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  620. verificationCode:kVerificationCode];
  621. [user updatePhoneNumberCredential:credential completion:^(NSError *_Nullable error) {
  622. XCTAssertTrue([NSThread isMainThread]);
  623. XCTAssertEqual(error.code, FIRAuthErrorCodeUserTokenExpired);
  624. XCTAssertNil([FIRAuth auth].currentUser);
  625. [expectation fulfill];
  626. }];
  627. }];
  628. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  629. OCMVerifyAll(_mockBackend);
  630. }
  631. #endif
  632. /** @fn testUpdatePasswordSuccess
  633. @brief Tests the flow of a successful @c updatePassword:completion: call.
  634. */
  635. - (void)testUpdatePasswordSuccess {
  636. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  637. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  638. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  639. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  640. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  641. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  642. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  643. completion:^(FIRUser *user) {
  644. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  645. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  646. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  647. FIRSetAccountInfoResponseCallback callback) {
  648. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  649. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  650. XCTAssertEqualObjects(request.password, kNewPassword);
  651. XCTAssertNil(request.localID);
  652. XCTAssertNil(request.displayName);
  653. XCTAssertNil(request.photoURL);
  654. XCTAssertNil(request.email);
  655. XCTAssertNil(request.providers);
  656. XCTAssertNil(request.deleteAttributes);
  657. XCTAssertNil(request.deleteProviders);
  658. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  659. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  660. OCMStub([mockSetAccountInfoResponse displayName]).andReturn(kNewDisplayName);
  661. callback(mockSetAccountInfoResponse, nil);
  662. });
  663. });
  664. [user updatePassword:kNewPassword completion:^(NSError *_Nullable error) {
  665. XCTAssertTrue([NSThread isMainThread]);
  666. XCTAssertNil(error);
  667. XCTAssertFalse(user.isAnonymous);
  668. [expectation fulfill];
  669. }];
  670. }];
  671. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  672. OCMVerifyAll(_mockBackend);
  673. }
  674. /** @fn testUpdatePasswordFailure
  675. @brief Tests the flow of a failed @c updatePassword:completion: call.
  676. */
  677. - (void)testUpdatePasswordFailure {
  678. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  679. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  680. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  681. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  682. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  683. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  684. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  685. completion:^(FIRUser *user) {
  686. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  687. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  688. .andDispatchError2([FIRAuthErrorUtils requiresRecentLoginErrorWithMessage:nil]);
  689. [user updatePassword:kNewPassword completion:^(NSError *_Nullable error) {
  690. XCTAssertTrue([NSThread isMainThread]);
  691. XCTAssertEqual(error.code, FIRAuthErrorCodeRequiresRecentLogin);
  692. XCTAssertEqual([FIRAuth auth].currentUser, user);
  693. [expectation fulfill];
  694. }];
  695. }];
  696. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  697. OCMVerifyAll(_mockBackend);
  698. }
  699. /** @fn testUpdateEmptyPasswordFailure
  700. @brief Tests the flow of a failed @c updatePassword:completion: call due to an empty password.
  701. */
  702. - (void)testUpdateEmptyPasswordFailure {
  703. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  704. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  705. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  706. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  707. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  708. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  709. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  710. completion:^(FIRUser *user) {
  711. [user updatePassword:@"" completion:^(NSError *_Nullable error) {
  712. XCTAssertTrue([NSThread isMainThread]);
  713. XCTAssertEqual(error.code, FIRAuthErrorCodeWeakPassword);
  714. [expectation fulfill];
  715. }];
  716. }];
  717. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  718. }
  719. /** @fn testUpdatePasswordFailureAutoSignOut
  720. @brief Tests the flow of a failed @c updatePassword:completion: call that automatically signs
  721. out.
  722. */
  723. - (void)testUpdatePasswordFailureAutoSignOut {
  724. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  725. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  726. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  727. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  728. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  729. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  730. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  731. completion:^(FIRUser *user) {
  732. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  733. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  734. .andDispatchError2([FIRAuthErrorUtils userDisabledErrorWithMessage:nil]);
  735. [user updatePassword:kNewPassword completion:^(NSError *_Nullable error) {
  736. XCTAssertTrue([NSThread isMainThread]);
  737. XCTAssertEqual(error.code, FIRAuthErrorCodeUserDisabled);
  738. XCTAssertNil([FIRAuth auth].currentUser);
  739. [expectation fulfill];
  740. }];
  741. }];
  742. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  743. OCMVerifyAll(_mockBackend);
  744. }
  745. /** @fn testChangeProfileSuccess
  746. @brief Tests a successful user profile change flow.
  747. */
  748. - (void)testChangeProfileSuccess {
  749. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  750. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  751. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  752. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  753. OCMStub([mockGetAccountInfoResponseUser photoURL]).andReturn(kPhotoURL);
  754. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  755. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  756. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  757. completion:^(FIRUser *user) {
  758. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  759. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  760. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  761. FIRSetAccountInfoResponseCallback callback) {
  762. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  763. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  764. XCTAssertEqualObjects(request.displayName, kNewDisplayName);
  765. XCTAssertEqualObjects(request.photoURL, [NSURL URLWithString:kNewPhotoURL]);
  766. XCTAssertNil(request.localID);
  767. XCTAssertNil(request.email);
  768. XCTAssertNil(request.password);
  769. XCTAssertNil(request.providers);
  770. XCTAssertNil(request.deleteAttributes);
  771. XCTAssertNil(request.deleteProviders);
  772. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  773. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  774. OCMStub([mockSetAccountInfoResponse displayName]).andReturn(kNewDisplayName);
  775. callback(mockSetAccountInfoResponse, nil);
  776. });
  777. });
  778. FIRUserProfileChangeRequest *profileChange = [user profileChangeRequest];
  779. profileChange.photoURL = [NSURL URLWithString:kNewPhotoURL];
  780. profileChange.displayName = kNewDisplayName;
  781. [profileChange commitChangesWithCompletion:^(NSError *_Nullable error) {
  782. XCTAssertTrue([NSThread isMainThread]);
  783. XCTAssertNil(error);
  784. XCTAssertEqualObjects(user.displayName, kNewDisplayName);
  785. XCTAssertEqualObjects(user.photoURL, [NSURL URLWithString:kNewPhotoURL]);
  786. [expectation fulfill];
  787. }];
  788. }];
  789. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  790. OCMVerifyAll(_mockBackend);
  791. }
  792. /** @fn testChangeProfileFailure
  793. @brief Tests a failed user profile change flow.
  794. */
  795. - (void)testChangeProfileFailure {
  796. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  797. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  798. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  799. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  800. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  801. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  802. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  803. completion:^(FIRUser *user) {
  804. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  805. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  806. .andDispatchError2([FIRAuthErrorUtils tooManyRequestsErrorWithMessage:nil]);
  807. FIRUserProfileChangeRequest *profileChange = [user profileChangeRequest];
  808. profileChange.displayName = kNewDisplayName;
  809. [profileChange commitChangesWithCompletion:^(NSError *_Nullable error) {
  810. XCTAssertTrue([NSThread isMainThread]);
  811. XCTAssertEqual(error.code, FIRAuthErrorCodeTooManyRequests);
  812. XCTAssertEqualObjects(user.displayName, kGoogleDisplayName);
  813. XCTAssertEqual([FIRAuth auth].currentUser, user);
  814. [expectation fulfill];
  815. }];
  816. }];
  817. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  818. OCMVerifyAll(_mockBackend);
  819. }
  820. /** @fn testChangeProfileFailureAutoSignOut
  821. @brief Tests a failed user profile change flow that automatically signs out.
  822. */
  823. - (void)testChangeProfileFailureAutoSignOut {
  824. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  825. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  826. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  827. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  828. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  829. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  830. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  831. completion:^(FIRUser *user) {
  832. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  833. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  834. .andDispatchError2([FIRAuthErrorUtils userNotFoundErrorWithMessage:nil]);
  835. FIRUserProfileChangeRequest *profileChange = [user profileChangeRequest];
  836. profileChange.displayName = kNewDisplayName;
  837. [profileChange commitChangesWithCompletion:^(NSError *_Nullable error) {
  838. XCTAssertTrue([NSThread isMainThread]);
  839. XCTAssertEqual(error.code, FIRAuthErrorCodeUserNotFound);
  840. XCTAssertEqualObjects(user.displayName, kGoogleDisplayName);
  841. XCTAssertNil([FIRAuth auth].currentUser);
  842. [expectation fulfill];
  843. }];
  844. }];
  845. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  846. OCMVerifyAll(_mockBackend);
  847. }
  848. /** @fn testReloadSuccess
  849. @brief Tests the flow of a successful @c reloadWithCompletion: call.
  850. */
  851. - (void)testReloadSuccess {
  852. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  853. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  854. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  855. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  856. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  857. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  858. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  859. completion:^(FIRUser *user) {
  860. id mockGetAccountInfoResponseUserNew = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  861. OCMStub([mockGetAccountInfoResponseUserNew localID]).andReturn(kLocalID);
  862. OCMStub([mockGetAccountInfoResponseUserNew email]).andReturn(kNewEmail);
  863. OCMStub([mockGetAccountInfoResponseUserNew displayName]).andReturn(kNewDisplayName);
  864. OCMStub([mockGetAccountInfoResponseUserNew passwordHash]).andReturn(kPasswordHash);
  865. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUserNew];
  866. [user reloadWithCompletion:^(NSError *_Nullable error) {
  867. XCTAssertTrue([NSThread isMainThread]);
  868. XCTAssertNil(error);
  869. XCTAssertEqualObjects(user.email, kNewEmail);
  870. XCTAssertEqualObjects(user.displayName, kNewDisplayName);
  871. [expectation fulfill];
  872. }];
  873. }];
  874. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  875. OCMVerifyAll(_mockBackend);
  876. }
  877. /** @fn testGetIDTokenResultSuccess
  878. @brief Tests the flow of a successful @c getIDTokenResultWithCompletion: call.
  879. */
  880. - (void)testGetIDTokenResultSuccess {
  881. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  882. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  883. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  884. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  885. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  886. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  887. id mockSecureTokenService = OCMClassMock([FIRSecureTokenService class]);
  888. OCMStub([mockSecureTokenService hasValidAccessToken]).andReturn(YES);
  889. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  890. completion:^(FIRUser *user) {
  891. [user getIDTokenResultWithCompletion:^(FIRAuthTokenResult *_Nullable tokenResult,
  892. NSError *_Nullable error) {
  893. XCTAssertTrue([NSThread isMainThread]);
  894. XCTAssertNil(error);
  895. XCTAssertEqualObjects(tokenResult.token, kAccessToken);
  896. XCTAssertTrue(tokenResult.issuedAtDate &&
  897. [tokenResult.issuedAtDate isKindOfClass:[NSDate class]]);
  898. XCTAssertTrue(tokenResult.authDate && [tokenResult.authDate isKindOfClass:[NSDate class]]);
  899. XCTAssertTrue(tokenResult.expirationDate &&
  900. [tokenResult.expirationDate isKindOfClass:[NSDate class]]);
  901. XCTAssertTrue(tokenResult.claims && [tokenResult.claims isKindOfClass:[NSDictionary class]]);
  902. [expectation fulfill];
  903. }];
  904. }];
  905. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  906. OCMVerifyAll(_mockBackend);
  907. }
  908. /** @fn testGetIDTokenResultForcingRefreshFailure
  909. @brief Tests the flow successful @c getIDTokenResultForcingRefresh:completion: calls.
  910. */
  911. - (void)testGetIDTokenResultForcingRefreshSuccess {
  912. [self getIDTokenResultForcingRefreshSuccessWithIDToken:kAccessToken];
  913. [self getIDTokenResultForcingRefreshSuccessWithIDToken:kAccessTokenLength415];
  914. [self getIDTokenResultForcingRefreshSuccessWithIDToken:kAccessTokenLength416];
  915. [self getIDTokenResultForcingRefreshSuccessWithIDToken:kAccessTokenLength523];
  916. }
  917. /** @fn testGetIDTokenResultForcingRefreshFailure
  918. @brief Tests the flow of a failed @c getIDTokenResultForcingRefresh:completion: call.
  919. */
  920. - (void)testGetIDTokenResultForcingRefreshFailure {
  921. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  922. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  923. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  924. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  925. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  926. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  927. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  928. completion:^(FIRUser *user) {
  929. OCMExpect([_mockBackend secureToken:[OCMArg any] callback:[OCMArg any]])
  930. .andCallBlock2(^(FIRSecureTokenRequest *_Nullable request,
  931. FIRSecureTokenResponseCallback callback) {
  932. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  933. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  934. callback(nil, [FIRAuthErrorUtils networkErrorWithUnderlyingError:[NSError new]]);
  935. });
  936. });
  937. [user getIDTokenResultForcingRefresh:YES
  938. completion:^(FIRAuthTokenResult *_Nullable tokenResult,
  939. NSError *_Nullable error) {
  940. XCTAssertTrue([NSThread isMainThread]);
  941. XCTAssertNil(tokenResult);
  942. XCTAssertEqual(error.code, FIRAuthErrorCodeNetworkError);
  943. [expectation fulfill];
  944. }];
  945. }];
  946. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  947. OCMVerifyAll(_mockBackend);
  948. }
  949. /** @fn testReloadFailure
  950. @brief Tests the flow of a failed @c reloadWithCompletion: call.
  951. */
  952. - (void)testReloadFailure {
  953. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  954. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  955. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  956. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  957. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  958. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  959. completion:^(FIRUser *user) {
  960. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  961. .andDispatchError2([FIRAuthErrorUtils quotaExceededErrorWithMessage:nil]);
  962. [user reloadWithCompletion:^(NSError *_Nullable error) {
  963. XCTAssertTrue([NSThread isMainThread]);
  964. XCTAssertEqual(error.code, FIRAuthErrorCodeQuotaExceeded);
  965. XCTAssertEqual([FIRAuth auth].currentUser, user);
  966. [expectation fulfill];
  967. }];
  968. }];
  969. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  970. OCMVerifyAll(_mockBackend);
  971. }
  972. /** @fn testReloadFailureAutoSignOut
  973. @brief Tests the flow of a failed @c reloadWithCompletion: call that automtatically signs out.
  974. */
  975. - (void)testReloadFailureAutoSignOut {
  976. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  977. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  978. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  979. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  980. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  981. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  982. completion:^(FIRUser *user) {
  983. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  984. .andDispatchError2([FIRAuthErrorUtils userTokenExpiredErrorWithMessage:nil]);
  985. [user reloadWithCompletion:^(NSError *_Nullable error) {
  986. XCTAssertTrue([NSThread isMainThread]);
  987. XCTAssertEqual(error.code, FIRAuthErrorCodeUserTokenExpired);
  988. XCTAssertNil([FIRAuth auth].currentUser);
  989. [expectation fulfill];
  990. }];
  991. }];
  992. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  993. OCMVerifyAll(_mockBackend);
  994. }
  995. /** @fn testReauthenticateSuccess
  996. @brief Tests the flow of a successful @c reauthenticateWithCredential:completion: call.
  997. */
  998. - (void)testReauthenticateSuccess {
  999. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1000. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1001. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1002. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  1003. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1004. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1005. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  1006. completion:^(FIRUser *user) {
  1007. OCMExpect([_mockBackend verifyPassword:[OCMArg any] callback:[OCMArg any]])
  1008. .andCallBlock2(^(FIRVerifyPasswordRequest *_Nullable request,
  1009. FIRVerifyPasswordResponseCallback callback) {
  1010. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1011. id mockVeriyPasswordResponse = OCMClassMock([FIRVerifyPasswordResponse class]);
  1012. // New authentication comes back with new access token.
  1013. OCMStub([mockVeriyPasswordResponse IDToken]).andReturn(kNewAccessToken);
  1014. OCMStub([mockVeriyPasswordResponse approximateExpirationDate])
  1015. .andReturn([NSDate dateWithTimeIntervalSinceNow:kAccessTokenTimeToLive]);
  1016. OCMStub([mockVeriyPasswordResponse refreshToken]).andReturn(kRefreshToken);
  1017. callback(mockVeriyPasswordResponse, nil);
  1018. });
  1019. });
  1020. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1021. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  1022. FIRGetAccountInfoResponseCallback callback) {
  1023. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1024. // Verify that the new access token is being used for subsequent requests.
  1025. XCTAssertEqualObjects(request.accessToken, kNewAccessToken);
  1026. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1027. id mockGetAccountInfoResponse = OCMClassMock([FIRGetAccountInfoResponse class]);
  1028. OCMStub([mockGetAccountInfoResponse users]).andReturn(@[ mockGetAccountInfoResponseUser ]);
  1029. callback(mockGetAccountInfoResponse, nil);
  1030. });
  1031. });
  1032. FIRAuthCredential *emailCredential =
  1033. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1034. [user reauthenticateWithCredential:emailCredential completion:^(NSError *_Nullable error) {
  1035. XCTAssertTrue([NSThread isMainThread]);
  1036. XCTAssertNil(error);
  1037. // Verify that the current user is unchanged.
  1038. XCTAssertEqual([FIRAuth auth].currentUser, user);
  1039. [expectation fulfill];
  1040. }];
  1041. }];
  1042. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1043. OCMVerifyAll(_mockBackend);
  1044. }
  1045. /** @fn testReauthenticateAndRetrieveDataSuccess
  1046. @brief Tests the flow of a successful @c reauthenticateAndRetrieveDataWithCredential:completion:
  1047. call.
  1048. */
  1049. - (void)testReauthenticateAndRetrieveDataSuccess {
  1050. [self expectVerifyAssertionRequest:FIRGoogleAuthProviderID
  1051. federatedID:kGoogleID
  1052. displayName:kGoogleDisplayName
  1053. profile:[[self class] googleProfile]
  1054. providerIDToken:kGoogleIDToken
  1055. providerAccessToken:kGoogleAccessToken];
  1056. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1057. [[FIRAuth auth] signOut:NULL];
  1058. FIRAuthCredential *googleCredential =
  1059. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1060. [[FIRAuth auth] signInAndRetrieveDataWithCredential:googleCredential
  1061. completion:^(FIRAuthDataResult *_Nullable authResult,
  1062. NSError *_Nullable error) {
  1063. XCTAssertTrue([NSThread isMainThread]);
  1064. [self assertUserGoogle:authResult.user];
  1065. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1066. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1067. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRGoogleAuthProviderID);
  1068. XCTAssertNil(error);
  1069. [self expectVerifyAssertionRequest:FIRGoogleAuthProviderID
  1070. federatedID:kGoogleID
  1071. displayName:kGoogleDisplayName
  1072. profile:[[self class] googleProfile]
  1073. providerIDToken:kGoogleIDToken
  1074. providerAccessToken:kGoogleAccessToken];
  1075. FIRAuthCredential *reauthenticateGoogleCredential =
  1076. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1077. [authResult.user
  1078. reauthenticateAndRetrieveDataWithCredential:reauthenticateGoogleCredential
  1079. completion:^(FIRAuthDataResult *_Nullable
  1080. reauthenticateAuthResult,
  1081. NSError *_Nullable error) {
  1082. XCTAssertTrue([NSThread isMainThread]);
  1083. XCTAssertNil(error);
  1084. // Verify that the current user is unchanged.
  1085. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1086. // Verify that the current user and reauthenticated user are not same pointers.
  1087. XCTAssertNotEqualObjects(authResult.user, reauthenticateAuthResult.user);
  1088. // Verify that anyway the current user and reauthenticated user have same IDs.
  1089. XCTAssertEqualObjects(authResult.user.uid, reauthenticateAuthResult.user.uid);
  1090. XCTAssertEqualObjects(authResult.user.displayName, reauthenticateAuthResult.user.displayName);
  1091. XCTAssertEqualObjects(reauthenticateAuthResult.additionalUserInfo.profile,
  1092. [[self class] googleProfile]);
  1093. XCTAssertEqualObjects(reauthenticateAuthResult.additionalUserInfo.username, kUserName);
  1094. XCTAssertEqualObjects(reauthenticateAuthResult.additionalUserInfo.providerID,
  1095. FIRGoogleAuthProviderID);
  1096. [expectation fulfill];
  1097. }];
  1098. }];
  1099. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1100. [self assertUserGoogle:[FIRAuth auth].currentUser];
  1101. OCMVerifyAll(_mockBackend);
  1102. }
  1103. /** @fn testReauthenticateFailure
  1104. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call.
  1105. */
  1106. - (void)testReauthenticateFailure {
  1107. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1108. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1109. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1110. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  1111. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1112. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1113. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  1114. completion:^(FIRUser *user) {
  1115. OCMExpect([_mockBackend verifyPassword:[OCMArg any] callback:[OCMArg any]])
  1116. .andCallBlock2(^(FIRVerifyPasswordRequest *_Nullable request,
  1117. FIRVerifyPasswordResponseCallback callback) {
  1118. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1119. id mockVeriyPasswordResponse = OCMClassMock([FIRVerifyPasswordResponse class]);
  1120. OCMStub([mockVeriyPasswordResponse IDToken]).andReturn(kNewAccessToken);
  1121. OCMStub([mockVeriyPasswordResponse approximateExpirationDate])
  1122. .andReturn([NSDate dateWithTimeIntervalSinceNow:kAccessTokenTimeToLive]);
  1123. OCMStub([mockVeriyPasswordResponse refreshToken]).andReturn(kRefreshToken);
  1124. callback(mockVeriyPasswordResponse, nil);
  1125. });
  1126. });
  1127. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1128. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  1129. FIRGetAccountInfoResponseCallback callback) {
  1130. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1131. id mockGetAccountInfoResponseUserNew = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1132. // The newly-signed-in user has a different ID.
  1133. OCMStub([mockGetAccountInfoResponseUserNew localID]).andReturn(kAnotherLocalID);
  1134. OCMStub([mockGetAccountInfoResponseUserNew email]).andReturn(kNewEmail);
  1135. OCMStub([mockGetAccountInfoResponseUserNew displayName]).andReturn(kNewDisplayName);
  1136. OCMStub([mockGetAccountInfoResponseUserNew passwordHash]).andReturn(kPasswordHash);
  1137. id mockGetAccountInfoResponse = OCMClassMock([FIRGetAccountInfoResponse class]);
  1138. OCMStub([mockGetAccountInfoResponse users])
  1139. .andReturn(@[ mockGetAccountInfoResponseUserNew ]);
  1140. callback(mockGetAccountInfoResponse, nil);
  1141. });
  1142. });
  1143. FIRAuthCredential *emailCredential =
  1144. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1145. [user reauthenticateWithCredential:emailCredential completion:^(NSError *_Nullable error) {
  1146. XCTAssertTrue([NSThread isMainThread]);
  1147. // Verify user mismatch error.
  1148. XCTAssertEqual(error.code, FIRAuthErrorCodeUserMismatch);
  1149. // Verify that the current user is unchanged.
  1150. XCTAssertEqual([FIRAuth auth].currentUser, user);
  1151. [expectation fulfill];
  1152. }];
  1153. }];
  1154. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1155. OCMVerifyAll(_mockBackend);
  1156. }
  1157. /** @fn testReauthenticateUserMismatchFailure
  1158. @brief Tests the flow of a failed @c reauthenticateWithCredential:completion: call due to trying
  1159. to reauthenticate a user that does not exist.
  1160. */
  1161. - (void)testReauthenticateUserMismatchFailure {
  1162. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1163. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1164. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1165. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  1166. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1167. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1168. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  1169. completion:^(FIRUser *user) {
  1170. OCMExpect([_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
  1171. .andCallBlock2(^(FIRVerifyAssertionRequest *_Nullable request,
  1172. FIRVerifyAssertionResponseCallback callback) {
  1173. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1174. callback(nil, [FIRAuthErrorUtils userNotFoundErrorWithMessage:nil]);
  1175. });
  1176. });
  1177. FIRAuthCredential *googleCredential =
  1178. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1179. [user reauthenticateWithCredential:googleCredential completion:^(NSError *_Nullable error) {
  1180. XCTAssertTrue([NSThread isMainThread]);
  1181. // Verify user mismatch error.
  1182. XCTAssertEqual(error.code, FIRAuthErrorCodeUserMismatch);
  1183. // Verify that the current user is unchanged.
  1184. XCTAssertEqual([FIRAuth auth].currentUser, user);
  1185. [expectation fulfill];
  1186. }];
  1187. }];
  1188. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1189. OCMVerifyAll(_mockBackend);
  1190. }
  1191. /** @fn testlinkAndRetrieveDataSuccess
  1192. @brief Tests the flow of a successful @c linkAndRetrieveDataWithCredential:completion:
  1193. call.
  1194. */
  1195. - (void)testlinkAndRetrieveDataSuccess {
  1196. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1197. federatedID:kFacebookID
  1198. displayName:kFacebookDisplayName
  1199. profile:[[self class] googleProfile]
  1200. providerIDToken:kFacebookIDToken
  1201. providerAccessToken:kFacebookAccessToken];
  1202. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1203. [[FIRAuth auth] signOut:NULL];
  1204. FIRAuthCredential *facebookCredential =
  1205. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1206. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1207. completion:^(FIRAuthDataResult *_Nullable authResult,
  1208. NSError *_Nullable error) {
  1209. XCTAssertTrue([NSThread isMainThread]);
  1210. [self assertUserFacebook:authResult.user];
  1211. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1212. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1213. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1214. XCTAssertNil(error);
  1215. [self expectVerifyAssertionRequest:FIRGoogleAuthProviderID
  1216. federatedID:kGoogleID
  1217. displayName:kGoogleDisplayName
  1218. profile:[[self class] googleProfile]
  1219. providerIDToken:kGoogleIDToken
  1220. providerAccessToken:kGoogleAccessToken];
  1221. FIRAuthCredential *linkGoogleCredential =
  1222. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1223. [authResult.user linkAndRetrieveDataWithCredential:linkGoogleCredential
  1224. completion:^(FIRAuthDataResult *_Nullable
  1225. linkAuthResult,
  1226. NSError *_Nullable error) {
  1227. XCTAssertTrue([NSThread isMainThread]);
  1228. XCTAssertNil(error);
  1229. // Verify that the current user is unchanged.
  1230. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1231. // Verify that the current user and reauthenticated user are same pointers.
  1232. XCTAssertEqualObjects(authResult.user, linkAuthResult.user);
  1233. // Verify that anyway the current user and linked user have same IDs.
  1234. XCTAssertEqualObjects(authResult.user.uid, linkAuthResult.user.uid);
  1235. XCTAssertEqualObjects(authResult.user.displayName, linkAuthResult.user.displayName);
  1236. XCTAssertEqualObjects(linkAuthResult.additionalUserInfo.profile,
  1237. [[self class] googleProfile]);
  1238. XCTAssertEqualObjects(linkAuthResult.additionalUserInfo.username, kUserName);
  1239. XCTAssertEqualObjects(linkAuthResult.additionalUserInfo.providerID,
  1240. FIRGoogleAuthProviderID);
  1241. [expectation fulfill];
  1242. }];
  1243. }];
  1244. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1245. [self assertUserGoogle:[FIRAuth auth].currentUser];
  1246. OCMVerifyAll(_mockBackend);
  1247. }
  1248. /** @fn testlinkAndRetrieveDataError
  1249. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1250. call with an error from the backend.
  1251. */
  1252. - (void)testlinkAndRetrieveDataError {
  1253. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1254. federatedID:kFacebookID
  1255. displayName:kFacebookDisplayName
  1256. profile:[[self class] googleProfile]
  1257. providerIDToken:kFacebookIDToken
  1258. providerAccessToken:kFacebookAccessToken];
  1259. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1260. [[FIRAuth auth] signOut:NULL];
  1261. FIRAuthCredential *facebookCredential =
  1262. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1263. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1264. completion:^(FIRAuthDataResult *_Nullable authResult,
  1265. NSError *_Nullable error) {
  1266. XCTAssertTrue([NSThread isMainThread]);
  1267. [self assertUserFacebook:authResult.user];
  1268. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1269. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1270. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1271. XCTAssertNil(error);
  1272. OCMExpect([_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
  1273. .andCallBlock2(^(FIRVerifyAssertionRequest *_Nullable request,
  1274. FIRVerifyAssertionResponseCallback callback) {
  1275. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1276. callback(nil,
  1277. [FIRAuthErrorUtils accountExistsWithDifferentCredentialErrorWithEmail:kEmail]);
  1278. });
  1279. });
  1280. FIRAuthCredential *linkGoogleCredential =
  1281. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1282. [authResult.user linkAndRetrieveDataWithCredential:linkGoogleCredential
  1283. completion:^(FIRAuthDataResult *_Nullable
  1284. linkAuthResult,
  1285. NSError *_Nullable error) {
  1286. XCTAssertTrue([NSThread isMainThread]);
  1287. XCTAssertNil(linkAuthResult);
  1288. XCTAssertEqual(error.code, FIRAuthErrorCodeAccountExistsWithDifferentCredential);
  1289. XCTAssertEqual(error.userInfo[FIRAuthErrorUserInfoEmailKey], kEmail);
  1290. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1291. [expectation fulfill];
  1292. }];
  1293. }];
  1294. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1295. OCMVerifyAll(_mockBackend);
  1296. }
  1297. /** @fn testlinkAndRetrieveDataProviderAlreadyLinked
  1298. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1299. call with FIRAuthErrorCodeProviderAlreadyLinked, which is a client side error.
  1300. */
  1301. - (void)testlinkAndRetrieveDataProviderAlreadyLinked {
  1302. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1303. federatedID:kFacebookID
  1304. displayName:kFacebookDisplayName
  1305. profile:[[self class] googleProfile]
  1306. providerIDToken:kFacebookIDToken
  1307. providerAccessToken:kFacebookAccessToken];
  1308. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1309. [[FIRAuth auth] signOut:NULL];
  1310. FIRAuthCredential *facebookCredential =
  1311. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1312. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1313. completion:^(FIRAuthDataResult *_Nullable authResult,
  1314. NSError *_Nullable error) {
  1315. XCTAssertTrue([NSThread isMainThread]);
  1316. [self assertUserFacebook:authResult.user];
  1317. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1318. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1319. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1320. XCTAssertNil(error);
  1321. FIRAuthCredential *linkFacebookCredential =
  1322. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1323. [authResult.user linkAndRetrieveDataWithCredential:linkFacebookCredential
  1324. completion:^(FIRAuthDataResult *_Nullable
  1325. linkAuthResult,
  1326. NSError *_Nullable error) {
  1327. XCTAssertTrue([NSThread isMainThread]);
  1328. XCTAssertNil(linkAuthResult);
  1329. XCTAssertEqual(error.code, FIRAuthErrorCodeProviderAlreadyLinked);
  1330. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1331. [expectation fulfill];
  1332. }];
  1333. }];
  1334. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1335. OCMVerifyAll(_mockBackend);
  1336. }
  1337. /** @fn testlinkAndRetrieveDataErrorAutoSignOut
  1338. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1339. call that automatically signs out.
  1340. */
  1341. - (void)testlinkAndRetrieveDataErrorAutoSignOut {
  1342. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1343. federatedID:kFacebookID
  1344. displayName:kFacebookDisplayName
  1345. profile:[[self class] googleProfile]
  1346. providerIDToken:kFacebookIDToken
  1347. providerAccessToken:kFacebookAccessToken];
  1348. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1349. [[FIRAuth auth] signOut:NULL];
  1350. FIRAuthCredential *facebookCredential =
  1351. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1352. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1353. completion:^(FIRAuthDataResult *_Nullable authResult,
  1354. NSError *_Nullable error) {
  1355. XCTAssertTrue([NSThread isMainThread]);
  1356. [self assertUserFacebook:authResult.user];
  1357. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1358. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1359. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1360. XCTAssertNil(error);
  1361. OCMExpect([_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
  1362. .andCallBlock2(^(FIRVerifyAssertionRequest *_Nullable request,
  1363. FIRVerifyAssertionResponseCallback callback) {
  1364. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1365. callback(nil, [FIRAuthErrorUtils userDisabledErrorWithMessage:nil]);
  1366. });
  1367. });
  1368. FIRAuthCredential *linkGoogleCredential =
  1369. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1370. [authResult.user linkAndRetrieveDataWithCredential:linkGoogleCredential
  1371. completion:^(FIRAuthDataResult *_Nullable
  1372. linkAuthResult,
  1373. NSError *_Nullable error) {
  1374. XCTAssertTrue([NSThread isMainThread]);
  1375. XCTAssertNil(linkAuthResult);
  1376. XCTAssertEqual(error.code, FIRAuthErrorCodeUserDisabled);
  1377. XCTAssertNil([FIRAuth auth].currentUser);
  1378. [expectation fulfill];
  1379. }];
  1380. }];
  1381. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1382. OCMVerifyAll(_mockBackend);
  1383. }
  1384. /** @fn testlinkEmailAndRetrieveDataSuccess
  1385. @brief Tests the flow of a successful @c linkAndRetrieveDataWithCredential:completion:
  1386. invocation for email credential.
  1387. */
  1388. - (void)testlinkEmailAndRetrieveDataSuccess {
  1389. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1390. federatedID:kFacebookID
  1391. displayName:kFacebookDisplayName
  1392. profile:[[self class] googleProfile]
  1393. providerIDToken:kFacebookIDToken
  1394. providerAccessToken:kFacebookAccessToken];
  1395. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1396. [[FIRAuth auth] signOut:NULL];
  1397. FIRAuthCredential *facebookCredential =
  1398. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1399. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1400. completion:^(FIRAuthDataResult *_Nullable authResult,
  1401. NSError *_Nullable error) {
  1402. XCTAssertTrue([NSThread isMainThread]);
  1403. [self assertUserFacebook:authResult.user];
  1404. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1405. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1406. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1407. XCTAssertNil(error);
  1408. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1409. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1410. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1411. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kEmailDisplayName);
  1412. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1413. // Get account info is expected to be invoked twice.
  1414. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  1415. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  1416. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1417. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  1418. FIRSetAccountInfoResponseCallback callback) {
  1419. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1420. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1421. XCTAssertEqualObjects(request.password, kFakePassword);
  1422. XCTAssertNil(request.localID);
  1423. XCTAssertNil(request.displayName);
  1424. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1425. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  1426. callback(mockSetAccountInfoResponse, nil);
  1427. });
  1428. });
  1429. FIRAuthCredential *linkEmailCredential =
  1430. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1431. [authResult.user linkAndRetrieveDataWithCredential:linkEmailCredential
  1432. completion:^(FIRAuthDataResult *_Nullable
  1433. linkAuthResult,
  1434. NSError *_Nullable error) {
  1435. XCTAssertTrue([NSThread isMainThread]);
  1436. XCTAssertNil(error);
  1437. XCTAssertEqualObjects(linkAuthResult.user.email, kEmail);
  1438. XCTAssertEqualObjects(linkAuthResult.user.displayName, kEmailDisplayName);
  1439. [expectation fulfill];
  1440. }];
  1441. }];
  1442. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1443. OCMVerifyAll(_mockBackend);
  1444. }
  1445. /** @fn testlinkEmailProviderAlreadyLinkedError
  1446. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1447. invocation for email credential and FIRAuthErrorCodeProviderAlreadyLinked which is a client
  1448. side error.
  1449. */
  1450. - (void)testlinkEmailProviderAlreadyLinkedError {
  1451. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1452. federatedID:kFacebookID
  1453. displayName:kFacebookDisplayName
  1454. profile:[[self class] googleProfile]
  1455. providerIDToken:kFacebookIDToken
  1456. providerAccessToken:kFacebookAccessToken];
  1457. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1458. [[FIRAuth auth] signOut:NULL];
  1459. FIRAuthCredential *facebookCredential =
  1460. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1461. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1462. completion:^(FIRAuthDataResult *_Nullable authResult,
  1463. NSError *_Nullable error) {
  1464. XCTAssertTrue([NSThread isMainThread]);
  1465. [self assertUserFacebook:authResult.user];
  1466. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1467. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1468. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1469. XCTAssertNil(error);
  1470. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1471. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1472. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1473. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kEmailDisplayName);
  1474. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1475. // Get account info is expected to be invoked twice.
  1476. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  1477. [self expectGetAccountInfoWithMockUserInfoResponse:mockGetAccountInfoResponseUser];
  1478. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1479. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  1480. FIRSetAccountInfoResponseCallback callback) {
  1481. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1482. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1483. XCTAssertEqualObjects(request.password, kFakePassword);
  1484. XCTAssertNil(request.localID);
  1485. XCTAssertNil(request.displayName);
  1486. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1487. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  1488. callback(mockSetAccountInfoResponse, nil);
  1489. });
  1490. });
  1491. FIRAuthCredential *linkEmailCredential =
  1492. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1493. [authResult.user linkAndRetrieveDataWithCredential:linkEmailCredential
  1494. completion:^(FIRAuthDataResult *_Nullable
  1495. linkAuthResult,
  1496. NSError *_Nullable error) {
  1497. XCTAssertNil(error);
  1498. XCTAssertEqualObjects(linkAuthResult.user.email, kEmail);
  1499. XCTAssertEqualObjects(linkAuthResult.user.displayName, kEmailDisplayName);
  1500. // Try linking same credential a second time to trigger client side error.
  1501. [authResult.user linkAndRetrieveDataWithCredential:linkEmailCredential
  1502. completion:^(FIRAuthDataResult *_Nullable
  1503. linkAuthResult,
  1504. NSError *_Nullable error) {
  1505. XCTAssertTrue([NSThread isMainThread]);
  1506. XCTAssertNil(linkAuthResult);
  1507. XCTAssertEqual(error.code, FIRAuthErrorCodeProviderAlreadyLinked);
  1508. [expectation fulfill];
  1509. }];
  1510. }];
  1511. }];
  1512. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1513. OCMVerifyAll(_mockBackend);
  1514. }
  1515. /** @fn testlinkEmailAndRetrieveDataError
  1516. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1517. invocation for email credential and an error from the backend.
  1518. */
  1519. - (void)testlinkEmailAndRetrieveDataError {
  1520. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1521. federatedID:kFacebookID
  1522. displayName:kFacebookDisplayName
  1523. profile:[[self class] googleProfile]
  1524. providerIDToken:kFacebookIDToken
  1525. providerAccessToken:kFacebookAccessToken];
  1526. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1527. [[FIRAuth auth] signOut:NULL];
  1528. FIRAuthCredential *facebookCredential =
  1529. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1530. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1531. completion:^(FIRAuthDataResult *_Nullable authResult,
  1532. NSError *_Nullable error) {
  1533. XCTAssertTrue([NSThread isMainThread]);
  1534. [self assertUserFacebook:authResult.user];
  1535. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1536. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1537. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1538. XCTAssertNil(error);
  1539. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1540. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  1541. FIRGetAccountInfoResponseCallback callback) {
  1542. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1543. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1544. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1545. callback(nil, [FIRAuthErrorUtils tooManyRequestsErrorWithMessage:nil]);
  1546. });
  1547. });
  1548. FIRAuthCredential *linkEmailCredential =
  1549. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1550. [authResult.user linkAndRetrieveDataWithCredential:linkEmailCredential
  1551. completion:^(FIRAuthDataResult *_Nullable
  1552. linkAuthResult,
  1553. NSError *_Nullable error) {
  1554. XCTAssertTrue([NSThread isMainThread]);
  1555. XCTAssertNil(linkAuthResult);
  1556. XCTAssertEqual(error.code, FIRAuthErrorCodeTooManyRequests);
  1557. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1558. [expectation fulfill];
  1559. }];
  1560. }];
  1561. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1562. OCMVerifyAll(_mockBackend);
  1563. }
  1564. /** @fn testlinkEmailAndRetrieveDataError
  1565. @brief Tests the flow of an unsuccessful @c linkAndRetrieveDataWithCredential:completion:
  1566. invocation that automatically signs out.
  1567. */
  1568. - (void)testlinkEmailAndRetrieveDataErrorAutoSignOut {
  1569. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1570. federatedID:kFacebookID
  1571. displayName:kFacebookDisplayName
  1572. profile:[[self class] googleProfile]
  1573. providerIDToken:kFacebookIDToken
  1574. providerAccessToken:kFacebookAccessToken];
  1575. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1576. [[FIRAuth auth] signOut:NULL];
  1577. FIRAuthCredential *facebookCredential =
  1578. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1579. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1580. completion:^(FIRAuthDataResult *_Nullable authResult,
  1581. NSError *_Nullable error) {
  1582. XCTAssertTrue([NSThread isMainThread]);
  1583. [self assertUserFacebook:authResult.user];
  1584. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1585. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1586. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1587. XCTAssertNil(error);
  1588. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1589. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  1590. FIRGetAccountInfoResponseCallback callback) {
  1591. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1592. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1593. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1594. callback(nil, [FIRAuthErrorUtils userTokenExpiredErrorWithMessage:nil]);
  1595. });
  1596. });
  1597. FIRAuthCredential *linkEmailCredential =
  1598. [FIREmailAuthProvider credentialWithEmail:kEmail password:kFakePassword];
  1599. [authResult.user linkAndRetrieveDataWithCredential:linkEmailCredential
  1600. completion:^(FIRAuthDataResult *_Nullable
  1601. linkAuthResult,
  1602. NSError *_Nullable error) {
  1603. XCTAssertTrue([NSThread isMainThread]);
  1604. XCTAssertNil(linkAuthResult);
  1605. XCTAssertEqual(error.code, FIRAuthErrorCodeUserTokenExpired);
  1606. XCTAssertNil([FIRAuth auth].currentUser);
  1607. [expectation fulfill];
  1608. }];
  1609. }];
  1610. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1611. OCMVerifyAll(_mockBackend);
  1612. }
  1613. /** @fn testlinkCredentialSuccess
  1614. @brief Tests the flow of a successful @c linkWithCredential:completion: call, without additional
  1615. IDP data.
  1616. */
  1617. - (void)testlinkCredentialSuccess {
  1618. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1619. federatedID:kFacebookID
  1620. displayName:kFacebookDisplayName
  1621. profile:[[self class] googleProfile]
  1622. providerIDToken:kFacebookIDToken
  1623. providerAccessToken:kFacebookAccessToken];
  1624. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1625. [[FIRAuth auth] signOut:NULL];
  1626. FIRAuthCredential *facebookCredential =
  1627. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1628. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1629. completion:^(FIRAuthDataResult *_Nullable authResult,
  1630. NSError *_Nullable error) {
  1631. XCTAssertTrue([NSThread isMainThread]);
  1632. [self assertUserFacebook:authResult.user];
  1633. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1634. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1635. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1636. XCTAssertNil(error);
  1637. [self expectVerifyAssertionRequest:FIRGoogleAuthProviderID
  1638. federatedID:kGoogleID
  1639. displayName:kGoogleDisplayName
  1640. profile:[[self class] googleProfile]
  1641. providerIDToken:kGoogleIDToken
  1642. providerAccessToken:kGoogleAccessToken];
  1643. FIRAuthCredential *linkGoogleCredential =
  1644. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1645. [authResult.user linkWithCredential:linkGoogleCredential
  1646. completion:^(FIRUser *_Nullable user,
  1647. NSError *_Nullable error) {
  1648. XCTAssertNil(error);
  1649. id<FIRUserInfo> userInfo = user.providerData.firstObject;
  1650. XCTAssertEqual(userInfo.providerID, FIRGoogleAuthProviderID);
  1651. XCTAssertEqual([FIRAuth auth].currentUser, authResult.user);
  1652. [expectation fulfill];
  1653. }];
  1654. }];
  1655. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1656. [self assertUserGoogle:[FIRAuth auth].currentUser];
  1657. OCMVerifyAll(_mockBackend);
  1658. }
  1659. /** @fn testlinkCredentialError
  1660. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion: call, with an error
  1661. from the backend.
  1662. */
  1663. - (void)testlinkCredentialError {
  1664. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1665. federatedID:kFacebookID
  1666. displayName:kFacebookDisplayName
  1667. profile:[[self class] googleProfile]
  1668. providerIDToken:kFacebookIDToken
  1669. providerAccessToken:kFacebookAccessToken];
  1670. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1671. [[FIRAuth auth] signOut:NULL];
  1672. FIRAuthCredential *facebookCredential =
  1673. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1674. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1675. completion:^(FIRAuthDataResult *_Nullable authResult,
  1676. NSError *_Nullable error) {
  1677. XCTAssertTrue([NSThread isMainThread]);
  1678. [self assertUserFacebook:authResult.user];
  1679. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1680. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1681. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1682. XCTAssertNil(error);
  1683. OCMExpect([_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
  1684. .andCallBlock2(^(FIRVerifyAssertionRequest *_Nullable request,
  1685. FIRVerifyAssertionResponseCallback callback) {
  1686. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1687. callback(nil, [FIRAuthErrorUtils userDisabledErrorWithMessage:nil]);
  1688. });
  1689. });
  1690. FIRAuthCredential *linkGoogleCredential =
  1691. [FIRGoogleAuthProvider credentialWithIDToken:kGoogleIDToken accessToken:kGoogleAccessToken];
  1692. [authResult.user linkWithCredential:linkGoogleCredential
  1693. completion:^(FIRUser *_Nullable user,
  1694. NSError *_Nullable error) {
  1695. XCTAssertNil(user);
  1696. XCTAssertEqual(error.code, FIRAuthErrorCodeUserDisabled);
  1697. [expectation fulfill];
  1698. }];
  1699. }];
  1700. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1701. OCMVerifyAll(_mockBackend);
  1702. }
  1703. /** @fn testlinkCredentialProviderAlreadyLinkedError
  1704. @brief Tests the flow of an unsuccessful @c linkWithCredential:completion: call, with a client
  1705. side error.
  1706. */
  1707. - (void)testlinkCredentialProviderAlreadyLinkedError {
  1708. [self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
  1709. federatedID:kFacebookID
  1710. displayName:kFacebookDisplayName
  1711. profile:[[self class] googleProfile]
  1712. providerIDToken:kFacebookIDToken
  1713. providerAccessToken:kFacebookAccessToken];
  1714. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1715. [[FIRAuth auth] signOut:NULL];
  1716. FIRAuthCredential *facebookCredential =
  1717. [FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
  1718. [[FIRAuth auth] signInAndRetrieveDataWithCredential:facebookCredential
  1719. completion:^(FIRAuthDataResult *_Nullable authResult,
  1720. NSError *_Nullable error) {
  1721. XCTAssertTrue([NSThread isMainThread]);
  1722. [self assertUserFacebook:authResult.user];
  1723. XCTAssertEqualObjects(authResult.additionalUserInfo.profile, [[self class] googleProfile]);
  1724. XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
  1725. XCTAssertEqualObjects(authResult.additionalUserInfo.providerID, FIRFacebookAuthProviderID);
  1726. XCTAssertNil(error);
  1727. FIRAuthCredential *linkFacebookCredential =
  1728. [FIRFacebookAuthProvider credentialWithAccessToken:kGoogleAccessToken];
  1729. [authResult.user linkWithCredential:linkFacebookCredential
  1730. completion:^(FIRUser *_Nullable user,
  1731. NSError *_Nullable error) {
  1732. XCTAssertNil(user);
  1733. XCTAssertEqual(error.code, FIRAuthErrorCodeProviderAlreadyLinked);
  1734. [expectation fulfill];
  1735. }];
  1736. }];
  1737. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1738. OCMVerifyAll(_mockBackend);
  1739. }
  1740. #if TARGET_OS_IOS
  1741. /** @fn testlinkPhoneAuthCredentialSuccess
  1742. @brief Tests the flow of a successful @c linkAndRetrieveDataWithCredential:completion:
  1743. call using a phoneAuthCredential.
  1744. */
  1745. - (void)testlinkPhoneAuthCredentialSuccess {
  1746. id (^mockUserInfoWithPhoneNumber)(NSString *) = ^(NSString *phoneNumber) {
  1747. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1748. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1749. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1750. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1751. if (phoneNumber.length) {
  1752. NSDictionary *userInfoDictionary = @{ @"providerId" : FIRPhoneAuthProviderID };
  1753. FIRGetAccountInfoResponseProviderUserInfo *userInfo =
  1754. [[FIRGetAccountInfoResponseProviderUserInfo alloc] initWithDictionary:userInfoDictionary];
  1755. OCMStub([mockGetAccountInfoResponseUser providerUserInfo]).andReturn(@[ userInfo ]);
  1756. OCMStub([mockGetAccountInfoResponseUser phoneNumber]).andReturn(phoneNumber);
  1757. }
  1758. return mockGetAccountInfoResponseUser;
  1759. };
  1760. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1761. id userInfoResponse = mockUserInfoWithPhoneNumber(nil);
  1762. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  1763. completion:^(FIRUser *user) {
  1764. [self expectVerifyPhoneNumberRequestWithPhoneNumber:kPhoneNumber isLinkOperation:YES error:nil];
  1765. id userInfoResponseUpdate = mockUserInfoWithPhoneNumber(kPhoneNumber);
  1766. [self expectGetAccountInfoWithMockUserInfoResponse:userInfoResponseUpdate];
  1767. FIRPhoneAuthCredential *credential =
  1768. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  1769. verificationCode:kVerificationCode];
  1770. [user linkAndRetrieveDataWithCredential:credential
  1771. completion:^(FIRAuthDataResult *_Nullable
  1772. linkAuthResult,
  1773. NSError *_Nullable error) {
  1774. XCTAssertNil(error);
  1775. XCTAssertEqualObjects([FIRAuth auth].currentUser.providerData.firstObject.providerID,
  1776. FIRPhoneAuthProviderID);
  1777. XCTAssertEqualObjects([FIRAuth auth].currentUser.phoneNumber, kPhoneNumber);
  1778. [expectation fulfill];
  1779. }];
  1780. }];
  1781. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1782. OCMVerifyAll(_mockBackend);
  1783. }
  1784. /** @fn testUnlinkPhoneAuthCredentialSuccess
  1785. @brief Tests the flow of a successful @c unlinkFromProvider:completion: call using a
  1786. @c FIRPhoneAuthProvider.
  1787. */
  1788. - (void)testUnlinkPhoneAuthCredentialSuccess {
  1789. id (^mockUserInfoWithPhoneNumber)(NSString *) = ^(NSString *phoneNumber) {
  1790. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1791. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1792. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1793. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1794. if (phoneNumber.length) {
  1795. NSDictionary *userInfoDictionary = @{ @"providerId" : FIRPhoneAuthProviderID };
  1796. FIRGetAccountInfoResponseProviderUserInfo *userInfo =
  1797. [[FIRGetAccountInfoResponseProviderUserInfo alloc] initWithDictionary:userInfoDictionary];
  1798. OCMStub([mockGetAccountInfoResponseUser providerUserInfo]).andReturn(@[ userInfo ]);
  1799. OCMStub([mockGetAccountInfoResponseUser phoneNumber]).andReturn(phoneNumber);
  1800. }
  1801. return mockGetAccountInfoResponseUser;
  1802. };
  1803. OCMExpect([_mockBackend setAccountInfo:[OCMArg any] callback:[OCMArg any]])
  1804. .andCallBlock2(^(FIRSetAccountInfoRequest *_Nullable request,
  1805. FIRSetAccountInfoResponseCallback callback) {
  1806. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1807. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1808. XCTAssertNotNil(request.deleteProviders);
  1809. XCTAssertNil(request.email);
  1810. XCTAssertNil(request.localID);
  1811. XCTAssertNil(request.displayName);
  1812. XCTAssertNil(request.photoURL);
  1813. XCTAssertNil(request.password);
  1814. XCTAssertNil(request.providers);
  1815. XCTAssertNil(request.deleteAttributes);
  1816. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1817. id mockSetAccountInfoResponse = OCMClassMock([FIRSetAccountInfoResponse class]);
  1818. callback(mockSetAccountInfoResponse, nil);
  1819. });
  1820. });
  1821. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1822. id userInfoResponse = mockUserInfoWithPhoneNumber(nil);
  1823. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  1824. completion:^(FIRUser *user) {
  1825. [self expectVerifyPhoneNumberRequestWithPhoneNumber:kPhoneNumber isLinkOperation:YES error:nil];
  1826. id userInfoResponseUpdate = mockUserInfoWithPhoneNumber(kPhoneNumber);
  1827. [self expectGetAccountInfoWithMockUserInfoResponse:userInfoResponseUpdate];
  1828. FIRPhoneAuthCredential *credential =
  1829. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  1830. verificationCode:kVerificationCode];
  1831. // Link phone credential.
  1832. [user linkAndRetrieveDataWithCredential:credential
  1833. completion:^(FIRAuthDataResult *_Nullable
  1834. linkAuthResult,
  1835. NSError *_Nullable error) {
  1836. XCTAssertNil(error);
  1837. XCTAssertEqualObjects([FIRAuth auth].currentUser.providerData.firstObject.providerID,
  1838. FIRPhoneAuthProviderID);
  1839. XCTAssertEqualObjects([FIRAuth auth].currentUser.phoneNumber, kPhoneNumber);
  1840. // Immediately unlink the phone auth provider.
  1841. [user unlinkFromProvider:FIRPhoneAuthProviderID
  1842. completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
  1843. XCTAssertNil(error);
  1844. XCTAssertNil([FIRAuth auth].currentUser.phoneNumber);
  1845. [expectation fulfill];
  1846. }];
  1847. }];
  1848. }];
  1849. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1850. OCMVerifyAll(_mockBackend);
  1851. }
  1852. /** @fn testlinkPhoneAuthCredentialFailure
  1853. @brief Tests the flow of a failed call to @c linkAndRetrieveDataWithCredential:completion: due
  1854. to a phone provider already being linked.
  1855. */
  1856. - (void)testlinkPhoneAuthCredentialFailure {
  1857. id (^mockUserInfoWithPhoneNumber)(NSString *) = ^(NSString *phoneNumber) {
  1858. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1859. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1860. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1861. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1862. if (phoneNumber.length) {
  1863. OCMStub([mockGetAccountInfoResponseUser phoneNumber]).andReturn(phoneNumber);
  1864. }
  1865. return mockGetAccountInfoResponseUser;
  1866. };
  1867. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1868. id userInfoResponse = mockUserInfoWithPhoneNumber(nil);
  1869. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  1870. completion:^(FIRUser *user) {
  1871. NSError *error = [FIRAuthErrorUtils providerAlreadyLinkedError];
  1872. [self expectVerifyPhoneNumberRequestWithPhoneNumber:nil isLinkOperation:YES error:error];
  1873. FIRPhoneAuthCredential *credential =
  1874. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  1875. verificationCode:kVerificationCode];
  1876. [user linkAndRetrieveDataWithCredential:credential
  1877. completion:^(FIRAuthDataResult *_Nullable
  1878. linkAuthResult,
  1879. NSError *_Nullable error) {
  1880. XCTAssertEqual(error.code, FIRAuthErrorCodeProviderAlreadyLinked);
  1881. [expectation fulfill];
  1882. }];
  1883. }];
  1884. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1885. OCMVerifyAll(_mockBackend);
  1886. }
  1887. /** @fn testlinkPhoneCredentialAlreadyExistsError
  1888. @brief Tests the flow of @c linkAndRetrieveDataWithCredential:completion:
  1889. call using a phoneAuthCredential and a credential already exisits error. In this case we
  1890. should get a FIRAuthCredential in the error object.
  1891. */
  1892. - (void)testlinkPhoneCredentialAlreadyExistsError {
  1893. id (^mockUserInfoWithPhoneNumber)(NSString *) = ^(NSString *phoneNumber) {
  1894. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1895. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1896. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1897. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1898. if (phoneNumber.length) {
  1899. OCMStub([mockGetAccountInfoResponseUser phoneNumber]).andReturn(phoneNumber);
  1900. }
  1901. return mockGetAccountInfoResponseUser;
  1902. };
  1903. void (^expectVerifyPhoneNumberRequest)(NSString *) = ^(NSString *phoneNumber) {
  1904. OCMExpect([_mockBackend verifyPhoneNumber:[OCMArg any] callback:[OCMArg any]])
  1905. .andCallBlock2(^(FIRVerifyPhoneNumberRequest *_Nullable request,
  1906. FIRVerifyPhoneNumberResponseCallback callback) {
  1907. XCTAssertEqualObjects(request.verificationID, kVerificationID);
  1908. XCTAssertEqualObjects(request.verificationCode, kVerificationCode);
  1909. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  1910. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1911. FIRPhoneAuthCredential *credential =
  1912. [[FIRPhoneAuthCredential alloc] initWithTemporaryProof:kTemporaryProof
  1913. phoneNumber:kPhoneNumber
  1914. providerID:FIRPhoneAuthProviderID];
  1915. callback(nil,
  1916. [FIRAuthErrorUtils credentialAlreadyInUseErrorWithMessage:nil
  1917. credential:credential]);
  1918. });
  1919. });
  1920. };
  1921. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1922. id userInfoResponse = mockUserInfoWithPhoneNumber(nil);
  1923. [self signInWithEmailPasswordWithMockUserInfoResponse:userInfoResponse
  1924. completion:^(FIRUser *user) {
  1925. expectVerifyPhoneNumberRequest(kPhoneNumber);
  1926. FIRPhoneAuthCredential *credential =
  1927. [[FIRPhoneAuthProvider provider] credentialWithVerificationID:kVerificationID
  1928. verificationCode:kVerificationCode];
  1929. [user linkAndRetrieveDataWithCredential:credential
  1930. completion:^(FIRAuthDataResult *_Nullable
  1931. linkAuthResult,
  1932. NSError *_Nullable error) {
  1933. XCTAssertNil(linkAuthResult);
  1934. XCTAssertEqual(error.code, FIRAuthErrorCodeCredentialAlreadyInUse);
  1935. FIRPhoneAuthCredential *credential = error.userInfo[FIRAuthUpdatedCredentialKey];
  1936. XCTAssertEqual(credential.temporaryProof, kTemporaryProof);
  1937. XCTAssertEqual(credential.phoneNumber, kPhoneNumber);
  1938. [expectation fulfill];
  1939. }];
  1940. }];
  1941. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1942. OCMVerifyAll(_mockBackend);
  1943. }
  1944. #endif
  1945. #pragma mark - Helpers
  1946. /** @fn getIDTokenResultForcingRefreshSuccess
  1947. @brief Helper for testing the flow of a successful @c
  1948. getIDTokenResultForcingRefresh:completion: call.
  1949. */
  1950. - (void)getIDTokenResultForcingRefreshSuccessWithIDToken:(NSString *)idToken {
  1951. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  1952. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  1953. OCMStub([mockGetAccountInfoResponseUser email]).andReturn(kEmail);
  1954. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(kGoogleDisplayName);
  1955. OCMStub([mockGetAccountInfoResponseUser passwordHash]).andReturn(kPasswordHash);
  1956. XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
  1957. [self signInWithEmailPasswordWithMockUserInfoResponse:mockGetAccountInfoResponseUser
  1958. completion:^(FIRUser *user) {
  1959. OCMExpect([_mockBackend secureToken:[OCMArg any] callback:[OCMArg any]])
  1960. .andCallBlock2(^(FIRSecureTokenRequest *_Nullable request,
  1961. FIRSecureTokenResponseCallback callback) {
  1962. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  1963. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1964. id mockSecureTokenResponse = OCMClassMock([FIRSecureTokenResponse class]);
  1965. OCMStub([mockSecureTokenResponse accessToken]).andReturn(idToken);
  1966. callback(mockSecureTokenResponse, nil);
  1967. });
  1968. });
  1969. [user getIDTokenResultForcingRefresh:YES
  1970. completion:^(FIRAuthTokenResult *_Nullable tokenResult,
  1971. NSError *_Nullable error) {
  1972. XCTAssertTrue([NSThread isMainThread]);
  1973. XCTAssertNil(error);
  1974. XCTAssertEqualObjects(tokenResult.token, idToken);
  1975. XCTAssertTrue(tokenResult.issuedAtDate &&
  1976. [tokenResult.issuedAtDate isKindOfClass:[NSDate class]]);
  1977. XCTAssertTrue(tokenResult.authDate && [tokenResult.authDate isKindOfClass:[NSDate class]]);
  1978. XCTAssertTrue(tokenResult.expirationDate &&
  1979. [tokenResult.expirationDate isKindOfClass:[NSDate class]]);
  1980. XCTAssertTrue(tokenResult.claims && [tokenResult.claims isKindOfClass:[NSDictionary class]]);
  1981. [expectation fulfill];
  1982. }];
  1983. }];
  1984. [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
  1985. OCMVerifyAll(_mockBackend);
  1986. }
  1987. /** @fn signInWithEmailPasswordWithMockGetAccountInfoResponse:completion:
  1988. @brief Signs in with an email and password account with mocked backend end calls.
  1989. @param mockUserInfoResponse A mocked FIRGetAccountInfoResponseUser object.
  1990. @param completion The completion block that takes the newly signed-in user as the only
  1991. parameter.
  1992. */
  1993. - (void)signInWithEmailPasswordWithMockUserInfoResponse:(id)mockUserInfoResponse
  1994. completion:(void (^)(FIRUser *user))completion {
  1995. OCMExpect([_mockBackend verifyPassword:[OCMArg any] callback:[OCMArg any]])
  1996. .andCallBlock2(^(FIRVerifyPasswordRequest *_Nullable request,
  1997. FIRVerifyPasswordResponseCallback callback) {
  1998. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  1999. id mockVeriyPasswordResponse = OCMClassMock([FIRVerifyPasswordResponse class]);
  2000. OCMStub([mockVeriyPasswordResponse IDToken]).andReturn(kAccessToken);
  2001. OCMStub([mockVeriyPasswordResponse approximateExpirationDate])
  2002. .andReturn([NSDate dateWithTimeIntervalSinceNow:kAccessTokenTimeToLive]);
  2003. OCMStub([mockVeriyPasswordResponse refreshToken]).andReturn(kRefreshToken);
  2004. callback(mockVeriyPasswordResponse, nil);
  2005. });
  2006. });
  2007. [self expectGetAccountInfoWithMockUserInfoResponse:mockUserInfoResponse];
  2008. [[FIRAuth auth] signOut:NULL];
  2009. [[FIRAuth auth] signInWithEmail:kEmail password:kFakePassword completion:^(FIRUser *_Nullable user,
  2010. NSError *_Nullable error) {
  2011. XCTAssertNotNil(user);
  2012. XCTAssertNil(error);
  2013. completion(user);
  2014. }];
  2015. }
  2016. /** @fn expectGetAccountInfoWithMockUserInfoResponse:
  2017. @brief Expects a GetAccountInfo request on the mock backend and calls back with provided
  2018. fake account data.
  2019. @param mockUserInfoResponse A mock @c FIRGetAccountInfoResponseUser object containing user info.
  2020. */
  2021. - (void)expectGetAccountInfoWithMockUserInfoResponse:(id)mockUserInfoResponse {
  2022. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  2023. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  2024. FIRGetAccountInfoResponseCallback callback) {
  2025. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  2026. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  2027. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  2028. id mockGetAccountInfoResponse = OCMClassMock([FIRGetAccountInfoResponse class]);
  2029. OCMStub([mockGetAccountInfoResponse users]).andReturn(@[ mockUserInfoResponse ]);
  2030. callback(mockGetAccountInfoResponse, nil);
  2031. });
  2032. });
  2033. }
  2034. /** @fn dictionaryWithUserInfoArray:
  2035. @brief Converts an array of @c FIRUserInfo into a dictionary that indexed by provider IDs.
  2036. @param userInfoArray An array of @c FIRUserInfo objects.
  2037. @return A dictionary contains same values as @c userInfoArray does but keyed by their
  2038. @c providerID .
  2039. */
  2040. - (NSDictionary<NSString *, id<FIRUserInfo>> *)
  2041. dictionaryWithUserInfoArray:(NSArray<id<FIRUserInfo>> *)userInfoArray {
  2042. NSMutableDictionary<NSString *, id<FIRUserInfo>> *map =
  2043. [NSMutableDictionary dictionaryWithCapacity:userInfoArray.count];
  2044. for (id<FIRUserInfo> userInfo in userInfoArray) {
  2045. XCTAssertNil(map[userInfo.providerID]);
  2046. map[userInfo.providerID] = userInfo;
  2047. }
  2048. return map;
  2049. }
  2050. /** @fn stubSecureTokensWithMockResponse
  2051. @brief Creates stubs on the mock response object with access and refresh tokens
  2052. @param mockResponse The mock response object.
  2053. */
  2054. - (void)stubTokensWithMockResponse:(id)mockResponse {
  2055. OCMStub([mockResponse IDToken]).andReturn(kAccessToken);
  2056. OCMStub([mockResponse approximateExpirationDate])
  2057. .andReturn([NSDate dateWithTimeIntervalSinceNow:kAccessTokenTimeToLive]);
  2058. OCMStub([mockResponse refreshToken]).andReturn(kRefreshToken);
  2059. }
  2060. /** @fn assertUserGoogle
  2061. @brief Asserts the given FIRUser matching the fake data returned by
  2062. @c expectGetAccountInfo:federatedID:displayName: .
  2063. @param user The user object to be verified.
  2064. */
  2065. - (void)assertUserGoogle:(FIRUser *)user {
  2066. XCTAssertNotNil(user);
  2067. XCTAssertEqualObjects(user.uid, kLocalID);
  2068. XCTAssertEqualObjects(user.displayName, kGoogleDisplayName);
  2069. XCTAssertEqual(user.providerData.count, 1u);
  2070. id<FIRUserInfo> googleUserInfo = user.providerData[0];
  2071. XCTAssertEqualObjects(googleUserInfo.providerID, FIRGoogleAuthProviderID);
  2072. XCTAssertEqualObjects(googleUserInfo.uid, kGoogleID);
  2073. XCTAssertEqualObjects(googleUserInfo.displayName, kGoogleDisplayName);
  2074. XCTAssertEqualObjects(googleUserInfo.email, kGoogleEmail);
  2075. }
  2076. /** @fn assertUserFacebook
  2077. @brief Asserts the given FIRUser matching the fake data returned by
  2078. @c expectGetAccountInfo:federatedID:displayName: .
  2079. @param user The user object to be verified.
  2080. */
  2081. - (void)assertUserFacebook:(FIRUser *)user {
  2082. XCTAssertNotNil(user);
  2083. XCTAssertEqualObjects(user.uid, kLocalID);
  2084. XCTAssertEqualObjects(user.displayName, kFacebookDisplayName);
  2085. XCTAssertEqual(user.providerData.count, 1u);
  2086. id<FIRUserInfo> googleUserInfo = user.providerData[0];
  2087. XCTAssertEqualObjects(googleUserInfo.providerID, FIRFacebookAuthProviderID);
  2088. XCTAssertEqualObjects(googleUserInfo.uid, kFacebookID);
  2089. XCTAssertEqualObjects(googleUserInfo.displayName, kFacebookDisplayName);
  2090. XCTAssertEqualObjects(googleUserInfo.email, kGoogleEmail);
  2091. }
  2092. /** @fn expectGetAccountInfo:federatedID:displayName:
  2093. @brief Expects a GetAccountInfo request on the mock backend and calls back with fake account
  2094. data for a Google Sign-In user.
  2095. */
  2096. - (void)expectGetAccountInfo:(NSString *)providerId
  2097. federatedID:(NSString *)federatedID
  2098. displayName:(NSString *)displayName {
  2099. OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
  2100. .andCallBlock2(^(FIRGetAccountInfoRequest *_Nullable request,
  2101. FIRGetAccountInfoResponseCallback callback) {
  2102. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  2103. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  2104. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  2105. id mockGoogleUserInfo = OCMClassMock([FIRGetAccountInfoResponseProviderUserInfo class]);
  2106. OCMStub([mockGoogleUserInfo providerID]).andReturn(providerId);
  2107. OCMStub([mockGoogleUserInfo displayName]).andReturn(displayName);
  2108. OCMStub([mockGoogleUserInfo federatedID]).andReturn(federatedID);
  2109. OCMStub([mockGoogleUserInfo email]).andReturn(kGoogleEmail);
  2110. id mockGetAccountInfoResponseUser = OCMClassMock([FIRGetAccountInfoResponseUser class]);
  2111. OCMStub([mockGetAccountInfoResponseUser localID]).andReturn(kLocalID);
  2112. OCMStub([mockGetAccountInfoResponseUser displayName]).andReturn(displayName);
  2113. OCMStub([mockGetAccountInfoResponseUser providerUserInfo])
  2114. .andReturn((@[ mockGoogleUserInfo ]));
  2115. id mockGetAccountInfoResponse = OCMClassMock([FIRGetAccountInfoResponse class]);
  2116. OCMStub([mockGetAccountInfoResponse users]).andReturn(@[ mockGetAccountInfoResponseUser ]);
  2117. callback(mockGetAccountInfoResponse, nil);
  2118. });
  2119. });
  2120. }
  2121. /** @fn expectVerifyAssertionRequest:federatedID:displayName:profile:providerAccessToken:
  2122. @brief Expects a Verify Assertion request on the mock backend and calls back with fake account
  2123. data.
  2124. */
  2125. - (void)expectVerifyAssertionRequest:(NSString *)providerId
  2126. federatedID:(NSString *)federatedID
  2127. displayName:(NSString *)displayName
  2128. profile:(NSDictionary *)profile
  2129. providerIDToken:(nullable NSString *)providerIDToken
  2130. providerAccessToken:(NSString *)providerAccessToken {
  2131. OCMExpect([_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
  2132. .andCallBlock2(^(FIRVerifyAssertionRequest *_Nullable request,
  2133. FIRVerifyAssertionResponseCallback callback) {
  2134. XCTAssertEqualObjects(request.APIKey, kAPIKey);
  2135. XCTAssertEqualObjects(request.providerID, providerId);
  2136. XCTAssertEqualObjects(request.providerIDToken, providerIDToken);
  2137. XCTAssertEqualObjects(request.providerAccessToken, providerAccessToken);
  2138. XCTAssertTrue(request.returnSecureToken);
  2139. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  2140. id mockVeriyAssertionResponse = OCMClassMock([FIRVerifyAssertionResponse class]);
  2141. OCMStub([mockVeriyAssertionResponse federatedID]).andReturn(federatedID);
  2142. OCMStub([mockVeriyAssertionResponse providerID]).andReturn(providerId);
  2143. OCMStub([mockVeriyAssertionResponse localID]).andReturn(kLocalID);
  2144. OCMStub([mockVeriyAssertionResponse displayName]).andReturn(displayName);
  2145. OCMStub([mockVeriyAssertionResponse profile]).andReturn(profile);
  2146. OCMStub([mockVeriyAssertionResponse username]).andReturn(kUserName);
  2147. [self stubTokensWithMockResponse:mockVeriyAssertionResponse];
  2148. callback(mockVeriyAssertionResponse, nil);
  2149. });
  2150. });
  2151. [self expectGetAccountInfo:providerId federatedID:federatedID displayName:displayName];
  2152. }
  2153. #if TARGET_OS_IOS
  2154. /** @fn expectVerifyPhoneNumberRequestWithPhoneNumber:error:
  2155. @brief Expects a verify phone numner request on the mock backend and calls back with fake
  2156. account data or an error.
  2157. @param phoneNumber Optionally; The phone number to use in the mocked response.
  2158. @param isLinkOperation Boolean value that indicates whether or not this method is triggered by
  2159. a link operation.
  2160. @param error Optionally; The error to return in the mocked response.
  2161. */
  2162. - (void)expectVerifyPhoneNumberRequestWithPhoneNumber:(nullable NSString *)phoneNumber
  2163. isLinkOperation:(BOOL)isLinkOperation
  2164. error:(nullable NSError*)error {
  2165. OCMExpect([_mockBackend verifyPhoneNumber:[OCMArg any] callback:[OCMArg any]])
  2166. .andCallBlock2(^(FIRVerifyPhoneNumberRequest *_Nullable request,
  2167. FIRVerifyPhoneNumberResponseCallback callback) {
  2168. XCTAssertEqualObjects(request.verificationID, kVerificationID);
  2169. XCTAssertEqualObjects(request.verificationCode, kVerificationCode);
  2170. if (isLinkOperation) {
  2171. XCTAssertEqual(request.operation, FIRAuthOperationTypeLink);
  2172. } else {
  2173. XCTAssertEqual(request.operation, FIRAuthOperationTypeUpdate);
  2174. }
  2175. XCTAssertEqualObjects(request.accessToken, kAccessToken);
  2176. dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
  2177. if (error) {
  2178. callback(nil, error);
  2179. return;
  2180. }
  2181. id mockVerifyPhoneNumberResponse = OCMClassMock([FIRVerifyPhoneNumberResponse class]);
  2182. OCMStub([mockVerifyPhoneNumberResponse phoneNumber]).andReturn(phoneNumber);
  2183. callback(mockVerifyPhoneNumberResponse, nil);
  2184. });
  2185. });
  2186. }
  2187. #endif
  2188. @end
  2189. NS_ASSUME_NONNULL_END