summaryrefslogtreecommitdiffstats
path: root/widget/tests/native_menus_window.xul
diff options
context:
space:
mode:
Diffstat (limited to 'widget/tests/native_menus_window.xul')
-rw-r--r--widget/tests/native_menus_window.xul285
1 files changed, 285 insertions, 0 deletions
diff --git a/widget/tests/native_menus_window.xul b/widget/tests/native_menus_window.xul
new file mode 100644
index 000000000..6e614d017
--- /dev/null
+++ b/widget/tests/native_menus_window.xul
@@ -0,0 +1,285 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="NativeMenuWindow"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="300"
+ height="300"
+ onload="onLoad();"
+ title="Native Menu Test">
+
+ <command id="cmd_FooItem0" oncommand="executedCommandID = 'cmd_FooItem0';"/>
+ <command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/>
+ <command id="cmd_BarItem0" oncommand="executedCommandID = 'cmd_BarItem0';"/>
+ <command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/>
+ <command id="cmd_NewItem0" oncommand="executedCommandID = 'cmd_NewItem0';"/>
+ <command id="cmd_NewItem1" oncommand="executedCommandID = 'cmd_NewItem1';"/>
+ <command id="cmd_NewItem2" oncommand="executedCommandID = 'cmd_NewItem2';"/>
+ <command id="cmd_NewItem3" oncommand="executedCommandID = 'cmd_NewItem3';"/>
+ <command id="cmd_NewItem4" oncommand="executedCommandID = 'cmd_NewItem4';"/>
+ <command id="cmd_NewItem5" oncommand="executedCommandID = 'cmd_NewItem5';"/>
+
+ <!-- We do not modify any menus or menu items defined here in testing. These
+ serve as a baseline structure for us to test after other modifications.
+ We add children to the menubar defined here and test by modifying those
+ children. -->
+ <menubar id="nativemenubar">
+ <menu id="foo" label="Foo">
+ <menupopup>
+ <menuitem label="FooItem0" command="cmd_FooItem0"/>
+ <menuitem label="FooItem1" command="cmd_FooItem1"/>
+ <menuseparator/>
+ <menu label="Bar">
+ <menupopup>
+ <menuitem label="BarItem0" command="cmd_BarItem0"/>
+ <menuitem label="BarItem1" command="cmd_BarItem1"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+ </menu>
+ </menubar>
+
+ <script type="application/javascript"><![CDATA[
+
+ function ok(condition, message) {
+ window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
+ }
+
+ function onTestsFinished() {
+ window.close();
+ window.opener.wrappedJSObject.SimpleTest.finish();
+ }
+
+ // Force a menu to update itself. All of the menus parents will be updated
+ // as well. An empty string will force a complete menu system reload.
+ function forceUpdateNativeMenuAt(location) {
+ var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+ try {
+ utils.forceUpdateNativeMenuAt(location);
+ }
+ catch (e) {
+ dump(e + "\n");
+ }
+ }
+
+ var executedCommandID = "";
+
+ function testItem(location, targetID) {
+ var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+ var correctCommandHandler = false;
+ try {
+ utils.activateNativeMenuItemAt(location);
+ correctCommandHandler = executedCommandID == targetID;
+ }
+ catch (e) {
+ dump(e + "\n");
+ }
+ finally {
+ executedCommandID = "";
+ return correctCommandHandler;
+ }
+ }
+
+ function createXULMenuPopup() {
+ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ var item = document.createElementNS(XUL_NS, "menupopup");
+ return item;
+ }
+
+ function createXULMenu(aLabel) {
+ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ var item = document.createElementNS(XUL_NS, "menu");
+ item.setAttribute("label", aLabel);
+ return item;
+ }
+
+ function createXULMenuItem(aLabel, aCommandId) {
+ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ var item = document.createElementNS(XUL_NS, "menuitem");
+ item.setAttribute("label", aLabel);
+ item.setAttribute("command", aCommandId);
+ return item;
+ }
+
+ function runBaseMenuTests() {
+ forceUpdateNativeMenuAt("0|3");
+ return testItem("0|0", "cmd_FooItem0") &&
+ testItem("0|1", "cmd_FooItem1") &&
+ testItem("0|3|0", "cmd_BarItem0") &&
+ testItem("0|3|1", "cmd_BarItem1");
+ }
+
+ function onLoad() {
+ var _delayedOnLoad = function() {
+ // First let's run the base menu tests.
+ ok(runBaseMenuTests());
+
+ // Set up some nodes that we'll use.
+ var menubarNode = document.getElementById("nativemenubar");
+ var newMenu0 = createXULMenu("NewMenu0");
+ var newMenu1 = createXULMenu("NewMenu1");
+ var newMenuPopup0 = createXULMenuPopup();
+ var newMenuPopup1 = createXULMenuPopup();
+ var newMenuItem0 = createXULMenuItem("NewMenuItem0", "cmd_NewItem0");
+ var newMenuItem1 = createXULMenuItem("NewMenuItem1", "cmd_NewItem1");
+ var newMenuItem2 = createXULMenuItem("NewMenuItem2", "cmd_NewItem2");
+ var newMenuItem3 = createXULMenuItem("NewMenuItem3", "cmd_NewItem3");
+ var newMenuItem4 = createXULMenuItem("NewMenuItem4", "cmd_NewItem4");
+ var newMenuItem5 = createXULMenuItem("NewMenuItem5", "cmd_NewItem5");
+
+ // Create another submenu with hierarchy via DOM manipulation.
+ // ******************
+ // * Foo * NewMenu0 * <- Menu bar
+ // ******************
+ // ****************
+ // * NewMenuItem0 * <- NewMenu0 submenu
+ // ****************
+ // * NewMenuItem1 *
+ // ****************
+ // * NewMenuItem2 *
+ // *******************************
+ // * NewMenu1 > * NewMenuItem3 * <- NewMenu1 submenu
+ // *******************************
+ // * NewMenuItem4 *
+ // ****************
+ // * NewMenuItem5 *
+ // ****************
+ newMenu0.appendChild(newMenuPopup0);
+ newMenuPopup0.appendChild(newMenuItem0);
+ newMenuPopup0.appendChild(newMenuItem1);
+ newMenuPopup0.appendChild(newMenuItem2);
+ newMenuPopup0.appendChild(newMenu1);
+ newMenu1.appendChild(newMenuPopup1);
+ newMenuPopup1.appendChild(newMenuItem3);
+ newMenuPopup1.appendChild(newMenuItem4);
+ newMenuPopup1.appendChild(newMenuItem5);
+ //XXX - we have to append the menu to the top-level of the menu bar
+ // only after constructing it. If we append before construction, it is
+ // invalid because it has no children and we don't validate it if we add
+ // children later.
+ menubarNode.appendChild(newMenu0);
+ forceUpdateNativeMenuAt("1|3");
+ // Run basic tests again.
+ ok(runBaseMenuTests());
+
+ // Error strings.
+ var sa = "Command handler(s) should have activated";
+ var sna = "Command handler(s) should not have activated";
+
+ // Test middle items.
+ ok(testItem("1|1", "cmd_NewItem1"), sa);
+ ok(testItem("1|3|1", "cmd_NewItem4"), sa);
+
+ // Hide newMenu0.
+ newMenu0.setAttribute("hidden", "true");
+ ok(runBaseMenuTests(), sa); // the base menu should still be unhidden
+ ok(!testItem("1|0", ""), sna);
+ ok(!testItem("1|1", ""), sna);
+ ok(!testItem("1|2", ""), sna);
+ ok(!testItem("1|3|0", ""), sna);
+ ok(!testItem("1|3|1", ""), sna);
+ ok(!testItem("1|3|2", ""), sna);
+
+ // Show newMenu0.
+ newMenu0.setAttribute("hidden", "false");
+ forceUpdateNativeMenuAt("1|3");
+ ok(runBaseMenuTests(), sa);
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+ ok(testItem("1|1", "cmd_NewItem1"), sa);
+ ok(testItem("1|2", "cmd_NewItem2"), sa);
+ ok(testItem("1|3|0", "cmd_NewItem3"), sa);
+ ok(testItem("1|3|1", "cmd_NewItem4"), sa);
+ ok(testItem("1|3|2", "cmd_NewItem5"), sa);
+
+ // Hide items.
+ newMenuItem1.setAttribute("hidden", "true");
+ newMenuItem4.setAttribute("hidden", "true");
+ forceUpdateNativeMenuAt("1|2");
+ ok(runBaseMenuTests(), sa);
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+ ok(testItem("1|1", "cmd_NewItem2"), sa);
+ ok(!testItem("1|2", ""), sna);
+ ok(testItem("1|2|0", "cmd_NewItem3"), sa);
+ ok(testItem("1|2|1", "cmd_NewItem5"), sa);
+ ok(!testItem("1|2|2", ""), sna);
+
+ // Show items.
+ newMenuItem1.setAttribute("hidden", "false");
+ newMenuItem4.setAttribute("hidden", "false");
+ forceUpdateNativeMenuAt("1|3");
+ ok(runBaseMenuTests(), sa);
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+ ok(testItem("1|1", "cmd_NewItem1"), sa);
+ ok(testItem("1|2", "cmd_NewItem2"), sa);
+ ok(testItem("1|3|0", "cmd_NewItem3"), sa);
+ ok(testItem("1|3|1", "cmd_NewItem4"), sa);
+ ok(testItem("1|3|2", "cmd_NewItem5"), sa);
+
+ // At this point in the tests the state of the menus has been returned
+ // to the originally diagramed state.
+
+ // Test command disabling
+ var cmd_NewItem0 = document.getElementById("cmd_NewItem0");
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+ cmd_NewItem0.setAttribute("disabled", "true");
+ ok(!testItem("1|0", "cmd_NewItem0"), sna);
+ cmd_NewItem0.removeAttribute("disabled");
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+
+ // Remove menu.
+ menubarNode.removeChild(newMenu0);
+ ok(runBaseMenuTests(), sa);
+ ok(!testItem("1|0", ""), sna);
+ ok(!testItem("1|1", ""), sna);
+ ok(!testItem("1|2", ""), sna);
+ ok(!testItem("1|3|0", ""), sna);
+ ok(!testItem("1|3|1", ""), sna);
+ ok(!testItem("1|3|2", ""), sna);
+ // return state to original diagramed state
+ menubarNode.appendChild(newMenu0);
+
+ // Test for bug 447042, make sure that adding a menu node with no children
+ // to the menu bar and then adding another menu node with children works.
+ // Menus with no children don't get their native menu items shown and that
+ // caused internal arrays to get out of sync and an append crashed.
+ var tmpMenu0 = createXULMenu("tmpMenu0");
+ menubarNode.removeChild(newMenu0);
+ menubarNode.appendChild(tmpMenu0);
+ menubarNode.appendChild(newMenu0);
+ forceUpdateNativeMenuAt("1|3");
+ ok(runBaseMenuTests());
+ ok(testItem("1|0", "cmd_NewItem0"), sa);
+ ok(testItem("1|1", "cmd_NewItem1"), sa);
+ ok(testItem("1|2", "cmd_NewItem2"), sa);
+ ok(testItem("1|3|0", "cmd_NewItem3"), sa);
+ ok(testItem("1|3|1", "cmd_NewItem4"), sa);
+ ok(testItem("1|3|2", "cmd_NewItem5"), sa);
+ // return state to original diagramed state
+ menubarNode.removeChild(tmpMenu0);
+ delete tmpMenu0;
+
+ // This test is basically a crash test for bug 433858.
+ newMenuItem1.setAttribute("hidden", "true");
+ newMenuItem2.setAttribute("hidden", "true");
+ newMenu1.setAttribute("hidden", "true");
+ forceUpdateNativeMenuAt("1");
+ newMenuItem1.setAttribute("hidden", "false");
+ newMenuItem2.setAttribute("hidden", "false");
+ newMenu1.setAttribute("hidden", "false");
+ forceUpdateNativeMenuAt("1");
+
+ onTestsFinished();
+ }
+
+ setTimeout(_delayedOnLoad, 1000);
+ }
+
+ ]]></script>
+</window>