| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/compose/compose_enabling.h" |
| |
| #include <memory> |
| |
| #include "base/json/values_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/test/gmock_expected_support.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/task_environment.h" |
| #include "base/types/expected.h" |
| #include "chrome/browser/about_flags.h" |
| #include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/translate/chrome_translate_client.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/autofill/core/common/aliases.h" |
| #include "components/compose/core/browser/compose_features.h" |
| #include "components/compose/core/browser/config.h" |
| #include "components/language/core/browser/language_model.h" |
| #include "components/signin/public/identity_manager/identity_test_environment.h" |
| #include "components/supervised_user/core/common/pref_names.h" |
| #include "components/supervised_user/core/common/supervised_user_constants.h" |
| #include "components/translate/core/browser/language_state.h" |
| #include "components/translate/core/browser/mock_translate_client.h" |
| #include "components/translate/core/browser/mock_translate_driver.h" |
| #include "components/translate/core/browser/mock_translate_ranker.h" |
| #include "components/translate/core/browser/translate_manager.h" |
| #include "components/unified_consent/pref_names.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using base::test::ErrorIs; |
| using base::test::FeatureRef; |
| using testing::_; |
| using testing::Return; |
| |
| namespace { |
| constexpr char kEmail[] = "[email protected]"; |
| constexpr char kExampleURL[] = "https://example.com"; |
| constexpr char kExampleBadURL[] = "chrome://version"; |
| using translate::testing::MockTranslateClient; |
| |
| class TestLanguageModel : public language::LanguageModel { |
| std::vector<LanguageDetails> GetLanguages() override { |
| return {LanguageDetails("en", 1.0)}; |
| } |
| }; |
| |
| class CustomMockOptimizationGuideKeyedService |
| : public MockOptimizationGuideKeyedService { |
| public: |
| CustomMockOptimizationGuideKeyedService() = default; |
| ~CustomMockOptimizationGuideKeyedService() override = default; |
| |
| MOCK_METHOD(void, |
| CanApplyOptimization, |
| (const GURL& url, |
| optimization_guide::proto::OptimizationType optimization_type, |
| optimization_guide::OptimizationGuideDecisionCallback callback)); |
| |
| MOCK_METHOD( |
| optimization_guide::OptimizationGuideDecision, |
| CanApplyOptimization, |
| (const GURL& url, |
| optimization_guide::proto::OptimizationType optimization_type, |
| optimization_guide::OptimizationMetadata* optimization_metadata)); |
| MOCK_METHOD(void, |
| RegisterOptimizationTypes, |
| (const std::vector<optimization_guide::proto::OptimizationType>& |
| optimization_types)); |
| MOCK_METHOD( |
| void, |
| CanApplyOptimizationOnDemand, |
| (const std::vector<GURL>& urls, |
| const base::flat_set<optimization_guide::proto::OptimizationType>& |
| optimization_types, |
| optimization_guide::proto::RequestContext request_context, |
| optimization_guide::OnDemandOptimizationGuideDecisionRepeatingCallback |
| callback, |
| std::optional<optimization_guide::proto::RequestContextMetadata> |
| request_context_metadata)); |
| }; |
| |
| void RegisterMockOptimizationGuideKeyedServiceFactory( |
| content::BrowserContext* context) { |
| MockOptimizationGuideKeyedService::InitializeWithExistingTestLocalState(); |
| OptimizationGuideKeyedServiceFactory::GetInstance()->SetTestingFactory( |
| context, base::BindRepeating([](content::BrowserContext* context) |
| -> std::unique_ptr<KeyedService> { |
| return std::make_unique< |
| testing::NiceMock<CustomMockOptimizationGuideKeyedService>>(); |
| })); |
| } |
| |
| } // namespace |
| |
| class ComposeEnablingTest : public BrowserWithTestWindowTest { |
| public: |
| ComposeEnablingTest() { |
| // Allows early registration of a override of the factory that instantiates |
| // OptimizationGuideKeyedService. |
| subscription_ = |
| BrowserContextDependencyManager::GetInstance() |
| ->RegisterCreateServicesCallbackForTesting(base::BindRepeating( |
| RegisterMockOptimizationGuideKeyedServiceFactory)); |
| } |
| |
| void SetUp() override { |
| BrowserWithTestWindowTest::SetUp(); |
| |
| // Set flags to their expected enabled/disabled state for these tests |
| // without relyong on their default state. In other words, a change in |
| // default state should not cause these tests to break. |
| // Note: individual tests may reset flags to their default state. |
| ResetFeaturesAndConfig( |
| {compose::features::kEnableCompose, |
| compose::features::kEnableComposeSavedStateNudge, |
| compose::features::kEnableComposeLanguageBypassForContextMenu, |
| compose::features::kEnableComposeSavedStateNotification}, |
| {compose::features::kEnableComposeProactiveNudge}); |
| |
| mock_translate_ranker_ = |
| std::make_unique<translate::testing::MockTranslateRanker>(); |
| mock_translate_client_ = |
| std::make_unique<MockTranslateClient>(&translate_driver_, nullptr); |
| translate_manager_ = std::make_unique<translate::TranslateManager>( |
| mock_translate_client_.get(), mock_translate_ranker_.get(), |
| language_model_.get()); |
| |
| // Note that AddTab makes its own ComposeEnabling as part of |
| // ChromeComposeClient. This can cause confusion when debugging tests. |
| // Don't confuse the two ComposeEnabling objects when debugging. |
| AddTab(browser(), GURL(kExampleBadURL)); |
| AddTab(browser(), GURL(kExampleURL)); |
| context_menu_params_.is_content_editable_for_autofill = true; |
| context_menu_params_.frame_origin = GetOrigin(); |
| |
| opt_guide_ = static_cast< |
| testing::NiceMock<CustomMockOptimizationGuideKeyedService>*>( |
| OptimizationGuideKeyedServiceFactory::GetForProfile(GetProfile())); |
| ON_CALL(*opt_guide_, |
| CanApplyOptimization( |
| _, optimization_guide::proto::OptimizationType::COMPOSE, |
| testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillByDefault( |
| [](const GURL& url, |
| optimization_guide::proto::OptimizationType optimization_type, |
| optimization_guide::OptimizationMetadata* metadata) |
| -> optimization_guide::OptimizationGuideDecision { |
| *metadata = {}; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| compose_hint_metadata.set_decision( |
| compose::ComposeHintDecision::COMPOSE_HINT_DECISION_ENABLED); |
| metadata->SetAnyMetadataForTesting(compose_hint_metadata); |
| return optimization_guide::OptimizationGuideDecision::kTrue; |
| }); |
| |
| ASSERT_TRUE(opt_guide_); |
| |
| // Build the ComposeEnabling object the tests will use, providing it with |
| // mocks for its dependencies. |
| // TODO(b/316625561) Simplify these tests more now that we have dependency |
| // injection. |
| compose_enabling_ = std::make_unique<ComposeEnabling>( |
| GetProfile(), identity_test_env_.identity_manager(), &opt_guide()); |
| |
| // Override un-mockable per-user checks. |
| scoped_skip_user_check_ = ComposeEnabling::ScopedSkipUserCheckForTesting(); |
| // Set the user country to US, a Compose default-enabled country. |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting("us"); |
| } |
| |
| void TearDown() override { |
| // We must destroy the ComposeEnabling while the opt_guide object is still |
| // valid so we can call unregister in the destructor. |
| compose_enabling_ = nullptr; |
| opt_guide_ = nullptr; |
| scoped_feature_list_.Reset(); |
| compose::ResetConfigForTesting(); |
| BrowserWithTestWindowTest::TearDown(); |
| MockOptimizationGuideKeyedService::ResetForTesting(); |
| } |
| |
| void SetProactiveNudgePref(bool pref_value) { |
| PrefService* prefs = GetProfile()->GetPrefs(); |
| prefs->SetBoolean(prefs::kEnableProactiveNudge, pref_value); |
| } |
| |
| void AddDomainToProactiveNudgeDisabledSitesPref() { |
| ScopedDictPrefUpdate update(GetProfile()->GetPrefs(), |
| prefs::kProactiveNudgeDisabledSitesWithTime); |
| update->Set(GetOrigin().Serialize(), base::TimeToValue(base::Time::Now())); |
| } |
| |
| void SignIn(signin::ConsentLevel consent_level) { |
| identity_test_env_.MakePrimaryAccountAvailable(kEmail, consent_level); |
| identity_test_env_.SetAutomaticIssueOfAccessTokens(true); |
| } |
| |
| // The Config depends on several features. Reset the config after setting |
| // new features. |
| void ResetFeaturesAndConfig( |
| const std::vector<FeatureRef>& enabled_features, |
| const std::vector<FeatureRef>& disabled_features) { |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); |
| compose::ResetConfigForTesting(); |
| } |
| |
| CustomMockOptimizationGuideKeyedService& opt_guide() { return *opt_guide_; } |
| |
| protected: |
| void SetLanguage(std::string lang) { |
| translate_manager_->GetLanguageState()->SetSourceLanguage(lang); |
| } |
| |
| url::Origin GetOrigin() { |
| return url::Origin::Create(browser() |
| ->tab_strip_model() |
| ->GetWebContentsAt(0) |
| ->GetLastCommittedURL()); |
| } |
| |
| content::RenderFrameHost* GetRenderFrameHost() { |
| return browser() |
| ->tab_strip_model() |
| ->GetWebContentsAt(0) |
| ->GetPrimaryMainFrame(); |
| } |
| |
| void CheckIsEnabledError(ComposeEnabling* compose_enabling, |
| compose::ComposeShowStatus error_show_status) { |
| EXPECT_EQ(compose_enabling->IsEnabled(), |
| base::unexpected(error_show_status)); |
| } |
| |
| base::test::ScopedFeatureList scoped_feature_list_; |
| signin::IdentityTestEnvironment identity_test_env_; |
| |
| content::ContextMenuParams context_menu_params_; |
| |
| base::CallbackListSubscription subscription_; |
| raw_ptr<testing::NiceMock<CustomMockOptimizationGuideKeyedService>> |
| opt_guide_; |
| |
| translate::testing::MockTranslateDriver translate_driver_; |
| std::unique_ptr<translate::testing::MockTranslateClient> |
| mock_translate_client_; |
| std::unique_ptr<translate::testing::MockTranslateRanker> |
| mock_translate_ranker_; |
| std::unique_ptr<TestLanguageModel> language_model_; |
| std::unique_ptr<translate::TranslateManager> translate_manager_; |
| |
| std::unique_ptr<ComposeEnabling> compose_enabling_; |
| ComposeEnabling::ScopedOverride scoped_skip_user_check_; |
| ComposeEnabling::ScopedOverride scoped_country_override_; |
| }; |
| |
| TEST_F(ComposeEnablingTest, EverythingDisabledTest) { |
| ResetFeaturesAndConfig({}, {compose::features::kEnableCompose}); |
| // We intentionally don't call sign in to make our state not signed in. |
| EXPECT_NE(compose_enabling_->IsEnabled(), base::ok()); |
| } |
| |
| TEST_F(ComposeEnablingTest, FeatureNotEnabledTest) { |
| ResetFeaturesAndConfig({}, {compose::features::kEnableCompose}); |
| // Sign in, with sync turned on. |
| SignIn(signin::ConsentLevel::kSync); |
| |
| CheckIsEnabledError(compose_enabling_.get(), |
| compose::ComposeShowStatus::kComposeFeatureFlagDisabled); |
| } |
| |
| TEST_F(ComposeEnablingTest, NotSignedInTest) { |
| base::HistogramTester histogram_tester; |
| // Intentionally skip the signin step. |
| CheckIsEnabledError(compose_enabling_.get(), |
| compose::ComposeShowStatus::kSignedOut); |
| |
| std::string autocomplete_attribute; |
| // Check that the proactive nudge does not show. |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| |
| EXPECT_EQ(should_trigger.error(), compose::ComposeShowStatus::kSignedOut); |
| } |
| |
| TEST_F(ComposeEnablingTest, SignedInErrorTest) { |
| // Sign in, with error. |
| AccountInfo account_info = identity_test_env_.MakePrimaryAccountAvailable( |
| kEmail, signin::ConsentLevel::kSync); |
| identity_test_env_.UpdatePersistentErrorOfRefreshTokenForAccount( |
| account_info.account_id, |
| GoogleServiceAuthError( |
| GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); |
| |
| CheckIsEnabledError(compose_enabling_.get(), |
| compose::ComposeShowStatus::kSignedOut); |
| } |
| |
| TEST_F(ComposeEnablingTest, ComposeEligibleTest) { |
| scoped_feature_list_.Reset(); |
| // Turn on the enable switch and off the eligible switch. |
| scoped_feature_list_.InitWithFeatures({compose::features::kEnableCompose}, |
| {compose::features::kComposeEligible}); |
| // Sign in, with sync turned on. |
| SignIn(signin::ConsentLevel::kSync); |
| |
| // The ComposeEligible switch should win, and disable the feature. |
| CheckIsEnabledError(compose_enabling_.get(), |
| compose::ComposeShowStatus::kNotComposeEligible); |
| } |
| |
| TEST_F(ComposeEnablingTest, EverythingEnabledTest) { |
| // Sign in, with sync turned on. |
| SignIn(signin::ConsentLevel::kSync); |
| EXPECT_EQ(compose_enabling_->IsEnabled(), base::ok()); |
| } |
| |
| TEST_F(ComposeEnablingTest, UserNotAllowedTest) { |
| // Sign in, with sync turned on. |
| SignIn(signin::ConsentLevel::kSync); |
| // Cause per-user check to fail. |
| scoped_skip_user_check_.reset(); |
| |
| EXPECT_THAT( |
| compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kUserNotAllowedByOptimizationGuide)); |
| } |
| |
| TEST_F(ComposeEnablingTest, StaticMethodEverythingDisabledTest) { |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures({}, |
| {compose::features::kEnableCompose}); |
| // We intentionally don't call sign in to make our state not signed in. |
| EXPECT_FALSE(ComposeEnabling::IsEnabledForProfile(GetProfile())); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuDisabledTest) { |
| // We intentionally disable the feature. |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures( |
| {compose::features::kEnableComposeSavedStateNudge}, |
| {compose::features::kEnableCompose}); |
| |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), |
| /*rfh=*/GetRenderFrameHost(), context_menu_params_)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuLanguageTest) { |
| // Disable the language bypass. |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures( |
| {compose::features::kEnableCompose}, |
| {compose::features::kEnableComposeLanguageBypassForContextMenu}); |
| // Enable all base requirements. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set the mock to return a language we support (English). |
| SetLanguage("en"); |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| EXPECT_TRUE( |
| compose_enabling_->IsPageLanguageSupported(translate_manager_.get())); |
| |
| // Set the mock to return a language we don't support (Esperanto). |
| SetLanguage("eo"); |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| EXPECT_FALSE( |
| compose_enabling_->IsPageLanguageSupported(translate_manager_.get())); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuLanguageBypassTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set the mock to return a language we don't support (Esperanto). |
| SetLanguage("eo"); |
| // Although the language is unsupported, ShouldTrigger should return true as |
| // the bypass is enabled. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| EXPECT_FALSE( |
| compose_enabling_->IsPageLanguageSupported(translate_manager_.get())); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuEmptyLanguageTest) { |
| // Disable the language bypass. |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures( |
| {compose::features::kEnableCompose}, |
| {compose::features::kEnableComposeLanguageBypassForContextMenu}); |
| // Enable all base requirements. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set the mock to return the empty string, simluating that translate doesn't |
| // have the answer yet. |
| SetLanguage(""); |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| EXPECT_TRUE( |
| compose_enabling_->IsPageLanguageSupported(translate_manager_.get())); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuUndeterminedLangugeTest) { |
| // Disable the language bypass. |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeatures( |
| {compose::features::kEnableCompose}, |
| {compose::features::kEnableComposeLanguageBypassForContextMenu}); |
| // Enable all base requirements. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set the mock to return "und", simluating that translate could not determine |
| // the page language. |
| SetLanguage("und"); |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| EXPECT_TRUE( |
| compose_enabling_->IsPageLanguageSupported(translate_manager_.get())); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuFieldTypeTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set ContextMenuParams to non-contenteditable and non-textarea, which we do |
| // not support. |
| context_menu_params_.is_content_editable_for_autofill = false; |
| context_menu_params_.form_control_type = |
| blink::mojom::FormControlType::kInputButton; |
| |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuIncorrectSchemeTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Get the rfh for the tab with the incorrect Scheme. |
| auto* rfh = |
| browser()->tab_strip_model()->GetWebContentsAt(1)->GetPrimaryMainFrame(); |
| |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), rfh, context_menu_params_)); |
| } |
| |
| TEST_F(ComposeEnablingTest, |
| ShouldTriggerContextMenuAllEnabledContentEditableTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuAllEnabledTextAreaTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set ContextMenuParams to textarea, which we support. |
| context_menu_params_.is_content_editable_for_autofill = false; |
| context_menu_params_.form_control_type = |
| blink::mojom::FormControlType::kTextArea; |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupDefaultTest) { |
| // Use the default feature values set in SetUp. |
| std::string autocomplete_attribute; |
| |
| // The saved state nudge is enabled by default. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| // The proactive nudge is disabled by default. |
| EXPECT_FALSE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupDisabledTest) { |
| // We intentionally disable the feature. |
| ResetFeaturesAndConfig({}, |
| {// Disable saved state nudge. |
| compose::features::kEnableComposeSavedStateNudge}); |
| |
| std::string autocomplete_attribute; |
| |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupLanguageTests) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| |
| // Enable the feature. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // Check that a non-English page blocks the proactive nudge but not the |
| // saved state nudge. |
| SetLanguage("eo"); |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| EXPECT_FALSE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| |
| // Check that both nudges are allowed with English. |
| SetLanguage("en"); |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| EXPECT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| |
| // Check that both nudges are allowed with "und". |
| SetLanguage("und"); |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| EXPECT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldNotTriggerProactivePopupAutocompleteOffTest) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| base::HistogramTester histogram_tester; |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| // Autocomplete is set to off for this page. |
| std::string autocomplete_attribute("off"); |
| |
| // The autocomplete attribute is ignored with saved state. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| // The autocomplete attribute is checked for the proactive nudge. |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true); |
| |
| EXPECT_EQ(should_trigger.error(), |
| compose::ComposeShowStatus::kAutocompleteOff); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldNotTriggerProactivePopupIfMSBBDisabled) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| base::HistogramTester histogram_tester; |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| std::string autocomplete_attribute; |
| |
| // The proactive nudge does not show when msbb is disabled. |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled=*/false); |
| ASSERT_EQ(should_trigger.error(), |
| compose::ComposeShowStatus::kProactiveNudgeDisabledByMSBB); |
| |
| // The proactive nudge shows when msbb is enabled. |
| EXPECT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled=*/true) |
| .has_value()); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupWithSavedStateTest) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // test all variants of: popup with, popup without state. |
| std::vector<std::pair<bool, bool>> tests = { |
| {true, true}, {true, false}, {false, true}, {false, false}}; |
| for (auto [saved_state_nudge, proactive_nudge] : tests) { |
| compose::Config& config = compose::GetMutableConfigForTesting(); |
| config.saved_state_nudge_enabled = saved_state_nudge; |
| config.proactive_nudge_enabled = proactive_nudge; |
| |
| EXPECT_EQ( |
| saved_state_nudge, |
| compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| EXPECT_EQ(proactive_nudge, |
| compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| } |
| } |
| |
| TEST_F(ComposeEnablingTest, ComposeSavedStateNotificationEnabledByDefault) { |
| std::string autocomplete_attribute; |
| |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kComposeDialogLostFocus)); |
| } |
| |
| TEST_F(ComposeEnablingTest, SavedStateNotificationWithSavedStateNudgeDisabled) { |
| ResetFeaturesAndConfig({}, |
| {compose::features::kEnableComposeSavedStateNudge}); |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // Saved State Notification does not trigger if saved state nudge is disabled. |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kComposeDialogLostFocus)); |
| } |
| |
| TEST_F(ComposeEnablingTest, |
| ShouldTriggerPopupSavedStateNotificationDisabledTest) { |
| // Disable the notification flag. |
| ResetFeaturesAndConfig( |
| {compose::features::kEnableComposeProactiveNudge}, |
| {compose::features::kEnableComposeSavedStateNotification}); |
| |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // Nudge still works, even if Saved State Notification is disabled. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| // Saved state notification is disabled. |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kComposeDialogLostFocus)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupIncorrectSchemeTest) { |
| base::HistogramTester histogram_tester; |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| compose::Config& config = compose::GetMutableConfigForTesting(); |
| config.saved_state_nudge_enabled = true; |
| config.proactive_nudge_enabled = true; |
| std::string autocomplete_attribute; |
| |
| // Use URL with incorrect scheme is checked when no previous state. |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| url::Origin(), GURL(kExampleBadURL), |
| /*is_msbb_enabled*/ true); |
| ASSERT_EQ(should_trigger.error(), |
| compose::ComposeShowStatus::kIncorrectScheme); |
| |
| // Use URL with incorrect scheme is not checked when there is previous state. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerPopupCrossOrigin) { |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| compose::Config& config = compose::GetMutableConfigForTesting(); |
| config.proactive_nudge_enabled = true; |
| std::string autocomplete_attribute; |
| |
| EXPECT_FALSE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), url::Origin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerContextMenuCrossOrigin) { |
| base::HistogramTester histogram_tester; |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| context_menu_params_.frame_origin = url::Origin(); |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| |
| // Check that a response result OK metric was emitted. |
| histogram_tester.ExpectUniqueSample( |
| compose::kComposeShowStatus, |
| compose::ComposeShowStatus::kFormFieldInCrossOriginFrame, 1); |
| } |
| |
| TEST_F(ComposeEnablingTest, GetOptimizationGuidanceShowNudgeTest) { |
| // Set up a fake metadata to return from the mock. |
| optimization_guide::OptimizationMetadata test_metadata; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| compose_hint_metadata.set_decision( |
| compose::ComposeHintDecision::COMPOSE_HINT_DECISION_ENABLED); |
| test_metadata.SetAnyMetadataForTesting(compose_hint_metadata); |
| |
| EXPECT_CALL(opt_guide(), |
| CanApplyOptimization( |
| GURL(kExampleURL), |
| optimization_guide::proto::OptimizationType::COMPOSE, |
| ::testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillRepeatedly(testing::DoAll( |
| testing::SetArgPointee<2>(test_metadata), |
| testing::Return( |
| optimization_guide::OptimizationGuideDecision::kTrue))); |
| |
| GURL example(kExampleURL); |
| compose::ComposeHintDecision decision = |
| compose_enabling_->GetOptimizationGuidanceForUrl(example, GetProfile()); |
| |
| // Verify response from CanApplyOptimization is as we expect. |
| EXPECT_EQ(compose::ComposeHintDecision::COMPOSE_HINT_DECISION_ENABLED, |
| decision); |
| } |
| |
| TEST_F(ComposeEnablingTest, GetOptimizationGuidanceNoFeedbackTest) { |
| // Set up a fake metadata to return from the mock. |
| optimization_guide::OptimizationMetadata test_metadata; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| compose_hint_metadata.set_decision( |
| compose::ComposeHintDecision::COMPOSE_HINT_DECISION_ENABLED); |
| test_metadata.SetAnyMetadataForTesting(compose_hint_metadata); |
| |
| EXPECT_CALL(opt_guide(), |
| CanApplyOptimization( |
| GURL(kExampleURL), |
| optimization_guide::proto::OptimizationType::COMPOSE, |
| ::testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillRepeatedly(testing::DoAll( |
| testing::SetArgPointee<2>(test_metadata), |
| testing::Return( |
| optimization_guide::OptimizationGuideDecision::kFalse))); |
| |
| GURL example(kExampleURL); |
| compose::ComposeHintDecision decision = |
| compose_enabling_->GetOptimizationGuidanceForUrl(example, GetProfile()); |
| |
| // Verify response from CanApplyOptimization is as we expect. |
| EXPECT_EQ(compose::ComposeHintDecision::COMPOSE_HINT_DECISION_UNSPECIFIED, |
| decision); |
| } |
| |
| TEST_F(ComposeEnablingTest, GetOptimizationGuidanceNoComposeMetadataTest) { |
| // Set up a fake metadata to return from the mock. |
| optimization_guide::OptimizationMetadata test_metadata; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| test_metadata.SetAnyMetadataForTesting(compose_hint_metadata); |
| |
| EXPECT_CALL(opt_guide(), |
| CanApplyOptimization( |
| GURL(kExampleURL), |
| optimization_guide::proto::OptimizationType::COMPOSE, |
| ::testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillRepeatedly(testing::DoAll( |
| testing::SetArgPointee<2>(test_metadata), |
| testing::Return( |
| optimization_guide::OptimizationGuideDecision::kTrue))); |
| |
| GURL example(kExampleURL); |
| compose::ComposeHintDecision decision = |
| compose_enabling_->GetOptimizationGuidanceForUrl(example, GetProfile()); |
| |
| // Verify response from CanApplyOptimization is as we expect. |
| EXPECT_EQ(compose::ComposeHintDecision::COMPOSE_HINT_DECISION_UNSPECIFIED, |
| decision); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerDisableComposeByPolicyTest) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set ContextMenuParams to textarea, which we support. |
| context_menu_params_.is_content_editable_for_autofill = false; |
| context_menu_params_.form_control_type = |
| blink::mojom::FormControlType::kTextArea; |
| |
| std::string autocomplete_attribute; |
| base::HistogramTester histogram_tester; |
| |
| // Set up a fake metadata to return from the mock. |
| optimization_guide::OptimizationMetadata test_metadata; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| compose_hint_metadata.set_decision( |
| compose::ComposeHintDecision::COMPOSE_HINT_DECISION_COMPOSE_DISABLED); |
| test_metadata.SetAnyMetadataForTesting(compose_hint_metadata); |
| |
| EXPECT_CALL(opt_guide(), |
| CanApplyOptimization( |
| GURL(kExampleURL), |
| optimization_guide::proto::OptimizationType::COMPOSE, |
| ::testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillRepeatedly(testing::DoAll( |
| testing::SetArgPointee<2>(test_metadata), |
| testing::Return( |
| optimization_guide::OptimizationGuideDecision::kTrue))); |
| |
| EXPECT_FALSE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| |
| // Check that the proactive nudge is also disabled. |
| EXPECT_FALSE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| |
| // The saved state is not disabled. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| // Verify the metrics reflect the decision not to show the page. |
| histogram_tester.ExpectUniqueSample( |
| compose::kComposeShowStatus, |
| compose::ComposeShowStatus::kPerUrlChecksFailed, 1); |
| } |
| |
| TEST_F(ComposeEnablingTest, ShouldTriggerDisableNudgeByPolicy) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| |
| // Enable everything. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| |
| // Set ContextMenuParams to textarea, which we support. |
| context_menu_params_.is_content_editable_for_autofill = false; |
| context_menu_params_.form_control_type = |
| blink::mojom::FormControlType::kTextArea; |
| |
| std::string autocomplete_attribute; |
| |
| // Set up a fake metadata to return from the mock. |
| optimization_guide::OptimizationMetadata test_metadata; |
| compose::ComposeHintMetadata compose_hint_metadata; |
| compose_hint_metadata.set_decision( |
| compose::ComposeHintDecision::COMPOSE_HINT_DECISION_DISABLE_NUDGE); |
| test_metadata.SetAnyMetadataForTesting(compose_hint_metadata); |
| |
| EXPECT_CALL(opt_guide(), |
| CanApplyOptimization( |
| GURL(kExampleURL), |
| optimization_guide::proto::OptimizationType::COMPOSE, |
| ::testing::An<optimization_guide::OptimizationMetadata*>())) |
| .WillRepeatedly(testing::DoAll( |
| testing::SetArgPointee<2>(test_metadata), |
| testing::Return( |
| optimization_guide::OptimizationGuideDecision::kTrue))); |
| |
| // The context is not disabled. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerContextMenu( |
| GetProfile(), translate_manager_.get(), /*rfh=*/GetRenderFrameHost(), |
| context_menu_params_)); |
| |
| // The saved state nudge is not disabled. |
| EXPECT_TRUE(compose_enabling_->ShouldTriggerSavedStatePopup( |
| autofill::AutofillSuggestionTriggerSource::kTextFieldValueChanged)); |
| |
| // Check that the proactive nudge is disabled. |
| EXPECT_FALSE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| // Check that the proactive nudge is not disabled if override is set in the |
| // config. |
| compose::GetMutableConfigForTesting() |
| .proactive_nudge_bypass_optimization_guide = true; |
| EXPECT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| } |
| |
| TEST_F(ComposeEnablingTest, ProactiveNudgeGlobalPreferenceTest) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| base::HistogramTester histogram_tester; |
| // Enable the feature. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // Preference is enabled by default, proactive nudge should trigger. |
| EXPECT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| |
| // When preference is disabled, proactive nudge should not trigger |
| SetProactiveNudgePref(false); |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true); |
| EXPECT_EQ(should_trigger.error(), |
| compose::ComposeShowStatus:: |
| kProactiveNudgeDisabledGloballyByUserPreference); |
| } |
| |
| TEST_F(ComposeEnablingTest, ProactiveNudgeDisabledSitesPreferenceTest) { |
| ResetFeaturesAndConfig({compose::features::kEnableComposeProactiveNudge}, {}); |
| base::HistogramTester histogram_tester; |
| // Enable the feature. |
| auto scoped_compose_enabled = |
| ComposeEnabling::ScopedEnableComposeForTesting(); |
| std::string autocomplete_attribute; |
| |
| // Preference is enabled by default, proactive nudge should trigger on default |
| // origin. |
| ASSERT_TRUE(compose_enabling_ |
| ->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, |
| /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), |
| GetOrigin(), GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true) |
| .has_value()); |
| |
| // When origin is added to disabled sites list, proactive nudge should not |
| // trigger. |
| AddDomainToProactiveNudgeDisabledSitesPref(); |
| auto should_trigger = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), |
| /*is_msbb_enabled*/ true); |
| EXPECT_EQ(should_trigger.error(), |
| compose::ComposeShowStatus:: |
| kProactiveNudgeDisabledForSiteByUserPreference); |
| } |
| |
| TEST_F(ComposeEnablingTest, ClientCountryNotInFinchCountryListForCompose) { |
| // Sets a country list via Finch that does not include "us". |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitAndEnableFeatureWithParameters( |
| compose::features::kEnableCompose, {{"enabled_countries", "a, b, c"}}); |
| compose::ResetConfigForTesting(); |
| EXPECT_THAT(compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kComposeNotEnabledInCountry)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ClientCountryUndefinedForCompose) { |
| // Replace the client country override with an undefined country. |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting(""); |
| EXPECT_THAT(compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kUndefinedCountry)); |
| } |
| |
| TEST_F(ComposeEnablingTest, AnyAndAllCountriesAllowedForCompose) { |
| // Set the country list to the wildcard element. |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitAndEnableFeatureWithParameters( |
| compose::features::kEnableCompose, {{"enabled_countries", "*"}}); |
| compose::ResetConfigForTesting(); |
| |
| // If the country check passes the signed out check will fail next. |
| EXPECT_THAT(compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| |
| // Check that country other than "us" is also accepted. |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting("aa"); |
| EXPECT_THAT(compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting(""); |
| EXPECT_THAT(compose_enabling_->IsEnabled(), |
| ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| } |
| |
| TEST_F(ComposeEnablingTest, |
| ClientCountryNotInFinchCountryListForProactiveNudge) { |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeaturesAndParameters( |
| {{compose::features::kEnableComposeProactiveNudge, |
| // Sets a country list for the proactive nudge that does not include |
| // "us". |
| {{"proactive_nudge_countries", "a, b, c"}}}, |
| {compose::features::kEnableCompose, {{"enabled_countries", "*"}}}}, |
| {}); |
| compose::ResetConfigForTesting(); |
| |
| std::string autocomplete_attribute; |
| auto no_state_status = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| EXPECT_THAT(no_state_status, |
| ErrorIs(compose::ComposeShowStatus::kComposeNotEnabledInCountry)); |
| } |
| |
| TEST_F(ComposeEnablingTest, ClientCountryUndefinedForProactiveNudge) { |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitAndEnableFeatureWithParameters( |
| compose::features::kEnableCompose, {{"enabled_countries", "*"}}); |
| compose::ResetConfigForTesting(); |
| |
| // Replace the client country override with an undefined country. |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting(""); |
| |
| std::string autocomplete_attribute; |
| auto no_state_status = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| EXPECT_THAT(no_state_status, |
| ErrorIs(compose::ComposeShowStatus::kUndefinedCountry)); |
| } |
| |
| TEST_F(ComposeEnablingTest, AnyAndAllCountriesAllowedForProactiveNudge) { |
| scoped_feature_list_.Reset(); |
| scoped_feature_list_.InitWithFeaturesAndParameters( |
| {{compose::features::kEnableComposeProactiveNudge, |
| // Set both client country lists to the wildcard element. |
| {{"proactive_nudge_countries", "*"}}}, |
| {compose::features::kEnableCompose, {{"enabled_countries", "*"}}}}, |
| {}); |
| compose::ResetConfigForTesting(); |
| |
| std::string autocomplete_attribute; |
| auto no_state_status = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| // If the country check passes the signed out check will fail next. |
| EXPECT_THAT(no_state_status, ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| |
| // Check that country other than "us" is also accepted. |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting("aa"); |
| |
| no_state_status = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| EXPECT_THAT(no_state_status, ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| |
| // Replace the client country override with an undefined country. |
| scoped_country_override_.reset(); |
| scoped_country_override_ = ComposeEnabling::OverrideCountryForTesting(""); |
| |
| no_state_status = compose_enabling_->ShouldTriggerNoStatePopup( |
| autocomplete_attribute, /*allows_writing_suggestions=*/true, GetProfile(), |
| GetProfile()->GetPrefs(), translate_manager_.get(), GetOrigin(), |
| GetOrigin(), GURL(kExampleURL), /*is_msbb_enabled*/ true); |
| EXPECT_THAT(no_state_status, ErrorIs(compose::ComposeShowStatus::kSignedOut)); |
| } |