// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/app/post_restore_app_agent.h"
#import "base/memory/raw_ptr.h"
#import "base/values.h"
#import "components/prefs/pref_registry_simple.h"
#import "components/prefs/testing_pref_service.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/application_delegate/app_state_observer.h"
#import "ios/chrome/browser/promos_manager/model/constants.h"
#import "ios/chrome/browser/promos_manager/model/mock_promos_manager.h"
#import "ios/chrome/browser/promos_manager/model/promos_manager.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/signin/model/authentication_service.h"
#import "ios/chrome/browser/signin/model/authentication_service_factory.h"
#import "ios/chrome/browser/signin/model/fake_authentication_service_delegate.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/browser/signin/model/fake_system_identity_manager.h"
#import "ios/chrome/browser/signin/model/identity_manager_factory.h"
#import "ios/chrome/browser/signin/model/signin_util.h"
#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gmock/include/gmock/gmock.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
using ::testing::_;
using ::testing::AnyNumber;
using testing::NiceMock;
namespace {
const char kFakePreRestoreAccountEmail[] = "[email protected]";
} // namespace
// Tests the PostRestoreAppAgent.
class PostRestoreAppAgentTest : public PlatformTest {
public:
explicit PostRestoreAppAgentTest() { CreateAppAgent(); }
void CreateAppAgent() {
app_agent_ = [[PostRestoreAppAgent alloc]
initWithPromosManager:CreatePromosManager()
authenticationService:CreateAuthService()
identityManager:GetIdentityManager()];
mockAppState_ = OCMClassMock([AppState class]);
[app_agent_ setAppState:mockAppState_];
}
MockPromosManager* CreatePromosManager() {
promos_manager_ = std::make_unique<NiceMock<MockPromosManager>>();
return promos_manager_.get();
}
AuthenticationService* CreateAuthService() {
TestChromeBrowserState::Builder builder;
builder.AddTestingFactory(
AuthenticationServiceFactory::GetInstance(),
AuthenticationServiceFactory::GetDefaultFactory());
browser_state_ = std::move(builder).Build();
AuthenticationServiceFactory::CreateAndInitializeForBrowserState(
browser_state_.get(),
std::make_unique<FakeAuthenticationServiceDelegate>());
auth_service_ =
AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
return auth_service_;
}
signin::IdentityManager* GetIdentityManager() {
return IdentityManagerFactory::GetForBrowserState(browser_state_.get());
}
void MockAppStateChange(InitStage initStage) {
OCMStub([mockAppState_ initStage]).andReturn(initStage);
[app_agent_ appState:mockAppState_
didTransitionFromInitStage:InitStageStart];
}
void SetFakePreRestoreAccountInfo() {
AccountInfo accountInfo;
accountInfo.email = kFakePreRestoreAccountEmail;
StorePreRestoreIdentity(local_state(), accountInfo,
/*history_sync_enabled=*/false);
}
// Signs in a fake identity.
void SignIn() {
FakeSystemIdentity* fake_identity = [FakeSystemIdentity fakeIdentity1];
FakeSystemIdentityManager* system_identity_manager =
FakeSystemIdentityManager::FromSystemIdentityManager(
GetApplicationContext()->GetSystemIdentityManager());
system_identity_manager->AddIdentity(fake_identity);
auth_service_->SignIn(fake_identity,
signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
}
PrefService* local_state() {
return GetApplicationContext()->GetLocalState();
}
protected:
IOSChromeScopedTestingLocalState scoped_testing_local_state_;
web::WebTaskEnvironment task_environment_;
std::unique_ptr<TestChromeBrowserState> browser_state_;
std::unique_ptr<MockPromosManager> promos_manager_;
raw_ptr<AuthenticationService> auth_service_;
id mockAppState_;
PostRestoreAppAgent* app_agent_;
};
// Tests the logic of whether a promo should be registered.
TEST_F(PostRestoreAppAgentTest, MaybeRegisterPromo) {
EXPECT_CALL(*promos_manager_.get(), RegisterPromoForSingleDisplay(_))
.Times(0);
EXPECT_CALL(*promos_manager_.get(), RegisterPromoForContinuousDisplay(_))
.Times(0);
// Scenarios which should not register a promo.
ClearPreRestoreIdentity(local_state());
MockAppStateChange(InitStageFinal);
SetFakePreRestoreAccountInfo();
MockAppStateChange(InitStageFinal);
ClearPreRestoreIdentity(local_state());
MockAppStateChange(InitStageFinal);
}
// Tests that the alert promo is registered.
TEST_F(PostRestoreAppAgentTest, RegisterPromoAlert) {
EXPECT_CALL(*promos_manager_.get(),
RegisterPromoForSingleDisplay(
promos_manager::Promo::PostRestoreSignInAlert))
.Times(1);
SetFakePreRestoreAccountInfo();
MockAppStateChange(InitStageFinal);
}
// Tests that the reauth prompt is disabled.
TEST_F(PostRestoreAppAgentTest, RegisterPromoDisablesReauthPrompt) {
SetFakePreRestoreAccountInfo();
auth_service_->SetReauthPromptForSignInAndSync();
EXPECT_TRUE(auth_service_->ShouldReauthPromptForSignInAndSync());
MockAppStateChange(InitStageFinal);
EXPECT_FALSE(auth_service_->ShouldReauthPromptForSignInAndSync());
}
// Tests that the alert promo is deregistered with the right conditions.
TEST_F(PostRestoreAppAgentTest, DeregisterPromoAlert) {
EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(_)).Times(1);
EXPECT_CALL(*promos_manager_.get(),
DeregisterPromo(promos_manager::Promo::PostRestoreSignInAlert))
.Times(1);
SetFakePreRestoreAccountInfo();
ClearPreRestoreIdentity(local_state());
MockAppStateChange(InitStageFinal);
}
// Tests that if a signin occurs, the promo is deregistered.
TEST_F(PostRestoreAppAgentTest, DeregisterPromoOnSignin) {
SetFakePreRestoreAccountInfo();
MockAppStateChange(InitStageFinal);
EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(_)).Times(1);
EXPECT_CALL(*promos_manager_.get(),
DeregisterPromo(promos_manager::Promo::PostRestoreSignInAlert))
.Times(1);
SignIn();
}