| 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
|
|
|