Chromium Code Reviews| Index: chrome/test/menu_item_view_test.cc |
| diff --git a/chrome/test/menu_item_view_test.cc b/chrome/test/menu_item_view_test.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3ae236e3f907380100e541d01a8fd0ff48ad2727 |
| --- /dev/null |
| +++ b/chrome/test/menu_item_view_test.cc |
| @@ -0,0 +1,499 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/automation/ui_controls.h" |
| +#include "chrome/test/interactive_ui/view_event_test_base.h" |
| +#include "views/controls/button/menu_button.h" |
| +#include "views/controls/menu/menu_controller.h" |
| +#include "views/controls/menu/menu_item_view.h" |
| +#include "views/controls/menu/submenu_view.h" |
| +#include "views/controls/menu/view_menu_delegate.h" |
| +#include "views/widget/root_view.h" |
| +#include "views/window/window.h" |
| + |
| +// This is a convenience base class for all tests to provide some |
| +// common functionality. It sets up a MenuButton and a MenuItemView |
| +// and clicks the MenuButton. |
| +// |
| +// Subclasses should implement: |
| +// BuildMenu() populate the menu |
| +// DoTestOnMessageLoop() initiate the test |
| +// |
| +// Subclasses can call: |
| +// Click() to post a mouse click on a View |
| +// |
| +// Although it should be possible to post a menu multiple times, |
| +// MenuItemView prevents repeated activation of a menu by clicks too |
| +// close in time. |
| +class MenuItemViewTestBase : public ViewEventTestBase, |
| + public views::ViewMenuDelegate, |
| + public views::MenuDelegate { |
| + public: |
| + MenuItemViewTestBase() : ViewEventTestBase(), |
|
sky
2011/05/11 14:26:10
wrap to next line and indent 4.
rhashimoto
2011/05/11 19:41:07
Done.
|
| + button_(NULL), |
| + menu_(NULL) { |
| + } |
| + |
| + virtual ~MenuItemViewTestBase() { |
| + } |
| + |
| + // ViewEventTestBase implementation. |
| + |
| + virtual void SetUp() OVERRIDE { |
| + button_ = new views::MenuButton(NULL, L"Menu Test", this, true); |
| + menu_.reset(new views::MenuItemView(this)); |
| + BuildMenu(menu_.get()); |
| + |
| + ViewEventTestBase::SetUp(); |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| + menu_.reset(NULL); |
| + ViewEventTestBase::TearDown(); |
| + } |
| + |
| + virtual views::View* CreateContentsView() OVERRIDE { |
| + return button_; |
| + } |
| + |
| + virtual gfx::Size GetPreferredSize() OVERRIDE { |
| + return button_->GetPreferredSize(); |
| + } |
| + |
| + // views::ViewMenuDelegate implementation. |
| + virtual void RunMenu(views::View* source, const gfx::Point& pt) OVERRIDE { |
| + gfx::Point screen_location; |
| + views::View::ConvertPointToScreen(source, &screen_location); |
| + gfx::Rect bounds(screen_location, source->size()); |
| + menu_->RunMenuAt( |
| + source->GetWindow()->GetNativeWindow(), |
| + button_, |
| + bounds, |
| + views::MenuItemView::TOPLEFT, |
| + true); |
| + } |
| + |
| + protected: |
| + // Generate a mouse click on the specified view and post a new task. |
| + virtual void Click(views::View* view, Task* next) { |
| + ui_controls::MoveMouseToCenterAndPress( |
| + view, |
| + ui_controls::LEFT, |
| + ui_controls::DOWN | ui_controls::UP, |
| + next); |
| + } |
| + |
| + virtual void BuildMenu(views::MenuItemView* menu) { |
| + } |
| + |
| +#if defined(TOOLKIT_USES_GTK) |
| + // GTK processes widget size changes with an idle task so RootView |
| + // sizes are not updated reliably before an automation mouse click. |
| + // This can result in the event being marked outside the menu |
| + // bounds. To work around this issue for testing, this code short |
| + // circuits the RootView size update by setting it directly. |
| + void WorkaroundGTKRace() { |
| + views::Widget* widget = menu_->GetSubmenu()->GetWidget(); |
| + if (widget) { |
| + widget->GetRootView()->SetSize( |
| + widget->GetClientAreaScreenBounds().size()); |
| + } |
| + } |
| +#endif |
| + |
| + views::MenuButton* button_; |
| + scoped_ptr<views::MenuItemView> menu_; |
| +}; |
| + |
| +// Simple test for clicking a menu item. This template class clicks on an |
| +// item and checks that the returned id matches. The index of the item |
| +// is the template argument. |
| +template<int INDEX> |
| +class MenuItemViewTestBasic : public MenuItemViewTestBase { |
| + public: |
| + MenuItemViewTestBasic() : last_command_(0) { |
| + } |
| + |
| + virtual ~MenuItemViewTestBasic() { |
| + } |
| + |
| + // views::MenuDelegate implementation |
| + virtual void ExecuteCommand(int id) OVERRIDE { |
| + last_command_ = id; |
| + } |
| + |
| + // MenuItemViewTestBase implementation |
| + virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE { |
| + menu->AppendMenuItemWithLabel(1, L"item 1"); |
| + menu->AppendMenuItemWithLabel(2, L"item 2"); |
| + menu->AppendSeparator(); |
| + menu->AppendMenuItemWithLabel(3, L"item 3"); |
| + } |
| + |
| + // ViewEventTestBase implementation |
| + virtual void DoTestOnMessageLoop() OVERRIDE { |
| + Click(button_, CreateEventTask(this, &MenuItemViewTestBasic::Step1)); |
| + } |
| + |
| + // Click on item INDEX. |
| + void Step1() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_TRUE(submenu->IsShowing()); |
| + ASSERT_EQ(3, submenu->GetMenuItemCount()); |
| + |
| + // click an item and pass control to the next step |
| + views::MenuItemView* item = submenu->GetMenuItemAt(INDEX); |
| + ASSERT_TRUE(item); |
| + Click(item, CreateEventTask(this, &MenuItemViewTestBasic::Step2)); |
| + } |
| + |
| + // Check the clicked item and complete the test. |
| + void Step2() { |
| + ASSERT_FALSE(menu_->GetSubmenu()->IsShowing()); |
| + ASSERT_EQ(INDEX + 1,last_command_); |
| + Done(); |
| + } |
| + |
| + private: |
| + int last_command_; |
| +}; |
| + |
| +// Click each item of a 3-item menu (with separator). |
| +typedef MenuItemViewTestBasic<0> MenuItemViewTestBasic0; |
| +typedef MenuItemViewTestBasic<1> MenuItemViewTestBasic1; |
| +typedef MenuItemViewTestBasic<2> MenuItemViewTestBasic2; |
| +VIEW_TEST(MenuItemViewTestBasic0, SelectItem0) |
| +VIEW_TEST(MenuItemViewTestBasic1, SelectItem1) |
| +VIEW_TEST(MenuItemViewTestBasic2, SelectItem2) |
| + |
| +// Test class for inserting a menu item while the menu is open. |
| +template<int INSERT_INDEX, int SELECT_INDEX> |
| +class MenuItemViewTestInsert : public MenuItemViewTestBase { |
| + public: |
| + MenuItemViewTestInsert() : last_command_(0), |
|
sky
2011/05/11 14:26:10
wrap and indent 4.
rhashimoto
2011/05/11 19:41:07
Done.
|
| + inserted_item_(NULL) { |
| + } |
| + |
| + virtual ~MenuItemViewTestInsert() { |
| + } |
| + |
| + // views::MenuDelegate implementation |
| + virtual void ExecuteCommand(int id) OVERRIDE { |
| + last_command_ = id; |
| + } |
| + |
| + // MenuItemViewTestBase implementation |
| + virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE { |
| + menu->AppendMenuItemWithLabel(1, L"item 1"); |
| + menu->AppendMenuItemWithLabel(2, L"item 2"); |
| + } |
| + |
| + // ViewEventTestBase implementation |
| + virtual void DoTestOnMessageLoop() OVERRIDE { |
| + Click(button_, CreateEventTask(this, &MenuItemViewTestInsert::Step1)); |
| + } |
| + |
| + // Insert item at INSERT_INDEX and click item at SELECT_INDEX. |
| + void Step1() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_TRUE(submenu->IsShowing()); |
| + ASSERT_EQ(2, submenu->GetMenuItemCount()); |
| + |
| + inserted_item_ = menu_->AddMenuItemAt(INSERT_INDEX, 1000, |
| + L"inserted item", SkBitmap(), |
| + views::MenuItemView::NORMAL); |
| + ASSERT_TRUE(inserted_item_); |
| + menu_->ChildrenChanged(); |
| +#if defined(TOOLKIT_USES_GTK) |
| + WorkaroundGTKRace(); |
| +#endif |
| + |
| + // click an item and pass control to the next step |
| + views::MenuItemView* item = submenu->GetMenuItemAt(SELECT_INDEX); |
| + ASSERT_TRUE(item); |
| + Click(item, CreateEventTask(this, &MenuItemViewTestInsert::Step2)); |
| + } |
| + |
| + // Check clicked item and complete test. |
| + void Step2() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_FALSE(submenu->IsShowing()); |
| + ASSERT_EQ(3, submenu->GetMenuItemCount()); |
| + |
| + if (SELECT_INDEX == INSERT_INDEX) |
| + ASSERT_EQ(1000, last_command_); |
| + else if (SELECT_INDEX < INSERT_INDEX) |
| + ASSERT_EQ(SELECT_INDEX + 1, last_command_); |
| + else |
| + ASSERT_EQ(SELECT_INDEX, last_command_); |
| + |
| + Done(); |
| + } |
| + |
| + private: |
| + int last_command_; |
| + views::MenuItemView* inserted_item_; |
| +}; |
| + |
| +// MenuItemViewTestInsertXY inserts an item at index X and selects the |
| +// item at index Y (after the insertion). The tests here cover |
| +// inserting at the beginning, middle, and end, crossbarred with |
| +// selecting the first and last item. |
| +typedef MenuItemViewTestInsert<0,0> MenuItemViewTestInsert00; |
| +typedef MenuItemViewTestInsert<0,2> MenuItemViewTestInsert02; |
| +typedef MenuItemViewTestInsert<1,0> MenuItemViewTestInsert10; |
| +typedef MenuItemViewTestInsert<1,2> MenuItemViewTestInsert12; |
| +typedef MenuItemViewTestInsert<2,0> MenuItemViewTestInsert20; |
| +typedef MenuItemViewTestInsert<2,2> MenuItemViewTestInsert22; |
| +VIEW_TEST(MenuItemViewTestInsert00, InsertItem00) |
| +VIEW_TEST(MenuItemViewTestInsert02, InsertItem02) |
| +VIEW_TEST(MenuItemViewTestInsert10, InsertItem10) |
| +VIEW_TEST(MenuItemViewTestInsert12, InsertItem12) |
| +VIEW_TEST(MenuItemViewTestInsert20, InsertItem20) |
| +VIEW_TEST(MenuItemViewTestInsert22, InsertItem22) |
| + |
| +// Test class for inserting a menu item while a submenu is open. |
| +template<int INSERT_INDEX> |
| +class MenuItemViewTestInsertWithSubmenu : public MenuItemViewTestBase { |
| + public: |
| + MenuItemViewTestInsertWithSubmenu() : last_command_(0), |
| + submenu_(NULL), |
| + inserted_item_(NULL) { |
| + } |
| + |
| + virtual ~MenuItemViewTestInsertWithSubmenu() { |
| + } |
| + |
| + // views::MenuDelegate implementation |
| + virtual void ExecuteCommand(int id) OVERRIDE { |
| + last_command_ = id; |
| + } |
| + |
| + // MenuItemViewTestBase implementation |
| + virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE { |
| + submenu_ = menu->AppendSubMenu(1, L"My Submenu"); |
| + submenu_->AppendMenuItemWithLabel(101, L"submenu item 1"); |
| + submenu_->AppendMenuItemWithLabel(101, L"submenu item 2"); |
| + menu->AppendMenuItemWithLabel(2, L"item 2"); |
| + } |
| + |
| + // ViewEventTestBase implementation |
| + virtual void DoTestOnMessageLoop() OVERRIDE { |
| + Click(button_, |
| + CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step1)); |
| + } |
| + |
| + // Post submenu. |
| + void Step1() { |
| + Click(submenu_, |
| + CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step2)); |
| + } |
| + |
| + // Insert item at INSERT_INDEX. |
| + void Step2() { |
| + inserted_item_ = menu_->AddMenuItemAt(INSERT_INDEX, 1000, |
| + L"inserted item", SkBitmap(), |
| + views::MenuItemView::NORMAL); |
| + ASSERT_TRUE(inserted_item_); |
| + menu_->ChildrenChanged(); |
| +#if defined(TOOLKIT_USES_GTK) |
| + WorkaroundGTKRace(); |
| +#endif |
| + |
| + Click(inserted_item_, |
| + CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step3)); |
| + } |
| + |
| + void Step3() { |
| + Done(); |
| + } |
| + |
| + private: |
|
sky
2011/05/11 14:26:10
indentation is off.
rhashimoto
2011/05/11 19:41:07
Done.
|
| + int last_command_; |
| + views::MenuItemView* submenu_; |
| + views::MenuItemView* inserted_item_; |
| +}; |
| + |
| +// MenuItemViewTestInsertWithSubmenuX posts a menu and its submenu, |
| +// then inserts an item in the top-level menu at X. |
| +typedef MenuItemViewTestInsertWithSubmenu<0> MenuItemViewTestInsertWithSubmenu0; |
| +typedef MenuItemViewTestInsertWithSubmenu<1> MenuItemViewTestInsertWithSubmenu1; |
| +VIEW_TEST(MenuItemViewTestInsertWithSubmenu0, InsertItemWithSubmenu0) |
| +VIEW_TEST(MenuItemViewTestInsertWithSubmenu1, InsertItemWithSubmenu1) |
| + |
| +// Test class for removing a menu item while the menu is open. |
| +template<int REMOVE_INDEX, int SELECT_INDEX> |
| +class MenuItemViewTestRemove : public MenuItemViewTestBase { |
| + public: |
| + MenuItemViewTestRemove() : last_command_(0) { |
| + } |
| + |
| + virtual ~MenuItemViewTestRemove() { |
| + } |
| + |
| + // views::MenuDelegate implementation |
| + virtual void ExecuteCommand(int id) OVERRIDE { |
| + last_command_ = id; |
| + } |
| + |
| + // MenuItemViewTestBase implementation |
| + virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE { |
| + menu->AppendMenuItemWithLabel(1, L"item 1"); |
| + menu->AppendMenuItemWithLabel(2, L"item 2"); |
| + menu->AppendMenuItemWithLabel(3, L"item 3"); |
| + } |
| + |
| + // ViewEventTestBase implementation |
| + virtual void DoTestOnMessageLoop() OVERRIDE { |
| + Click(button_, CreateEventTask(this, &MenuItemViewTestRemove::Step1)); |
| + } |
| + |
| + // Remove item at REMOVE_INDEX and click item at SELECT_INDEX. |
| + void Step1() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_TRUE(submenu->IsShowing()); |
| + ASSERT_EQ(3, submenu->GetMenuItemCount()); |
| + |
| + // remove |
| + menu_->RemoveMenuItemAt(REMOVE_INDEX); |
| + menu_->ChildrenChanged(); |
| +#if defined(TOOLKIT_USES_GTK) |
| + WorkaroundGTKRace(); |
| +#endif |
| + |
| + // click |
| + views::MenuItemView* item = submenu->GetMenuItemAt(SELECT_INDEX); |
| + ASSERT_TRUE(item); |
| + Click(item, CreateEventTask(this, &MenuItemViewTestRemove::Step2)); |
| + } |
| + |
| + // Check clicked item and complete test. |
| + void Step2() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_FALSE(submenu->IsShowing()); |
| + ASSERT_EQ(2, submenu->GetMenuItemCount()); |
| + |
| + if (SELECT_INDEX < REMOVE_INDEX) |
| + ASSERT_EQ(SELECT_INDEX + 1, last_command_); |
| + else |
| + ASSERT_EQ(SELECT_INDEX + 2, last_command_); |
| + |
| + Done(); |
| + } |
| + |
| + private: |
| + int last_command_; |
| +}; |
| + |
| +typedef MenuItemViewTestRemove<0,0> MenuItemViewTestRemove00; |
| +typedef MenuItemViewTestRemove<0,1> MenuItemViewTestRemove01; |
| +typedef MenuItemViewTestRemove<1,0> MenuItemViewTestRemove10; |
| +typedef MenuItemViewTestRemove<1,1> MenuItemViewTestRemove11; |
| +typedef MenuItemViewTestRemove<2,0> MenuItemViewTestRemove20; |
| +typedef MenuItemViewTestRemove<2,1> MenuItemViewTestRemove21; |
| +VIEW_TEST(MenuItemViewTestRemove00, RemoveItem00) |
| +VIEW_TEST(MenuItemViewTestRemove01, RemoveItem01) |
| +VIEW_TEST(MenuItemViewTestRemove10, RemoveItem10) |
| +VIEW_TEST(MenuItemViewTestRemove11, RemoveItem11) |
| +VIEW_TEST(MenuItemViewTestRemove20, RemoveItem20) |
| +VIEW_TEST(MenuItemViewTestRemove21, RemoveItem21) |
| + |
| +// Test class for removing a menu item while a submenu is open. |
| +template<int REMOVE_INDEX> |
| +class MenuItemViewTestRemoveWithSubmenu : public MenuItemViewTestBase { |
| + public: |
| + MenuItemViewTestRemoveWithSubmenu() : last_command_(0), |
| + submenu_(NULL) { |
| + } |
| + |
| + virtual ~MenuItemViewTestRemoveWithSubmenu() { |
| + } |
| + |
| + // views::MenuDelegate implementation |
| + virtual void ExecuteCommand(int id) OVERRIDE { |
| + last_command_ = id; |
| + } |
| + |
| + // MenuItemViewTestBase implementation |
| + virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE { |
| + menu->AppendMenuItemWithLabel(1, L"item 1"); |
| + submenu_ = menu->AppendSubMenu(2, L"My Submenu"); |
| + submenu_->AppendMenuItemWithLabel(101, L"submenu item 1"); |
| + submenu_->AppendMenuItemWithLabel(102, L"submenu item 2"); |
| + } |
| + |
| + // ViewEventTestBase implementation |
| + virtual void DoTestOnMessageLoop() OVERRIDE { |
| + Click(button_, |
| + CreateEventTask(this, &MenuItemViewTestRemoveWithSubmenu::Step1)); |
| + } |
| + |
| + // Post submenu. |
| + void Step1() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_TRUE(submenu->IsShowing()); |
| + |
| + Click(submenu_, |
| + CreateEventTask(this, &MenuItemViewTestRemoveWithSubmenu::Step2)); |
| + } |
| + |
| + // Remove item at REMOVE_INDEX and select it to exit the menu loop. |
| + void Step2() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_TRUE(submenu->IsShowing()); |
| + ASSERT_EQ(2, submenu->GetMenuItemCount()); |
| + |
| + // remove |
| + menu_->RemoveMenuItemAt(REMOVE_INDEX); |
| + menu_->ChildrenChanged(); |
| +#if defined(TOOLKIT_USES_GTK) |
| + WorkaroundGTKRace(); |
| +#endif |
| + |
| + // click |
| + Click(button_, |
| + CreateEventTask(this, &MenuItemViewTestRemoveWithSubmenu::Step3)); |
| + } |
| + |
| + void Step3() { |
| + ASSERT_TRUE(menu_.get()); |
| + |
| + views::SubmenuView* submenu = menu_->GetSubmenu(); |
| + ASSERT_TRUE(submenu); |
| + ASSERT_FALSE(submenu->IsShowing()); |
| + ASSERT_EQ(1, submenu->GetMenuItemCount()); |
| + |
| + Done(); |
| + } |
| + |
| + private: |
|
sky
2011/05/11 14:26:10
indentation is off.
rhashimoto
2011/05/11 19:41:07
Done.
|
| + int last_command_; |
| + views::MenuItemView* submenu_; |
| +}; |
| + |
| +typedef MenuItemViewTestRemoveWithSubmenu<0> MenuItemViewTestRemoveWithSubmenu0; |
| +typedef MenuItemViewTestRemoveWithSubmenu<1> MenuItemViewTestRemoveWithSubmenu1; |
| +VIEW_TEST(MenuItemViewTestRemoveWithSubmenu0, RemoveItemWithSubmenu0) |
| +VIEW_TEST(MenuItemViewTestRemoveWithSubmenu1, RemoveItemWithSubmenu1) |