- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / controls / combobox / combobox_unittest.cc
1 // Copyright 2013 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 "ui/views/controls/combobox/combobox.h"
6
7 #include <set>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "ui/base/models/combobox_model.h"
11 #include "ui/events/event.h"
12 #include "ui/events/keycodes/keyboard_codes.h"
13 #include "ui/views/ime/mock_input_method.h"
14 #include "ui/views/test/views_test_base.h"
15 #include "ui/views/widget/widget.h"
16
17 namespace {
18
19 // A wrapper of Combobox to intercept the result of OnKeyPressed() and
20 // OnKeyReleased() methods.
21 class TestCombobox : public views::Combobox {
22  public:
23   explicit TestCombobox(ui::ComboboxModel* model)
24       : Combobox(model),
25         key_handled_(false),
26         key_received_(false) {
27   }
28
29   virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
30     key_received_ = true;
31     key_handled_ = views::Combobox::OnKeyPressed(e);
32     return key_handled_;
33   }
34
35   virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
36     key_received_ = true;
37     key_handled_ = views::Combobox::OnKeyReleased(e);
38     return key_handled_;
39   }
40
41   bool key_handled() const { return key_handled_; }
42   bool key_received() const { return key_received_; }
43
44   void clear() {
45     key_received_ = key_handled_ = false;
46   }
47
48  private:
49   bool key_handled_;
50   bool key_received_;
51
52   DISALLOW_COPY_AND_ASSIGN(TestCombobox);
53 };
54
55 // A concrete class is needed to test the combobox.
56 class TestComboboxModel : public ui::ComboboxModel {
57  public:
58   TestComboboxModel() {}
59   virtual ~TestComboboxModel() {}
60
61   // ui::ComboboxModel:
62   virtual int GetItemCount() const OVERRIDE {
63     return 10;
64   }
65   virtual string16 GetItemAt(int index) OVERRIDE {
66     DCHECK(!IsItemSeparatorAt(index));
67     return ASCIIToUTF16(IsItemSeparatorAt(index) ? "SEPARATOR" : "ITEM");
68   }
69   virtual bool IsItemSeparatorAt(int index) OVERRIDE {
70     return separators_.find(index) != separators_.end();
71   }
72
73   void SetSeparators(const std::set<int>& separators) {
74     separators_ = separators;
75   }
76
77  private:
78   std::set<int> separators_;
79
80   DISALLOW_COPY_AND_ASSIGN(TestComboboxModel);
81 };
82
83 }  // namespace
84
85 namespace views {
86
87 class ComboboxTest : public ViewsTestBase {
88  public:
89   ComboboxTest() : widget_(NULL), combobox_(NULL), input_method_(NULL) {}
90
91   virtual void TearDown() OVERRIDE {
92     if (widget_)
93       widget_->Close();
94     ViewsTestBase::TearDown();
95   }
96
97   void InitCombobox() {
98     model_.reset(new TestComboboxModel());
99
100     ASSERT_FALSE(combobox_);
101     combobox_ = new TestCombobox(model_.get());
102     combobox_->set_id(1);
103
104     widget_ = new Widget;
105     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
106     params.bounds = gfx::Rect(100, 100, 100, 100);
107     widget_->Init(params);
108     View* container = new View();
109     widget_->SetContentsView(container);
110     container->AddChildView(combobox_);
111
112     input_method_ = new MockInputMethod();
113     widget_->ReplaceInputMethod(input_method_);
114
115     // Assumes the Widget is always focused.
116     input_method_->OnFocus();
117
118     combobox_->RequestFocus();
119   }
120
121  protected:
122   void SendKeyEvent(ui::KeyboardCode key_code) {
123     ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, 0, false);
124     input_method_->DispatchKeyEvent(event);
125   }
126
127   View* GetFocusedView() {
128     return widget_->GetFocusManager()->GetFocusedView();
129   }
130
131   // We need widget to populate wrapper class.
132   Widget* widget_;
133
134   // |combobox_| will be allocated InitCombobox() and then owned by |widget_|.
135   TestCombobox* combobox_;
136
137   // Combobox does not take ownership of the model, hence it needs to be scoped.
138   scoped_ptr<TestComboboxModel> model_;
139
140   // For testing input method related behaviors.
141   MockInputMethod* input_method_;
142 };
143
144 TEST_F(ComboboxTest, KeyTest) {
145   InitCombobox();
146   SendKeyEvent(ui::VKEY_END);
147   EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount());
148   SendKeyEvent(ui::VKEY_HOME);
149   EXPECT_EQ(combobox_->selected_index(), 0);
150   SendKeyEvent(ui::VKEY_DOWN);
151   SendKeyEvent(ui::VKEY_DOWN);
152   EXPECT_EQ(combobox_->selected_index(), 2);
153   SendKeyEvent(ui::VKEY_RIGHT);
154   EXPECT_EQ(combobox_->selected_index(), 2);
155   SendKeyEvent(ui::VKEY_LEFT);
156   EXPECT_EQ(combobox_->selected_index(), 2);
157   SendKeyEvent(ui::VKEY_UP);
158   EXPECT_EQ(combobox_->selected_index(), 1);
159   SendKeyEvent(ui::VKEY_PRIOR);
160   EXPECT_EQ(combobox_->selected_index(), 0);
161   SendKeyEvent(ui::VKEY_NEXT);
162   EXPECT_EQ(combobox_->selected_index(), model_->GetItemCount() - 1);
163 }
164
165 // Check that if a combobox is disabled before it has a native wrapper, then the
166 // native wrapper inherits the disabled state when it gets created.
167 TEST_F(ComboboxTest, DisabilityTest) {
168   model_.reset(new TestComboboxModel());
169
170   ASSERT_FALSE(combobox_);
171   combobox_ = new TestCombobox(model_.get());
172   combobox_->SetEnabled(false);
173
174   widget_ = new Widget;
175   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
176   params.bounds = gfx::Rect(100, 100, 100, 100);
177   widget_->Init(params);
178   View* container = new View();
179   widget_->SetContentsView(container);
180   container->AddChildView(combobox_);
181   EXPECT_FALSE(combobox_->enabled());
182 }
183
184 // Verifies that we don't select a separator line in combobox when navigating
185 // through keyboard.
186 TEST_F(ComboboxTest, SkipSeparatorSimple) {
187   InitCombobox();
188   std::set<int> separators;
189   separators.insert(2);
190   model_->SetSeparators(separators);
191   EXPECT_EQ(0, combobox_->selected_index());
192   SendKeyEvent(ui::VKEY_DOWN);
193   EXPECT_EQ(1, combobox_->selected_index());
194   SendKeyEvent(ui::VKEY_DOWN);
195   EXPECT_EQ(3, combobox_->selected_index());
196   SendKeyEvent(ui::VKEY_UP);
197   EXPECT_EQ(1, combobox_->selected_index());
198   SendKeyEvent(ui::VKEY_HOME);
199   EXPECT_EQ(0, combobox_->selected_index());
200   SendKeyEvent(ui::VKEY_PRIOR);
201   EXPECT_EQ(0, combobox_->selected_index());
202   SendKeyEvent(ui::VKEY_END);
203   EXPECT_EQ(9, combobox_->selected_index());
204 }
205
206 // Verifies that we never select the separator that is in the beginning of the
207 // combobox list when navigating through keyboard.
208 TEST_F(ComboboxTest, SkipSeparatorBeginning) {
209   InitCombobox();
210   std::set<int> separators;
211   separators.insert(0);
212   model_->SetSeparators(separators);
213   EXPECT_EQ(0, combobox_->selected_index());
214   SendKeyEvent(ui::VKEY_DOWN);
215   EXPECT_EQ(1, combobox_->selected_index());
216   SendKeyEvent(ui::VKEY_DOWN);
217   EXPECT_EQ(2, combobox_->selected_index());
218   SendKeyEvent(ui::VKEY_UP);
219   EXPECT_EQ(1, combobox_->selected_index());
220   SendKeyEvent(ui::VKEY_HOME);
221   EXPECT_EQ(1, combobox_->selected_index());
222   SendKeyEvent(ui::VKEY_PRIOR);
223   EXPECT_EQ(1, combobox_->selected_index());
224   SendKeyEvent(ui::VKEY_END);
225   EXPECT_EQ(9, combobox_->selected_index());
226 }
227
228 // Verifies that we never select the separator that is in the end of the
229 // combobox list when navigating through keyboard.
230 TEST_F(ComboboxTest, SkipSeparatorEnd) {
231   InitCombobox();
232   std::set<int> separators;
233   separators.insert(model_->GetItemCount() - 1);
234   model_->SetSeparators(separators);
235   combobox_->SetSelectedIndex(8);
236   SendKeyEvent(ui::VKEY_DOWN);
237   EXPECT_EQ(8, combobox_->selected_index());
238   SendKeyEvent(ui::VKEY_UP);
239   EXPECT_EQ(7, combobox_->selected_index());
240   SendKeyEvent(ui::VKEY_END);
241   EXPECT_EQ(8, combobox_->selected_index());
242 }
243
244 // Verifies that we never select any of the adjacent separators (multiple
245 // consecutive) that appear in the beginning of the combobox list when
246 // navigating through keyboard.
247 TEST_F(ComboboxTest, SkipMultipleSeparatorsAtBeginning) {
248   InitCombobox();
249   std::set<int> separators;
250   separators.insert(0);
251   separators.insert(1);
252   separators.insert(2);
253   model_->SetSeparators(separators);
254   EXPECT_EQ(0, combobox_->selected_index());
255   SendKeyEvent(ui::VKEY_DOWN);
256   EXPECT_EQ(3, combobox_->selected_index());
257   SendKeyEvent(ui::VKEY_UP);
258   EXPECT_EQ(3, combobox_->selected_index());
259   SendKeyEvent(ui::VKEY_NEXT);
260   EXPECT_EQ(9, combobox_->selected_index());
261   SendKeyEvent(ui::VKEY_HOME);
262   EXPECT_EQ(3, combobox_->selected_index());
263   SendKeyEvent(ui::VKEY_END);
264   EXPECT_EQ(9, combobox_->selected_index());
265   SendKeyEvent(ui::VKEY_PRIOR);
266   EXPECT_EQ(3, combobox_->selected_index());
267 }
268
269 // Verifies that we never select any of the adjacent separators (multiple
270 // consecutive) that appear in the middle of the combobox list when navigating
271 // through keyboard.
272 TEST_F(ComboboxTest, SkipMultipleAdjacentSeparatorsAtMiddle) {
273   InitCombobox();
274   std::set<int> separators;
275   separators.insert(4);
276   separators.insert(5);
277   separators.insert(6);
278   model_->SetSeparators(separators);
279   combobox_->SetSelectedIndex(3);
280   SendKeyEvent(ui::VKEY_DOWN);
281   EXPECT_EQ(7, combobox_->selected_index());
282   SendKeyEvent(ui::VKEY_UP);
283   EXPECT_EQ(3, combobox_->selected_index());
284 }
285
286 // Verifies that we never select any of the adjacent separators (multiple
287 // consecutive) that appear in the end of the combobox list when navigating
288 // through keyboard.
289 TEST_F(ComboboxTest, SkipMultipleSeparatorsAtEnd) {
290   InitCombobox();
291   std::set<int> separators;
292   separators.insert(7);
293   separators.insert(8);
294   separators.insert(9);
295   model_->SetSeparators(separators);
296   combobox_->SetSelectedIndex(6);
297   SendKeyEvent(ui::VKEY_DOWN);
298   EXPECT_EQ(6, combobox_->selected_index());
299   SendKeyEvent(ui::VKEY_UP);
300   EXPECT_EQ(5, combobox_->selected_index());
301   SendKeyEvent(ui::VKEY_HOME);
302   EXPECT_EQ(0, combobox_->selected_index());
303   SendKeyEvent(ui::VKEY_NEXT);
304   EXPECT_EQ(6, combobox_->selected_index());
305   SendKeyEvent(ui::VKEY_PRIOR);
306   EXPECT_EQ(0, combobox_->selected_index());
307   SendKeyEvent(ui::VKEY_END);
308   EXPECT_EQ(6, combobox_->selected_index());
309 }
310
311 TEST_F(ComboboxTest, GetTextForRowTest) {
312   InitCombobox();
313   std::set<int> separators;
314   separators.insert(0);
315   separators.insert(1);
316   separators.insert(9);
317   model_->SetSeparators(separators);
318   for (int i = 0; i < combobox_->GetRowCount(); ++i) {
319     if (separators.count(i) != 0)
320       EXPECT_TRUE(combobox_->GetTextForRow(i).empty()) << i;
321     else
322       EXPECT_EQ(ASCIIToUTF16("ITEM"), combobox_->GetTextForRow(i)) << i;
323   }
324 }
325
326 }  // namespace views