| Index: ios/chrome/browser/ui/authentication/authentication_flow_unittest.mm
|
| diff --git a/ios/chrome/browser/ui/authentication/authentication_flow_unittest.mm b/ios/chrome/browser/ui/authentication/authentication_flow_unittest.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4276ab1d8effae545908b043fe41a4bea8d6c30f
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/authentication/authentication_flow_unittest.mm
|
| @@ -0,0 +1,303 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
|
| +
|
| +#include <memory>
|
| +
|
| +#import "base/mac/scoped_block.h"
|
| +#import "base/mac/scoped_nsobject.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/test/ios/wait_util.h"
|
| +#include "components/pref_registry/pref_registry_syncable.h"
|
| +#include "components/sync_preferences/pref_service_mock_factory.h"
|
| +#include "components/sync_preferences/pref_service_syncable.h"
|
| +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
|
| +#include "ios/chrome/browser/prefs/browser_prefs.h"
|
| +#include "ios/chrome/browser/signin/authentication_service_factory.h"
|
| +#import "ios/chrome/browser/signin/authentication_service_fake.h"
|
| +#import "ios/chrome/browser/ui/authentication/authentication_flow_performer.h"
|
| +#include "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
|
| +#include "ios/web/public/test/test_web_thread_bundle.h"
|
| +#import "testing/gtest_mac.h"
|
| +#import "testing/platform_test.h"
|
| +#import "third_party/ocmock/gtest_support.h"
|
| +#import "third_party/ocmock/ocmock_extensions.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +namespace {
|
| +
|
| +class AuthenticationFlowTest : public PlatformTest {
|
| + protected:
|
| + void SetUp() override {
|
| + PlatformTest::SetUp();
|
| +
|
| + TestChromeBrowserState::Builder builder;
|
| + builder.AddTestingFactory(
|
| + AuthenticationServiceFactory::GetInstance(),
|
| + AuthenticationServiceFake::CreateAuthenticationService);
|
| + builder.SetPrefService(CreatePrefService());
|
| + browser_state_ = builder.Build();
|
| + ios::FakeChromeIdentityService* identityService =
|
| + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
|
| + identityService->AddIdentities(@[ @"identity1", @"identity2" ]);
|
| + identity1_ =
|
| + [identityService->GetAllIdentitiesSortedForDisplay() objectAtIndex:0];
|
| + identity2_ =
|
| + [identityService->GetAllIdentitiesSortedForDisplay() objectAtIndex:1];
|
| + sign_in_completion_.reset(
|
| + ^(BOOL success) {
|
| + finished_ = true;
|
| + signed_in_success_ = success;
|
| + },
|
| + base::scoped_policy::RETAIN);
|
| + finished_ = false;
|
| + signed_in_success_ = false;
|
| + }
|
| +
|
| + std::unique_ptr<sync_preferences::PrefServiceSyncable> CreatePrefService() {
|
| + sync_preferences::PrefServiceMockFactory factory;
|
| + scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
|
| + new user_prefs::PrefRegistrySyncable);
|
| + std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs =
|
| + factory.CreateSyncable(registry.get());
|
| + RegisterBrowserStatePrefs(registry.get());
|
| + return prefs;
|
| + }
|
| +
|
| + AuthenticationFlowPerformer* GetAuthenticationFlowPerformer() {
|
| + return static_cast<AuthenticationFlowPerformer*>(performer_.get());
|
| + }
|
| +
|
| + // Creates a new AuthenticationFlow with default values for fields that are
|
| + // not directly useful.
|
| + void CreateAuthenticationFlow(ShouldClearData shouldClearData,
|
| + PostSignInAction postSignInAction) {
|
| + ChromeIdentity* identity = identity1_;
|
| + view_controller_.reset(
|
| + [[OCMockObject niceMockForClass:[UIViewController class]] retain]);
|
| + authentication_flow_.reset([[AuthenticationFlow alloc]
|
| + initWithBrowserState:browser_state_.get()
|
| + identity:identity
|
| + shouldClearData:shouldClearData
|
| + postSignInAction:postSignInAction
|
| + presentingViewController:view_controller_]);
|
| + performer_.reset([[OCMockObject
|
| + mockForClass:[AuthenticationFlowPerformer class]] retain]);
|
| + [authentication_flow_
|
| + setPerformerForTesting:GetAuthenticationFlowPerformer()];
|
| + }
|
| +
|
| + // Checks if the AuthenticationFlow operation has completed, and whether it
|
| + // was successful.
|
| + void CheckSignInCompletion(bool expectedSignedIn) {
|
| + base::test::ios::WaitUntilCondition(^bool {
|
| + return finished_;
|
| + });
|
| + EXPECT_EQ(true, finished_);
|
| + EXPECT_EQ(expectedSignedIn, signed_in_success_);
|
| + [performer_ verify];
|
| + }
|
| +
|
| + web::TestWebThreadBundle thread_bundle_;
|
| + base::scoped_nsobject<AuthenticationFlow> authentication_flow_;
|
| + std::unique_ptr<TestChromeBrowserState> browser_state_;
|
| + ChromeIdentity* identity1_;
|
| + ChromeIdentity* identity2_;
|
| + base::scoped_nsobject<OCMockObject> performer_;
|
| + base::mac::ScopedBlock<signin_ui::CompletionCallback> sign_in_completion_;
|
| + base::scoped_nsobject<UIViewController> view_controller_;
|
| +
|
| + // State of the flow
|
| + bool finished_;
|
| + bool signed_in_success_;
|
| +};
|
| +
|
| +// Tests a Sign In of a normal account on the same profile, merging user data
|
| +// and showing the sync settings.
|
| +TEST_F(AuthenticationFlowTest, TestSignInSimple) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_MERGE_DATA,
|
| + POST_SIGNIN_ACTION_START_SYNC);
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFetchManagedStatus:nil];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andReturnBool:NO]
|
| + shouldHandleMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()];
|
| +
|
| + [[performer_ expect] signInIdentity:identity1_
|
| + withHostedDomain:nil
|
| + toBrowserState:browser_state_.get()];
|
| +
|
| + [[performer_ expect] commitSyncForBrowserState:browser_state_.get()];
|
| +
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(true);
|
| +}
|
| +
|
| +// Tests that signing in an already signed in account correctly signs it out
|
| +// and back in.
|
| +TEST_F(AuthenticationFlowTest, TestAlreadySignedIn) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_MERGE_DATA,
|
| + POST_SIGNIN_ACTION_NONE);
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFetchManagedStatus:nil];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andReturnBool:NO]
|
| + shouldHandleMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didSignOut];
|
| + }] signOutBrowserState:browser_state_.get()];
|
| +
|
| + [[performer_ expect] signInIdentity:identity1_
|
| + withHostedDomain:nil
|
| + toBrowserState:browser_state_.get()];
|
| +
|
| + AuthenticationServiceFactory::GetForBrowserState(browser_state_.get())
|
| + ->SignIn(identity1_, std::string());
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(true);
|
| +}
|
| +
|
| +// Tests a Sign In of a different account, requiring a sign out of the already
|
| +// signed in account, and asking the user whether data should be cleared or
|
| +// merged.
|
| +TEST_F(AuthenticationFlowTest, TestSignOutUserChoice) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_USER_CHOICE,
|
| + POST_SIGNIN_ACTION_START_SYNC);
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFetchManagedStatus:nil];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andReturnBool:YES]
|
| + shouldHandleMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_
|
| + didChooseClearDataPolicy:SHOULD_CLEAR_DATA_CLEAR_DATA];
|
| + }] promptMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()
|
| + viewController:view_controller_];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didSignOut];
|
| + }] signOutBrowserState:browser_state_.get()];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didClearData];
|
| + }] clearData:browser_state_.get()];
|
| +
|
| + [[performer_ expect] signInIdentity:identity1_
|
| + withHostedDomain:nil
|
| + toBrowserState:browser_state_.get()];
|
| +
|
| + [[performer_ expect] commitSyncForBrowserState:browser_state_.get()];
|
| +
|
| + AuthenticationServiceFactory::GetForBrowserState(browser_state_.get())
|
| + ->SignIn(identity2_, std::string());
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(true);
|
| +}
|
| +
|
| +// Tests the cancelling of a Sign In.
|
| +TEST_F(AuthenticationFlowTest, TestCancel) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_USER_CHOICE,
|
| + POST_SIGNIN_ACTION_START_SYNC);
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFetchManagedStatus:nil];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andReturnBool:YES]
|
| + shouldHandleMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ cancelAndDismiss];
|
| + }] promptMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()
|
| + viewController:view_controller_];
|
| +
|
| + [[performer_ expect] cancelAndDismiss];
|
| +
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(false);
|
| +}
|
| +
|
| +// Tests the fetch managed status failure case.
|
| +TEST_F(AuthenticationFlowTest, TestFailFetchManagedStatus) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_MERGE_DATA,
|
| + POST_SIGNIN_ACTION_START_SYNC);
|
| +
|
| + NSError* error = [NSError errorWithDomain:@"foo" code:0 userInfo:nil];
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFailFetchManagedStatus:error];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation* invocation) {
|
| + ProceduralBlock completionBlock;
|
| + [invocation getArgument:&completionBlock atIndex:3];
|
| + completionBlock();
|
| + }] showAuthenticationError:[OCMArg any]
|
| + withCompletion:[OCMArg any]
|
| + viewController:view_controller_];
|
| +
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(false);
|
| +}
|
| +
|
| +// Tests the managed sign in confirmation dialog is shown when signing in to
|
| +// a managed identity.
|
| +TEST_F(AuthenticationFlowTest, TestShowManagedConfirmation) {
|
| + CreateAuthenticationFlow(SHOULD_CLEAR_DATA_CLEAR_DATA,
|
| + POST_SIGNIN_ACTION_START_SYNC);
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didFetchManagedStatus:@"foo.com"];
|
| + }] fetchManagedStatus:browser_state_.get()
|
| + forIdentity:identity1_];
|
| +
|
| + [[[performer_ expect] andReturnBool:NO]
|
| + shouldHandleMergeCaseForIdentity:identity1_
|
| + browserState:browser_state_.get()];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didAcceptManagedConfirmation];
|
| + }] showManagedConfirmationForHostedDomain:@"foo.com"
|
| + viewController:view_controller_];
|
| +
|
| + [[[performer_ expect] andDo:^(NSInvocation*) {
|
| + [authentication_flow_ didClearData];
|
| + }] clearData:browser_state_.get()];
|
| +
|
| + [[performer_ expect] signInIdentity:identity1_
|
| + withHostedDomain:@"foo.com"
|
| + toBrowserState:browser_state_.get()];
|
| +
|
| + [[performer_ expect] commitSyncForBrowserState:browser_state_.get()];
|
| +
|
| + [authentication_flow_ startSignInWithCompletion:sign_in_completion_];
|
| +
|
| + CheckSignInCompletion(true);
|
| +}
|
| +
|
| +} // namespace
|
|
|