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"
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
;
30 // An dummy implementation of MenuRunnerHandler to check if the dropdown menu is
32 class TestMenuRunnerHandler
: public MenuRunnerHandler
{
34 TestMenuRunnerHandler() : executed_(false) {}
36 bool executed() const { return executed_
; }
38 virtual MenuRunner::RunResult
RunMenuAt(Widget
* parent
,
40 const gfx::Rect
& bounds
,
41 MenuAnchorPosition anchor
,
42 ui::MenuSourceType source_type
,
43 int32 types
) OVERRIDE
{
45 return MenuRunner::NORMAL_EXIT
;
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
{
58 explicit TestCombobox(ui::ComboboxModel
* model
)
61 key_received_(false) {}
63 virtual bool OnKeyPressed(const ui::KeyEvent
& e
) OVERRIDE
{
65 key_handled_
= Combobox::OnKeyPressed(e
);
69 virtual bool OnKeyReleased(const ui::KeyEvent
& e
) OVERRIDE
{
71 key_handled_
= Combobox::OnKeyReleased(e
);
75 bool key_handled() const { return key_handled_
; }
76 bool key_received() const { return key_received_
; }
79 key_received_
= key_handled_
= false;
86 DISALLOW_COPY_AND_ASSIGN(TestCombobox
);
89 // A concrete class is needed to test the combobox.
90 class TestComboboxModel
: public ui::ComboboxModel
{
92 TestComboboxModel() {}
93 virtual ~TestComboboxModel() {}
95 static const int kItemCount
= 10;
98 virtual int GetItemCount() const OVERRIDE
{
101 virtual base::string16
GetItemAt(int index
) OVERRIDE
{
102 if (IsItemSeparatorAt(index
)) {
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())
122 void SetSeparators(const std::set
<int>& separators
) {
123 separators_
= separators
;
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
{
135 explicit VectorComboboxModel(std::vector
<std::string
>* 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
{
151 std::vector
<std::string
>* values_
;
154 class EvilListener
: public ComboboxListener
{
156 EvilListener() : deleted_(false) {}
157 virtual ~EvilListener() {};
160 virtual void OnPerformAction(Combobox
* combobox
) OVERRIDE
{
165 bool deleted() const { return deleted_
; }
170 DISALLOW_COPY_AND_ASSIGN(EvilListener
);
173 class TestComboboxListener
: public views::ComboboxListener
{
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_
;
196 int perform_action_index_
;
197 int actions_performed_
;
200 DISALLOW_COPY_AND_ASSIGN(TestComboboxListener
);
205 class ComboboxTest
: public ViewsTestBase
{
207 ComboboxTest() : widget_(NULL
), combobox_(NULL
) {}
209 virtual void TearDown() OVERRIDE
{
212 ViewsTestBase::TearDown();
215 void InitCombobox(const std::set
<int>* separators
) {
216 model_
.reset(new TestComboboxModel());
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();
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
,
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
,
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.
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
) {
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
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
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
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
;
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
) {
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
) {
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());
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
) {
513 TestComboboxListener listener
;
514 combobox_
->set_listener(&listener
);
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
) {
533 TestComboboxListener listener
;
534 combobox_
->set_listener(&listener
);
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
) {
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
) {
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
) {
592 TestComboboxListener listener
;
593 combobox_
->set_listener(&listener
);
595 combobox_
->SetStyle(Combobox::STYLE_ACTION
);
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
);
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
) {
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";
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();
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'
670 combobox
.SetStyle(Combobox::STYLE_ACTION
);
671 EXPECT_EQ(short_item_width
, combobox
.content_size_
.width());
674 TEST_F(ComboboxTest
, TypingPrefixNotifiesListener
) {
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.
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());