1 // Copyright 2014 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
5 #include "chrome/browser/chromeos/input_method/ui/candidate_view.h"
6
7 #include <stddef.h>
8
9 #include "base/check.h"
10 #include "base/stl_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/aura/window.h"
13 #include "ui/events/test/event_generator.h"
14 #include "ui/gfx/geometry/insets.h"
15 #include "ui/views/controls/button/button.h"
16 #include "ui/views/layout/box_layout.h"
17 #include "ui/views/layout/fill_layout.h"
18 #include "ui/views/test/views_test_base.h"
19 #include "ui/views/widget/widget_delegate.h"
20
21 namespace ui {
22 namespace ime {
23 namespace {
24
25 const char* const kDummyCandidates[] = {
26 "candidate1",
27 "candidate2",
28 "candidate3",
29 };
30
31 } // namespace
32
33 class CandidateViewTest : public views::ViewsTestBase {
34 public:
35 CandidateViewTest() = default;
36 ~CandidateViewTest() override = default;
37
SetUp()38 void SetUp() override {
39 views::ViewsTestBase::SetUp();
40
41 views::Widget::InitParams init_params(
42 CreateParams(views::Widget::InitParams::TYPE_WINDOW));
43
44 init_params.delegate = new views::WidgetDelegateView();
45
46 container_ = init_params.delegate->GetContentsView();
47 container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
48 views::BoxLayout::Orientation::kVertical));
49 for (size_t i = 0; i < base::size(kDummyCandidates); ++i) {
50 CandidateView* candidate = new CandidateView(
51 views::Button::PressedCallback(), ui::CandidateWindow::VERTICAL);
52 ui::CandidateWindow::Entry entry;
53 entry.value = base::UTF8ToUTF16(kDummyCandidates[i]);
54 candidate->SetEntry(entry);
55 container_->AddChildView(candidate);
56 }
57
58 widget_ = new views::Widget();
59 widget_->Init(std::move(init_params));
60 widget_->Show();
61
62 aura::Window* native_window = widget_->GetNativeWindow();
63 event_generator_ = std::make_unique<ui::test::EventGenerator>(
64 native_window->GetRootWindow(), native_window);
65 }
66
TearDown()67 void TearDown() override {
68 widget_->Close();
69
70 views::ViewsTestBase::TearDown();
71 }
72
73 protected:
GetCandidateAt(size_t index)74 CandidateView* GetCandidateAt(size_t index) {
75 return static_cast<CandidateView*>(container_->children()[index]);
76 }
77
GetHighlightedCount() const78 size_t GetHighlightedCount() const {
79 const auto& children = container_->children();
80 return std::count_if(
81 children.cbegin(), children.cend(),
82 [](const views::View* v) { return !!v->background(); });
83 }
84
GetHighlightedIndex() const85 int GetHighlightedIndex() const {
86 const auto& children = container_->children();
87 const auto it =
88 std::find_if(children.cbegin(), children.cend(),
89 [](const views::View* v) { return !!v->background(); });
90 return (it == children.cend()) ? -1 : std::distance(children.cbegin(), it);
91 }
92
event_generator()93 ui::test::EventGenerator* event_generator() { return event_generator_.get(); }
94
95 private:
96 views::Widget* widget_ = nullptr;
97 views::View* container_ = nullptr;
98 std::unique_ptr<ui::test::EventGenerator> event_generator_;
99
100 DISALLOW_COPY_AND_ASSIGN(CandidateViewTest);
101 };
102
TEST_F(CandidateViewTest,MouseHovers)103 TEST_F(CandidateViewTest, MouseHovers) {
104 GetCandidateAt(0)->SetHighlighted(true);
105
106 EXPECT_EQ(1u, GetHighlightedCount());
107 EXPECT_EQ(0, GetHighlightedIndex());
108
109 // Mouse hover shouldn't change the background.
110 event_generator()->MoveMouseTo(
111 GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
112 EXPECT_EQ(1u, GetHighlightedCount());
113 EXPECT_EQ(0, GetHighlightedIndex());
114
115 // Mouse hover shouldn't change the background.
116 event_generator()->MoveMouseTo(
117 GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
118 EXPECT_EQ(1u, GetHighlightedCount());
119 EXPECT_EQ(0, GetHighlightedIndex());
120
121 // Mouse hover shouldn't change the background.
122 event_generator()->MoveMouseTo(
123 GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
124 EXPECT_EQ(1u, GetHighlightedCount());
125 EXPECT_EQ(0, GetHighlightedIndex());
126 }
127
TEST_F(CandidateViewTest,MouseClick)128 TEST_F(CandidateViewTest, MouseClick) {
129 bool clicked = false;
130 CandidateView* view = GetCandidateAt(1);
131 view->SetCallback(
132 base::BindRepeating([](bool* clicked) { *clicked = true; }, &clicked));
133 event_generator()->MoveMouseTo(view->GetBoundsInScreen().CenterPoint());
134 event_generator()->ClickLeftButton();
135 EXPECT_TRUE(clicked);
136 }
137
TEST_F(CandidateViewTest,ClickAndMove)138 TEST_F(CandidateViewTest, ClickAndMove) {
139 GetCandidateAt(0)->SetHighlighted(true);
140
141 EXPECT_EQ(1u, GetHighlightedCount());
142 EXPECT_EQ(0, GetHighlightedIndex());
143
144 bool clicked = false;
145 CandidateView* view = GetCandidateAt(1);
146 view->SetCallback(
147 base::BindRepeating([](bool* clicked) { *clicked = true; }, &clicked));
148 event_generator()->MoveMouseTo(
149 GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
150 event_generator()->PressLeftButton();
151 EXPECT_EQ(1u, GetHighlightedCount());
152 EXPECT_EQ(2, GetHighlightedIndex());
153
154 // Highlight follows the drag.
155 event_generator()->MoveMouseTo(view->GetBoundsInScreen().CenterPoint());
156 EXPECT_EQ(1u, GetHighlightedCount());
157 EXPECT_EQ(1, GetHighlightedIndex());
158
159 event_generator()->MoveMouseTo(
160 GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
161 EXPECT_EQ(1u, GetHighlightedCount());
162 EXPECT_EQ(0, GetHighlightedIndex());
163
164 event_generator()->MoveMouseTo(view->GetBoundsInScreen().CenterPoint());
165 EXPECT_EQ(1u, GetHighlightedCount());
166 EXPECT_EQ(1, GetHighlightedIndex());
167
168 EXPECT_FALSE(clicked);
169 event_generator()->ReleaseLeftButton();
170 EXPECT_TRUE(clicked);
171 }
172
173 } // namespace ime
174 } // namespace ui
175