1// Copyright 2014 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.
4
5#include "base/strings/utf_string_conversions.h"
6#include "chrome/browser/ui/views/menu_test_base.h"
7#include "ui/views/controls/menu/menu_item_view.h"
8#include "ui/views/controls/menu/submenu_view.h"
9
10using base::ASCIIToUTF16;
11
12// Simple test for clicking a menu item.  This template class clicks on an
13// item and checks that the returned id matches.  The index of the item
14// is the template argument.
15template<int INDEX>
16class MenuItemViewTestBasic : public MenuTestBase {
17 public:
18  MenuItemViewTestBasic() {
19  }
20
21  virtual ~MenuItemViewTestBasic() {
22  }
23
24  // MenuTestBase implementation
25  virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE {
26    menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1"));
27    menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2"));
28    menu->AppendSeparator();
29    menu->AppendMenuItemWithLabel(3, ASCIIToUTF16("item 3"));
30  }
31
32  // Click on item INDEX.
33  virtual void DoTestWithMenuOpen() OVERRIDE {
34    views::SubmenuView* submenu = menu()->GetSubmenu();
35    ASSERT_TRUE(submenu);
36    ASSERT_TRUE(submenu->IsShowing());
37    ASSERT_EQ(3, submenu->GetMenuItemCount());
38
39    // click an item and pass control to the next step
40    views::MenuItemView* item = submenu->GetMenuItemAt(INDEX);
41    ASSERT_TRUE(item);
42    Click(item, CreateEventTask(this, &MenuItemViewTestBasic::Step2));
43  }
44
45  // Check the clicked item and complete the test.
46  void Step2() {
47    ASSERT_FALSE(menu()->GetSubmenu()->IsShowing());
48    ASSERT_EQ(INDEX + 1, last_command());
49    Done();
50  }
51
52 private:
53  DISALLOW_COPY_AND_ASSIGN(MenuItemViewTestBasic);
54};
55
56// Click each item of a 3-item menu (with separator).
57typedef MenuItemViewTestBasic<0> MenuItemViewTestBasic0;
58typedef MenuItemViewTestBasic<1> MenuItemViewTestBasic1;
59typedef MenuItemViewTestBasic<2> MenuItemViewTestBasic2;
60VIEW_TEST(MenuItemViewTestBasic0, SelectItem0)
61VIEW_TEST(MenuItemViewTestBasic1, SelectItem1)
62VIEW_TEST(MenuItemViewTestBasic2, SelectItem2)
63
64// Test class for inserting a menu item while the menu is open.
65template<int INSERT_INDEX, int SELECT_INDEX>
66class MenuItemViewTestInsert : public MenuTestBase {
67 public:
68  MenuItemViewTestInsert() : inserted_item_(NULL) {
69  }
70
71  virtual ~MenuItemViewTestInsert() {
72  }
73
74  // MenuTestBase implementation
75  virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE {
76    menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1"));
77    menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2"));
78  }
79
80  // Insert item at INSERT_INDEX and click item at SELECT_INDEX.
81  virtual void DoTestWithMenuOpen() OVERRIDE {
82    views::SubmenuView* submenu = menu()->GetSubmenu();
83    ASSERT_TRUE(submenu);
84    ASSERT_TRUE(submenu->IsShowing());
85    ASSERT_EQ(2, submenu->GetMenuItemCount());
86
87    inserted_item_ = menu()->AddMenuItemAt(INSERT_INDEX,
88                                           1000,
89                                           ASCIIToUTF16("inserted item"),
90                                           base::string16(),
91                                           base::string16(),
92                                           gfx::ImageSkia(),
93                                           views::MenuItemView::NORMAL,
94                                           ui::NORMAL_SEPARATOR);
95    ASSERT_TRUE(inserted_item_);
96    menu()->ChildrenChanged();
97
98    // click an item and pass control to the next step
99    views::MenuItemView* item = submenu->GetMenuItemAt(SELECT_INDEX);
100    ASSERT_TRUE(item);
101    Click(item, CreateEventTask(this, &MenuItemViewTestInsert::Step2));
102  }
103
104  // Check clicked item and complete test.
105  void Step2() {
106    views::SubmenuView* submenu = menu()->GetSubmenu();
107    ASSERT_TRUE(submenu);
108    ASSERT_FALSE(submenu->IsShowing());
109    ASSERT_EQ(3, submenu->GetMenuItemCount());
110
111    if (SELECT_INDEX == INSERT_INDEX)
112      ASSERT_EQ(1000, last_command());
113    else if (SELECT_INDEX < INSERT_INDEX)
114      ASSERT_EQ(SELECT_INDEX + 1, last_command());
115    else
116      ASSERT_EQ(SELECT_INDEX, last_command());
117
118    Done();
119  }
120
121 private:
122  views::MenuItemView* inserted_item_;
123
124  DISALLOW_COPY_AND_ASSIGN(MenuItemViewTestInsert);
125};
126
127// MenuItemViewTestInsertXY inserts an item at index X and selects the
128// item at index Y (after the insertion).  The tests here cover
129// inserting at the beginning, middle, and end, crossbarred with
130// selecting the first and last item.
131typedef MenuItemViewTestInsert<0,0> MenuItemViewTestInsert00;
132typedef MenuItemViewTestInsert<0,2> MenuItemViewTestInsert02;
133typedef MenuItemViewTestInsert<1,0> MenuItemViewTestInsert10;
134typedef MenuItemViewTestInsert<1,2> MenuItemViewTestInsert12;
135typedef MenuItemViewTestInsert<2,0> MenuItemViewTestInsert20;
136typedef MenuItemViewTestInsert<2,2> MenuItemViewTestInsert22;
137VIEW_TEST(MenuItemViewTestInsert00, InsertItem00)
138VIEW_TEST(MenuItemViewTestInsert02, InsertItem02)
139VIEW_TEST(MenuItemViewTestInsert10, InsertItem10)
140VIEW_TEST(MenuItemViewTestInsert12, InsertItem12)
141VIEW_TEST(MenuItemViewTestInsert20, InsertItem20)
142VIEW_TEST(MenuItemViewTestInsert22, InsertItem22)
143
144// Test class for inserting a menu item while a submenu is open.
145template<int INSERT_INDEX>
146class MenuItemViewTestInsertWithSubmenu : public MenuTestBase {
147 public:
148  MenuItemViewTestInsertWithSubmenu() :
149      submenu_(NULL),
150      inserted_item_(NULL) {
151  }
152
153  virtual ~MenuItemViewTestInsertWithSubmenu() {
154  }
155
156  // MenuTestBase implementation
157  virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE {
158    submenu_ = menu->AppendSubMenu(1, ASCIIToUTF16("My Submenu"));
159    submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 1"));
160    submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 2"));
161    menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2"));
162  }
163
164  // Post submenu.
165  virtual void DoTestWithMenuOpen() OVERRIDE {
166    Click(submenu_,
167          CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step2));
168  }
169
170  // Insert item at INSERT_INDEX.
171  void Step2() {
172    inserted_item_ = menu()->AddMenuItemAt(INSERT_INDEX,
173                                           1000,
174                                           ASCIIToUTF16("inserted item"),
175                                           base::string16(),
176                                           base::string16(),
177                                           gfx::ImageSkia(),
178                                           views::MenuItemView::NORMAL,
179                                           ui::NORMAL_SEPARATOR);
180    ASSERT_TRUE(inserted_item_);
181    menu()->ChildrenChanged();
182
183    Click(inserted_item_,
184          CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step3));
185  }
186
187  void Step3() {
188    Done();
189  }
190
191 private:
192  views::MenuItemView* submenu_;
193  views::MenuItemView* inserted_item_;
194
195  DISALLOW_COPY_AND_ASSIGN(MenuItemViewTestInsertWithSubmenu);
196};
197
198// MenuItemViewTestInsertWithSubmenuX posts a menu and its submenu,
199// then inserts an item in the top-level menu at X.
200typedef MenuItemViewTestInsertWithSubmenu<0> MenuItemViewTestInsertWithSubmenu0;
201typedef MenuItemViewTestInsertWithSubmenu<1> MenuItemViewTestInsertWithSubmenu1;
202VIEW_TEST(MenuItemViewTestInsertWithSubmenu0, InsertItemWithSubmenu0)
203VIEW_TEST(MenuItemViewTestInsertWithSubmenu1, InsertItemWithSubmenu1)
204
205// Test class for removing a menu item while the menu is open.
206template<int REMOVE_INDEX, int SELECT_INDEX>
207class MenuItemViewTestRemove : public MenuTestBase {
208 public:
209  MenuItemViewTestRemove() {
210  }
211
212  virtual ~MenuItemViewTestRemove() {
213  }
214
215  // MenuTestBase implementation
216  virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE {
217    menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1"));
218    menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2"));
219    menu->AppendMenuItemWithLabel(3, ASCIIToUTF16("item 3"));
220  }
221
222  // Remove item at REMOVE_INDEX and click item at SELECT_INDEX.
223  virtual void DoTestWithMenuOpen() OVERRIDE {
224    views::SubmenuView* submenu = menu()->GetSubmenu();
225    ASSERT_TRUE(submenu);
226    ASSERT_TRUE(submenu->IsShowing());
227    ASSERT_EQ(3, submenu->GetMenuItemCount());
228
229    // remove
230    menu()->RemoveMenuItemAt(REMOVE_INDEX);
231    menu()->ChildrenChanged();
232
233    // click
234    views::MenuItemView* item = submenu->GetMenuItemAt(SELECT_INDEX);
235    ASSERT_TRUE(item);
236    Click(item, CreateEventTask(this, &MenuItemViewTestRemove::Step2));
237  }
238
239  // Check clicked item and complete test.
240  void Step2() {
241    views::SubmenuView* submenu = menu()->GetSubmenu();
242    ASSERT_TRUE(submenu);
243    ASSERT_FALSE(submenu->IsShowing());
244    ASSERT_EQ(2, submenu->GetMenuItemCount());
245
246    if (SELECT_INDEX < REMOVE_INDEX)
247      ASSERT_EQ(SELECT_INDEX + 1, last_command());
248    else
249      ASSERT_EQ(SELECT_INDEX + 2, last_command());
250
251    Done();
252  }
253
254 private:
255  DISALLOW_COPY_AND_ASSIGN(MenuItemViewTestRemove);
256};
257
258typedef MenuItemViewTestRemove<0,0> MenuItemViewTestRemove00;
259typedef MenuItemViewTestRemove<0,1> MenuItemViewTestRemove01;
260typedef MenuItemViewTestRemove<1,0> MenuItemViewTestRemove10;
261typedef MenuItemViewTestRemove<1,1> MenuItemViewTestRemove11;
262typedef MenuItemViewTestRemove<2,0> MenuItemViewTestRemove20;
263typedef MenuItemViewTestRemove<2,1> MenuItemViewTestRemove21;
264VIEW_TEST(MenuItemViewTestRemove00, RemoveItem00)
265VIEW_TEST(MenuItemViewTestRemove01, RemoveItem01)
266VIEW_TEST(MenuItemViewTestRemove10, RemoveItem10)
267VIEW_TEST(MenuItemViewTestRemove11, RemoveItem11)
268VIEW_TEST(MenuItemViewTestRemove20, RemoveItem20)
269VIEW_TEST(MenuItemViewTestRemove21, RemoveItem21)
270
271// Test class for removing a menu item while a submenu is open.
272template<int REMOVE_INDEX>
273class MenuItemViewTestRemoveWithSubmenu : public MenuTestBase {
274 public:
275  MenuItemViewTestRemoveWithSubmenu() : submenu_(NULL) {
276  }
277
278  virtual ~MenuItemViewTestRemoveWithSubmenu() {
279  }
280
281  // MenuTestBase implementation
282  virtual void BuildMenu(views::MenuItemView* menu) OVERRIDE {
283    menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1"));
284    submenu_ = menu->AppendSubMenu(2, ASCIIToUTF16("My Submenu"));
285    submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 1"));
286    submenu_->AppendMenuItemWithLabel(102, ASCIIToUTF16("submenu item 2"));
287  }
288
289  // Post submenu.
290  virtual void DoTestWithMenuOpen() OVERRIDE {
291    views::SubmenuView* submenu = menu()->GetSubmenu();
292    ASSERT_TRUE(submenu);
293    ASSERT_TRUE(submenu->IsShowing());
294
295    Click(submenu_,
296          CreateEventTask(this, &MenuItemViewTestRemoveWithSubmenu::Step2));
297  }
298
299  // Remove item at REMOVE_INDEX and press escape to exit the menu loop.
300  void Step2() {
301    views::SubmenuView* submenu = menu()->GetSubmenu();
302    ASSERT_TRUE(submenu);
303    ASSERT_TRUE(submenu->IsShowing());
304    ASSERT_EQ(2, submenu->GetMenuItemCount());
305
306    // remove
307    menu()->RemoveMenuItemAt(REMOVE_INDEX);
308    menu()->ChildrenChanged();
309
310    // click
311    KeyPress(ui::VKEY_ESCAPE,
312             CreateEventTask(this, &MenuItemViewTestRemoveWithSubmenu::Step3));
313  }
314
315  void Step3() {
316    views::SubmenuView* submenu = menu()->GetSubmenu();
317    ASSERT_TRUE(submenu);
318    ASSERT_FALSE(submenu->IsShowing());
319    ASSERT_EQ(1, submenu->GetMenuItemCount());
320
321    Done();
322  }
323
324 private:
325  views::MenuItemView* submenu_;
326
327  DISALLOW_COPY_AND_ASSIGN(MenuItemViewTestRemoveWithSubmenu);
328};
329
330typedef MenuItemViewTestRemoveWithSubmenu<0> MenuItemViewTestRemoveWithSubmenu0;
331typedef MenuItemViewTestRemoveWithSubmenu<1> MenuItemViewTestRemoveWithSubmenu1;
332
333#if defined(USE_OZONE)
334// ozone bringup - http://crbug.com/401304
335#define MAYBE_RemoveItemWithSubmenu0 DISABLED_RemoveItemWithSubmenu0
336#define MAYBE_RemoveItemWithSubmenu1 DISABLED_RemoveItemWithSubmenu1
337#else
338#define MAYBE_RemoveItemWithSubmenu0 RemoveItemWithSubmenu0
339#define MAYBE_RemoveItemWithSubmenu1 RemoveItemWithSubmenu1
340#endif
341
342VIEW_TEST(MenuItemViewTestRemoveWithSubmenu0, MAYBE_RemoveItemWithSubmenu0)
343VIEW_TEST(MenuItemViewTestRemoveWithSubmenu1, MAYBE_RemoveItemWithSubmenu1)
344