Index: ui/views/controls/combobox/combobox_unittest.cc |
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc |
index a3cba309a1be69d127474ef093c97cee5945a35c..2a488a2215afc80ed145f73107bbb9f8f09d7d53 100644 |
--- a/ui/views/controls/combobox/combobox_unittest.cc |
+++ b/ui/views/controls/combobox/combobox_unittest.cc |
@@ -11,6 +11,7 @@ |
#include "ui/base/ime/input_method.h" |
#include "ui/base/ime/text_input_client.h" |
#include "ui/base/models/combobox_model.h" |
+#include "ui/base/models/menu_model.h" |
#include "ui/events/event.h" |
#include "ui/events/event_constants.h" |
#include "ui/events/event_utils.h" |
@@ -25,6 +26,27 @@ |
using base::ASCIIToUTF16; |
namespace views { |
+namespace test { |
+ |
+class ComboboxTestApi { |
+ public: |
+ explicit ComboboxTestApi(Combobox* combobox) : combobox_(combobox) {} |
+ |
+ void PerformActionAt(int index) { menu_model()->ActivatedAt(index); } |
+ void InstallTestMenuRunner(int* menu_show_count); |
+ |
+ gfx::Size content_size() { return combobox_->content_size_; } |
+ ui::MenuModel* menu_model() { return combobox_->menu_model_adapter_.get(); } |
+ |
+ private: |
+ Combobox* combobox_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ComboboxTestApi); |
+}; |
+ |
+} // namespace test |
+ |
+using test::ComboboxTestApi; |
namespace { |
@@ -32,22 +54,20 @@ namespace { |
// shown or not. |
class TestMenuRunnerHandler : public MenuRunnerHandler { |
public: |
- TestMenuRunnerHandler() : executed_(false) {} |
- |
- bool executed() const { return executed_; } |
- |
+ explicit TestMenuRunnerHandler(int* show_counter) |
+ : show_counter_(show_counter) {} |
MenuRunner::RunResult RunMenuAt(Widget* parent, |
MenuButton* button, |
const gfx::Rect& bounds, |
MenuAnchorPosition anchor, |
ui::MenuSourceType source_type, |
int32 types) override { |
- executed_ = true; |
+ *show_counter_ += 1; |
return MenuRunner::NORMAL_EXIT; |
} |
private: |
- bool executed_; |
+ int* show_counter_; |
DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler); |
}; |
@@ -93,10 +113,10 @@ class TestComboboxModel : public ui::ComboboxModel { |
TestComboboxModel() {} |
~TestComboboxModel() override {} |
- static const int kItemCount = 10; |
+ enum { kItemCount = 10 }; |
// ui::ComboboxModel: |
- int GetItemCount() const override { return kItemCount; } |
+ int GetItemCount() const override { return item_count_; } |
base::string16 GetItemAt(int index) override { |
if (IsItemSeparatorAt(index)) { |
NOTREACHED(); |
@@ -122,8 +142,11 @@ class TestComboboxModel : public ui::ComboboxModel { |
separators_ = separators; |
} |
+ void set_item_count(int item_count) { item_count_ = item_count; } |
+ |
private: |
std::set<int> separators_; |
+ int item_count_ = kItemCount; |
DISALLOW_COPY_AND_ASSIGN(TestComboboxModel); |
}; |
@@ -135,15 +158,21 @@ class VectorComboboxModel : public ui::ComboboxModel { |
: values_(values) {} |
~VectorComboboxModel() override {} |
+ void set_default_index(int default_index) { default_index_ = default_index; } |
+ |
// ui::ComboboxModel: |
int GetItemCount() const override { return (int)values_->size(); } |
base::string16 GetItemAt(int index) override { |
return ASCIIToUTF16(values_->at(index)); |
} |
bool IsItemSeparatorAt(int index) override { return false; } |
+ int GetDefaultIndex() const override { return default_index_; } |
private: |
std::vector<std::string>* values_; |
+ int default_index_ = 0; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(VectorComboboxModel); |
}; |
class EvilListener : public ComboboxListener { |
@@ -197,6 +226,14 @@ class TestComboboxListener : public views::ComboboxListener { |
} // namespace |
+void ComboboxTestApi::InstallTestMenuRunner(int* menu_show_count) { |
+ combobox_->menu_runner_.reset( |
+ new MenuRunner(menu_model(), MenuRunner::COMBOBOX)); |
+ test::MenuRunnerTestAPI test_api(combobox_->menu_runner_.get()); |
+ test_api.SetMenuRunnerHandler( |
+ make_scoped_ptr(new TestMenuRunnerHandler(menu_show_count))); |
+} |
+ |
class ComboboxTest : public ViewsTestBase { |
public: |
ComboboxTest() : widget_(NULL), combobox_(NULL) {} |
@@ -215,6 +252,7 @@ class ComboboxTest : public ViewsTestBase { |
ASSERT_FALSE(combobox_); |
combobox_ = new TestCombobox(model_.get()); |
+ test_api_.reset(new ComboboxTestApi(combobox_)); |
combobox_->set_id(1); |
widget_ = new Widget; |
@@ -262,9 +300,13 @@ class ComboboxTest : public ViewsTestBase { |
// |combobox_| will be allocated InitCombobox() and then owned by |widget_|. |
TestCombobox* combobox_; |
+ scoped_ptr<ComboboxTestApi> test_api_; |
// Combobox does not take ownership of the model, hence it needs to be scoped. |
scoped_ptr<TestComboboxModel> model_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ComboboxTest); |
}; |
TEST_F(ComboboxTest, KeyTest) { |
@@ -485,7 +527,7 @@ TEST_F(ComboboxTest, ListenerHandlesDelete) { |
TestCombobox* combobox = new TestCombobox(&model); |
scoped_ptr<EvilListener> evil_listener(new EvilListener()); |
combobox->set_listener(evil_listener.get()); |
- ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2)); |
+ ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); |
EXPECT_TRUE(evil_listener->deleted()); |
// With STYLE_ACTION |
@@ -494,7 +536,7 @@ TEST_F(ComboboxTest, ListenerHandlesDelete) { |
evil_listener.reset(new EvilListener()); |
combobox->set_listener(evil_listener.get()); |
combobox->SetStyle(Combobox::STYLE_ACTION); |
- ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2)); |
+ ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); |
EXPECT_TRUE(evil_listener->deleted()); |
} |
@@ -505,17 +547,15 @@ TEST_F(ComboboxTest, Click) { |
combobox_->set_listener(&listener); |
combobox_->Layout(); |
+ int menu_show_count = 0; |
+ test_api_->InstallTestMenuRunner(&menu_show_count); |
// Click the left side. The menu is shown. |
- TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); |
- scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); |
- test::MenuRunnerTestAPI test_api( |
- combobox_->dropdown_list_menu_runner_.get()); |
- test_api.SetMenuRunnerHandler(menu_runner_handler.Pass()); |
+ EXPECT_EQ(0, menu_show_count); |
PerformClick(gfx::Point(combobox_->x() + 1, |
combobox_->y() + combobox_->height() / 2)); |
EXPECT_FALSE(listener.on_perform_action_called()); |
- EXPECT_TRUE(test_menu_runner_handler->executed()); |
+ EXPECT_EQ(1, menu_show_count); |
} |
TEST_F(ComboboxTest, ClickButDisabled) { |
@@ -528,15 +568,12 @@ TEST_F(ComboboxTest, ClickButDisabled) { |
combobox_->SetEnabled(false); |
// Click the left side, but nothing happens since the combobox is disabled. |
- TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); |
- scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); |
- test::MenuRunnerTestAPI test_api( |
- combobox_->dropdown_list_menu_runner_.get()); |
- test_api.SetMenuRunnerHandler(menu_runner_handler.Pass()); |
+ int menu_show_count = 0; |
+ test_api_->InstallTestMenuRunner(&menu_show_count); |
PerformClick(gfx::Point(combobox_->x() + 1, |
combobox_->y() + combobox_->height() / 2)); |
EXPECT_FALSE(listener.on_perform_action_called()); |
- EXPECT_FALSE(test_menu_runner_handler->executed()); |
+ EXPECT_EQ(0, menu_show_count); |
} |
TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) { |
@@ -587,27 +624,20 @@ TEST_F(ComboboxTest, NotifyOnClickWithMouse) { |
combobox_->Layout(); |
// Click the right side (arrow button). The menu is shown. |
- TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler(); |
- scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler); |
- scoped_ptr<test::MenuRunnerTestAPI> test_api( |
- new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get())); |
- test_api->SetMenuRunnerHandler(menu_runner_handler.Pass()); |
- |
+ int menu_show_count = 0; |
+ test_api_->InstallTestMenuRunner(&menu_show_count); |
+ EXPECT_EQ(0, menu_show_count); |
PerformClick(gfx::Point(combobox_->x() + combobox_->width() - 1, |
combobox_->y() + combobox_->height() / 2)); |
EXPECT_FALSE(listener.on_perform_action_called()); |
- EXPECT_TRUE(test_menu_runner_handler->executed()); |
+ EXPECT_EQ(1, menu_show_count); |
// Click the left side (text button). The click event is notified. |
- test_menu_runner_handler = new TestMenuRunnerHandler(); |
- menu_runner_handler.reset(test_menu_runner_handler); |
- test_api.reset( |
- new test::MenuRunnerTestAPI(combobox_->dropdown_list_menu_runner_.get())); |
- test_api->SetMenuRunnerHandler(menu_runner_handler.Pass()); |
+ test_api_->InstallTestMenuRunner(&menu_show_count); |
PerformClick(gfx::Point(combobox_->x() + 1, |
combobox_->y() + combobox_->height() / 2)); |
EXPECT_TRUE(listener.on_perform_action_called()); |
- EXPECT_FALSE(test_menu_runner_handler->executed()); |
+ EXPECT_EQ(1, menu_show_count); // Unchanged. |
EXPECT_EQ(0, listener.perform_action_index()); |
} |
@@ -632,6 +662,7 @@ TEST_F(ComboboxTest, ContentWidth) { |
std::vector<std::string> values; |
VectorComboboxModel model(&values); |
TestCombobox combobox(&model); |
+ ComboboxTestApi test_api(&combobox); |
std::string long_item = "this is the long item"; |
std::string short_item = "s"; |
@@ -640,12 +671,12 @@ TEST_F(ComboboxTest, ContentWidth) { |
values[0] = long_item; |
combobox.ModelChanged(); |
- const int long_item_width = combobox.content_size_.width(); |
+ const int long_item_width = test_api.content_size().width(); |
values[0] = short_item; |
combobox.ModelChanged(); |
- const int short_item_width = combobox.content_size_.width(); |
+ const int short_item_width = test_api.content_size().width(); |
values.resize(2); |
values[0] = short_item; |
@@ -654,12 +685,56 @@ TEST_F(ComboboxTest, ContentWidth) { |
// When the style is STYLE_NORMAL, the width will fit with the longest item. |
combobox.SetStyle(Combobox::STYLE_NORMAL); |
- EXPECT_EQ(long_item_width, combobox.content_size_.width()); |
+ EXPECT_EQ(long_item_width, test_api.content_size().width()); |
- // When the style is STYLE_ACTION, the width will fit with the first items' |
+ // When the style is STYLE_ACTION, the width will fit with the selected item's |
// width. |
combobox.SetStyle(Combobox::STYLE_ACTION); |
- EXPECT_EQ(short_item_width, combobox.content_size_.width()); |
+ EXPECT_EQ(short_item_width, test_api.content_size().width()); |
+} |
+ |
+// Test that model updates preserve the selected index, so long as it is in |
+// range. |
+TEST_F(ComboboxTest, ModelChanged) { |
+ InitCombobox(nullptr); |
+ |
+ EXPECT_EQ(0, combobox_->GetSelectedRow()); |
+ EXPECT_EQ(10, combobox_->GetRowCount()); |
+ |
+ combobox_->SetSelectedIndex(4); |
+ EXPECT_EQ(4, combobox_->GetSelectedRow()); |
+ |
+ model_->set_item_count(5); |
+ combobox_->ModelChanged(); |
+ EXPECT_EQ(5, combobox_->GetRowCount()); |
+ EXPECT_EQ(4, combobox_->GetSelectedRow()); // Unchanged. |
+ |
+ model_->set_item_count(4); |
+ combobox_->ModelChanged(); |
+ EXPECT_EQ(4, combobox_->GetRowCount()); |
+ EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
+ |
+ // Restore a non-zero selection. |
+ combobox_->SetSelectedIndex(2); |
+ EXPECT_EQ(2, combobox_->GetSelectedRow()); |
+ |
+ // Make the selected index a separator. |
+ std::set<int> separators; |
+ separators.insert(2); |
+ model_->SetSeparators(separators); |
+ combobox_->ModelChanged(); |
+ EXPECT_EQ(4, combobox_->GetRowCount()); |
+ EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
+ |
+ // Restore a non-zero selection. |
+ combobox_->SetSelectedIndex(1); |
+ EXPECT_EQ(1, combobox_->GetSelectedRow()); |
+ |
+ // Test an empty model. |
+ model_->set_item_count(0); |
+ combobox_->ModelChanged(); |
+ EXPECT_EQ(0, combobox_->GetRowCount()); |
+ EXPECT_EQ(0, combobox_->GetSelectedRow()); // Resets. |
} |
TEST_F(ComboboxTest, TypingPrefixNotifiesListener) { |
@@ -692,4 +767,42 @@ TEST_F(ComboboxTest, TypingPrefixNotifiesListener) { |
EXPECT_EQ(2, listener.perform_action_index()); |
} |
+// Test properties on the Combobox menu model. |
+TEST_F(ComboboxTest, MenuModel) { |
+ const int kSeparatorIndex = 3; |
+ std::set<int> separators; |
+ separators.insert(kSeparatorIndex); |
+ InitCombobox(&separators); |
+ |
+ ui::MenuModel* menu_model = test_api_->menu_model(); |
+ |
+ EXPECT_EQ(TestComboboxModel::kItemCount, menu_model->GetItemCount()); |
+ EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, |
+ menu_model->GetTypeAt(kSeparatorIndex)); |
+ |
+#if defined(OS_MACOSX) |
+ // Comboboxes on Mac should have checkmarks, with the selected item checked, |
+ EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(0)); |
+ EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu_model->GetTypeAt(1)); |
+ EXPECT_TRUE(menu_model->IsItemCheckedAt(0)); |
+ EXPECT_FALSE(menu_model->IsItemCheckedAt(1)); |
+ |
+ combobox_->SetSelectedIndex(1); |
+ EXPECT_FALSE(menu_model->IsItemCheckedAt(0)); |
+ EXPECT_TRUE(menu_model->IsItemCheckedAt(1)); |
+#else |
+ EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(0)); |
+ EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu_model->GetTypeAt(1)); |
+#endif |
+ |
+ EXPECT_EQ(ASCIIToUTF16("PEANUT BUTTER"), menu_model->GetLabelAt(0)); |
+ EXPECT_EQ(ASCIIToUTF16("JELLY"), menu_model->GetLabelAt(1)); |
+ |
+ // Check that with STYLE_ACTION, the first item (only) is not shown. |
+ EXPECT_TRUE(menu_model->IsVisibleAt(0)); |
+ combobox_->SetStyle(Combobox::STYLE_ACTION); |
+ EXPECT_FALSE(menu_model->IsVisibleAt(0)); |
+ EXPECT_TRUE(menu_model->IsVisibleAt(1)); |
+} |
+ |
} // namespace views |