FirebaseAuthApiTests.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  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 <FirebaseCore/FIRApp.h>
  19. #import "FirebaseAuth.h"
  20. #import "AuthCredentials.h"
  21. #ifdef NO_NETWORK
  22. #import "ITUIOSTestUtil.h"
  23. #endif
  24. #import <GTMSessionFetcher/GTMSessionFetcher.h>
  25. #import <GTMSessionFetcher/GTMSessionFetcherService.h>
  26. /** The user name string for Custom Auth testing account. */
  27. static NSString *const kCustomAuthTestingAccountUserID = KCUSTOM_AUTH_USER_ID;
  28. /** The url for obtaining a valid custom token string used to test Custom Auth. */
  29. static NSString *const kCustomTokenUrl = KCUSTOM_AUTH_TOKEN_URL;
  30. /** The url for obtaining an expired but valid custom token string used to test Custom Auth failure.
  31. */
  32. static NSString *const kExpiredCustomTokenUrl = KCUSTOM_AUTH_TOKEN_EXPIRED_URL;
  33. /** Facebook app access token that will be used for Facebook Graph API, which is different from
  34. * account access token.
  35. */
  36. static NSString *const kFacebookAppAccessToken = KFACEBOOK_APP_ACCESS_TOKEN;
  37. /** Facebook app ID that will be used for Facebook Graph API. */
  38. static NSString *const kFacebookAppID = KFACEBOOK_APP_ID;
  39. static NSString *const kFacebookGraphApiAuthority = @"graph.facebook.com";
  40. static NSString *const kFacebookTestAccountName = KFACEBOOK_USER_NAME;
  41. static NSString *const kGoogleTestAccountName = KGOOGLE_USER_NAME;
  42. /** The invalid custom token string for testing Custom Auth. */
  43. static NSString *const kInvalidCustomToken = @"invalid token.";
  44. /** The testing email address for testCreateAccountWithEmailAndPassword. */
  45. static NSString *const kTestingEmailToCreateUser = @"abc@xyz.com";
  46. /** The testing email address for testSignInExistingUserWithEmailAndPassword. */
  47. static NSString *const kExistingTestingEmailToSignIn = @"456@abc.com";
  48. /** The testing email address for testUpdatingUsersEmail. */
  49. static NSString *const kNewTestingEmail = @"updatedEmail@abc.com";
  50. /** The testing password for testSignInExistingUserWithModifiedEmailAndPassword. */
  51. static NSString *const kNewTestingPasswordToSignIn = @"password_new";
  52. /** Error message for invalid custom token sign in. */
  53. NSString *kInvalidTokenErrorMessage =
  54. @"The custom token format is incorrect. Please check the documentation.";
  55. NSString *kGoogleCliendId = KGOOGLE_CLIENT_ID;
  56. /** Refresh token of Google test account to exchange for access token. Refresh token never expires
  57. * unless user revokes it. If this refresh token expires, tests in record mode will fail and this
  58. * token needs to be updated.
  59. */
  60. NSString *kGoogleTestAccountRefreshToken = KGOOGLE_TEST_ACCOUNT_REFRESH_TOKEN;
  61. static NSTimeInterval const kExpectationsTimeout = 10;
  62. #ifdef NO_NETWORK
  63. #define SKIP_IF_ON_MOBILE_HARNESS \
  64. if ([ITUIOSTestUtil isOnMobileHarness]) { \
  65. NSLog(@"Skipping '%@' on mobile harness", NSStringFromSelector(_cmd)); \
  66. return; \
  67. }
  68. #else
  69. #define SKIP_IF_ON_MOBILE_HARNESS
  70. #endif
  71. @interface ApiTests : XCTestCase
  72. @end
  73. @implementation ApiTests
  74. /** To reset the app so that each test sees the app in a clean state. */
  75. - (void)setUp {
  76. [super setUp];
  77. [self signOut];
  78. }
  79. #pragma mark - Tests
  80. /**
  81. * This test runs in replay mode by default. To run in a different mode follow the instructions
  82. * below.
  83. *
  84. * Blaze: --test_arg=\'--networkReplayMode=(replay|record|disabled|observe)\'
  85. *
  86. * Xcode:
  87. * Update the following flag in the xcscheme.
  88. * --networkReplayMode=(replay|record|disabled|observe)
  89. */
  90. - (void)testCreateAccountWithEmailAndPassword {
  91. SKIP_IF_ON_MOBILE_HARNESS
  92. FIRAuth *auth = [FIRAuth auth];
  93. if (!auth) {
  94. XCTFail(@"Could not obtain auth object.");
  95. }
  96. XCTestExpectation *expectation =
  97. [self expectationWithDescription:@"Created account with email and password."];
  98. [auth createUserWithEmail:kTestingEmailToCreateUser
  99. password:@"password"
  100. completion:^(FIRAuthDataResult *result, NSError *error) {
  101. if (error) {
  102. NSLog(@"createUserWithEmail has error: %@", error);
  103. }
  104. [expectation fulfill];
  105. }];
  106. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  107. handler:^(NSError *error) {
  108. if (error != nil) {
  109. XCTFail(@"Failed to wait for expectations "
  110. @"in creating account. Error: %@",
  111. error.localizedDescription);
  112. }
  113. }];
  114. XCTAssertEqualObjects(auth.currentUser.email, kTestingEmailToCreateUser);
  115. // Clean up the created Firebase user for future runs.
  116. [self deleteCurrentFirebaseUser];
  117. }
  118. - (void)testUpdatingUsersEmail {
  119. SKIP_IF_ON_MOBILE_HARNESS
  120. FIRAuth *auth = [FIRAuth auth];
  121. if (!auth) {
  122. XCTFail(@"Could not obtain auth object.");
  123. }
  124. __block NSError *apiError;
  125. XCTestExpectation *expectation =
  126. [self expectationWithDescription:@"Created account with email and password."];
  127. [auth createUserWithEmail:kTestingEmailToCreateUser
  128. password:@"password"
  129. completion:^(FIRAuthDataResult *user, NSError *error) {
  130. apiError = error;
  131. [expectation fulfill];
  132. }];
  133. [self waitForExpectationsWithTimeout:kExpectationsTimeout handler:nil];
  134. expectation = [self expectationWithDescription:@"Created account with email and password."];
  135. XCTAssertEqualObjects(auth.currentUser.email, kTestingEmailToCreateUser);
  136. XCTAssertNil(apiError);
  137. [auth.currentUser updateEmail:kNewTestingEmail
  138. completion:^(NSError *_Nullable error) {
  139. apiError = error;
  140. [expectation fulfill];
  141. }];
  142. [self waitForExpectationsWithTimeout:kExpectationsTimeout handler:nil];
  143. XCTAssertNil(apiError);
  144. XCTAssertEqualObjects(auth.currentUser.email, kNewTestingEmail);
  145. // Clean up the created Firebase user for future runs.
  146. [self deleteCurrentFirebaseUser];
  147. }
  148. - (void)testLinkAnonymousAccountToFacebookAccount {
  149. FIRAuth *auth = [FIRAuth auth];
  150. if (!auth) {
  151. XCTFail(@"Could not obtain auth object.");
  152. }
  153. [self signInAnonymously];
  154. NSDictionary *userInfoDict = [self createFacebookTestingAccount];
  155. NSString *facebookAccessToken = userInfoDict[@"access_token"];
  156. NSLog(@"Facebook testing account access token is: %@", facebookAccessToken);
  157. NSString *facebookAccountId = userInfoDict[@"id"];
  158. NSLog(@"Facebook testing account id is: %@", facebookAccountId);
  159. FIRAuthCredential *credential =
  160. [FIRFacebookAuthProvider credentialWithAccessToken:facebookAccessToken];
  161. XCTestExpectation *expectation = [self expectationWithDescription:@"Facebook linking finished."];
  162. [auth.currentUser linkWithCredential:credential
  163. completion:^(FIRUser *user, NSError *error) {
  164. if (error) {
  165. NSLog(@"Link to Facebok error: %@", error);
  166. }
  167. [expectation fulfill];
  168. }];
  169. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  170. handler:^(NSError *error) {
  171. if (error != nil) {
  172. XCTFail(@"Failed to wait for expectations "
  173. @"in linking to Facebook. Error: %@",
  174. error.localizedDescription);
  175. }
  176. }];
  177. NSArray<id<FIRUserInfo>> *providerData = auth.currentUser.providerData;
  178. XCTAssertEqual([providerData count], 1);
  179. XCTAssertEqualObjects([providerData[0] providerID], @"facebook.com");
  180. // Clean up the created Firebase/Facebook user for future runs.
  181. [self deleteCurrentFirebaseUser];
  182. [self deleteFacebookTestingAccountbyId:facebookAccountId];
  183. }
  184. - (void)testSignInAnonymously {
  185. [self signInAnonymously];
  186. XCTAssertTrue([FIRAuth auth].currentUser.anonymous);
  187. [self deleteCurrentFirebaseUser];
  188. }
  189. - (void)testSignInExistingUserWithEmailAndPassword {
  190. FIRAuth *auth = [FIRAuth auth];
  191. if (!auth) {
  192. XCTFail(@"Could not obtain auth object.");
  193. }
  194. XCTestExpectation *expectation =
  195. [self expectationWithDescription:@"Signed in existing account with email and password."];
  196. [auth signInWithEmail:kExistingTestingEmailToSignIn
  197. password:@"password"
  198. completion:^(FIRAuthDataResult *user, NSError *error) {
  199. if (error) {
  200. NSLog(@"Signing in existing account has error: %@", error);
  201. }
  202. [expectation fulfill];
  203. }];
  204. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  205. handler:^(NSError *error) {
  206. if (error != nil) {
  207. XCTFail(@"Failed to wait for expectations "
  208. @"in signing in existing account. Error: %@",
  209. error.localizedDescription);
  210. }
  211. }];
  212. XCTAssertEqualObjects(auth.currentUser.email, kExistingTestingEmailToSignIn);
  213. }
  214. - (void)testSignInWithValidCustomAuthToken {
  215. FIRAuth *auth = [FIRAuth auth];
  216. if (!auth) {
  217. XCTFail(@"Could not obtain auth object.");
  218. }
  219. NSError *error;
  220. NSString *customToken = [NSString stringWithContentsOfURL:[NSURL URLWithString:kCustomTokenUrl]
  221. encoding:NSUTF8StringEncoding
  222. error:&error];
  223. if (!customToken) {
  224. XCTFail(@"There was an error retrieving the custom token: %@", error);
  225. }
  226. NSLog(@"The valid token is: %@", customToken);
  227. XCTestExpectation *expectation =
  228. [self expectationWithDescription:@"CustomAuthToken sign-in finished."];
  229. [auth signInWithCustomToken:customToken
  230. completion:^(FIRAuthDataResult *_Nullable result, NSError *_Nullable error) {
  231. if (error) {
  232. NSLog(@"Valid token sign in error: %@", error);
  233. }
  234. [expectation fulfill];
  235. }];
  236. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  237. handler:^(NSError *error) {
  238. if (error != nil) {
  239. XCTFail(@"Failed to wait for expectations "
  240. @"in CustomAuthToken sign in. Error: %@",
  241. error.localizedDescription);
  242. }
  243. }];
  244. XCTAssertEqualObjects(auth.currentUser.uid, kCustomAuthTestingAccountUserID);
  245. }
  246. - (void)testSignInWithValidCustomAuthExpiredToken {
  247. FIRAuth *auth = [FIRAuth auth];
  248. if (!auth) {
  249. XCTFail(@"Could not obtain auth object.");
  250. }
  251. NSError *error;
  252. NSString *customToken =
  253. [NSString stringWithContentsOfURL:[NSURL URLWithString:kExpiredCustomTokenUrl]
  254. encoding:NSUTF8StringEncoding
  255. error:&error];
  256. if (!customToken) {
  257. XCTFail(@"There was an error retrieving the custom token: %@", error);
  258. }
  259. XCTestExpectation *expectation =
  260. [self expectationWithDescription:@"CustomAuthToken sign-in finished."];
  261. __block NSError *apiError;
  262. [auth signInWithCustomToken:customToken
  263. completion:^(FIRAuthDataResult *_Nullable result, NSError *_Nullable error) {
  264. if (error) {
  265. apiError = error;
  266. }
  267. [expectation fulfill];
  268. }];
  269. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  270. handler:^(NSError *error) {
  271. if (error != nil) {
  272. XCTFail(@"Failed to wait for expectations "
  273. @"in CustomAuthToken sign in. Error: %@",
  274. error.localizedDescription);
  275. }
  276. }];
  277. XCTAssertNil(auth.currentUser);
  278. XCTAssertEqual(apiError.code, FIRAuthErrorCodeInvalidCustomToken);
  279. }
  280. - (void)testInMemoryUserAfterSignOut {
  281. FIRAuth *auth = [FIRAuth auth];
  282. if (!auth) {
  283. XCTFail(@"Could not obtain auth object.");
  284. }
  285. NSError *error;
  286. NSString *customToken = [NSString stringWithContentsOfURL:[NSURL URLWithString:kCustomTokenUrl]
  287. encoding:NSUTF8StringEncoding
  288. error:&error];
  289. if (!customToken) {
  290. XCTFail(@"There was an error retrieving the custom token: %@", error);
  291. }
  292. XCTestExpectation *expectation =
  293. [self expectationWithDescription:@"CustomAuthToken sign-in finished."];
  294. __block NSError *rpcError;
  295. [auth signInWithCustomToken:customToken
  296. completion:^(FIRAuthDataResult *_Nullable result, NSError *_Nullable error) {
  297. if (error) {
  298. rpcError = error;
  299. }
  300. [expectation fulfill];
  301. }];
  302. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  303. handler:^(NSError *error) {
  304. if (error != nil) {
  305. XCTFail(@"Failed to wait for expectations "
  306. @"in CustomAuthToken sign in. Error: %@",
  307. error.localizedDescription);
  308. }
  309. }];
  310. XCTAssertEqualObjects(auth.currentUser.uid, kCustomAuthTestingAccountUserID);
  311. XCTAssertNil(rpcError);
  312. FIRUser *inMemoryUser = auth.currentUser;
  313. XCTestExpectation *expectation1 = [self expectationWithDescription:@"Profile data change."];
  314. [auth signOut:NULL];
  315. rpcError = nil;
  316. NSString *newEmailAddress = [self fakeRandomEmail];
  317. XCTAssertNotEqualObjects(newEmailAddress, inMemoryUser.email);
  318. [inMemoryUser updateEmail:newEmailAddress completion:^(NSError *_Nullable error) {
  319. rpcError = error;
  320. [expectation1 fulfill];
  321. }];
  322. [self waitForExpectationsWithTimeout:kExpectationsTimeout handler:nil];
  323. XCTAssertEqualObjects(inMemoryUser.email, newEmailAddress);
  324. XCTAssertNil(rpcError);
  325. XCTAssertNil(auth.currentUser);
  326. }
  327. - (void)testSignInWithInvalidCustomAuthToken {
  328. FIRAuth *auth = [FIRAuth auth];
  329. if (!auth) {
  330. XCTFail(@"Could not obtain auth object.");
  331. }
  332. XCTestExpectation *expectation =
  333. [self expectationWithDescription:@"Invalid CustomAuthToken sign-in finished."];
  334. [auth signInWithCustomToken:kInvalidCustomToken
  335. completion:^(FIRAuthDataResult *_Nullable result, NSError *_Nullable error) {
  336. XCTAssertEqualObjects(error.localizedDescription, kInvalidTokenErrorMessage);
  337. [expectation fulfill];
  338. }];
  339. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  340. handler:^(NSError *error) {
  341. if (error != nil) {
  342. XCTFail(@"Failed to wait for expectations "
  343. @"in CustomAuthToken sign in. Error: %@",
  344. error.localizedDescription);
  345. }
  346. }];
  347. }
  348. - (void)testSignInWithFaceboook {
  349. FIRAuth *auth = [FIRAuth auth];
  350. if (!auth) {
  351. XCTFail(@"Could not obtain auth object.");
  352. }
  353. NSDictionary *userInfoDict = [self createFacebookTestingAccount];
  354. NSString *facebookAccessToken = userInfoDict[@"access_token"];
  355. NSLog(@"Facebook testing account access token is: %@", facebookAccessToken);
  356. NSString *facebookAccountId = userInfoDict[@"id"];
  357. NSLog(@"Facebook testing account id is: %@", facebookAccountId);
  358. FIRAuthCredential *credential =
  359. [FIRFacebookAuthProvider credentialWithAccessToken:facebookAccessToken];
  360. XCTestExpectation *expectation = [self expectationWithDescription:@"Facebook sign-in finished."];
  361. [auth signInWithCredential:credential
  362. completion:^(FIRUser *user, NSError *error) {
  363. if (error) {
  364. NSLog(@"Facebook sign in error: %@", error);
  365. }
  366. [expectation fulfill];
  367. }];
  368. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  369. handler:^(NSError *error) {
  370. if (error != nil) {
  371. XCTFail(@"Failed to wait for expectations "
  372. @"in Facebook sign in. Error: %@",
  373. error.localizedDescription);
  374. }
  375. }];
  376. XCTAssertEqualObjects(auth.currentUser.displayName, kFacebookTestAccountName);
  377. // Clean up the created Firebase/Facebook user for future runs.
  378. [self deleteCurrentFirebaseUser];
  379. [self deleteFacebookTestingAccountbyId:facebookAccountId];
  380. }
  381. - (void)testSignInWithGoogle {
  382. FIRAuth *auth = [FIRAuth auth];
  383. if (!auth) {
  384. XCTFail(@"Could not obtain auth object.");
  385. }
  386. NSDictionary *userInfoDict = [self getGoogleAccessToken];
  387. NSString *googleAccessToken = userInfoDict[@"access_token"];
  388. NSString *googleIdToken = userInfoDict[@"id_token"];
  389. FIRAuthCredential *credential =
  390. [FIRGoogleAuthProvider credentialWithIDToken:googleIdToken accessToken:googleAccessToken];
  391. XCTestExpectation *expectation =
  392. [self expectationWithDescription:@"Signing in with Google finished."];
  393. [auth signInWithCredential:credential
  394. completion:^(FIRUser *user, NSError *error) {
  395. if (error) {
  396. NSLog(@"Signing in with Google had error: %@", error);
  397. }
  398. [expectation fulfill];
  399. }];
  400. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  401. handler:^(NSError *error) {
  402. if (error != nil) {
  403. XCTFail(@"Failed to wait for expectations "
  404. @"in Signing in with Google. Error: %@",
  405. error.localizedDescription);
  406. }
  407. }];
  408. XCTAssertEqualObjects(auth.currentUser.displayName, kGoogleTestAccountName);
  409. // Clean up the created Firebase/Facebook user for future runs.
  410. [self deleteCurrentFirebaseUser];
  411. }
  412. #pragma mark - Helpers
  413. /** Generate fake random email address */
  414. - (NSString *)fakeRandomEmail {
  415. NSMutableString *fakeEmail = [[NSMutableString alloc] init];
  416. for (int i=0; i<10; i++) {
  417. [fakeEmail appendString:
  418. [NSString stringWithFormat:@"%c", 'a' + arc4random_uniform('z' - 'a' + 1)]];
  419. }
  420. [fakeEmail appendString:@"@gmail.com"];
  421. return fakeEmail;
  422. }
  423. /** Sign out current account. */
  424. - (void)signOut {
  425. NSError *signOutError;
  426. BOOL status = [[FIRAuth auth] signOut:&signOutError];
  427. // Just log the error because we don't want to fail the test if signing out
  428. // fails.
  429. if (!status) {
  430. NSLog(@"Error signing out: %@", signOutError);
  431. }
  432. }
  433. /** Creates a Facebook testing account using Facebook Graph API and return a dictionary that
  434. * constains "id", "access_token", "login_url", "email" and "password" of the created account.
  435. */
  436. - (NSDictionary *)createFacebookTestingAccount {
  437. // Build the URL.
  438. NSString *urltoCreateTestUser =
  439. [NSString stringWithFormat:@"https://%@/%@/accounts/test-users", kFacebookGraphApiAuthority,
  440. kFacebookAppID];
  441. // Build the POST request.
  442. NSString *bodyString =
  443. [NSString stringWithFormat:@"installed=true&name=%@&permissions=read_stream&access_token=%@",
  444. kFacebookTestAccountName, kFacebookAppAccessToken];
  445. NSData *postData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
  446. GTMSessionFetcherService *service = [[GTMSessionFetcherService alloc] init];
  447. GTMSessionFetcher *fetcher = [service fetcherWithURLString:urltoCreateTestUser];
  448. fetcher.bodyData = postData;
  449. [fetcher setRequestValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
  450. XCTestExpectation *expectation =
  451. [self expectationWithDescription:@"Creating Facebook account finished."];
  452. __block NSData *data = nil;
  453. [fetcher beginFetchWithCompletionHandler:^(NSData *receivedData, NSError *error) {
  454. if (error) {
  455. NSLog(@"Creating Facebook account finished with error: %@", error);
  456. return;
  457. }
  458. data = receivedData;
  459. [expectation fulfill];
  460. }];
  461. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  462. handler:^(NSError *error) {
  463. if (error != nil) {
  464. XCTFail(@"Failed to wait for expectations "
  465. @"in creating Facebook account. Error: %@",
  466. error.localizedDescription);
  467. }
  468. }];
  469. NSString *userInfo = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  470. NSLog(@"The info of created Facebook testing account is: %@", userInfo);
  471. // Parses the access token from the JSON data.
  472. NSDictionary *userInfoDict =
  473. [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
  474. return userInfoDict;
  475. }
  476. /** Clean up the created user for tests' future runs. */
  477. - (void)deleteCurrentFirebaseUser {
  478. FIRAuth *auth = [FIRAuth auth];
  479. if (!auth) {
  480. NSLog(@"Could not obtain auth object.");
  481. }
  482. XCTestExpectation *expectation =
  483. [self expectationWithDescription:@"Delete current user finished."];
  484. [auth.currentUser deleteWithCompletion:^(NSError *_Nullable error) {
  485. if (error) {
  486. XCTFail(@"Failed to delete user. Error: %@.", error);
  487. }
  488. [expectation fulfill];
  489. }];
  490. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  491. handler:^(NSError *error) {
  492. if (error != nil) {
  493. XCTFail(@"Failed to wait for expectations "
  494. @"in deleting user. Error: %@",
  495. error.localizedDescription);
  496. }
  497. }];
  498. }
  499. - (void)signInAnonymously {
  500. FIRAuth *auth = [FIRAuth auth];
  501. if (!auth) {
  502. XCTFail(@"Could not obtain auth object.");
  503. }
  504. XCTestExpectation *expectation =
  505. [self expectationWithDescription:@"Anonymousy sign-in finished."];
  506. [auth signInAnonymouslyWithCompletion:^(FIRAuthDataResult *result, NSError *error) {
  507. if (error) {
  508. NSLog(@"Anonymousy sign in error: %@", error);
  509. }
  510. [expectation fulfill];
  511. }];
  512. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  513. handler:^(NSError *error) {
  514. if (error != nil) {
  515. XCTFail(@"Failed to wait for expectations "
  516. @"in anonymousy sign in. Error: %@",
  517. error.localizedDescription);
  518. }
  519. }];
  520. }
  521. /** Delete a Facebook testing account by account Id using Facebook Graph API. */
  522. - (void)deleteFacebookTestingAccountbyId:(NSString *)accountId {
  523. // Build the URL.
  524. NSString *urltoDeleteTestUser =
  525. [NSString stringWithFormat:@"https://%@/%@", kFacebookGraphApiAuthority, accountId];
  526. // Build the POST request.
  527. NSString *bodyString =
  528. [NSString stringWithFormat:@"method=delete&access_token=%@", kFacebookAppAccessToken];
  529. NSData *postData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
  530. GTMSessionFetcherService *service = [[GTMSessionFetcherService alloc] init];
  531. GTMSessionFetcher *fetcher = [service fetcherWithURLString:urltoDeleteTestUser];
  532. fetcher.bodyData = postData;
  533. [fetcher setRequestValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
  534. XCTestExpectation *expectation =
  535. [self expectationWithDescription:@"Deleting Facebook account finished."];
  536. [fetcher beginFetchWithCompletionHandler:^(NSData *receivedData, NSError *error) {
  537. NSString *deleteResult =
  538. [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
  539. NSLog(@"The result of deleting Facebook account is: %@", deleteResult);
  540. if (error) {
  541. NSLog(@"Deleting Facebook account finished with error: %@", error);
  542. }
  543. [expectation fulfill];
  544. }];
  545. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  546. handler:^(NSError *error) {
  547. if (error != nil) {
  548. XCTFail(@"Failed to wait for expectations "
  549. @"in deleting Facebook account. Error: %@",
  550. error.localizedDescription);
  551. }
  552. }];
  553. }
  554. /** Sends http request to Google OAuth2 token server to use refresh token to exchange for Google
  555. * access token. Returns a dictionary that constains "access_token", "token_type", "expires_in" and
  556. * "id_token".
  557. */
  558. - (NSDictionary *)getGoogleAccessToken {
  559. NSString *googleOauth2TokenServerUrl = @"https://www.googleapis.com/oauth2/v4/token";
  560. NSString *bodyString =
  561. [NSString stringWithFormat:@"client_id=%@&grant_type=refresh_token&refresh_token=%@",
  562. kGoogleCliendId, kGoogleTestAccountRefreshToken];
  563. NSData *postData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
  564. GTMSessionFetcherService *service = [[GTMSessionFetcherService alloc] init];
  565. GTMSessionFetcher *fetcher = [service fetcherWithURLString:googleOauth2TokenServerUrl];
  566. fetcher.bodyData = postData;
  567. [fetcher setRequestValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  568. XCTestExpectation *expectation =
  569. [self expectationWithDescription:@"Exchanging Google account tokens finished."];
  570. __block NSData *data = nil;
  571. [fetcher beginFetchWithCompletionHandler:^(NSData *receivedData, NSError *error) {
  572. if (error) {
  573. NSLog(@"Exchanging Google account tokens finished with error: %@", error);
  574. return;
  575. }
  576. data = receivedData;
  577. [expectation fulfill];
  578. }];
  579. [self waitForExpectationsWithTimeout:kExpectationsTimeout
  580. handler:^(NSError *error) {
  581. if (error != nil) {
  582. XCTFail(@"Failed to wait for expectations "
  583. @"in exchanging Google account tokens. Error: %@",
  584. error.localizedDescription);
  585. }
  586. }];
  587. NSString *userInfo = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  588. NSLog(@"The info of exchanged result is: %@", userInfo);
  589. NSDictionary *userInfoDict =
  590. [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
  591. return userInfoDict;
  592. }
  593. @end