aboutsummaryrefslogtreecommitdiffhomepage
path: root/Example
diff options
context:
space:
mode:
authorGravatar Paul Beusterien <paulbeusterien@google.com>2018-03-07 07:47:09 -0800
committerGravatar GitHub <noreply@github.com>2018-03-07 07:47:09 -0800
commit8ef0f1490a72fd700f609dc9971ec16868d6747b (patch)
tree61cdcbb7099535abd791dc523d8e2d19268faf4f /Example
parent0b8f216e4ce85b968ac0803d729cd24eb110d0b6 (diff)
Adds Email link sign-in (#882)
Diffstat (limited to 'Example')
-rw-r--r--Example/Auth/Sample/MainViewController.m127
-rw-r--r--Example/Auth/Tests/FIRAuthTests.m286
-rw-r--r--Example/Auth/Tests/FIREmailLinkRequestTests.m137
-rw-r--r--Example/Auth/Tests/FIREmailLinkSignInResponseTests.m195
-rw-r--r--Example/Auth/Tests/FIRGetOOBConfirmationCodeRequestTests.m43
-rw-r--r--Example/Firebase.xcodeproj/project.pbxproj10
6 files changed, 793 insertions, 5 deletions
diff --git a/Example/Auth/Sample/MainViewController.m b/Example/Auth/Sample/MainViewController.m
index 31c103a..36ef92d 100644
--- a/Example/Auth/Sample/MainViewController.m
+++ b/Example/Auth/Sample/MainViewController.m
@@ -91,6 +91,16 @@ static NSString *const kSetPhotoURLText = @"Set Photo url";
*/
static NSString *const kSignInGoogleButtonText = @"Sign in with Google";
+/** @var kSignInWithEmailLink
+ @brief The text of the "Sign in with Email Link" button.
+ */
+static NSString *const kSignInWithEmailLink = @"Sign in with Email Link";
+
+/** @var kSendEmailSignInLink
+ @brief The text of the "Send Email SignIn link" button
+*/
+static NSString *const kSendEmailSignInLink = @"Send Email Sign in Link";
+
/** @var kSignInAndRetrieveGoogleButtonText
@brief The text of the "Sign in with Google and retrieve data" button.
*/
@@ -279,6 +289,11 @@ static NSString *const kUnlinkFromEmailPassword = @"Unlink from Email/Password";
*/
static NSString *const kGetProvidersForEmail = @"Get Provider IDs for Email";
+/** @var kGetAllSignInMethodsForEmail
+ @brief The text of the "Get sign-in methods for Email" button.
+ */
+static NSString *const kGetAllSignInMethodsForEmail = @"Get Sign-in methods for Email";
+
/** @var kActionCodeTypeDescription
@brief The description of the "Action Type" entry.
*/
@@ -722,6 +737,10 @@ typedef enum {
action:^{ [weakSelf createUserAuthDataResult]; }],
[StaticContentTableViewCell cellWithTitle:kSignInGoogleButtonText
action:^{ [weakSelf signInGoogle]; }],
+ [StaticContentTableViewCell cellWithTitle:kSignInWithEmailLink
+ action:^{ [weakSelf signInWithEmailLink]; }],
+ [StaticContentTableViewCell cellWithTitle:kSendEmailSignInLink
+ action:^{ [weakSelf sendEmailSignInLink]; }],
[StaticContentTableViewCell cellWithTitle:kSignInGoogleAndRetrieveDataButtonText
action:^{ [weakSelf signInGoogleAndRetrieveData]; }],
[StaticContentTableViewCell cellWithTitle:kSignInFacebookButtonText
@@ -754,6 +773,8 @@ typedef enum {
action:^{ [weakSelf reloadUser]; }],
[StaticContentTableViewCell cellWithTitle:kGetProvidersForEmail
action:^{ [weakSelf getProvidersForEmail]; }],
+ [StaticContentTableViewCell cellWithTitle:kGetAllSignInMethodsForEmail
+ action:^{ [weakSelf getAllSignInMethodsForEmail]; }],
[StaticContentTableViewCell cellWithTitle:kUpdateEmailText
action:^{ [weakSelf updateEmail]; }],
[StaticContentTableViewCell cellWithTitle:kUpdatePasswordText
@@ -1657,7 +1678,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
/** @fn signInEmailPassword
- @brief Invoked when "sign in with Email/Password" row is pressed.
+ @brief Invoked when "Sign in with Email/Password" row is pressed.
*/
- (void)signInEmailPassword {
[self showTextInputPromptWithMessage:@"Email Address:"
@@ -1724,6 +1745,75 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}];
}
+/** @fn signInWithEmailLink
+ @brief Invoked when "Sign in with email link" row is pressed.
+ */
+- (void)signInWithEmailLink {
+ [self showTextInputPromptWithMessage:@"Email Address:"
+ keyboardType:UIKeyboardTypeEmailAddress
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
+ if (!userPressedOK || !email.length) {
+ return;
+ }
+ [self showTextInputPromptWithMessage:@"Email Sign-In Link:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable link) {
+ if (!userPressedOK) {
+ return;
+ }
+ if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
+ [self showSpinner:^{
+ [[AppManager auth] signInWithEmail:email
+ link:link
+ completion:^(FIRAuthDataResult *_Nullable authResult,
+ NSError *_Nullable error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self logFailure:@"sign-in with Email/Sign-In failed" error:error];
+ } else {
+ [self logSuccess:@"sign-in with Email/Sign-In link succeeded."];
+ [self log:[NSString stringWithFormat:@"UID: %@",authResult.user.uid]];
+ }
+ [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
+ }];
+ }];
+ }];
+ } else {
+ [self log:@"The sign-in link is invalid"];
+ }
+ }];
+ }];
+}
+
+/** @fn sendEmailSignInLink
+ @brief Invoked when "Send email sign-in link" row is pressed.
+ */
+- (void)sendEmailSignInLink {
+ [self showTextInputPromptWithMessage:@"Email:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable userInput) {
+ if (!userPressedOK) {
+ return;
+ }
+ [self showSpinner:^{
+ void (^requestEmailSignInLink)(void (^)(NSError *)) = ^(void (^completion)(NSError *)) {
+ [[AppManager auth] sendSignInLinkToEmail:userInput
+ actionCodeSettings:[self actionCodeSettings]
+ completion:completion];
+ };
+ requestEmailSignInLink(^(NSError *_Nullable error) {
+ [self hideSpinner:^{
+ if (error) {
+ [self logFailure:@"Email Link request failed" error:error];
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ [self logSuccess:@"Email Link request succeeded."];
+ [self showMessagePrompt:@"Sent"];
+ }];
+ });
+ }];
+ }];
+}
+
/** @fn signUpNewEmail
@brief Invoked if sign-in is attempted with new email/password.
@remarks Should only be called if @c FIRAuthErrorCodeInvalidEmail is encountered on attepmt to
@@ -2245,6 +2335,39 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}];
}
+/** @fn getAllSignInMethodsForEmail
+ @brief Prompts user for an email address, calls @c FIRAuth.getAllSignInMethodsForEmail:callback:
+ and displays the result.
+ */
+- (void)getAllSignInMethodsForEmail {
+ [self showTextInputPromptWithMessage:@"Email:"
+ completionBlock:^(BOOL userPressedOK, NSString *_Nullable userInput) {
+ if (!userPressedOK || !userInput.length) {
+ return;
+ }
+
+ [self showSpinner:^{
+ [[AppManager auth] fetchSignInMethodsForEmail:userInput
+ completion:^(NSArray<NSString *> *_Nullable signInMethods,
+ NSError *_Nullable error) {
+ if (error) {
+ [self logFailure:@"get sign-in methods for email failed" error:error];
+ } else {
+ [self logSuccess:@"get sign-in methods for email succeeded."];
+ }
+ [self hideSpinner:^{
+ if (error) {
+ [self showMessagePrompt:error.localizedDescription];
+ return;
+ }
+ [self showMessagePrompt:[signInMethods componentsJoinedByString:@", "]];
+ }];
+ }];
+ }];
+ }];
+}
+
+
/** @fn actionCodeRequestTypeString
@brief Returns a string description for the type of the next action code request.
*/
@@ -2486,6 +2609,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return @"Recover Email";
case FIRActionCodeOperationPasswordReset:
return @"Password Reset";
+ case FIRActionCodeOperationEmailLink:
+ return @"Email Sign-In Link";
case FIRActionCodeOperationUnknown:
return @"Unknown action";
}
diff --git a/Example/Auth/Tests/FIRAuthTests.m b/Example/Auth/Tests/FIRAuthTests.m
index b22c600..914c58b 100644
--- a/Example/Auth/Tests/FIRAuthTests.m
+++ b/Example/Auth/Tests/FIRAuthTests.m
@@ -33,6 +33,8 @@
#import "FIRAuthBackend.h"
#import "FIRCreateAuthURIRequest.h"
#import "FIRCreateAuthURIResponse.h"
+#import "FIREmailLinkSignInRequest.h"
+#import "FIREmailLinkSignInResponse.h"
#import "FIRGetAccountInfoRequest.h"
#import "FIRGetAccountInfoResponse.h"
#import "FIRGetOOBConfirmationCodeRequest.h"
@@ -56,6 +58,7 @@
#import "FIRApp+FIRAuthUnitTests.h"
#import "OCMStubRecorder+FIRAuthUnitTests.h"
#import <OCMock/OCMock.h>
+#import "FIRActionCodeSettings.h"
#if TARGET_OS_IOS
#import "FIRPhoneAuthCredential.h"
@@ -167,6 +170,38 @@ static NSString *const kVerificationCode = @"12345678";
*/
static NSString *const kVerificationID = @"55432";
+/** @var kContinueURL
+ @brief Fake string value of continue url.
+ */
+static NSString *const kContinueURL = @"continueURL";
+
+/** @var kCanHandleCodeInAppKey
+ @brief The key for the request parameter indicating whether the action code can be handled in
+ the app or not.
+ */
+static NSString *const kCanHandleCodeInAppKey = @"canHandleCodeInApp";
+
+/** @var kFIREmailLinkAuthSignInMethod
+ @brief Fake email link sign-in method for testing.
+ */
+static NSString *const kFIREmailLinkAuthSignInMethod = @"emailLink";
+
+/** @var kFIRFacebookAuthSignInMethod
+ @brief Fake Facebook sign-in method for testing.
+ */
+static NSString *const kFIRFacebookAuthSignInMethod = @"facebook.com";
+
+/** @var kBadSignInEmailLink
+ @brief Bad sign-in link to test email link sign-in
+ */
+static NSString *const kBadSignInEmailLink = @"http://www.facebook.com";
+
+/** @var kFakeEmailSignInlink
+ @brief Fake email sign-in link
+ */
+static NSString *const kFakeEmailSignInlink = @"https://fex9s.app.goo.gl?link="
+ "https://fb-sa-upgraded.firebaseapp.com/_?mode%3DsignIn%26oobCode%3Dtestoobcode";
+
/** @var kExpectationTimeout
@brief The maximum time waiting for expectations to fulfill.
*/
@@ -360,6 +395,39 @@ static const NSTimeInterval kWaitInterval = .5;
OCMVerifyAll(_mockBackend);
}
+/** @fn testFetchSignInMethodsForEmailSuccess
+ @brief Tests the flow of a successful @c fetchSignInMethodsForEmail:completion: call.
+ */
+- (void)testFetchSignInMethodsForEmailSuccess {
+ NSArray<NSString *> *allSignInMethods =
+ @[ kFIREmailLinkAuthSignInMethod, kFIRFacebookAuthSignInMethod ];
+ OCMExpect([_mockBackend createAuthURI:[OCMArg any]
+ callback:[OCMArg any]])
+ .andCallBlock2(^(FIRCreateAuthURIRequest *_Nullable request,
+ FIRCreateAuthURIResponseCallback callback) {
+ XCTAssertEqualObjects(request.identifier, kEmail);
+ XCTAssertNotNil(request.endpoint);
+ XCTAssertEqualObjects(request.APIKey, kAPIKey);
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
+ id mockCreateAuthURIResponse = OCMClassMock([FIRCreateAuthURIResponse class]);
+ OCMStub([mockCreateAuthURIResponse signinMethods]).andReturn(allSignInMethods);
+ callback(mockCreateAuthURIResponse, nil);
+ });
+ });
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] fetchSignInMethodsForEmail:kEmail
+ completion:^(NSArray<NSString *> *_Nullable signInMethods,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertEqualObjects(signInMethods, allSignInMethods);
+ XCTAssertTrue([allSignInMethods isKindOfClass:[NSArray class]]);
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
/** @fn testFetchProvidersForEmailSuccessDeprecatedProviderID
@brief Tests the flow of a successful @c fetchProvidersForEmail:completion: call using the
deprecated FIREmailPasswordAuthProviderID.
@@ -416,6 +484,25 @@ static const NSTimeInterval kWaitInterval = .5;
OCMVerifyAll(_mockBackend);
}
+/** @fn testFetchSignInMethodsForEmailFailure
+ @brief Tests the flow of a failed @c fetchSignInMethodsForEmail:completion: call.
+ */
+- (void)testFetchSignInMethodsForEmailFailure {
+ OCMExpect([_mockBackend createAuthURI:[OCMArg any] callback:[OCMArg any]])
+ .andDispatchError2([FIRAuthErrorUtils tooManyRequestsErrorWithMessage:nil]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] fetchSignInMethodsForEmail:kEmail
+ completion:^(NSArray<NSString *> *_Nullable signInMethods,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertNil(signInMethods);
+ XCTAssertEqual(error.code, FIRAuthErrorCodeTooManyRequests);
+ XCTAssertNotNil(error.userInfo[NSLocalizedDescriptionKey]);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
#if TARGET_OS_IOS
/** @fn testPhoneAuthSuccess
@brief Tests the flow of a successful @c signInWithCredential:completion for phone auth.
@@ -501,6 +588,63 @@ static const NSTimeInterval kWaitInterval = .5;
}
#endif
+/** @fn testSignInWithEmailLinkSuccess
+ @brief Tests the flow of a successful @c signInWithEmail:link:completion: call.
+ */
+- (void)testSignInWithEmailLinkSuccess {
+ NSString *fakeCode = @"testoobcode";
+ OCMExpect([_mockBackend emailLinkSignin:[OCMArg any] callback:[OCMArg any]])
+ .andCallBlock2(^(FIREmailLinkSignInRequest *_Nullable request,
+ FIREmailLinkSigninResponseCallback callback) {
+ XCTAssertEqualObjects(request.email, kEmail);
+ XCTAssertEqualObjects(request.oobCode, fakeCode);
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
+ id mockEmailLinkSignInResponse = OCMClassMock([FIREmailLinkSignInResponse class]);
+ [self stubTokensWithMockResponse:mockEmailLinkSignInResponse];
+ callback(mockEmailLinkSignInResponse, nil);
+ OCMStub([mockEmailLinkSignInResponse refreshToken]).andReturn(kRefreshToken);
+ });
+ });
+ [self expectGetAccountInfo];
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] signOut:NULL];
+ [[FIRAuth auth] signInWithEmail:kEmail
+ link:kFakeEmailSignInlink
+ completion:^(FIRAuthDataResult *_Nullable authResult,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertNotNil(authResult.user);
+ XCTAssertEqualObjects(authResult.user.refreshToken, kRefreshToken);
+ XCTAssertFalse(authResult.user.anonymous);
+ XCTAssertEqualObjects(authResult.user.email, kEmail);
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ [self assertUser:[FIRAuth auth].currentUser];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testSignInWithEmailLinkFailure
+ @brief Tests the flow of a failed @c signInWithEmail:link:completion: call.
+ */
+- (void)testSignInWithEmailLinkFailure {
+ OCMExpect([_mockBackend emailLinkSignin:[OCMArg any] callback:[OCMArg any]])
+ ._andDispatchError2([FIRAuthErrorUtils invalidActionCodeErrorWithMessage:nil]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] signOut:NULL];
+ [[FIRAuth auth] signInWithEmail:kEmail
+ link:kFakeEmailSignInlink
+ completion:^(FIRAuthDataResult *_Nullable authResult,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertEqual(error.code, FIRAuthErrorCodeInvalidActionCode);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
/** @fn testSignInWithEmailPasswordSuccess
@brief Tests the flow of a successful @c signInWithEmail:password:completion: call.
*/
@@ -521,8 +665,10 @@ static const NSTimeInterval kWaitInterval = .5;
[self expectGetAccountInfo];
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[[FIRAuth auth] signOut:NULL];
- [[FIRAuth auth] signInWithEmail:kEmail password:kFakePassword completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[FIRAuth auth] signInWithEmail:kEmail
+ password:kFakePassword
+ completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
XCTAssertTrue([NSThread isMainThread]);
[self assertUser:user];
XCTAssertNil(error);
@@ -541,8 +687,10 @@ static const NSTimeInterval kWaitInterval = .5;
.andDispatchError2([FIRAuthErrorUtils wrongPasswordErrorWithMessage:nil]);
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[[FIRAuth auth] signOut:NULL];
- [[FIRAuth auth] signInWithEmail:kEmail password:kFakePassword completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[FIRAuth auth] signInWithEmail:kEmail
+ password:kFakePassword
+ completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
XCTAssertTrue([NSThread isMainThread]);
XCTAssertNil(user);
XCTAssertEqual(error.code, FIRAuthErrorCodeWrongPassword);
@@ -829,6 +977,68 @@ static const NSTimeInterval kWaitInterval = .5;
OCMVerifyAll(_mockBackend);
}
+/** @fn testSignInWithEmailLinkCredentialSuccess
+ @brief Tests the flow of a successfully @c signInWithCredential:completion: call with an
+ email sign-in link credential using FIREmailAuthProvider.
+ */
+- (void)testSignInWithEmailLinkCredentialSuccess {
+ NSString *fakeCode = @"testoobcode";
+ OCMExpect([_mockBackend emailLinkSignin:[OCMArg any] callback:[OCMArg any]])
+ .andCallBlock2(^(FIREmailLinkSignInRequest *_Nullable request,
+ FIREmailLinkSigninResponseCallback callback) {
+ XCTAssertEqualObjects(request.email, kEmail);
+ XCTAssertEqualObjects(request.oobCode, fakeCode);
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
+ id mockEmailLinkSigninResponse = OCMClassMock([FIREmailLinkSignInResponse class]);
+ [self stubTokensWithMockResponse:mockEmailLinkSigninResponse];
+ callback(mockEmailLinkSigninResponse, nil);
+ });
+ });
+ [self expectGetAccountInfo];
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] signOut:NULL];
+ FIRAuthCredential *emailCredential =
+ [FIREmailAuthProvider credentialWithEmail:kEmail link:kFakeEmailSignInlink];
+ [[FIRAuth auth] signInAndRetrieveDataWithCredential:emailCredential
+ completion:^(FIRAuthDataResult *_Nullable authResult,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertNotNil(authResult.user);
+ XCTAssertEqualObjects(authResult.user.refreshToken, kRefreshToken);
+ XCTAssertFalse(authResult.user.anonymous);
+ XCTAssertEqualObjects(authResult.user.email, kEmail);
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ [self assertUser:[FIRAuth auth].currentUser];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testSignInWithEmailLinkCredentialFailure
+ @brief Tests the flow of a failed @c signInWithCredential:completion: call with an
+ email-email sign-in link credential using FIREmailAuthProvider.
+ */
+- (void)testSignInWithEmailLinkCredentialFailure {
+ OCMExpect([_mockBackend emailLinkSignin:[OCMArg any] callback:[OCMArg any]])
+ .andDispatchError2([FIRAuthErrorUtils userDisabledErrorWithMessage:nil]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] signOut:NULL];
+ FIRAuthCredential *emailCredential =
+ [FIREmailAuthProvider credentialWithEmail:kEmail link:kFakeEmailSignInlink];
+ [[FIRAuth auth] signInWithCredential:emailCredential completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertNil(user);
+ XCTAssertEqual(error.code, FIRAuthErrorCodeUserDisabled);
+ XCTAssertNotNil(error.userInfo[NSLocalizedDescriptionKey]);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ XCTAssertNil([FIRAuth auth].currentUser);
+ OCMVerifyAll(_mockBackend);
+}
+
/** @fn testSignInWithEmailCredentialSuccess
@brief Tests the flow of a successfully @c signInWithCredential:completion: call with an
email-password credential.
@@ -1504,6 +1714,65 @@ static const NSTimeInterval kWaitInterval = .5;
OCMVerifyAll(_mockBackend);
}
+/** @fn testSendSignInLinkToEmailSuccess
+ @brief Tests the flow of a successful @c sendSignInLinkToEmail:actionCodeSettings:completion:
+ call.
+ */
+- (void)testSendSignInLinkToEmailSuccess {
+ OCMExpect([_mockBackend getOOBConfirmationCode:[OCMArg any] callback:[OCMArg any]])
+ .andCallBlock2(^(FIRGetOOBConfirmationCodeRequest *_Nullable request,
+ FIRGetOOBConfirmationCodeResponseCallback callback) {
+ XCTAssertEqualObjects(request.APIKey, kAPIKey);
+ XCTAssertEqualObjects(request.email, kEmail);
+ XCTAssertEqualObjects(request.continueURL, kContinueURL);
+ XCTAssertTrue(request.handleCodeInApp);
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
+ callback([[FIRGetOOBConfirmationCodeResponse alloc] init], nil);
+ });
+ });
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] sendSignInLinkToEmail:kEmail
+ actionCodeSettings:[self fakeActionCodeSettings]
+ completion:^(NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertNil(error);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testSendSignInLinkToEmailFailure
+ @brief Tests the flow of a failed @c sendSignInLinkToEmail:actionCodeSettings:completion:
+ call.
+ */
+- (void)testSendSignInLinkToEmailFailure {
+ OCMExpect([_mockBackend getOOBConfirmationCode:[OCMArg any] callback:[OCMArg any]])
+ .andDispatchError2([FIRAuthErrorUtils appNotAuthorizedError]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] sendSignInLinkToEmail:kEmail
+ actionCodeSettings:[self fakeActionCodeSettings]
+ completion:^(NSError *_Nullable error) {
+ XCTAssertTrue([NSThread isMainThread]);
+ XCTAssertEqual(error.code, FIRAuthErrorCodeAppNotAuthorized);
+ XCTAssertNotNil(error.userInfo[NSLocalizedDescriptionKey]);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn fakeActionCodeSettings
+ @brief Constructs and returns a fake instance of @c FIRActionCodeSettings for testing.
+ @return An instance of @c FIRActionCodeSettings for testing.
+ */
+- (FIRActionCodeSettings *)fakeActionCodeSettings {
+ FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc]init];
+ actionCodeSettings.URL = [NSURL URLWithString:kContinueURL];
+ actionCodeSettings.handleCodeInApp = YES;
+ return actionCodeSettings;
+}
+
/** @fn testSignOut
@brief Tests the @c signOut: method.
*/
@@ -1515,6 +1784,15 @@ static const NSTimeInterval kWaitInterval = .5;
XCTAssertNil([FIRAuth auth].currentUser);
}
+/** @fn testIsSignInWithEmailLink
+ @brief Tests the @c isSignInWithEmailLink: method.
+*/
+- (void)testIsSignInWithEmailLink {
+ XCTAssertTrue([[FIRAuth auth] isSignInWithEmailLink:kFakeEmailSignInlink]);
+ XCTAssertFalse([[FIRAuth auth] isSignInWithEmailLink:kBadSignInEmailLink]);
+ XCTAssertFalse([[FIRAuth auth] isSignInWithEmailLink:@""]);
+}
+
/** @fn testAuthStateChanges
@brief Tests @c addAuthStateDidChangeListener: and @c removeAuthStateDidChangeListener: methods.
*/
diff --git a/Example/Auth/Tests/FIREmailLinkRequestTests.m b/Example/Auth/Tests/FIREmailLinkRequestTests.m
new file mode 100644
index 0000000..90d7c18
--- /dev/null
+++ b/Example/Auth/Tests/FIREmailLinkRequestTests.m
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <XCTest/XCTest.h>
+
+#import "FIRAuthErrors.h"
+#import "FIRAuthBackend.h"
+#import "FIREmailLinkSignInRequest.h"
+#import "FIREmailLinkSignInResponse.h"
+#import "FIRFakeBackendRPCIssuer.h"
+
+/** @var kTestAPIKey
+ @brief Fake API key used for testing.
+ */
+static NSString *const kTestAPIKey = @"APIKey";
+
+/** @var kTestEmail
+ @brief The key for the "email" value in the request.
+ */
+static NSString *const kTestEmail = @"TestEmail@email.com";
+
+/** @var kTestOOBCode
+ @brief The test value for the "oobCode" in the request.
+ */
+static NSString *const kTestOOBCode = @"TestOOBCode";
+
+/** @var kTestIDToken
+ @brief The test value for "idToken" in the request.
+ */
+static NSString *const kTestIDToken = @"testIDToken";
+
+/** @var kEmailKey
+ @brief The key for the "identifier" value in the request.
+ */
+static NSString *const kEmailKey = @"email";
+
+/** @var kEmailLinkKey
+ @brief The key for the "oobCode" value in the request.
+ */
+static NSString *const kOOBCodeKey = @"oobCode";
+
+/** @var kIDTokenKey
+ @brief The key for the "IDToken" value in the request.
+ */
+static NSString *const kIDTokenKey = @"idToken";
+
+/** @var kExpectedAPIURL
+ @brief The value of the expected URL (including the backend endpoint) in the request.
+ */
+static NSString *const kExpectedAPIURL =
+ @"https://www.googleapis.com/identitytoolkit/v3/relyingparty/emailLinkSignin?key=APIKey";
+
+/** @class FIREmailLinkRequestTests
+ @brief Tests for @c FIREmailLinkRequests.
+ */
+@interface FIREmailLinkRequestTests : XCTestCase
+@end
+
+@implementation FIREmailLinkRequestTests {
+ /** @var _RPCIssuer
+ @brief This backend RPC issuer is used to fake network responses for each test in the suite.
+ In the @c setUp method we initialize this and set @c FIRAuthBackend's RPC issuer to it.
+ */
+ FIRFakeBackendRPCIssuer *_RPCIssuer;
+
+ /** @var _requestConfiguration
+ @brief This is the request configuration used for testing.
+ */
+ FIRAuthRequestConfiguration *_requestConfiguration;
+}
+
+- (void)setUp {
+ [super setUp];
+ FIRFakeBackendRPCIssuer *RPCIssuer = [[FIRFakeBackendRPCIssuer alloc] init];
+ [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:RPCIssuer];
+ _RPCIssuer = RPCIssuer;
+ _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:kTestAPIKey];
+}
+
+- (void)tearDown {
+ _RPCIssuer = nil;
+ _requestConfiguration = nil;
+ [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:nil];
+ [super tearDown];
+}
+
+/** @fn testEmailLinkRequestCreation
+ @brief Tests the email link sign-in request with mandatory parameters.
+ */
+- (void)testEmailLinkRequest {
+ FIREmailLinkSignInRequest *request =
+ [[FIREmailLinkSignInRequest alloc] initWithEmail:kTestEmail
+ oobCode:kTestOOBCode
+ requestConfiguration:_requestConfiguration];
+ [FIRAuthBackend emailLinkSignin:request callback:^(FIREmailLinkSignInResponse *_Nullable response,
+ NSError *_Nullable error) {
+ }];
+ XCTAssertEqualObjects(_RPCIssuer.requestURL.absoluteString, kExpectedAPIURL);
+ XCTAssertNotNil(_RPCIssuer.decodedRequest);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kEmailKey], kTestEmail);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kOOBCodeKey], kTestOOBCode);
+ XCTAssertNil(_RPCIssuer.decodedRequest[kIDTokenKey]);
+}
+
+/** @fn testEmailLinkRequestCreationOptional
+ @brief Tests the email link sign-in request with mandatory parameters and optional ID token.
+ */
+- (void)testEmailLinkRequestCreationOptional {
+ FIREmailLinkSignInRequest *request =
+ [[FIREmailLinkSignInRequest alloc] initWithEmail:kTestEmail
+ oobCode:kTestOOBCode
+ requestConfiguration:_requestConfiguration];
+ request.IDToken = kTestIDToken;
+ [FIRAuthBackend emailLinkSignin:request callback:^(FIREmailLinkSignInResponse *_Nullable response,
+ NSError *_Nullable error) {
+ }];
+ XCTAssertEqualObjects(_RPCIssuer.requestURL.absoluteString, kExpectedAPIURL);
+ XCTAssertNotNil(_RPCIssuer.decodedRequest);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kEmailKey], kTestEmail);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kOOBCodeKey], kTestOOBCode);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kIDTokenKey], kTestIDToken);
+}
+
+@end
diff --git a/Example/Auth/Tests/FIREmailLinkSignInResponseTests.m b/Example/Auth/Tests/FIREmailLinkSignInResponseTests.m
new file mode 100644
index 0000000..cc2c544
--- /dev/null
+++ b/Example/Auth/Tests/FIREmailLinkSignInResponseTests.m
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <XCTest/XCTest.h>
+
+#import "FIRAuthErrors.h"
+#import "FIRAuthErrorUtils.h"
+#import "FIRAuthBackend.h"
+#import "FIREmailLinkSignInRequest.h"
+#import "FIREmailLinkSignInResponse.h"
+#import "FIRFakeBackendRPCIssuer.h"
+
+/** @var kTestAPIKey
+ @brief Fake API key used for testing.
+ */
+static NSString *const kTestAPIKey = @"APIKey";
+
+/** @var kTestEmail
+ @brief The key for the "email" value in the request.
+ */
+static NSString *const kTestEmail = @"TestEmail@email.com";
+
+/** @var kTestOOBCode
+ @brief The test value for the "oobCode" in the request.
+ */
+static NSString *const kTestOOBCode = @"TestOOBCode";
+
+/** @var kTestIDToken
+ @brief The test value for "idToken" in the request.
+ */
+static NSString *const kTestIDToken = @"testIDToken";
+
+/** @var kEmailKey
+ @brief The key for the "identifier" value in the request.
+ */
+static NSString *const kEmailKey = @"email";
+
+/** @var kEmailLinkKey
+ @brief The key for the "emailLink" value in the request.
+ */
+static NSString *const kOOBCodeKey = @"oobCode";
+
+/** @var kIDTokenKey
+ @brief The key for the "IDToken" value in the request.
+ */
+static NSString *const kIDTokenKey = @"idToken";
+
+/** @var kTestIDTokenResponse
+ @brief A fake ID Token in the server response.
+ */
+static NSString *const kTestIDTokenResponse = @"fakeToken";
+
+/** @var kTestEmailResponse
+ @brief A fake email in the server response.
+ */
+static NSString *const kTestEmailResponse = @"fake email";
+
+/** @var kTestRefreshToken
+ @brief A fake refresh token in the server response.
+ */
+static NSString *const kTestRefreshToken = @"testRefreshToken";
+
+/** @var kInvalidEmailErrorMessage
+ @brief The error returned by the server if the email is invalid.
+ */
+static NSString *const kInvalidEmailErrorMessage = @"INVALID_EMAIL";
+
+/** @var kTestTokenExpirationTimeInterval
+ @brief The fake time interval that it takes a token to expire.
+ */
+static const NSTimeInterval kTestTokenExpirationTimeInterval = 55 * 60;
+
+/** @var kMaxDifferenceBetweenDates
+ @brief The maximum difference between time two dates (in seconds), after which they will be
+ considered different.
+ */
+static const NSTimeInterval kMaxDifferenceBetweenDates = 0.0001;
+
+/** @var kFakeIsNewUSerFlag
+ @brief The fake fake isNewUser flag in the response.
+ */
+static const BOOL kFakeIsNewUSerFlag = YES;
+
+/** @class FIREmailLinkRequestTests
+ @brief Tests for @c FIREmailLinkRequests.
+ */
+@interface FIREmailLinkSignInResponseTests : XCTestCase
+@end
+
+@implementation FIREmailLinkSignInResponseTests {
+ /** @var _RPCIssuer
+ @brief This backend RPC issuer is used to fake network responses for each test in the suite.
+ In the @c setUp method we initialize this and set @c FIRAuthBackend's RPC issuer to it.
+ */
+ FIRFakeBackendRPCIssuer *_RPCIssuer;
+
+ /** @var _requestConfiguration
+ @brief This is the request configuration used for testing.
+ */
+ FIRAuthRequestConfiguration *_requestConfiguration;
+}
+
+- (void)setUp {
+ [super setUp];
+ FIRFakeBackendRPCIssuer *RPCIssuer = [[FIRFakeBackendRPCIssuer alloc] init];
+ [FIRAuthBackend setDefaultBackendImplementationWithRPCIssuer:RPCIssuer];
+ _RPCIssuer = RPCIssuer;
+ _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:kTestAPIKey];
+}
+
+/** @fn testFailedEmailLinkSignInResponse
+ @brief Tests a failed email link sign-in response.
+ */
+- (void)testFailedEmailLinkSignInResponse {
+ FIREmailLinkSignInRequest *request =
+ [[FIREmailLinkSignInRequest alloc] initWithEmail:kTestEmail
+ oobCode:kTestOOBCode
+ requestConfiguration:_requestConfiguration];
+
+ __block BOOL callbackInvoked = NO;
+ __block FIREmailLinkSignInResponse *RPCResponse;
+ __block NSError *RPCError;
+ [FIRAuthBackend emailLinkSignin:request
+ callback:^(FIREmailLinkSignInResponse *_Nullable response,
+ NSError *_Nullable error) {
+ callbackInvoked = YES;
+ RPCResponse = response;
+ RPCError = error;
+ }];
+
+ [_RPCIssuer respondWithServerErrorMessage:kInvalidEmailErrorMessage];
+
+ XCTAssert(callbackInvoked);
+ XCTAssertNil(RPCResponse);
+ XCTAssertEqual(RPCError.code, FIRAuthErrorCodeInvalidEmail);
+}
+
+/** @fn testSuccessfulEmailLinkSignInResponse
+ @brief Tests a succesful email link sign-in response.
+ */
+- (void)testSuccessfulEmailLinkSignInResponse {
+ FIREmailLinkSignInRequest *request =
+ [[FIREmailLinkSignInRequest alloc] initWithEmail:kTestEmail
+ oobCode:kTestOOBCode
+ requestConfiguration:_requestConfiguration];
+
+ __block BOOL callbackInvoked = NO;
+ __block FIREmailLinkSignInResponse *RPCResponse;
+ __block NSError *RPCError;
+ [FIRAuthBackend emailLinkSignin:request
+ callback:^(FIREmailLinkSignInResponse *_Nullable response,
+ NSError *_Nullable error) {
+ callbackInvoked = YES;
+ RPCResponse = response;
+ RPCError = error;
+ }];
+
+ [_RPCIssuer respondWithJSON:@{
+ @"idToken" : kTestIDTokenResponse,
+ @"email" : kTestEmailResponse,
+ @"isNewUser" : kFakeIsNewUSerFlag ? @YES : @NO,
+ @"expiresIn" : [NSString stringWithFormat:@"%f",kTestTokenExpirationTimeInterval],
+ @"refreshToken" : kTestRefreshToken,
+ }];
+
+ XCTAssert(callbackInvoked);
+ XCTAssertNil(RPCError);
+ XCTAssertNotNil(RPCResponse);
+ XCTAssertEqualObjects(RPCResponse.IDToken, kTestIDTokenResponse);
+ XCTAssertEqualObjects(RPCResponse.email, kTestEmailResponse);
+ XCTAssertEqualObjects(RPCResponse.refreshToken, kTestRefreshToken);
+ XCTAssertTrue(RPCResponse.isNewUser);
+ NSTimeInterval expirationTimeInterval =
+ [RPCResponse.approximateExpirationDate timeIntervalSinceNow];
+ NSTimeInterval testTimeInterval =
+ [[NSDate dateWithTimeIntervalSinceNow:kTestTokenExpirationTimeInterval] timeIntervalSinceNow];
+ NSTimeInterval timeIntervalDifference =
+ fabs(expirationTimeInterval - testTimeInterval);
+ XCTAssert(timeIntervalDifference < kMaxDifferenceBetweenDates);
+}
+
+@end
diff --git a/Example/Auth/Tests/FIRGetOOBConfirmationCodeRequestTests.m b/Example/Auth/Tests/FIRGetOOBConfirmationCodeRequestTests.m
index 965af8a..b11c759 100644
--- a/Example/Auth/Tests/FIRGetOOBConfirmationCodeRequestTests.m
+++ b/Example/Auth/Tests/FIRGetOOBConfirmationCodeRequestTests.m
@@ -49,6 +49,11 @@ static NSString *const kPasswordResetRequestTypeValue = @"PASSWORD_RESET";
*/
static NSString *const kVerifyEmailRequestTypeValue = @"VERIFY_EMAIL";
+/** @var kEmailLinkSignInTypeValue
+ @brief The value for the "EMAIL_SIGNIN" request type.
+ */
+static NSString *const kEmailLinkSignInTypeValue = @"EMAIL_SIGNIN";
+
/** @var kEmailKey
@brief The name of the "email" property in the request.
*/
@@ -124,6 +129,7 @@ static NSString *const kCanHandleCodeInAppKey = @"canHandleCodeInApp";
/** @class FIRGetOOBConfirmationCodeRequestTests
@brief Tests for @c FIRGetOOBConfirmationCodeRequest.
*/
+
@interface FIRGetOOBConfirmationCodeRequestTests : XCTestCase
@end
@implementation FIRGetOOBConfirmationCodeRequestTests {
@@ -190,6 +196,43 @@ static NSString *const kCanHandleCodeInAppKey = @"canHandleCodeInApp";
[NSNumber numberWithBool:YES]);
}
+/** @fn testSignInWithEmailLinkRequest
+ @brief Tests the encoding of a email sign-in link request.
+ */
+- (void)testSignInWithEmailLinkRequest {
+ FIRGetOOBConfirmationCodeRequest *request =
+ [FIRGetOOBConfirmationCodeRequest signInWithEmailLinkRequest:kTestEmail
+ actionCodeSettings:[self fakeActionCodeSettings]
+ requestConfiguration:_requestConfiguration];
+
+ __block BOOL callbackInvoked;
+ __block FIRGetOOBConfirmationCodeResponse *RPCResponse;
+ __block NSError *RPCError;
+ [FIRAuthBackend getOOBConfirmationCode:request
+ callback:^(FIRGetOOBConfirmationCodeResponse *_Nullable response,
+ NSError *_Nullable error) {
+ callbackInvoked = YES;
+ RPCResponse = response;
+ RPCError = error;
+ }];
+
+ XCTAssertEqualObjects(_RPCIssuer.requestURL.absoluteString, kExpectedAPIURL);
+ XCTAssertNotNil(_RPCIssuer.decodedRequest);
+ XCTAssert([_RPCIssuer.decodedRequest isKindOfClass:[NSDictionary class]]);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kEmailKey], kTestEmail);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kRequestTypeKey], kEmailLinkSignInTypeValue);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kContinueURLKey], kContinueURL);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kIosBundleIDKey], kIosBundleID);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kAndroidPackageNameKey], kAndroidPackageName);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kAndroidMinimumVersionKey],
+ kAndroidMinimumVersion);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kAndroidInstallAppKey],
+ [NSNumber numberWithBool:YES]);
+ XCTAssertEqualObjects(_RPCIssuer.decodedRequest[kCanHandleCodeInAppKey],
+ [NSNumber numberWithBool:YES]);
+}
+
+
/** @fn testEmailVerificationRequest
@brief Tests the encoding of an email verification request.
*/
diff --git a/Example/Firebase.xcodeproj/project.pbxproj b/Example/Firebase.xcodeproj/project.pbxproj
index c8400d6..7c00d1c 100644
--- a/Example/Firebase.xcodeproj/project.pbxproj
+++ b/Example/Firebase.xcodeproj/project.pbxproj
@@ -135,6 +135,8 @@
7E26CF28514D041D284F00A5 /* Pods_Database_Tests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5318F3AE32EEBCC9FF608813 /* Pods_Database_Tests_tvOS.framework */; };
7E5BD38D202BFB8CD9CCEB53 /* Pods_Auth_EarlGreyTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FAA82401DA4259800B142EA /* Pods_Auth_EarlGreyTests.framework */; };
7E9485421F578AC4005A3939 /* FIRAuthURLPresenterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E94853F1F578A9D005A3939 /* FIRAuthURLPresenterTests.m */; };
+ 7EE21F7A1FE89193009B1370 /* FIREmailLinkRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EE21F791FE89193009B1370 /* FIREmailLinkRequestTests.m */; };
+ 7EE21F7C1FE8919E009B1370 /* FIREmailLinkSignInResponseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EE21F7B1FE8919D009B1370 /* FIREmailLinkSignInResponseTests.m */; };
7EFA2E041F71C93300DD354F /* FIRUserMetadataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EFA2E031F71C93300DD354F /* FIRUserMetadataTests.m */; };
7F41B0EFBDDA90CB9CE6CE5B /* Pods_Database_Tests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61377AC9FE132A8D7BF71881 /* Pods_Database_Tests_macOS.framework */; };
822CE316AE9827F7F0889B30 /* Pods_Auth_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9878B57CF73D2F865992E6EA /* Pods_Auth_Example_macOS.framework */; };
@@ -1037,6 +1039,8 @@
7981511F571E13DECA09B4B1 /* Pods-Core_Example_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Core_Example_macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Core_Example_macOS/Pods-Core_Example_macOS.release.xcconfig"; sourceTree = "<group>"; };
7E94853F1F578A9D005A3939 /* FIRAuthURLPresenterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRAuthURLPresenterTests.m; sourceTree = "<group>"; };
7ED0DF69C095C21EFC81F672 /* Pods-Database_Example_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Database_Example_tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Database_Example_tvOS/Pods-Database_Example_tvOS.release.xcconfig"; sourceTree = "<group>"; };
+ 7EE21F791FE89193009B1370 /* FIREmailLinkRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIREmailLinkRequestTests.m; sourceTree = "<group>"; };
+ 7EE21F7B1FE8919D009B1370 /* FIREmailLinkSignInResponseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIREmailLinkSignInResponseTests.m; sourceTree = "<group>"; };
7EFA2E031F71C93300DD354F /* FIRUserMetadataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUserMetadataTests.m; sourceTree = "<group>"; };
8496034D8156555C5FCF8F14 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
84EC7975F05977AE75E90A12 /* Pods_Database_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Database_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -2371,9 +2375,11 @@
DE9315001E86C6FF0083EDBF /* FIRAuthGlobalWorkQueueTests.m */,
DE9315011E86C6FF0083EDBF /* FIRAuthKeychainTests.m */,
DE750DB81EB3DD4000A75E47 /* FIRAuthNotificationManagerTests.m */,
+ 7EE21F791FE89193009B1370 /* FIREmailLinkRequestTests.m */,
DE9315021E86C6FF0083EDBF /* FIRAuthSerialTaskQueueTests.m */,
DE9315031E86C6FF0083EDBF /* FIRAuthTests.m */,
7E94853F1F578A9D005A3939 /* FIRAuthURLPresenterTests.m */,
+ 7EE21F7B1FE8919D009B1370 /* FIREmailLinkSignInResponseTests.m */,
DE9315041E86C6FF0083EDBF /* FIRAuthUserDefaultsStorageTests.m */,
DE9315051E86C6FF0083EDBF /* FIRCreateAuthURIRequestTests.m */,
DE9315061E86C6FF0083EDBF /* FIRCreateAuthURIResponseTests.m */,
@@ -4662,6 +4668,7 @@
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Database_Tests_tvOS-checkManifestLockResult.txt",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -5425,6 +5432,7 @@
);
name = "[CP] Copy Pods Resources";
outputPaths = (
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -6188,6 +6196,7 @@
DE9315571E86C71C0083EDBF /* FIRAdditionalUserInfoTests.m in Sources */,
DE750DBF1EB3DD6C00A75E47 /* FIRAuthAppCredentialManagerTests.m in Sources */,
DE93157B1E86C71C0083EDBF /* FIRVerifyPasswordResponseTests.m in Sources */,
+ 7EE21F7A1FE89193009B1370 /* FIREmailLinkRequestTests.m in Sources */,
DE93155B1E86C71C0083EDBF /* FIRAuthDispatcherTests.m in Sources */,
DE9315791E86C71C0083EDBF /* FIRVerifyCustomTokenResponseTests.m in Sources */,
DE9315601E86C71C0083EDBF /* FIRAuthUserDefaultsStorageTests.m in Sources */,
@@ -6216,6 +6225,7 @@
DE93155A1E86C71C0083EDBF /* FIRAuthBackendRPCImplementationTests.m in Sources */,
DE93157D1E86C71C0083EDBF /* FIRVerifyPhoneNumberResponseTests.m in Sources */,
DE93157E1E86C71C0083EDBF /* OCMStubRecorder+FIRAuthUnitTests.m in Sources */,
+ 7EE21F7C1FE8919E009B1370 /* FIREmailLinkSignInResponseTests.m in Sources */,
DE9315771E86C71C0083EDBF /* FIRVerifyAssertionResponseTests.m in Sources */,
DE9315721E86C71C0083EDBF /* FIRSignUpNewUserRequestTests.m in Sources */,
DE9315671E86C71C0083EDBF /* FIRGetAccountInfoResponseTests.m in Sources */,