FIRGetOOBConfirmationCodeResponseTests.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <XCTest/XCTest.h>
  17. #import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRActionCodeSettings.h"
  18. #import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthErrors.h"
  19. #import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h"
  20. #import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeRequest.h"
  21. #import "FirebaseAuth/Sources/Backend/RPC/FIRGetOOBConfirmationCodeResponse.h"
  22. #import "FirebaseAuth/Tests/Unit/FIRFakeBackendRPCIssuer.h"
  23. /** @var kTestEmail
  24. @brief Testing user email adadress.
  25. */
  26. static NSString *const kTestEmail = @"test@gmail.com";
  27. /** @var kTestAccessToken
  28. @brief Testing access token.
  29. */
  30. static NSString *const kTestAccessToken = @"ACCESS_TOKEN";
  31. /** @var kTestAPIKey
  32. @brief Fake API key used for testing.
  33. */
  34. static NSString *const kTestAPIKey = @"APIKey";
  35. /** @var kTestFirebaseAppID
  36. @brief Fake Firebase app ID used for testing.
  37. */
  38. static NSString *const kTestFirebaseAppID = @"appID";
  39. /** @var kOOBCodeKey
  40. @brief The name of the field in the response JSON for the OOB code.
  41. */
  42. static NSString *const kOOBCodeKey = @"oobCode";
  43. /** @var kTestOOBCode
  44. @brief Fake OOB Code used for testing.
  45. */
  46. static NSString *const kTestOOBCode = @"OOBCode";
  47. /** @var kEmailNotFoundMessage
  48. @brief The value of the "message" field returned for an "email not found" error.
  49. */
  50. static NSString *const kEmailNotFoundMessage = @"EMAIL_NOT_FOUND: fake custom message";
  51. /** @var kMissingEmailErrorMessage
  52. @brief The value of the "message" field returned for a "missing email" error.
  53. */
  54. static NSString *const kMissingEmailErrorMessage = @"MISSING_EMAIL";
  55. /** @var kInvalidEmailErrorMessage
  56. @brief The error returned by the server if the email is invalid.
  57. */
  58. static NSString *const kInvalidEmailErrorMessage = @"INVALID_EMAIL:";
  59. /** @var kInvalidMessagePayloadErrorMessage
  60. @brief This is the prefix for the error message the server responds with if an invalid message
  61. payload was sent.
  62. */
  63. static NSString *const kInvalidMessagePayloadErrorMessage = @"INVALID_MESSAGE_PAYLOAD";
  64. /** @var kInvalidSenderErrorMessage
  65. @brief This is the prefix for the error message the server responds with if invalid sender is
  66. used to send the email for updating user's email address.
  67. */
  68. static NSString *const kInvalidSenderErrorMessage = @"INVALID_SENDER";
  69. /** @var kMissingIosBundleIDErrorMessage
  70. @brief This is the error message the server will respond with if iOS bundle ID is missing but
  71. the iOS App store ID is provided.
  72. */
  73. static NSString *const kMissingIosBundleIDErrorMessage = @"MISSING_IOS_BUNDLE_ID";
  74. /** @var kMissingAndroidPackageNameErrorMessage
  75. @brief This is the error message the server will respond with if Android Package Name is missing
  76. but the flag indicating the app should be installed is set to true.
  77. */
  78. static NSString *const kMissingAndroidPackageNameErrorMessage = @"MISSING_ANDROID_PACKAGE_NAME";
  79. /** @var kUnauthorizedDomainErrorMessage
  80. @brief This is the error message the server will respond with if the domain of the continue URL
  81. specified is not allowlisted in the Firebase console.
  82. */
  83. static NSString *const kUnauthorizedDomainErrorMessage = @"UNAUTHORIZED_DOMAIN";
  84. /** @var kInvalidRecipientEmailErrorMessage
  85. @brief This is the prefix for the error message the server responds with if the recipient email
  86. is invalid.
  87. */
  88. static NSString *const kInvalidRecipientEmailErrorMessage = @"INVALID_RECIPIENT_EMAIL";
  89. /** @var kInvalidContinueURIErrorMessage
  90. @brief This is the error returned by the backend if the continue URL provided in the request
  91. is invalid.
  92. */
  93. static NSString *const kInvalidContinueURIErrorMessage = @"INVALID_CONTINUE_URI";
  94. /** @var kMissingContinueURIErrorMessage
  95. @brief This is the error message the server will respond with if there was no continue URI
  96. present in a request that required one.
  97. */
  98. static NSString *const kMissingContinueURIErrorMessage = @"MISSING_CONTINUE_URI";
  99. /** @var kIosBundleID
  100. @brief Fake iOS bundle ID for testing.
  101. */
  102. static NSString *const kIosBundleID = @"testBundleID";
  103. /** @class FIRGetOOBConfirmationCodeResponseTests
  104. @brief Tests for @c FIRGetOOBConfirmationCodeResponse.
  105. */
  106. @interface FIRGetOOBConfirmationCodeResponseTests : XCTestCase
  107. @end
  108. @implementation FIRGetOOBConfirmationCodeResponseTests {
  109. /** @var _RPCIssuer
  110. @brief This backend RPC issuer is used to fake network responses for each test in the suite.
  111. In the @c setUp method we initialize this and set @c FIRAuthBackend's RPC issuer to it.
  112. */
  113. FIRFakeBackendRPCIssuer *_RPCIssuer;
  114. /** @var _requestConfiguration
  115. @brief This is the request configuration used for testing.
  116. */
  117. FIRAuthRequestConfiguration *_requestConfiguration;
  118. }
  119. - (void)setUp {
  120. [super setUp];
  121. FIRFakeBackendRPCIssuer *RPCIssuer = [[FIRFakeBackendRPCIssuer alloc] init];
  122. [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:RPCIssuer];
  123. _RPCIssuer = RPCIssuer;
  124. _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:kTestAPIKey
  125. appID:kTestFirebaseAppID];
  126. }
  127. - (void)tearDown {
  128. _requestConfiguration = nil;
  129. _RPCIssuer = nil;
  130. [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:nil];
  131. [super tearDown];
  132. }
  133. /** @fn testSuccessfulPasswordResetResponse
  134. @brief This test simulates a complete password reset response (with OOB Code) and makes sure
  135. it succeeds, and we get the OOB Code decoded correctly.
  136. */
  137. - (void)testSuccessfulPasswordResetResponse {
  138. FIRGetOOBConfirmationCodeRequest *request =
  139. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  140. actionCodeSettings:[self fakeActionCodeSettings]
  141. requestConfiguration:_requestConfiguration];
  142. __block BOOL callbackInvoked;
  143. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  144. __block NSError *RPCError;
  145. [FIRAuthBackend getOOBConfirmationCode:request
  146. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  147. NSError *_Nullable error) {
  148. callbackInvoked = YES;
  149. RPCResponse = response;
  150. RPCError = error;
  151. }];
  152. [_RPCIssuer respondWithJSON:@{kOOBCodeKey : kTestOOBCode}];
  153. XCTAssert(callbackInvoked);
  154. XCTAssertNil(RPCError);
  155. XCTAssertNotNil(RPCResponse);
  156. XCTAssertEqualObjects(RPCResponse.OOBCode, kTestOOBCode);
  157. }
  158. /** @fn testSuccessfulPasswordResetResponseWithoutOOBCode
  159. @brief This test simulates a password reset request where we don't receive the optional OOBCode
  160. response value. It should still succeed.
  161. */
  162. - (void)testSuccessfulPasswordResetResponseWithoutOOBCode {
  163. FIRGetOOBConfirmationCodeRequest *request =
  164. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  165. actionCodeSettings:[self fakeActionCodeSettings]
  166. requestConfiguration:_requestConfiguration];
  167. __block BOOL callbackInvoked;
  168. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  169. __block NSError *RPCError;
  170. [FIRAuthBackend getOOBConfirmationCode:request
  171. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  172. NSError *_Nullable error) {
  173. callbackInvoked = YES;
  174. RPCResponse = response;
  175. RPCError = error;
  176. }];
  177. [_RPCIssuer respondWithJSON:@{}];
  178. XCTAssert(callbackInvoked);
  179. XCTAssertNil(RPCError);
  180. XCTAssertNotNil(RPCResponse);
  181. XCTAssertNil(RPCResponse.OOBCode);
  182. }
  183. /** @fn testEmailNotFoundError
  184. @brief This test checks for email not found responses, and makes sure they are decoded to the
  185. correct error response.
  186. */
  187. - (void)testEmailNotFoundError {
  188. FIRGetOOBConfirmationCodeRequest *request =
  189. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  190. actionCodeSettings:[self fakeActionCodeSettings]
  191. requestConfiguration:_requestConfiguration];
  192. __block BOOL callbackInvoked;
  193. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  194. __block NSError *RPCError;
  195. [FIRAuthBackend getOOBConfirmationCode:request
  196. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  197. NSError *_Nullable error) {
  198. callbackInvoked = YES;
  199. RPCResponse = response;
  200. RPCError = error;
  201. }];
  202. [_RPCIssuer respondWithServerErrorMessage:kEmailNotFoundMessage];
  203. XCTAssert(callbackInvoked);
  204. XCTAssertNotNil(RPCError);
  205. XCTAssertEqualObjects(RPCError.domain, FIRAuthErrorDomain);
  206. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeUserNotFound);
  207. XCTAssertNil(RPCResponse);
  208. }
  209. /** @fn testMissingEmailError
  210. @brief This test checks for missing email responses, and makes sure they are decoded to the
  211. correct error response.
  212. */
  213. - (void)testMissingEmailError {
  214. FIRGetOOBConfirmationCodeRequest *request = [FIRGetOOBConfirmationCodeRequest
  215. verifyEmailRequestWithAccessToken:kTestAccessToken
  216. actionCodeSettings:[self fakeActionCodeSettings]
  217. requestConfiguration:_requestConfiguration];
  218. __block BOOL callbackInvoked;
  219. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  220. __block NSError *RPCError;
  221. [FIRAuthBackend getOOBConfirmationCode:request
  222. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  223. NSError *_Nullable error) {
  224. callbackInvoked = YES;
  225. RPCResponse = response;
  226. RPCError = error;
  227. }];
  228. [_RPCIssuer respondWithServerErrorMessage:kMissingEmailErrorMessage];
  229. XCTAssert(callbackInvoked);
  230. XCTAssertNotNil(RPCError);
  231. XCTAssertEqualObjects(RPCError.domain, FIRAuthErrorDomain);
  232. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeMissingEmail);
  233. XCTAssertNil(RPCResponse);
  234. }
  235. /** @fn testInvalidEmailError
  236. @brief This test checks for the INVALID_EMAIL error message from the backend.
  237. */
  238. - (void)testInvalidEmailError {
  239. FIRGetOOBConfirmationCodeRequest *request =
  240. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  241. actionCodeSettings:[self fakeActionCodeSettings]
  242. requestConfiguration:_requestConfiguration];
  243. __block BOOL callbackInvoked;
  244. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  245. __block NSError *RPCError;
  246. [FIRAuthBackend getOOBConfirmationCode:request
  247. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  248. NSError *_Nullable error) {
  249. callbackInvoked = YES;
  250. RPCResponse = response;
  251. RPCError = error;
  252. }];
  253. [_RPCIssuer respondWithServerErrorMessage:kInvalidEmailErrorMessage];
  254. XCTAssert(callbackInvoked);
  255. XCTAssertNotNil(RPCError);
  256. XCTAssertEqualObjects(RPCError.domain, FIRAuthErrorDomain);
  257. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidEmail);
  258. XCTAssertNil(RPCResponse);
  259. }
  260. /** @fn testInvalidMessagePayloadError
  261. @brief Tests for @c FIRAuthErrorCodeInvalidMessagePayload.
  262. */
  263. - (void)testInvalidMessagePayloadError {
  264. FIRGetOOBConfirmationCodeRequest *request =
  265. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  266. actionCodeSettings:[self fakeActionCodeSettings]
  267. requestConfiguration:_requestConfiguration];
  268. __block BOOL callbackInvoked;
  269. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  270. __block NSError *RPCError;
  271. [FIRAuthBackend getOOBConfirmationCode:request
  272. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  273. NSError *_Nullable error) {
  274. callbackInvoked = YES;
  275. RPCResponse = response;
  276. RPCError = error;
  277. }];
  278. [_RPCIssuer respondWithServerErrorMessage:kInvalidMessagePayloadErrorMessage];
  279. XCTAssert(callbackInvoked);
  280. XCTAssertNil(RPCResponse);
  281. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidMessagePayload);
  282. }
  283. /** @fn testInvalidSenderError
  284. @brief Tests for @c FIRAuthErrorCodeInvalidSender.
  285. */
  286. - (void)testInvalidSenderError {
  287. FIRGetOOBConfirmationCodeRequest *request =
  288. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  289. actionCodeSettings:[self fakeActionCodeSettings]
  290. requestConfiguration:_requestConfiguration];
  291. __block BOOL callbackInvoked;
  292. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  293. __block NSError *RPCError;
  294. [FIRAuthBackend getOOBConfirmationCode:request
  295. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  296. NSError *_Nullable error) {
  297. callbackInvoked = YES;
  298. RPCResponse = response;
  299. RPCError = error;
  300. }];
  301. [_RPCIssuer respondWithServerErrorMessage:kInvalidSenderErrorMessage];
  302. XCTAssert(callbackInvoked);
  303. XCTAssertNil(RPCResponse);
  304. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidSender);
  305. }
  306. /** @fn testMissingIosBundleIDError
  307. @brief Tests for @c FIRAuthErrorCodeMissingIosBundleID.
  308. */
  309. - (void)testMissingIosBundleIDError {
  310. FIRGetOOBConfirmationCodeRequest *request =
  311. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  312. actionCodeSettings:[self fakeActionCodeSettings]
  313. requestConfiguration:_requestConfiguration];
  314. __block BOOL callbackInvoked;
  315. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  316. __block NSError *RPCError;
  317. [FIRAuthBackend getOOBConfirmationCode:request
  318. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  319. NSError *_Nullable error) {
  320. callbackInvoked = YES;
  321. RPCResponse = response;
  322. RPCError = error;
  323. }];
  324. [_RPCIssuer respondWithServerErrorMessage:kMissingIosBundleIDErrorMessage];
  325. XCTAssert(callbackInvoked);
  326. XCTAssertNil(RPCResponse);
  327. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeMissingIosBundleID);
  328. }
  329. /** @fn testMissingAndroidPackageNameError
  330. @brief Tests for @c FIRAuthErrorCodeMissingAndroidPackageName.
  331. */
  332. - (void)testMissingAndroidPackageNameError {
  333. FIRGetOOBConfirmationCodeRequest *request =
  334. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  335. actionCodeSettings:[self fakeActionCodeSettings]
  336. requestConfiguration:_requestConfiguration];
  337. __block BOOL callbackInvoked;
  338. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  339. __block NSError *RPCError;
  340. [FIRAuthBackend getOOBConfirmationCode:request
  341. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  342. NSError *_Nullable error) {
  343. callbackInvoked = YES;
  344. RPCResponse = response;
  345. RPCError = error;
  346. }];
  347. [_RPCIssuer respondWithServerErrorMessage:kMissingAndroidPackageNameErrorMessage];
  348. XCTAssert(callbackInvoked);
  349. XCTAssertNil(RPCResponse);
  350. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeMissingAndroidPackageName);
  351. }
  352. /** @fn testUnauthorizedDomainError
  353. @brief Tests for @c FIRAuthErrorCodeUnauthorizedDomain.
  354. */
  355. - (void)testUnauthorizedDomainError {
  356. FIRGetOOBConfirmationCodeRequest *request =
  357. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  358. actionCodeSettings:[self fakeActionCodeSettings]
  359. requestConfiguration:_requestConfiguration];
  360. __block BOOL callbackInvoked;
  361. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  362. __block NSError *RPCError;
  363. [FIRAuthBackend getOOBConfirmationCode:request
  364. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  365. NSError *_Nullable error) {
  366. callbackInvoked = YES;
  367. RPCResponse = response;
  368. RPCError = error;
  369. }];
  370. [_RPCIssuer respondWithServerErrorMessage:kUnauthorizedDomainErrorMessage];
  371. XCTAssert(callbackInvoked);
  372. XCTAssertNil(RPCResponse);
  373. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeUnauthorizedDomain);
  374. }
  375. /** @fn testInvalidContinueURIError
  376. @brief Tests for @c FIRAuthErrorCodeInvalidContinueAuthURI.
  377. */
  378. - (void)testInvalidContinueURIError {
  379. FIRGetOOBConfirmationCodeRequest *request =
  380. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  381. actionCodeSettings:[self fakeActionCodeSettings]
  382. requestConfiguration:_requestConfiguration];
  383. __block BOOL callbackInvoked;
  384. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  385. __block NSError *RPCError;
  386. [FIRAuthBackend getOOBConfirmationCode:request
  387. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  388. NSError *_Nullable error) {
  389. callbackInvoked = YES;
  390. RPCResponse = response;
  391. RPCError = error;
  392. }];
  393. [_RPCIssuer respondWithServerErrorMessage:kInvalidContinueURIErrorMessage];
  394. XCTAssert(callbackInvoked);
  395. XCTAssertNil(RPCResponse);
  396. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidContinueURI);
  397. }
  398. /** @fn testMissingContinueURIError
  399. @brief Tests for @c FIRAuthErrorCodeMissingContinueURI.
  400. */
  401. - (void)testMissingContinueURIError {
  402. FIRGetOOBConfirmationCodeRequest *request =
  403. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  404. actionCodeSettings:[self fakeActionCodeSettings]
  405. requestConfiguration:_requestConfiguration];
  406. __block BOOL callbackInvoked;
  407. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  408. __block NSError *RPCError;
  409. [FIRAuthBackend getOOBConfirmationCode:request
  410. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  411. NSError *_Nullable error) {
  412. callbackInvoked = YES;
  413. RPCResponse = response;
  414. RPCError = error;
  415. }];
  416. [_RPCIssuer respondWithServerErrorMessage:kMissingContinueURIErrorMessage];
  417. XCTAssert(callbackInvoked);
  418. XCTAssertNil(RPCResponse);
  419. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeMissingContinueURI);
  420. }
  421. /** @fn testInvalidRecipientEmailError
  422. @brief Tests for @c FIRAuthErrorCodeInvalidRecipientEmail.
  423. */
  424. - (void)testInvalidRecipientEmailError {
  425. FIRGetOOBConfirmationCodeRequest *request =
  426. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  427. actionCodeSettings:[self fakeActionCodeSettings]
  428. requestConfiguration:_requestConfiguration];
  429. __block BOOL callbackInvoked;
  430. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  431. __block NSError *RPCError;
  432. [FIRAuthBackend getOOBConfirmationCode:request
  433. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  434. NSError *_Nullable error) {
  435. callbackInvoked = YES;
  436. RPCResponse = response;
  437. RPCError = error;
  438. }];
  439. [_RPCIssuer respondWithServerErrorMessage:kInvalidRecipientEmailErrorMessage];
  440. XCTAssert(callbackInvoked);
  441. XCTAssertNil(RPCResponse);
  442. XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidRecipientEmail);
  443. }
  444. /** @fn testSuccessfulEmailVerificationResponse
  445. @brief This test is really not much different than the original test for password reset. But
  446. it's here for completeness sake.
  447. */
  448. - (void)testSuccessfulEmailVerificationResponse {
  449. FIRGetOOBConfirmationCodeRequest *request =
  450. [FIRGetOOBConfirmationCodeRequest passwordResetRequestWithEmail:kTestEmail
  451. actionCodeSettings:[self fakeActionCodeSettings]
  452. requestConfiguration:_requestConfiguration];
  453. __block BOOL callbackInvoked;
  454. __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
  455. __block NSError *RPCError;
  456. [FIRAuthBackend getOOBConfirmationCode:request
  457. callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
  458. NSError *_Nullable error) {
  459. callbackInvoked = YES;
  460. RPCResponse = response;
  461. RPCError = error;
  462. }];
  463. [_RPCIssuer respondWithJSON:@{kOOBCodeKey : kTestOOBCode}];
  464. XCTAssert(callbackInvoked);
  465. XCTAssertNil(RPCError);
  466. XCTAssertNotNil(RPCResponse);
  467. XCTAssertEqualObjects(RPCResponse.OOBCode, kTestOOBCode);
  468. }
  469. #pragma mark - Helpers
  470. /** @fn fakeActionCodeSettings
  471. @brief Constructs and returns a fake instance of @c FIRActionCodeSettings for testing.
  472. @return An instance of @c FIRActionCodeSettings for testing.
  473. */
  474. - (FIRActionCodeSettings *)fakeActionCodeSettings {
  475. FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
  476. [actionCodeSettings setIOSBundleID:kIosBundleID];
  477. return actionCodeSettings;
  478. }
  479. @end