123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // Copyright 2020 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.
- #include "ash/assistant/assistant_controller_impl.h"
- #include <map>
- #include <memory>
- #include <string>
- #include "ash/assistant/test/assistant_ash_test_base.h"
- #include "ash/assistant/test/test_assistant_service.h"
- #include "ash/assistant/util/deep_link_util.h"
- #include "ash/constants/ash_features.h"
- #include "ash/constants/ash_pref_names.h"
- #include "ash/public/cpp/assistant/controller/assistant_controller_observer.h"
- #include "ash/public/cpp/test/test_new_window_delegate.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "ash/style/dark_light_mode_controller_impl.h"
- #include "base/scoped_observation.h"
- #include "base/test/scoped_feature_list.h"
- #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h"
- #include "chromeos/constants/chromeos_features.h"
- #include "testing/gmock/include/gmock/gmock.h"
- namespace ash {
- namespace {
- // MockAssistantControllerObserver ---------------------------------------------
- class MockAssistantControllerObserver : public AssistantControllerObserver {
- public:
- MockAssistantControllerObserver() = default;
- ~MockAssistantControllerObserver() override = default;
- // AssistantControllerObserver:
- MOCK_METHOD(void, OnAssistantControllerConstructed, (), (override));
- MOCK_METHOD(void, OnAssistantControllerDestroying, (), (override));
- MOCK_METHOD(void, OnAssistantReady, (), (override));
- MOCK_METHOD(void,
- OnDeepLinkReceived,
- (assistant::util::DeepLinkType type,
- (const std::map<std::string, std::string>& params)),
- (override));
- MOCK_METHOD(void,
- OnOpeningUrl,
- (const GURL& url, bool in_background, bool from_server),
- (override));
- MOCK_METHOD(void,
- OnUrlOpened,
- (const GURL& url, bool from_server),
- (override));
- };
- class MockAssistantUiModelObserver : public AssistantUiModelObserver {
- public:
- MockAssistantUiModelObserver() = default;
- ~MockAssistantUiModelObserver() override = default;
- MOCK_METHOD(void,
- OnUiVisibilityChanged,
- (AssistantVisibility new_visibility,
- AssistantVisibility old_visibility,
- absl::optional<AssistantEntryPoint> entry_point,
- absl::optional<AssistantExitPoint> exit_point),
- (override));
- };
- // MockNewWindowDelegate -------------------------------------------------------
- class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> {
- public:
- // TestNewWindowDelegate:
- MOCK_METHOD(void,
- OpenUrl,
- (const GURL& url, OpenUrlFrom from, Disposition disposition),
- (override));
- MOCK_METHOD(void,
- OpenFeedbackPage,
- (NewWindowDelegate::FeedbackSource source,
- const std::string& description_template),
- (override));
- };
- // AssistantControllerImplTest -------------------------------------------------
- class AssistantControllerImplTest : public AssistantAshTestBase {
- public:
- AssistantControllerImplTest() {
- auto delegate = std::make_unique<MockNewWindowDelegate>();
- new_window_delegate_ = delegate.get();
- delegate_provider_ =
- std::make_unique<TestNewWindowDelegateProvider>(std::move(delegate));
- }
- AssistantController* controller() { return AssistantController::Get(); }
- MockNewWindowDelegate& new_window_delegate() { return *new_window_delegate_; }
- const AssistantUiModel* ui_model() {
- return AssistantUiController::Get()->GetModel();
- }
- TestAssistantService* test_assistant_service() {
- return &test_assistant_service_;
- }
- private:
- MockNewWindowDelegate* new_window_delegate_;
- std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_;
- // AssistantService must outlive AssistantController as destructor can
- // reference AssistantService.
- TestAssistantService test_assistant_service_;
- };
- } // namespace
- // Tests -----------------------------------------------------------------------
- // Tests that AssistantController observers are notified of deep link received.
- TEST_F(AssistantControllerImplTest, NotifiesDeepLinkReceived) {
- testing::NiceMock<MockAssistantControllerObserver> controller_observer_mock;
- base::ScopedObservation<AssistantController, AssistantControllerObserver>
- scoped_controller_obs{&controller_observer_mock};
- scoped_controller_obs.Observe(controller());
- EXPECT_CALL(controller_observer_mock, OnDeepLinkReceived)
- .WillOnce(
- testing::Invoke([](assistant::util::DeepLinkType type,
- const std::map<std::string, std::string>& params) {
- EXPECT_EQ(assistant::util::DeepLinkType::kQuery, type);
- EXPECT_EQ("weather",
- assistant::util::GetDeepLinkParam(
- params, assistant::util::DeepLinkParam::kQuery)
- .value());
- }));
- controller()->OpenUrl(
- assistant::util::CreateAssistantQueryDeepLink("weather"));
- }
- // Tests that AssistantController observers are notified of URLs opening and
- // having been opened. Note that it is important that these events be notified
- // before and after the URL is actually opened respectively.
- TEST_F(AssistantControllerImplTest, NotifiesOpeningUrlAndUrlOpened) {
- testing::NiceMock<MockAssistantControllerObserver> controller_observer_mock;
- base::ScopedObservation<AssistantController, AssistantControllerObserver>
- scoped_controller_obs{&controller_observer_mock};
- scoped_controller_obs.Observe(controller());
- // Enforce ordering of events.
- testing::InSequence sequence;
- EXPECT_CALL(controller_observer_mock, OnOpeningUrl)
- .WillOnce(testing::Invoke(
- [](const GURL& url, bool in_background, bool from_server) {
- EXPECT_EQ(GURL("https://g.co/"), url);
- EXPECT_TRUE(in_background);
- EXPECT_TRUE(from_server);
- }));
- EXPECT_CALL(new_window_delegate(),
- OpenUrl(GURL("https://g.co/"),
- NewWindowDelegate::OpenUrlFrom::kUserInteraction,
- NewWindowDelegate::Disposition::kNewForegroundTab));
- EXPECT_CALL(controller_observer_mock, OnUrlOpened)
- .WillOnce(testing::Invoke([](const GURL& url, bool from_server) {
- EXPECT_EQ(GURL("https://g.co/"), url);
- EXPECT_TRUE(from_server);
- }));
- controller()->OpenUrl(GURL("https://g.co/"), /*in_background=*/true,
- /*from_server=*/true);
- }
- TEST_F(AssistantControllerImplTest, NotOpenUrlIfAssistantNotReady) {
- testing::NiceMock<MockAssistantControllerObserver> controller_observer_mock;
- base::ScopedObservation<AssistantController, AssistantControllerObserver>
- scoped_controller_obs{&controller_observer_mock};
- scoped_controller_obs.Observe(controller());
- EXPECT_CALL(controller_observer_mock, OnOpeningUrl).Times(0);
- controller()->SetAssistant(nullptr);
- controller()->OpenUrl(GURL("https://g.co/"), /*in_background=*/true,
- /*from_server=*/true);
- }
- TEST_F(AssistantControllerImplTest, OpensFeedbackPageForFeedbackDeeplink) {
- testing::NiceMock<MockAssistantControllerObserver> controller_observer_mock;
- base::ScopedObservation<AssistantController, AssistantControllerObserver>
- scoped_controller_obs{&controller_observer_mock};
- scoped_controller_obs.Observe(controller());
- EXPECT_CALL(controller_observer_mock, OnDeepLinkReceived)
- .WillOnce(
- testing::Invoke([](assistant::util::DeepLinkType type,
- const std::map<std::string, std::string>& params) {
- EXPECT_EQ(assistant::util::DeepLinkType::kFeedback, type);
- std::map<std::string, std::string> expected_params;
- EXPECT_EQ(params, expected_params);
- }));
- EXPECT_CALL(new_window_delegate(), OpenFeedbackPage)
- .WillOnce([](NewWindowDelegate::FeedbackSource source,
- const std::string& description_template) {
- EXPECT_EQ(NewWindowDelegate::FeedbackSource::kFeedbackSourceAssistant,
- source);
- EXPECT_EQ(std::string(), description_template);
- });
- controller()->OpenUrl(GURL("googleassistant://send-feedback"),
- /*in_background=*/false, /*from_server=*/true);
- }
- TEST_F(AssistantControllerImplTest, ClosesAssistantUiForFeedbackDeeplink) {
- ShowAssistantUi();
- testing::NiceMock<MockAssistantUiModelObserver> ui_model_observer_mock;
- ui_model()->AddObserver(&ui_model_observer_mock);
- testing::InSequence sequence;
- EXPECT_CALL(ui_model_observer_mock, OnUiVisibilityChanged)
- .WillOnce([](AssistantVisibility new_visibility,
- AssistantVisibility old_visibility,
- absl::optional<AssistantEntryPoint> entry_point,
- absl::optional<AssistantExitPoint> exit_point) {
- EXPECT_EQ(old_visibility, AssistantVisibility::kVisible);
- EXPECT_EQ(new_visibility, AssistantVisibility::kClosing);
- EXPECT_FALSE(entry_point.has_value());
- EXPECT_EQ(exit_point.value(), AssistantExitPoint::kUnspecified);
- });
- EXPECT_CALL(ui_model_observer_mock, OnUiVisibilityChanged)
- .WillOnce([](AssistantVisibility new_visibility,
- AssistantVisibility old_visibility,
- absl::optional<AssistantEntryPoint> entry_point,
- absl::optional<AssistantExitPoint> exit_point) {
- EXPECT_EQ(old_visibility, AssistantVisibility::kClosing);
- EXPECT_EQ(new_visibility, AssistantVisibility::kClosed);
- EXPECT_FALSE(entry_point.has_value());
- EXPECT_EQ(exit_point.value(), AssistantExitPoint::kUnspecified);
- });
- controller()->OpenUrl(GURL("googleassistant://send-feedback"),
- /*in_background=*/false, /*from_server=*/true);
- ui_model()->RemoveObserver(&ui_model_observer_mock);
- }
- // Make sure that AssistantControllerImpl sets dark mode = false even if the
- // flag is off. SettingsController won't set options if dark mode bit is not
- // set.
- TEST_F(AssistantControllerImplTest, ColorModeIsSetWhenAssistantIsReadyFlagOff) {
- // ProductivityLauncher uses DarkLightMode colors.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatures(
- /*enabled_features=*/{}, /*disabled_features=*/{
- chromeos::features::kDarkLightMode, features::kNotificationsRefresh,
- features::kProductivityLauncher});
- controller()->SetAssistant(test_assistant_service());
- ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value());
- EXPECT_FALSE(test_assistant_service()->dark_mode_enabled().value());
- }
- TEST_F(AssistantControllerImplTest, ColorModeIsUpdated) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(chromeos::features::kDarkLightMode);
- ASSERT_TRUE(chromeos::features::IsDarkLightModeEnabled());
- auto* active_user_pref_service =
- Shell::Get()->session_controller()->GetPrimaryUserPrefService();
- ASSERT_TRUE(active_user_pref_service);
- auto* dark_light_mode_controller = DarkLightModeControllerImpl::Get();
- dark_light_mode_controller->OnActiveUserPrefServiceChanged(
- active_user_pref_service);
- controller()->SetAssistant(test_assistant_service());
- const bool initial_dark_mode_status =
- dark_light_mode_controller->IsDarkModeEnabled();
- ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value());
- EXPECT_EQ(initial_dark_mode_status,
- test_assistant_service()->dark_mode_enabled().value());
- // Switch the color mode.
- dark_light_mode_controller->ToggleColorMode();
- ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value());
- EXPECT_NE(initial_dark_mode_status,
- test_assistant_service()->dark_mode_enabled().value());
- }
- } // namespace ash
|