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 "ash/ime/candidate_view.h"
6
7#include "base/logging.h"
8#include "base/strings/utf_string_conversions.h"
9#include "ui/aura/test/event_generator.h"
10#include "ui/aura/window.h"
11#include "ui/views/controls/button/button.h"
12#include "ui/views/layout/box_layout.h"
13#include "ui/views/layout/fill_layout.h"
14#include "ui/views/test/views_test_base.h"
15#include "ui/views/widget/widget_delegate.h"
16
17namespace ash {
18namespace ime {
19namespace {
20
21const char* const kDummyCandidates[] = {
22  "candidate1",
23  "candidate2",
24  "candidate3",
25};
26
27}  // namespace
28
29class CandidateViewTest : public views::ViewsTestBase,
30                          public views::ButtonListener {
31 public:
32  CandidateViewTest() : widget_(NULL), last_pressed_(NULL) {}
33  virtual ~CandidateViewTest() {}
34
35  virtual void SetUp() OVERRIDE {
36    views::ViewsTestBase::SetUp();
37
38    views::Widget::InitParams init_params(CreateParams(
39        views::Widget::InitParams::TYPE_WINDOW));
40
41    init_params.delegate = new views::WidgetDelegateView();
42
43    container_ = init_params.delegate->GetContentsView();
44    container_->SetLayoutManager(
45        new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
46    for (size_t i = 0; i < arraysize(kDummyCandidates); ++i) {
47      CandidateView* candidate = new CandidateView(
48          this, ui::CandidateWindow::VERTICAL);
49      ui::CandidateWindow::Entry entry;
50      entry.value = base::UTF8ToUTF16(kDummyCandidates[i]);
51      candidate->SetEntry(entry);
52      container_->AddChildView(candidate);
53    }
54
55    widget_ = new views::Widget();
56    widget_->Init(init_params);
57    widget_->Show();
58
59    aura::Window* native_window = widget_->GetNativeWindow();
60    event_generator_.reset(new aura::test::EventGenerator(
61        native_window->GetRootWindow(), native_window));
62  }
63
64  virtual void TearDown() OVERRIDE {
65    widget_->Close();
66
67    views::ViewsTestBase::TearDown();
68  }
69
70 protected:
71  CandidateView* GetCandidateAt(int index) {
72    return static_cast<CandidateView*>(container_->child_at(index));
73  }
74
75  int GetHighlightedIndex(int* highlighted_count) const {
76    *highlighted_count = 0;
77    int last_highlighted = -1;
78    for (int i = 0; i < container_->child_count(); ++i) {
79      if (container_->child_at(i)->background() != NULL) {
80        (*highlighted_count)++;
81        last_highlighted = i;
82      }
83    }
84    return last_highlighted;
85  }
86
87  int GetLastPressedIndexAndReset() {
88    for (int i = 0; i < container_->child_count(); ++i) {
89      if (last_pressed_ == container_->child_at(i)) {
90        last_pressed_ = NULL;
91        return i;
92      }
93    }
94
95    DCHECK(last_pressed_ == NULL);
96    last_pressed_ = NULL;
97    return -1;
98  }
99
100  aura::test::EventGenerator* event_generator() {
101    return event_generator_.get();
102  }
103
104 private:
105  virtual void ButtonPressed(views::Button* sender,
106                             const ui::Event& event) OVERRIDE {
107    last_pressed_ = sender;
108  }
109
110  views::Widget* widget_;
111  views::View* container_;
112  scoped_ptr<aura::test::EventGenerator> event_generator_;
113  views::View* last_pressed_;
114
115  DISALLOW_COPY_AND_ASSIGN(CandidateViewTest);
116};
117
118TEST_F(CandidateViewTest, MouseHovers) {
119  GetCandidateAt(0)->SetHighlighted(true);
120
121  int highlighted_count = 0;
122  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
123  EXPECT_EQ(1, highlighted_count);
124
125  // Mouse hover shouldn't change the background.
126  event_generator()->MoveMouseTo(
127      GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
128  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
129  EXPECT_EQ(1, highlighted_count);
130
131  // Mouse hover shouldn't change the background.
132  event_generator()->MoveMouseTo(
133      GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
134  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
135  EXPECT_EQ(1, highlighted_count);
136
137  // Mouse hover shouldn't change the background.
138  event_generator()->MoveMouseTo(
139      GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
140  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
141  EXPECT_EQ(1, highlighted_count);
142}
143
144TEST_F(CandidateViewTest, MouseClick) {
145  event_generator()->MoveMouseTo(
146      GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
147  event_generator()->ClickLeftButton();
148  EXPECT_EQ(1, GetLastPressedIndexAndReset());
149}
150
151TEST_F(CandidateViewTest, ClickAndMove) {
152  GetCandidateAt(0)->SetHighlighted(true);
153
154  int highlighted_count = 0;
155  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
156  EXPECT_EQ(1, highlighted_count);
157
158  event_generator()->MoveMouseTo(
159      GetCandidateAt(2)->GetBoundsInScreen().CenterPoint());
160  event_generator()->PressLeftButton();
161  EXPECT_EQ(2, GetHighlightedIndex(&highlighted_count));
162  EXPECT_EQ(1, highlighted_count);
163
164  // Highlight follows the drag.
165  event_generator()->MoveMouseTo(
166      GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
167  EXPECT_EQ(1, GetHighlightedIndex(&highlighted_count));
168  EXPECT_EQ(1, highlighted_count);
169
170  event_generator()->MoveMouseTo(
171      GetCandidateAt(0)->GetBoundsInScreen().CenterPoint());
172  EXPECT_EQ(0, GetHighlightedIndex(&highlighted_count));
173  EXPECT_EQ(1, highlighted_count);
174
175  event_generator()->MoveMouseTo(
176      GetCandidateAt(1)->GetBoundsInScreen().CenterPoint());
177  EXPECT_EQ(1, GetHighlightedIndex(&highlighted_count));
178  EXPECT_EQ(1, highlighted_count);
179
180  event_generator()->ReleaseLeftButton();
181  EXPECT_EQ(1, GetLastPressedIndexAndReset());
182}
183
184}  // namespace ime
185}  // namespace ash
186