help_bubble_view_unittest.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright 2020 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 "components/user_education/views/help_bubble_view.h"
  5. #include <memory>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/callback_forward.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/test/mock_callback.h"
  12. #include "components/user_education/common/feature_promo_specification.h"
  13. #include "components/user_education/common/help_bubble_params.h"
  14. #include "components/user_education/views/help_bubble_delegate.h"
  15. #include "components/user_education/views/help_bubble_factory_views.h"
  16. #include "testing/gmock/include/gmock/gmock.h"
  17. #include "ui/base/accelerators/accelerator.h"
  18. #include "ui/base/interaction/element_tracker.h"
  19. #include "ui/base/interaction/expect_call_in_scope.h"
  20. #include "ui/base/interaction/interaction_test_util.h"
  21. #include "ui/base/theme_provider.h"
  22. #include "ui/views/interaction/interaction_test_util_views.h"
  23. #include "ui/views/test/views_test_base.h"
  24. #include "ui/views/widget/widget.h"
  25. #include "ui/views/widget/widget_observer.h"
  26. namespace user_education {
  27. namespace {
  28. // Fake delegate implementation that does not depend on the browser.
  29. class TestDelegate : public HelpBubbleDelegate {
  30. public:
  31. TestDelegate() = default;
  32. ~TestDelegate() override = default;
  33. std::vector<ui::Accelerator> GetPaneNavigationAccelerators(
  34. ui::TrackedElement* anchor_element) const override {
  35. return std::vector<ui::Accelerator>();
  36. }
  37. // These methods return text contexts that will be handled by the app's
  38. // typography system.
  39. int GetTitleTextContext() const override { return 0; }
  40. int GetBodyTextContext() const override { return 0; }
  41. int GetButtonTextContext() const override { return 0; }
  42. // These methods return color codes that will be handled by the app's theming
  43. // system.
  44. ui::ColorId GetHelpBubbleBackgroundColorId() const override { return 0; }
  45. ui::ColorId GetHelpBubbleForegroundColorId() const override { return 0; }
  46. ui::ColorId GetHelpBubbleDefaultButtonBackgroundColorId() const override {
  47. return 0;
  48. }
  49. ui::ColorId GetHelpBubbleDefaultButtonForegroundColorId() const override {
  50. return 0;
  51. }
  52. ui::ColorId GetHelpBubbleButtonBorderColorId() const override { return 0; }
  53. ui::ColorId GetHelpBubbleCloseButtonInkDropColorId() const override {
  54. return 0;
  55. }
  56. };
  57. // Fake theme provider. There's a similar TestThemeProvider in chrome/test but
  58. // we're avoiding using chrome-specific code here.
  59. class TestThemeProvider : public ui::ThemeProvider {
  60. public:
  61. TestThemeProvider() = default;
  62. ~TestThemeProvider() override = default;
  63. gfx::ImageSkia* GetImageSkiaNamed(int id) const override { return nullptr; }
  64. color_utils::HSL GetTint(int id) const override { return color_utils::HSL(); }
  65. int GetDisplayProperty(int id) const override { return 0; }
  66. bool ShouldUseNativeFrame() const override { return false; }
  67. bool HasCustomImage(int id) const override { return false; }
  68. base::RefCountedMemory* GetRawData(
  69. int id,
  70. ui::ResourceScaleFactor scale_factor) const override {
  71. return nullptr;
  72. }
  73. };
  74. // A top-level widget that reports a dummy theme provider.
  75. class TestThemedWidget : public views::Widget {
  76. public:
  77. const ui::ThemeProvider* GetThemeProvider() const override {
  78. return &test_theme_provider_;
  79. }
  80. private:
  81. TestThemeProvider test_theme_provider_;
  82. };
  83. } // namespace
  84. // Unit tests for HelpBubbleView. Timeout functionality isn't tested here due to
  85. // the vagaries of trying to get simulated timed events to run without a full
  86. // execution environment (specifically, Mac tests were extremely flaky without
  87. // the browser).
  88. //
  89. // Timeouts are tested in:
  90. // chrome/browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc
  91. class HelpBubbleViewTest : public views::ViewsTestBase {
  92. public:
  93. HelpBubbleViewTest() = default;
  94. ~HelpBubbleViewTest() override = default;
  95. void SetUp() override {
  96. ViewsTestBase::SetUp();
  97. widget_ = std::make_unique<TestThemedWidget>();
  98. widget_->Init(CreateParamsForTestWidget());
  99. view_ = widget_->SetContentsView(std::make_unique<views::View>());
  100. widget_->Show();
  101. }
  102. void TearDown() override {
  103. widget_.reset();
  104. ViewsTestBase::TearDown();
  105. }
  106. protected:
  107. HelpBubbleView* CreateHelpBubbleView(HelpBubbleParams params) {
  108. return new HelpBubbleView(&test_delegate_, view_, std::move(params));
  109. }
  110. HelpBubbleView* CreateHelpBubbleView(base::RepeatingClosure button_callback) {
  111. HelpBubbleParams params;
  112. params.body_text = u"To X, do Y";
  113. params.arrow = HelpBubbleArrow::kTopRight;
  114. if (button_callback) {
  115. HelpBubbleButtonParams button_params;
  116. button_params.text = u"Go away";
  117. button_params.is_default = true;
  118. button_params.callback = std::move(button_callback);
  119. params.buttons.push_back(std::move(button_params));
  120. }
  121. return CreateHelpBubbleView(std::move(params));
  122. }
  123. TestDelegate test_delegate_;
  124. base::raw_ptr<views::View> view_;
  125. std::unique_ptr<views::Widget> widget_;
  126. };
  127. TEST_F(HelpBubbleViewTest, CallButtonCallback_Mouse) {
  128. UNCALLED_MOCK_CALLBACK(base::RepeatingClosure, mock_callback);
  129. HelpBubbleView* const bubble = CreateHelpBubbleView(mock_callback.Get());
  130. // Simulate clicks on dismiss button.
  131. EXPECT_CALL_IN_SCOPE(
  132. mock_callback, Run,
  133. views::test::InteractionTestUtilSimulatorViews::PressButton(
  134. bubble->GetDefaultButtonForTesting(),
  135. ui::test::InteractionTestUtil::InputType::kMouse));
  136. bubble->GetWidget()->Close();
  137. }
  138. TEST_F(HelpBubbleViewTest, CallButtonCallback_Keyboard) {
  139. UNCALLED_MOCK_CALLBACK(base::RepeatingClosure, mock_callback);
  140. HelpBubbleView* const bubble = CreateHelpBubbleView(mock_callback.Get());
  141. // Simulate clicks on dismiss button.
  142. EXPECT_CALL_IN_SCOPE(
  143. mock_callback, Run,
  144. views::test::InteractionTestUtilSimulatorViews::PressButton(
  145. bubble->GetDefaultButtonForTesting(),
  146. ui::test::InteractionTestUtil::InputType::kKeyboard));
  147. bubble->GetWidget()->Close();
  148. }
  149. TEST_F(HelpBubbleViewTest, StableButtonOrder) {
  150. HelpBubbleParams params;
  151. params.body_text = u"To X, do Y";
  152. params.arrow = HelpBubbleArrow::kTopRight;
  153. constexpr char16_t kButton1Text[] = u"button 1";
  154. constexpr char16_t kButton2Text[] = u"button 2";
  155. constexpr char16_t kButton3Text[] = u"button 3";
  156. HelpBubbleButtonParams button1;
  157. button1.text = kButton1Text;
  158. button1.is_default = false;
  159. params.buttons.push_back(std::move(button1));
  160. HelpBubbleButtonParams button2;
  161. button2.text = kButton2Text;
  162. button2.is_default = true;
  163. params.buttons.push_back(std::move(button2));
  164. HelpBubbleButtonParams button3;
  165. button3.text = kButton3Text;
  166. button3.is_default = false;
  167. params.buttons.push_back(std::move(button3));
  168. auto* bubble = new HelpBubbleView(&test_delegate_, view_, std::move(params));
  169. EXPECT_EQ(kButton1Text, bubble->GetNonDefaultButtonForTesting(0)->GetText());
  170. EXPECT_EQ(kButton2Text, bubble->GetDefaultButtonForTesting()->GetText());
  171. EXPECT_EQ(kButton3Text, bubble->GetNonDefaultButtonForTesting(1)->GetText());
  172. }
  173. } // namespace user_education