@@ -0,0 +1,258 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtTest 1.0
19+import Ubuntu.Components 1.3
20+import Ubuntu.Components.ListItems 1.3
21+import Unity.Application 0.1
22+import QMenuModel 0.1
23+import Unity.Test 0.1
24+import Utils 0.1
25+
26+import "../../../qml/ApplicationMenus"
27+import "../Stages"
28+
29+Item {
30+ id: root
31+ width: Math.max(units.gu(100), page.width + units.gu(6))
32+ height: Math.max(units.gu(50), page.height + units.gu(6))
33+
34+ Binding {
35+ target: MouseTouchAdaptor
36+ property: "enabled"
37+ value: false
38+ }
39+
40+ DesktopMenuData { id: desktopMenuData }
41+
42+ Keys.onEscapePressed: {
43+ page.closePopup(true);
44+ }
45+
46+ MenuPage {
47+ id: page
48+ focus: true
49+
50+ anchors {
51+ left: parent.left
52+ top: parent.top
53+ leftMargin: units.gu(3)
54+ topMargin: units.gu(3)
55+ }
56+
57+ delegateModel: rootDelegate.submenuItems
58+ MenuItemDelegateBase {
59+ id: rootDelegate
60+ menuModel: UnityMenuModel {
61+ id: menuBackend
62+ modelData: desktopMenuData.generateTestData(3, 3, 0);
63+ }
64+ }
65+ }
66+
67+ SignalSpy {
68+ id: activatedSpy
69+ target: menuBackend
70+ signalName: "activated"
71+ }
72+
73+ UnityTestCase {
74+ id: testCase
75+ name: "MenuPage"
76+ when: windowShown
77+
78+ property bool clickNavigate: true
79+
80+ function init() {
81+ page.closePopup(true);
82+ menuBackend.modelData = desktopMenuData.generateTestData(3, 3, 0);
83+ activatedSpy.clear();
84+ }
85+
86+ // visit and verify that all the backend menus have been created
87+ function recurseMenuConstruction(rows, menuPageName) {
88+ for (var i = 0; i < rows.length; ++i) {
89+ var rowData = rows[i]["rowData"];
90+
91+ var menuPage = findChild(page, menuPageName);
92+ verify(menuPage);
93+ var menuItem = findChild(menuPage, menuPageName+"-menu"+i);
94+ verify(menuItem);
95+
96+ // recurse into submenu
97+ var submenu = rows[i]["submenu"];
98+ if (submenu) {
99+ if (clickNavigate) {
100+ mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
101+ } else {
102+ mouseMove(menuItem, menuItem.width/2, menuItem.height/2);
103+ }
104+ tryCompare(menuPage, "openItem", menuItem);
105+ recurseMenuConstruction(submenu, menuPageName+"-subMenu"+i);
106+ }
107+ }
108+ }
109+
110+ function test_hoverNavigation_data() {
111+ return [
112+ { tag: "long", testData: desktopMenuData.generateTestData(4, 2, 0) },
113+ { tag: "deep", testData: desktopMenuData.generateTestData(2, 4, 0) }
114+ ]
115+ }
116+
117+ function test_hoverNavigation(data) {
118+ clickNavigate = false;
119+ menuBackend.modelData = data.testData;
120+
121+ recurseMenuConstruction(data.testData, "menuPage");
122+ }
123+
124+ function test_clickNavigation_data() {
125+ return [
126+ { tag: "long", testData: desktopMenuData.generateTestData(4, 2, 0) },
127+ { tag: "deep", testData: desktopMenuData.generateTestData(2, 4, 0) }
128+ ]
129+ }
130+
131+ function test_clickNavigation(data) {
132+ clickNavigate = true;
133+ menuBackend.modelData = data.testData;
134+
135+ recurseMenuConstruction(data.testData, "menuPage");
136+ }
137+
138+ function test_checkableMenuTogglesOnClick() {
139+ menuBackend.modelData = desktopMenuData.singleCheckable;
140+
141+ var menuItem = findChild(page, "menuPage-menu0");
142+ verify(menuItem);
143+ verify(menuItem.delegate.isCheck);
144+ verify(menuItem.delegate.isToggled === false);
145+
146+ mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
147+
148+ compare(menuItem.delegate.isToggled, true, "Checkable menu should have toggled");
149+ }
150+
151+ function test_keyboardNavigation_DownKeySelectsAndOpensNextMenuItemAndRotates() {
152+ menuBackend.modelData = desktopMenuData.generateTestData(4, 2, 3);
153+ var listView = findChild(page, "menuPage-ListView");
154+ verify(listView);
155+
156+ var menuItem0 = findChild(page, "menuPage-menu0"); verify(menuItem0);
157+ var menuItem1 = findChild(page, "menuPage-menu1"); verify(menuItem1);
158+ var menuItem2 = findChild(page, "menuPage-menu2"); verify(menuItem2);
159+ verify(menuItem2.delegate.isSeparator);
160+ var menuItem3 = findChild(page, "menuPage-menu3"); verify(menuItem3);
161+
162+ keyClick(Qt.Key_Down, Qt.NoModifier, 100);
163+ compare(listView.selectedItem, menuItem0);
164+ tryCompare(page, "openItem", menuItem0);
165+
166+ keyClick(Qt.Key_Down, Qt.NoModifier, 100);
167+ compare(listView.selectedItem, menuItem1);
168+ tryCompare(page, "openItem", menuItem1);
169+
170+ // Skip separator
171+
172+ keyClick(Qt.Key_Down, Qt.NoModifier, 100);
173+ compare(listView.selectedItem, menuItem3);
174+ tryCompare(page, "openItem", menuItem3);
175+
176+ keyClick(Qt.Key_Down, Qt.NoModifier, 100);
177+ compare(listView.selectedItem, menuItem0);
178+ tryCompare(page, "openItem", menuItem0);
179+ }
180+
181+ function test_keyboardNavigation_UpKeySelectsAndOpensPreviousMenuItemAndRotates() {
182+ menuBackend.modelData = desktopMenuData.generateTestData(4, 2, 3);
183+ var listView = findChild(page, "menuPage-ListView");
184+ verify(listView);
185+
186+ var menuItem0 = findChild(page, "menuPage-menu0"); verify(menuItem0);
187+ var menuItem1 = findChild(page, "menuPage-menu1"); verify(menuItem1);
188+ var menuItem2 = findChild(page, "menuPage-menu2"); verify(menuItem2);
189+ verify(menuItem2.delegate.isSeparator);
190+ var menuItem3 = findChild(page, "menuPage-menu3"); verify(menuItem3);
191+
192+ keyClick(Qt.Key_Up, Qt.NoModifier, 100);
193+ compare(listView.selectedItem, menuItem3);
194+ tryCompare(page, "openItem", menuItem3);
195+
196+ // Skip separator
197+
198+ keyClick(Qt.Key_Up, Qt.NoModifier, 100);
199+ compare(listView.selectedItem, menuItem1);
200+ tryCompare(page, "openItem", menuItem1);
201+
202+ keyClick(Qt.Key_Up, Qt.NoModifier, 100);
203+ compare(listView.selectedItem, menuItem0);
204+ tryCompare(page, "openItem", menuItem0);
205+
206+ keyClick(Qt.Key_Up, Qt.NoModifier, 100);
207+ compare(listView.selectedItem, menuItem3);
208+ tryCompare(page, "openItem", menuItem3);
209+ }
210+
211+ function test_keyboardNavigation_RightKeyEntersSubMenu() {
212+ menuBackend.modelData = desktopMenuData.generateTestData(2, 2, 0);
213+
214+ var menuItem = findChild(page, "menuPage-menu0");
215+ verify(menuItem);
216+ page.open(menuItem, true);
217+ compare(page.openItem, menuItem);
218+
219+ var submenu = findChild(page, "menuPage-subMenu0");
220+ verify(submenu);
221+ var listView = findChild(page, "menuPage-subMenu0-ListView");
222+ verify(listView);
223+ menuItem = findChild(page, "menuPage-subMenu0-menu0");
224+ verify(menuItem);
225+
226+ keyClick(Qt.Key_Right, Qt.NoModifier);
227+ compare(listView.selectedItem, menuItem);
228+ }
229+
230+ function test_keyboardNavigation_LeftKeyClosesSubMenu() {
231+ menuBackend.modelData = desktopMenuData.generateTestData(2, 2, 0);
232+
233+ var menuItem = findChild(page, "menuPage-menu0");
234+ verify(menuItem);
235+ page.open(menuItem, true, 0); // quick open & select item 0
236+
237+ compare(page.openItem, menuItem);
238+ keyClick(Qt.Key_Left, Qt.NoModifier);
239+ compare(page.openItem, undefined);
240+ }
241+
242+ function test_mnemonics() {
243+ var menuItem0 = findChild(page, "menuPage-menu0"); verify(menuItem0);
244+
245+ keyClick(Qt.Key_A, Qt.NoModifier);
246+ tryCompare(page, "openItem", menuItem0);
247+
248+ var submenu0 = findChild(menuItem0, "menuPage-subMenu0"); verify(submenu0);
249+ var submenu0_menuItem1 = findChild(submenu0, "menuPage-subMenu0-menu1"); verify(submenu0_menuItem1);
250+
251+ keyClick(Qt.Key_B, Qt.NoModifier);
252+ tryCompare(submenu0, "openItem", submenu0_menuItem1);
253+
254+ keyClick(Qt.Key_B, Qt.NoModifier);
255+ compare(activatedSpy.signalArguments, [{ "0": "menuA.B.B" }], "Activate should have been emmited once");
256+ }
257+ }
258+}