Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / views / controls / combobox / combobox_unittest.cc
blob5621525586692f1c5ed2919b3396b69602102f24
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.
5 #include "ui/views/controls/combobox/combobox.h"
7 #include <set>
9 #include "base/basictypes.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "ui/base/ime/text_input_client.h"
12 #include "ui/base/models/combobox_model.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/events/keycodes/keyboard_codes.h"
16 #include "ui/views/controls/combobox/combobox_listener.h"
17 #include "ui/views/controls/menu/menu_runner.h"
18 #include "ui/views/controls/menu/menu_runner_handler.h"
19 #include "ui/views/ime/mock_input_method.h"
20 #include "ui/views/test/menu_runner_test_api.h"
21 #include "ui/views/test/views_test_base.h"
22 #include "ui/views/widget/widget.h"
24 using base::ASCIIToUTF16;
26 namespace views {
28 namespace {
30 // An dummy implementation of MenuRunnerHandler to check if the dropdown menu is
31 // shown or not.
32 class TestMenuRunnerHandler : public MenuRunnerHandler {
33 public:
34 TestMenuRunnerHandler() : executed_(false) {}
36 bool executed() const { return executed_; }
38 virtual MenuRunner::RunResult RunMenuAt(Widget* parent,
39 MenuButton* button,
40 const gfx::Rect& bounds,
41 MenuAnchorPosition anchor,
42 ui::MenuSourceType source_type,
43 int32 types) OVERRIDE {
44 executed_ = true;
45 return MenuRunner::NORMAL_EXIT;
48 private:
49 bool executed_;
51 DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler);
54 // A wrapper of Combobox to intercept the result of OnKeyPressed() and
55 // OnKeyReleased() methods.
56 class TestCombobox : public Combobox {
57 public:
58 explicit TestCombobox(ui::ComboboxModel* model)
59 : Combobox(model),
60 key_handled_(false),
61 key_received_(false) {}
63 virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
64 key_received_ = true;
65 key_handled_ = Combobox::OnKeyPressed(e);
66 return key_handled_;
69 virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
70 key_received_ = true;
71 key_handled_ = Combobox::OnKeyReleased(e);
72 return key_handled_;
75 bool key_handled() const { return key_handled_; }
76 bool key_received() const { return key_received_; }
78 void clear() {
79 key_received_ = key_handled_ = false;
82 private:
83 bool key_handled_;
84 bool key_received_;
86 DISALLOW_COPY_AND_ASSIGN(TestCombobox);
89 // A concrete class is needed to test the combobox.
90 class TestComboboxModel : public ui::ComboboxModel {
91 public:
92 TestComboboxModel() {}
93 virtual ~TestComboboxModel() {}
95 static const int kItemCount = 10;
97 // ui::ComboboxModel:
98 virtual int GetItemCount() const OVERRIDE {
99 return kItemCount;
101 virtual base::string16 GetItemAt(int index) OVERRIDE {
102 if (IsItemSeparatorAt(index)) {
103 NOTREACHED();
104 return ASCIIToUTF16("SEPARATOR");
106 return ASCIIToUTF16(index % 2 == 0 ? "PEANUT BUTTER" : "JELLY");
108 virtual bool IsItemSeparatorAt(int index) OVERRIDE {
109 return separators_.find(index) != separators_.end();
112 virtual int GetDefaultIndex() const OVERRIDE {
113 // Return the first index that is not a separator.
114 for (int index = 0; index < kItemCount; ++index) {
115 if (separators_.find(index) == separators_.end())
116 return index;
118 NOTREACHED();
119 return 0;
122 void SetSeparators(const std::set<int>& separators) {
123 separators_ = separators;
126 private:
127 std::set<int> separators_;
129 DISALLOW_COPY_AND_ASSIGN(TestComboboxModel);
132 // A combobox model which refers to a vector.
133 class VectorComboboxModel : public ui::ComboboxModel {
134 public:
135 explicit VectorComboboxModel(std::vector<std::string>* values)
136 : values_(values) {}
137 virtual ~VectorComboboxModel() {}
139 // ui::ComboboxModel:
140 virtual int GetItemCount() const OVERRIDE {
141 return (int)values_->size();
143 virtual base::string16 GetItemAt(int index) OVERRIDE {
144 return ASCIIToUTF16(values_->at(index));
146 virtual bool IsItemSeparatorAt(int index) OVERRIDE {
147 return false;
150 private:
151 std::vector<std::string>* values_;
154 class EvilListener : public ComboboxListener {
155 public:
156 EvilListener() : deleted_(false) {}
157 virtual ~EvilListener() {};
159 // ComboboxListener:
160 virtual void OnPerformAction(Combobox* combobox) OVERRIDE {
161 delete combobox;
162 deleted_ = true;
165 bool deleted() const { return deleted_; }
167 private:
168 bool deleted_;
170 DISALLOW_COPY_AND_ASSIGN(EvilListener);
173 class TestComboboxListener : public views::ComboboxListener {
174 public:
175 TestComboboxListener() : perform_action_index_(-1), actions_performed_(0) {}
176 virtual ~TestComboboxListener() {}
178 virtual void OnPerformAction(views::Combobox* combobox) OVERRIDE {
179 perform_action_index_ = combobox->selected_index();
180 actions_performed_++;
183 int perform_action_index() const {
184 return perform_action_index_;
187 bool on_perform_action_called() const {
188 return actions_performed_ > 0;
191 int actions_performed() const {
192 return actions_performed_;
195 private:
196 int perform_action_index_;
197 int actions_performed_;
199 private:
200 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener);
203 } // namespace
205 class ComboboxTest : public ViewsTestBase {
206 public:
207 ComboboxTest() : widget_(NULL), combobox_(NULL) {}
209 virtual void TearDown() OVERRIDE {
210 if (widget_)
211 widget_->Close();
212 ViewsTestBase::TearDown();
215 void InitCombobox(const std::set<int>* separators) {
216 model_.reset(new TestComboboxModel());
218 if (separators)
219 model_->SetSeparators(*separators);
221 ASSERT_FALSE(combobox_);
222 combobox_ = new TestCombobox(model_.get());
223 combobox_->set_id(1);
225 widget_ = new Widget;
226 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
227 params.bounds = gfx::Rect(200, 200, 200, 200);
228 widget_->Init(params);
229 View* container = new View();
230 widget_->SetContentsView(container);
231 container->AddChildView(combobox_);
233 widget_->ReplaceInputMethod(new MockInputMethod);
235 // Assumes the Widget is always focused.
236 widget_->GetInputMethod()->OnFocus();
238 combobox_->RequestFocus();
239 combobox_->SizeToPreferredSize();
242 protected:
243 void SendKeyEvent(ui::KeyboardCode key_code) {
244 SendKeyEventWithType(key_code, ui::ET_KEY_PRESSED);
247 void SendKeyEventWithType(ui::KeyboardCode key_code, ui::EventType type) {
248 ui::KeyEvent event(type, key_code, ui::EF_NONE);
249 widget_->GetInputMethod()->DispatchKeyEvent(event);
252 View* GetFocusedView() {
253 return widget_->GetFocusManager()->GetFocusedView();
256 void PerformClick(const gfx::Point& point) {
257 ui::MouseEvent pressed_event = ui::MouseEvent(ui::ET_MOUSE_PRESSED, point,
258 point,
259 ui::EF_LEFT_MOUSE_BUTTON,
260 ui::EF_LEFT_MOUSE_BUTTON);
261 widget_->OnMouseEvent(&pressed_event);
262 ui::MouseEvent released_event = ui::MouseEvent(ui::ET_MOUSE_RELEASED, point,
263 point,
264 ui::EF_LEFT_MOUSE_BUTTON,
265 ui::EF_LEFT_MOUSE_BUTTON);
266 widget_->OnMouseEvent(&released_event);
269 // We need widget to populate wrapper class.
270 Widget* widget_;
272 // |combobox_| will be allocated InitCombobox() and then owned by |widget_|.
273 TestCombobox* combobox_;
275 // Combobox does not take ownership of the model, hence it needs to be scoped.
276 scoped_ptr<TestComboboxModel> model_;
279 TEST_F(ComboboxTest, KeyTest) {
280 InitCombobox(NULL);
281 SendKeyEvent(ui::VKEY_END);
282 EXPECT_EQ(combobox_->selected_index() + 1, model_->GetItemCount());
283 SendKeyEvent(ui::VKEY_HOME);
284 EXPECT_EQ(combobox_->selected_index(), 0);
285 SendKeyEvent(ui::VKEY_DOWN);
286 SendKeyEvent(ui::VKEY_DOWN);
287 EXPECT_EQ(combobox_->selected_index(), 2);
288 SendKeyEvent(ui::VKEY_RIGHT);
289 EXPECT_EQ(combobox_->selected_index(), 2);
290 SendKeyEvent(ui::VKEY_LEFT);
291 EXPECT_EQ(combobox_->selected_index(), 2);
292 SendKeyEvent(ui::VKEY_UP);
293 EXPECT_EQ(combobox_->selected_index(), 1);
294 SendKeyEvent(ui::VKEY_PRIOR);
295 EXPECT_EQ(combobox_->selected_index(), 0);
296 SendKeyEvent(ui::VKEY_NEXT);
297 EXPECT_EQ(combobox_->selected_index(), model_->GetItemCount() - 1);
300 // Check that if a combobox is disabled before it has a native wrapper, then the
301 // native wrapper inherits the disabled state when it gets created.
302 TEST_F(ComboboxTest, DisabilityTest) {
303 model_.reset(new TestComboboxModel());
305 ASSERT_FALSE(combobox_);
306 combobox_ = new TestCombobox(model_.get());
307 combobox_->SetEnabled(false);
309 widget_ = new Widget;
310 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
311 params.bounds = gfx::Rect(100, 100, 100, 100);
312 widget_->Init(params);
313 View* container = new View();
314 widget_->SetContentsView(container);
315 container->AddChildView(combobox_);
316 EXPECT_FALSE(combobox_->enabled());
319 // Verifies that we don't select a separator line in combobox when navigating
320 // through keyboard.
321 TEST_F(ComboboxTest, SkipSeparatorSimple) {
322 std::set<int> separators;
323 separators.insert(2);
324 InitCombobox(&separators);
325 EXPECT_EQ(0, combobox_->selected_index());
326 SendKeyEvent(ui::VKEY_DOWN);
327 EXPECT_EQ(1, combobox_->selected_index());
328 SendKeyEvent(ui::VKEY_DOWN);
329 EXPECT_EQ(3, combobox_->selected_index());
330 SendKeyEvent(ui::VKEY_UP);
331 EXPECT_EQ(1, combobox_->selected_index());
332 SendKeyEvent(ui::VKEY_HOME);
333 EXPECT_EQ(0, combobox_->selected_index());
334 SendKeyEvent(ui::VKEY_PRIOR);
335 EXPECT_EQ(0, combobox_->selected_index());
336 SendKeyEvent(ui::VKEY_END);
337 EXPECT_EQ(9, combobox_->selected_index());
340 // Verifies that we never select the separator that is in the beginning of the
341 // combobox list when navigating through keyboard.
342 TEST_F(ComboboxTest, SkipSeparatorBeginning) {
343 std::set<int> separators;
344 separators.insert(0);
345 InitCombobox(&separators);
346 EXPECT_EQ(1, combobox_->selected_index());
347 SendKeyEvent(ui::VKEY_DOWN);
348 EXPECT_EQ(2, combobox_->selected_index());
349 SendKeyEvent(ui::VKEY_DOWN);
350 EXPECT_EQ(3, combobox_->selected_index());
351 SendKeyEvent(ui::VKEY_UP);
352 EXPECT_EQ(2, combobox_->selected_index());
353 SendKeyEvent(ui::VKEY_HOME);
354 EXPECT_EQ(1, combobox_->selected_index());
355 SendKeyEvent(ui::VKEY_PRIOR);
356 EXPECT_EQ(1, combobox_->selected_index());
357 SendKeyEvent(ui::VKEY_END);
358 EXPECT_EQ(9, combobox_->selected_index());
361 // Verifies that we never select the separator that is in the end of the
362 // combobox list when navigating through keyboard.
363 TEST_F(ComboboxTest, SkipSeparatorEnd) {
364 std::set<int> separators;
365 separators.insert(TestComboboxModel::kItemCount - 1);
366 InitCombobox(&separators);
367 combobox_->SetSelectedIndex(8);
368 SendKeyEvent(ui::VKEY_DOWN);
369 EXPECT_EQ(8, combobox_->selected_index());
370 SendKeyEvent(ui::VKEY_UP);
371 EXPECT_EQ(7, combobox_->selected_index());
372 SendKeyEvent(ui::VKEY_END);
373 EXPECT_EQ(8, combobox_->selected_index());
376 // Verifies that we never select any of the adjacent separators (multiple
377 // consecutive) that appear in the beginning of the combobox list when
378 // navigating through keyboard.
379 TEST_F(ComboboxTest, SkipMultipleSeparatorsAtBeginning) {
380 std::set<int> separators;
381 separators.insert(0);
382 separators.insert(1);
383 separators.insert(2);
384 InitCombobox(&separators);
385 EXPECT_EQ(3, combobox_->selected_index());
386 SendKeyEvent(ui::VKEY_DOWN);
387 EXPECT_EQ(4, combobox_->selected_index());
388 SendKeyEvent(ui::VKEY_UP);
389 EXPECT_EQ(3, combobox_->selected_index());
390 SendKeyEvent(ui::VKEY_NEXT);
391 EXPECT_EQ(9, combobox_->selected_index());
392 SendKeyEvent(ui::VKEY_HOME);
393 EXPECT_EQ(3, combobox_->selected_index());
394 SendKeyEvent(ui::VKEY_END);
395 EXPECT_EQ(9, combobox_->selected_index());
396 SendKeyEvent(ui::VKEY_PRIOR);
397 EXPECT_EQ(3, combobox_->selected_index());
400 // Verifies that we never select any of the adjacent separators (multiple
401 // consecutive) that appear in the middle of the combobox list when navigating
402 // through keyboard.
403 TEST_F(ComboboxTest, SkipMultipleAdjacentSeparatorsAtMiddle) {
404 std::set<int> separators;
405 separators.insert(4);
406 separators.insert(5);
407 separators.insert(6);
408 InitCombobox(&separators);
409 combobox_->SetSelectedIndex(3);
410 SendKeyEvent(ui::VKEY_DOWN);
411 EXPECT_EQ(7, combobox_->selected_index());
412 SendKeyEvent(ui::VKEY_UP);
413 EXPECT_EQ(3, combobox_->selected_index());
416 // Verifies that we never select any of the adjacent separators (multiple
417 // consecutive) that appear in the end of the combobox list when navigating
418 // through keyboard.
419 TEST_F(ComboboxTest, SkipMultipleSeparatorsAtEnd) {
420 std::set<int> separators;
421 separators.insert(7);
422 separators.insert(8);
423 separators.insert(9);
424 InitCombobox(&separators);
425 combobox_->SetSelectedIndex(6);
426 SendKeyEvent(ui::VKEY_DOWN);
427 EXPECT_EQ(6, combobox_->selected_index());
428 SendKeyEvent(ui::VKEY_UP);
429 EXPECT_EQ(5, combobox_->selected_index());
430 SendKeyEvent(ui::VKEY_HOME);
431 EXPECT_EQ(0, combobox_->selected_index());
432 SendKeyEvent(ui::VKEY_NEXT);
433 EXPECT_EQ(6, combobox_->selected_index());
434 SendKeyEvent(ui::VKEY_PRIOR);
435 EXPECT_EQ(0, combobox_->selected_index());
436 SendKeyEvent(ui::VKEY_END);
437 EXPECT_EQ(6, combobox_->selected_index());
440 TEST_F(ComboboxTest, GetTextForRowTest) {
441 std::set<int> separators;
442 separators.insert(0);
443 separators.insert(1);
444 separators.insert(9);
445 InitCombobox(&separators);
446 for (int i = 0; i < combobox_->GetRowCount(); ++i) {
447 if (separators.count(i) != 0) {
448 EXPECT_TRUE(combobox_->GetTextForRow(i).empty()) << i;
449 } else {
450 EXPECT_EQ(ASCIIToUTF16(i % 2 == 0 ? "PEANUT BUTTER" : "JELLY"),
451 combobox_->GetTextForRow(i)) << i;
456 // Verifies selecting the first matching value (and returning whether found).
457 TEST_F(ComboboxTest, SelectValue) {
458 InitCombobox(NULL);
459 ASSERT_EQ(model_->GetDefaultIndex(), combobox_->selected_index());
460 EXPECT_TRUE(combobox_->SelectValue(ASCIIToUTF16("PEANUT BUTTER")));
461 EXPECT_EQ(0, combobox_->selected_index());
462 EXPECT_TRUE(combobox_->SelectValue(ASCIIToUTF16("JELLY")));
463 EXPECT_EQ(1, combobox_->selected_index());
464 EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("BANANAS")));
465 EXPECT_EQ(1, combobox_->selected_index());
467 // With the action style, the selected index is always 0.
468 combobox_->SetStyle(Combobox::STYLE_ACTION);
469 EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("PEANUT BUTTER")));
470 EXPECT_EQ(0, combobox_->selected_index());
471 EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("JELLY")));
472 EXPECT_EQ(0, combobox_->selected_index());
473 EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("BANANAS")));
474 EXPECT_EQ(0, combobox_->selected_index());
477 TEST_F(ComboboxTest, SelectIndexActionStyle) {
478 InitCombobox(NULL);
480 // With the action style, the selected index is always 0.
481 combobox_->SetStyle(Combobox::STYLE_ACTION);
482 combobox_->SetSelectedIndex(1);
483 EXPECT_EQ(0, combobox_->selected_index());
484 combobox_->SetSelectedIndex(2);
485 EXPECT_EQ(0, combobox_->selected_index());
486 combobox_->SetSelectedIndex(3);
487 EXPECT_EQ(0, combobox_->selected_index());
490 TEST_F(ComboboxTest, ListenerHandlesDelete) {
491 TestComboboxModel model;
493 // |combobox| will be deleted on change.
494 TestCombobox* combobox = new TestCombobox(&model);
495 scoped_ptr<EvilListener> evil_listener(new EvilListener());
496 combobox->set_listener(evil_listener.get());
497 ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2));
498 EXPECT_TRUE(evil_listener->deleted());
500 // With STYLE_ACTION
501 // |combobox| will be deleted on change.
502 combobox = new TestCombobox(&model);
503 evil_listener.reset(new EvilListener());
504 combobox->set_listener(evil_listener.get());
505 combobox->SetStyle(Combobox::STYLE_ACTION);
506 ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2));
507 EXPECT_TRUE(evil_listener->deleted());
510 TEST_F(ComboboxTest, Click) {
511 InitCombobox(NULL);
513 TestComboboxListener listener;
514 combobox_->set_listener(&listener);
516 combobox_->Layout();
518 // Click the left side. The menu is shown.
519 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler();
520 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler);
521 test::MenuRunnerTestAPI test_api(
522 combobox_->dropdown_list_menu_runner_.get());
523 test_api.SetMenuRunnerHandler(menu_runner_handler.Pass());
524 PerformClick(gfx::Point(combobox_->x() + 1,
525 combobox_->y() + combobox_->height() / 2));
526 EXPECT_FALSE(listener.on_perform_action_called());
527 EXPECT_TRUE(test_menu_runner_handler->executed());
530 TEST_F(ComboboxTest, ClickButDisabled) {
531 InitCombobox(NULL);
533 TestComboboxListener listener;
534 combobox_->set_listener(&listener);
536 combobox_->Layout();
537 combobox_->SetEnabled(false);
539 // Click the left side, but nothing happens since the combobox is disabled.
540 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler();
541 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler);
542 test::MenuRunnerTestAPI test_api(
543 combobox_->dropdown_list_menu_runner_.get());
544 test_api.SetMenuRunnerHandler(menu_runner_handler.Pass());
545 PerformClick(gfx::Point(combobox_->x() + 1,
546 combobox_->y() + combobox_->height() / 2));
547 EXPECT_FALSE(listener.on_perform_action_called());
548 EXPECT_FALSE(test_menu_runner_handler->executed());
551 TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) {
552 InitCombobox(NULL);
554 TestComboboxListener listener;
555 combobox_->set_listener(&listener);
557 // With STYLE_NORMAL, the click event is ignored.
558 SendKeyEvent(ui::VKEY_RETURN);
559 EXPECT_FALSE(listener.on_perform_action_called());
561 // With STYLE_ACTION, the click event is notified.
562 combobox_->SetStyle(Combobox::STYLE_ACTION);
563 SendKeyEvent(ui::VKEY_RETURN);
564 EXPECT_TRUE(listener.on_perform_action_called());
565 EXPECT_EQ(0, listener.perform_action_index());
568 TEST_F(ComboboxTest, NotifyOnClickWithSpaceKey) {
569 InitCombobox(NULL);
571 TestComboboxListener listener;
572 combobox_->set_listener(&listener);
574 // With STYLE_NORMAL, the click event is ignored.
575 SendKeyEvent(ui::VKEY_SPACE);
576 EXPECT_FALSE(listener.on_perform_action_called());
577 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED);
578 EXPECT_FALSE(listener.on_perform_action_called());
580 // With STYLE_ACTION, the click event is notified after releasing.
581 combobox_->SetStyle(Combobox::STYLE_ACTION);
582 SendKeyEvent(ui::VKEY_SPACE);
583 EXPECT_FALSE(listener.on_perform_action_called());
584 SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED);
585 EXPECT_TRUE(listener.on_perform_action_called());
586 EXPECT_EQ(0, listener.perform_action_index());
589 TEST_F(ComboboxTest, NotifyOnClickWithMouse) {
590 InitCombobox(NULL);
592 TestComboboxListener listener;
593 combobox_->set_listener(&listener);
595 combobox_->SetStyle(Combobox::STYLE_ACTION);
596 combobox_->Layout();
598 // Click the right side (arrow button). The menu is shown.
599 TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler();
600 scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler);
601 scoped_ptr<test::MenuRunnerTestAPI> test_api(
602 new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get()));
603 test_api->SetMenuRunnerHandler(menu_runner_handler.Pass());
605 PerformClick(gfx::Point(combobox_->x() + combobox_->width() - 1,
606 combobox_->y() + combobox_->height() / 2));
607 EXPECT_FALSE(listener.on_perform_action_called());
608 EXPECT_TRUE(test_menu_runner_handler->executed());
610 // Click the left side (text button). The click event is notified.
611 test_menu_runner_handler = new TestMenuRunnerHandler();
612 menu_runner_handler.reset(test_menu_runner_handler);
613 test_api.reset(
614 new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get()));
615 test_api->SetMenuRunnerHandler(menu_runner_handler.Pass());
616 PerformClick(gfx::Point(combobox_->x() + 1,
617 combobox_->y() + combobox_->height() / 2));
618 EXPECT_TRUE(listener.on_perform_action_called());
619 EXPECT_FALSE(test_menu_runner_handler->executed());
620 EXPECT_EQ(0, listener.perform_action_index());
623 TEST_F(ComboboxTest, ConsumingPressKeyEvents) {
624 InitCombobox(NULL);
626 EXPECT_FALSE(combobox_->OnKeyPressed(
627 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE)));
628 EXPECT_FALSE(combobox_->OnKeyPressed(
629 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE)));
631 // When the combobox's style is STYLE_ACTION, pressing events of a space key
632 // or an enter key will be consumed.
633 combobox_->SetStyle(Combobox::STYLE_ACTION);
634 EXPECT_TRUE(combobox_->OnKeyPressed(
635 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE)));
636 EXPECT_TRUE(combobox_->OnKeyPressed(
637 ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, ui::EF_NONE)));
640 TEST_F(ComboboxTest, ContentWidth) {
641 std::vector<std::string> values;
642 VectorComboboxModel model(&values);
643 TestCombobox combobox(&model);
645 std::string long_item = "this is the long item";
646 std::string short_item = "s";
648 values.resize(1);
649 values[0] = long_item;
650 combobox.ModelChanged();
652 const int long_item_width = combobox.content_size_.width();
654 values[0] = short_item;
655 combobox.ModelChanged();
657 const int short_item_width = combobox.content_size_.width();
659 values.resize(2);
660 values[0] = short_item;
661 values[1] = long_item;
662 combobox.ModelChanged();
664 // When the style is STYLE_NORMAL, the width will fit with the longest item.
665 combobox.SetStyle(Combobox::STYLE_NORMAL);
666 EXPECT_EQ(long_item_width, combobox.content_size_.width());
668 // When the style is STYLE_ACTION, the width will fit with the first items'
669 // width.
670 combobox.SetStyle(Combobox::STYLE_ACTION);
671 EXPECT_EQ(short_item_width, combobox.content_size_.width());
674 TEST_F(ComboboxTest, TypingPrefixNotifiesListener) {
675 InitCombobox(NULL);
677 TestComboboxListener listener;
678 combobox_->set_listener(&listener);
680 // Type the first character of the second menu item ("JELLY").
681 combobox_->GetTextInputClient()->InsertChar('J', ui::EF_NONE);
682 EXPECT_EQ(1, listener.actions_performed());
683 EXPECT_EQ(1, listener.perform_action_index());
685 // Type the second character of "JELLY", item shouldn't change and
686 // OnPerformAction() shouldn't be re-called.
687 combobox_->GetTextInputClient()->InsertChar('E', ui::EF_NONE);
688 EXPECT_EQ(1, listener.actions_performed());
689 EXPECT_EQ(1, listener.perform_action_index());
691 // Clears the typed text.
692 combobox_->OnBlur();
694 // Type the first character of "PEANUT BUTTER", which should change the
695 // selected index and perform an action.
696 combobox_->GetTextInputClient()->InsertChar('P', ui::EF_NONE);
697 EXPECT_EQ(2, listener.actions_performed());
698 EXPECT_EQ(2, listener.perform_action_index());
701 } // namespace views