|
1 <?xml version="1.0"?> |
|
2 |
|
3 <?xml-stylesheet href="chrome://global/skin" type="text/css"?> |
|
4 |
|
5 <window id="StandaloneNativeMenuWindow" |
|
6 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
7 width="300" |
|
8 height="300" |
|
9 onload="onLoad();" |
|
10 title="nsIStandaloneNativeMenu Test"> |
|
11 |
|
12 <command id="cmd_FooItem0" oncommand="executedCommandID = 'cmd_FooItem0';"/> |
|
13 <command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/> |
|
14 <command id="cmd_BarItem0" oncommand="executedCommandID = 'cmd_BarItem0';"/> |
|
15 <command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/> |
|
16 <command id="cmd_NewItem0" oncommand="executedCommandID = 'cmd_NewItem0';"/> |
|
17 <command id="cmd_NewItem1" oncommand="executedCommandID = 'cmd_NewItem1';"/> |
|
18 <command id="cmd_NewItem2" oncommand="executedCommandID = 'cmd_NewItem2';"/> |
|
19 <command id="cmd_NewItem3" oncommand="executedCommandID = 'cmd_NewItem3';"/> |
|
20 <command id="cmd_NewItem4" oncommand="executedCommandID = 'cmd_NewItem4';"/> |
|
21 <command id="cmd_NewItem5" oncommand="executedCommandID = 'cmd_NewItem5';"/> |
|
22 |
|
23 <!-- We do not modify any menus or menu items defined here in testing. These |
|
24 serve as a baseline structure for us to test after other modifications. |
|
25 We add children to the menubar defined here and test by modifying those |
|
26 children. --> |
|
27 <popupset> |
|
28 <menupopup id="standalonenativemenu"> |
|
29 <menu id="foo" label="Foo"> |
|
30 <menupopup> |
|
31 <menuitem label="FooItem0" command="cmd_FooItem0"/> |
|
32 <menuitem label="FooItem1" command="cmd_FooItem1"/> |
|
33 <menuseparator/> |
|
34 <menu label="Bar"> |
|
35 <menupopup> |
|
36 <menuitem label="BarItem0" command="cmd_BarItem0"/> |
|
37 <menuitem label="BarItem1" command="cmd_BarItem1"/> |
|
38 </menupopup> |
|
39 </menu> |
|
40 </menupopup> |
|
41 </menu> |
|
42 </menupopup> |
|
43 </popupset> |
|
44 |
|
45 <script type="application/javascript"><![CDATA[ |
|
46 |
|
47 function ok(condition, message) { |
|
48 window.opener.wrappedJSObject.SimpleTest.ok(condition, message); |
|
49 } |
|
50 |
|
51 function todo(condition, message) { |
|
52 window.opener.wrappedJSObject.SimpleTest.todo(condition, message); |
|
53 } |
|
54 |
|
55 function onTestsFinished() { |
|
56 window.close(); |
|
57 window.opener.wrappedJSObject.SimpleTest.finish(); |
|
58 } |
|
59 |
|
60 var executedCommandID = ""; |
|
61 |
|
62 function testItem(menu, location, targetID) { |
|
63 var correctCommandHandler = false; |
|
64 try { |
|
65 menu.menuWillOpen(); |
|
66 menu.activateNativeMenuItemAt(location); |
|
67 correctCommandHandler = executedCommandID == targetID; |
|
68 } |
|
69 catch (e) { |
|
70 dump(e + "\n"); |
|
71 } |
|
72 finally { |
|
73 executedCommandID = ""; |
|
74 return correctCommandHandler; |
|
75 } |
|
76 } |
|
77 |
|
78 var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |
|
79 |
|
80 function createXULMenuPopup() { |
|
81 return document.createElementNS(XUL_NS, "menupopup"); |
|
82 } |
|
83 |
|
84 function createXULMenu(aLabel) { |
|
85 var item = document.createElementNS(XUL_NS, "menu"); |
|
86 item.setAttribute("label", aLabel); |
|
87 return item; |
|
88 } |
|
89 |
|
90 function createXULMenuItem(aLabel, aCommandId) { |
|
91 var item = document.createElementNS(XUL_NS, "menuitem"); |
|
92 item.setAttribute("label", aLabel); |
|
93 item.setAttribute("command", aCommandId); |
|
94 return item; |
|
95 } |
|
96 |
|
97 function runBaseMenuTests(menu) { |
|
98 menu.forceUpdateNativeMenuAt("0|3"); |
|
99 return testItem(menu, "0|0", "cmd_FooItem0") && |
|
100 testItem(menu, "0|1", "cmd_FooItem1") && |
|
101 testItem(menu, "0|3|0", "cmd_BarItem0") && |
|
102 testItem(menu, "0|3|1", "cmd_BarItem1"); |
|
103 } |
|
104 |
|
105 function onLoad() { |
|
106 var _delayedOnLoad = function() { |
|
107 var Cc = Components.classes; |
|
108 var Ci = Components.interfaces; |
|
109 |
|
110 var menuNode = document.getElementById("standalonenativemenu"); |
|
111 var menu; |
|
112 try { |
|
113 menu = Cc["@mozilla.org/widget/standalonenativemenu;1"].createInstance(Ci.nsIStandaloneNativeMenu); |
|
114 menu.init(menuNode); |
|
115 } catch (e) { |
|
116 ok(false, "Create nsIStandaloneNativeMenu instance"); |
|
117 onTestsFinished(); |
|
118 return; |
|
119 } |
|
120 |
|
121 // First let's run the base menu tests. |
|
122 ok(runBaseMenuTests(menu), "base tests #1"); |
|
123 |
|
124 // Set up some nodes that we'll use. |
|
125 //var menubarNode = document.getElementById("nativemenubar"); |
|
126 var newMenu0 = createXULMenu("NewMenu0"); |
|
127 var newMenu1 = createXULMenu("NewMenu1"); |
|
128 var newMenuPopup0 = createXULMenuPopup(); |
|
129 var newMenuPopup1 = createXULMenuPopup(); |
|
130 var newMenuItem0 = createXULMenuItem("NewMenuItem0", "cmd_NewItem0"); |
|
131 var newMenuItem1 = createXULMenuItem("NewMenuItem1", "cmd_NewItem1"); |
|
132 var newMenuItem2 = createXULMenuItem("NewMenuItem2", "cmd_NewItem2"); |
|
133 var newMenuItem3 = createXULMenuItem("NewMenuItem3", "cmd_NewItem3"); |
|
134 var newMenuItem4 = createXULMenuItem("NewMenuItem4", "cmd_NewItem4"); |
|
135 var newMenuItem5 = createXULMenuItem("NewMenuItem5", "cmd_NewItem5"); |
|
136 |
|
137 // Create another submenu with hierarchy via DOM manipulation. |
|
138 // ****************** |
|
139 // * Foo * NewMenu0 * <- Menu bar |
|
140 // ****************** |
|
141 // **************** |
|
142 // * NewMenuItem0 * <- NewMenu0 submenu |
|
143 // **************** |
|
144 // * NewMenuItem1 * |
|
145 // **************** |
|
146 // * NewMenuItem2 * |
|
147 // ******************************* |
|
148 // * NewMenu1 > * NewMenuItem3 * <- NewMenu1 submenu |
|
149 // ******************************* |
|
150 // * NewMenuItem4 * |
|
151 // **************** |
|
152 // * NewMenuItem5 * |
|
153 // **************** |
|
154 newMenu0.appendChild(newMenuPopup0); |
|
155 newMenuPopup0.appendChild(newMenuItem0); |
|
156 newMenuPopup0.appendChild(newMenuItem1); |
|
157 newMenuPopup0.appendChild(newMenuItem2); |
|
158 newMenuPopup0.appendChild(newMenu1); |
|
159 newMenu1.appendChild(newMenuPopup1); |
|
160 newMenuPopup1.appendChild(newMenuItem3); |
|
161 newMenuPopup1.appendChild(newMenuItem4); |
|
162 newMenuPopup1.appendChild(newMenuItem5); |
|
163 //XXX - we have to append the menu to the top-level of the menu bar |
|
164 // only after constructing it. If we append before construction, it is |
|
165 // invalid because it has no children and we don't validate it if we add |
|
166 // children later. |
|
167 menuNode.appendChild(newMenu0); |
|
168 menu.forceUpdateNativeMenuAt("1|3"); |
|
169 // Run basic tests again. |
|
170 ok(runBaseMenuTests(menu), "base tests #2"); |
|
171 |
|
172 // Error strings. |
|
173 var sa = "Command handler(s) should have activated"; |
|
174 var sna = "Command handler(s) should not have activated"; |
|
175 |
|
176 // Test middle items. |
|
177 ok(testItem(menu, "1|1", "cmd_NewItem1"), "#1:" + sa); |
|
178 ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#2:" + sa); |
|
179 |
|
180 // Hide newMenu0. |
|
181 newMenu0.setAttribute("hidden", "true"); |
|
182 ok(runBaseMenuTests(menu), "base tests #3: " + sa); // the base menu should still be unhidden |
|
183 ok(!testItem(menu, "1|0", ""), "#3:" + sna); |
|
184 ok(!testItem(menu, "1|1", ""), "#4:" + sna); |
|
185 ok(!testItem(menu, "1|2", ""), "#5:" + sna); |
|
186 ok(!testItem(menu, "1|3|0", ""), "#6:" + sna); |
|
187 ok(!testItem(menu, "1|3|1", ""), "#7:" + sna); |
|
188 ok(!testItem(menu, "1|3|2", ""), "#8:" + sna); |
|
189 |
|
190 // Show newMenu0. |
|
191 newMenu0.setAttribute("hidden", "false"); |
|
192 menu.forceUpdateNativeMenuAt("1|3"); |
|
193 ok(runBaseMenuTests(menu), "base tests #4:" + sa); |
|
194 ok(testItem(menu, "1|0", "cmd_NewItem0"), "#9:" + sa); |
|
195 ok(testItem(menu, "1|1", "cmd_NewItem1"), "#10:" + sa); |
|
196 ok(testItem(menu, "1|2", "cmd_NewItem2"), "#11:" + sa); |
|
197 ok(testItem(menu, "1|3|0", "cmd_NewItem3"), "#12:" + sa); |
|
198 ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#13:" + sa); |
|
199 ok(testItem(menu, "1|3|2", "cmd_NewItem5"), "#14:" + sa); |
|
200 |
|
201 // Hide items. |
|
202 newMenuItem1.setAttribute("hidden", "true"); |
|
203 newMenuItem4.setAttribute("hidden", "true"); |
|
204 menu.forceUpdateNativeMenuAt("1|2"); |
|
205 ok(runBaseMenuTests(menu), "base tests #5:" + sa); |
|
206 ok(testItem(menu, "1|0", "cmd_NewItem0"), "#15:" + sa); |
|
207 ok(testItem(menu, "1|1", "cmd_NewItem2"), "#16:" + sa); |
|
208 ok(!testItem(menu, "1|2", ""), "#17:" + sna); |
|
209 ok(testItem(menu, "1|2|0", "cmd_NewItem3"), "#18:" + sa); |
|
210 ok(testItem(menu, "1|2|1", "cmd_NewItem5"), "#19:" + sa); |
|
211 ok(!testItem(menu, "1|2|2", ""), "#20:" + sna); |
|
212 |
|
213 // Show items. |
|
214 newMenuItem1.setAttribute("hidden", "false"); |
|
215 newMenuItem4.setAttribute("hidden", "false"); |
|
216 //forceUpdateNativeMenuAt("1|3"); |
|
217 ok(runBaseMenuTests(menu), "base tests #6:" + sa); |
|
218 ok(testItem(menu, "1|0", "cmd_NewItem0"), "#21:" + sa); |
|
219 ok(testItem(menu, "1|1", "cmd_NewItem1"), "#22:" + sa); |
|
220 ok(testItem(menu, "1|2", "cmd_NewItem2"), "#23:" + sa); |
|
221 ok(testItem(menu, "1|3|0", "cmd_NewItem3"), "#24:" + sa); |
|
222 ok(testItem(menu, "1|3|1", "cmd_NewItem4"), "#25:" + sa); |
|
223 ok(testItem(menu, "1|3|2", "cmd_NewItem5"), "#26:" + sa); |
|
224 |
|
225 // At this point in the tests the state of the menus has been returned |
|
226 // to the originally diagramed state. |
|
227 |
|
228 // Remove menu. |
|
229 menuNode.removeChild(newMenu0); |
|
230 ok(runBaseMenuTests(menu), "base tests #7:" + sa); |
|
231 ok(!testItem(menu, "1|0", ""), "#27:" + sna); |
|
232 ok(!testItem(menu, "1|1", ""), "#28:" + sna); |
|
233 ok(!testItem(menu, "1|2", ""), "#29:" + sna); |
|
234 ok(!testItem(menu, "1|3|0", ""), "#30:" + sna); |
|
235 ok(!testItem(menu, "1|3|1", ""), "#31:" + sna); |
|
236 ok(!testItem(menu, "1|3|2", ""), "#32:" + sna); |
|
237 // return state to original diagramed state |
|
238 menuNode.appendChild(newMenu0); |
|
239 |
|
240 // Test for bug 447042, make sure that adding a menu node with no children |
|
241 // to the menu bar and then adding another menu node with children works. |
|
242 // Menus with no children don't get their native menu items shown and that |
|
243 // caused internal arrays to get out of sync and an append crashed. |
|
244 var tmpMenu0 = createXULMenu("tmpMenu0"); |
|
245 menuNode.removeChild(newMenu0); |
|
246 menuNode.appendChild(tmpMenu0); |
|
247 menuNode.appendChild(newMenu0); |
|
248 menu.forceUpdateNativeMenuAt("1|3"); |
|
249 //todo(runBaseMenuTests(menu), "base tests #8"); |
|
250 todo(testItem(menu, "1|0", "cmd_NewItem0"), "#33:" +sa); |
|
251 todo(testItem(menu, "1|1", "cmd_NewItem1"), "#34:" +sa); |
|
252 todo(testItem(menu, "1|2", "cmd_NewItem2"), "#35:" +sa); |
|
253 todo(testItem(menu, "1|3|0", "cmd_NewItem3"), "#36:" +sa); |
|
254 todo(testItem(menu, "1|3|1", "cmd_NewItem4"), "#37:" +sa); |
|
255 todo(testItem(menu, "1|3|2", "cmd_NewItem5"), "#38:" +sa); |
|
256 // return state to original diagramed state |
|
257 menuNode.removeChild(tmpMenu0); |
|
258 delete tmpMenu0; |
|
259 |
|
260 // This test is basically a crash test for bug 433858. |
|
261 newMenuItem1.setAttribute("hidden", "true"); |
|
262 newMenuItem2.setAttribute("hidden", "true"); |
|
263 newMenu1.setAttribute("hidden", "true"); |
|
264 menu.forceUpdateNativeMenuAt("1"); |
|
265 newMenuItem1.setAttribute("hidden", "false"); |
|
266 newMenuItem2.setAttribute("hidden", "false"); |
|
267 newMenu1.setAttribute("hidden", "false"); |
|
268 menu.forceUpdateNativeMenuAt("1"); |
|
269 |
|
270 onTestsFinished(); |
|
271 } |
|
272 |
|
273 setTimeout(_delayedOnLoad, 1000); |
|
274 } |
|
275 |
|
276 ]]></script> |
|
277 </window> |