assistant_overlay_unittest.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/shelf/assistant_overlay.h"
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "ash/constants/ash_pref_names.h"
  9. #include "ash/constants/ash_switches.h"
  10. #include "ash/public/cpp/assistant/assistant_state.h"
  11. #include "ash/public/cpp/shelf_config.h"
  12. #include "ash/session/session_controller_impl.h"
  13. #include "ash/shelf/home_button.h"
  14. #include "ash/shelf/shelf_navigation_widget.h"
  15. #include "ash/shelf/shelf_view.h"
  16. #include "ash/shelf/shelf_view_test_api.h"
  17. #include "ash/shelf/shelf_widget.h"
  18. #include "ash/shell.h"
  19. #include "ash/test/ash_test_base.h"
  20. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  21. #include "base/command_line.h"
  22. #include "base/memory/ptr_util.h"
  23. #include "base/test/scoped_feature_list.h"
  24. #include "base/test/task_environment.h"
  25. #include "base/time/time.h"
  26. #include "chromeos/ash/services/assistant/public/cpp/assistant_enums.h"
  27. #include "testing/gmock/include/gmock/gmock-matchers.h"
  28. #include "testing/gmock/include/gmock/gmock.h"
  29. #include "testing/gtest/include/gtest/gtest-param-test.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. #include "ui/compositor/layer.h"
  32. #include "ui/events/event.h"
  33. #include "ui/events/event_constants.h"
  34. #include "ui/events/gesture_event_details.h"
  35. #include "ui/events/types/event_type.h"
  36. #include "ui/gfx/geometry/point_conversions.h"
  37. #include "ui/gfx/geometry/rect.h"
  38. #include "ui/views/view.h"
  39. #include "ui/wm/core/window_util.h"
  40. namespace ash {
  41. namespace {
  42. constexpr base::TimeDelta kAssistantAnimationDelay = base::Milliseconds(200);
  43. constexpr char kAssistantOverlayClassName[] = "AssistantOverlay";
  44. enum TestVariant { kClamshell, kTablet, kTabletWithBackButton };
  45. class AssistantOverlayTest : public AshTestBase,
  46. public testing::WithParamInterface<TestVariant> {
  47. public:
  48. AssistantOverlayTest()
  49. : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
  50. void SetUp() override {
  51. // In Tablet mode, home button is shown if a board has kAshEnableTabletMode
  52. // and kAccessibilityTabletModeShelfNavigationButtonsEnabled is true.
  53. base::CommandLine::ForCurrentProcess()->AppendSwitch(
  54. switches::kAshEnableTabletMode);
  55. AshTestBase::SetUp();
  56. // Enable Assistant
  57. Shell::Get()->session_controller()->GetPrimaryUserPrefService()->SetBoolean(
  58. assistant::prefs::kAssistantEnabled, true);
  59. AssistantState* assistant_state = AssistantState::Get();
  60. assistant_state->NotifyFeatureAllowed(
  61. assistant::AssistantAllowedState::ALLOWED);
  62. assistant_state->NotifyStatusChanged(assistant::AssistantStatus::READY);
  63. const TestVariant test_variant = GetParam();
  64. switch (test_variant) {
  65. case kClamshell:
  66. ASSERT_FALSE(Shell::Get()->IsInTabletMode());
  67. break;
  68. case kTablet:
  69. Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
  70. prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled, true);
  71. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  72. ASSERT_FALSE(ShelfConfig::Get()->is_in_app());
  73. break;
  74. case kTabletWithBackButton:
  75. Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
  76. prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled, true);
  77. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  78. // A back button is shown if there is an active window.
  79. CreateTestWindow();
  80. ActivateTestWindow();
  81. ASSERT_TRUE(ShelfConfig::Get()->is_in_app());
  82. break;
  83. }
  84. }
  85. void TearDown() override {
  86. window_.reset();
  87. AshTestBase::TearDown();
  88. }
  89. protected:
  90. const views::View* GetAssistantOverlay() {
  91. for (const views::View* child : home_button()->children()) {
  92. if (std::string(child->GetClassName()) == kAssistantOverlayClassName) {
  93. return child;
  94. }
  95. }
  96. return nullptr;
  97. }
  98. HomeButton* home_button() {
  99. return GetPrimaryShelf()
  100. ->shelf_widget()
  101. ->navigation_widget()
  102. ->GetHomeButton();
  103. }
  104. std::vector<gfx::Rect> TakeClipRectSnapshot(const ui::Layer* layer) {
  105. std::vector<gfx::Rect> clip_rects;
  106. while (layer) {
  107. clip_rects.push_back(layer->clip_rect());
  108. layer = layer->parent();
  109. }
  110. return clip_rects;
  111. }
  112. void SendGestureEventToHomeButton(ui::EventType type) {
  113. ui::GestureEvent event(0, 0, ui::EF_NONE, base::TimeTicks(),
  114. ui::GestureEventDetails(type));
  115. home_button()->OnGestureEvent(&event);
  116. }
  117. void ActivateTestWindow() { wm::ActivateWindow(window_.get()); }
  118. private:
  119. void CreateTestWindow() {
  120. window_ = AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
  121. }
  122. std::unique_ptr<aura::Window> window_;
  123. };
  124. INSTANTIATE_TEST_SUITE_P(All,
  125. AssistantOverlayTest,
  126. testing::Values(TestVariant::kClamshell,
  127. TestVariant::kTablet,
  128. TestVariant::kTabletWithBackButton));
  129. // AssistantOverlay renders burst animation which goes outside of its view size.
  130. // Make sure that it's not clipped by an ancestor layer.
  131. //
  132. // For long press, events and expectations are follows:
  133. // - ET_GESTURE_TAP_DOWN: Ripple animation starts
  134. // - ET_GESTURE_LONG_PRESS: Burst animation starts (clip rect will be restored
  135. // after the animation)
  136. // - ET_GESTURE_TAP_CANCEL: Nothing should happen
  137. // - ET_GESTURE_LONG_TAP: Nothing should happen
  138. TEST_P(AssistantOverlayTest, BurstAnimationWithLongPress) {
  139. const views::View* assistant_overlay = GetAssistantOverlay();
  140. ASSERT_THAT(assistant_overlay, testing::NotNull());
  141. const ui::Layer* assistant_overlay_layer = assistant_overlay->layer();
  142. std::vector<gfx::Rect> clip_rect_snapshot_before =
  143. TakeClipRectSnapshot(assistant_overlay_layer);
  144. SendGestureEventToHomeButton(ui::ET_GESTURE_TAP_DOWN);
  145. // HomeButtonController delays assistant animation for
  146. // kAssistantAnimationDelay.
  147. task_environment()->FastForwardBy(kAssistantAnimationDelay);
  148. // Confirm that no clip rect is set in ancestor layers.
  149. std::vector<gfx::Rect> clip_rects_during_animation =
  150. TakeClipRectSnapshot(assistant_overlay_layer);
  151. for (const gfx::Rect& clip_rect : clip_rects_during_animation) {
  152. EXPECT_TRUE(clip_rect.IsEmpty());
  153. }
  154. // AssistantOverlay starts burst animation with ET_GESTURE_LONG_PRESS.
  155. SendGestureEventToHomeButton(ui::ET_GESTURE_LONG_PRESS);
  156. // Burst animation ends immediately in this test case. Confirm that clip rect
  157. // is restored now.
  158. EXPECT_EQ(TakeClipRectSnapshot(assistant_overlay_layer),
  159. clip_rect_snapshot_before);
  160. SendGestureEventToHomeButton(ui::ET_GESTURE_TAP_CANCEL);
  161. SendGestureEventToHomeButton(ui::ET_GESTURE_LONG_TAP);
  162. // Confirm that nothing should happen with the following TAP_CANCEL and
  163. // LONG_TAP events.
  164. EXPECT_EQ(TakeClipRectSnapshot(assistant_overlay_layer),
  165. clip_rect_snapshot_before);
  166. }
  167. // AssistantOverlay renders a ripple animation with a tap, which goes beyond the
  168. // size of home button.
  169. TEST_P(AssistantOverlayTest, RippleAnimationWithTap) {
  170. const views::View* assistant_overlay = GetAssistantOverlay();
  171. ASSERT_THAT(assistant_overlay, testing::NotNull());
  172. const ui::Layer* assistant_overlay_layer = assistant_overlay->layer();
  173. std::vector<gfx::Rect> clip_rect_snapshot_before =
  174. TakeClipRectSnapshot(assistant_overlay_layer);
  175. SendGestureEventToHomeButton(ui::ET_GESTURE_TAP_DOWN);
  176. // HomeButtonController delays assistant animation for
  177. // kAssistantAnimationDelay.
  178. task_environment()->FastForwardBy(kAssistantAnimationDelay);
  179. // Confirm that no clip rect is set in ancestor layers.
  180. std::vector<gfx::Rect> clip_rects_during_animation =
  181. TakeClipRectSnapshot(assistant_overlay_layer);
  182. for (const gfx::Rect& clip_rect : clip_rects_during_animation) {
  183. EXPECT_TRUE(clip_rect.IsEmpty());
  184. }
  185. SendGestureEventToHomeButton(ui::ET_GESTURE_TAP);
  186. // The above tap will de-activate test window and hides back button.
  187. // Re-activate the window to show a back button. Clip rect can be different if
  188. // no back button is shown.
  189. if (GetParam() == kTabletWithBackButton)
  190. ActivateTestWindow();
  191. EXPECT_EQ(TakeClipRectSnapshot(assistant_overlay_layer),
  192. clip_rect_snapshot_before);
  193. }
  194. } // namespace
  195. } // namespace ash