toolkit/content/tests/chrome/popup_trigger.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 var gMenuPopup = null;
michael@0 2 var gTrigger = null;
michael@0 3 var gIsMenu = false;
michael@0 4 var gScreenX = -1, gScreenY = -1;
michael@0 5 var gCachedEvent = null;
michael@0 6 var gCachedEvent2 = null;
michael@0 7
michael@0 8 function cacheEvent(modifiers)
michael@0 9 {
michael@0 10 var cachedEvent = null;
michael@0 11
michael@0 12 var mouseFn = function(event) {
michael@0 13 cachedEvent = event;
michael@0 14 }
michael@0 15
michael@0 16 window.addEventListener("mousedown", mouseFn, false);
michael@0 17 synthesizeMouse(document.documentElement, 0, 0, modifiers);
michael@0 18 window.removeEventListener("mousedown", mouseFn, false);
michael@0 19
michael@0 20 return cachedEvent;
michael@0 21 }
michael@0 22
michael@0 23 function runTests()
michael@0 24 {
michael@0 25 if (screen.height < 768) {
michael@0 26 ok(false, "popup tests are likely to fail for screen heights less than 768 pixels");
michael@0 27 }
michael@0 28
michael@0 29 gMenuPopup = document.getElementById("thepopup");
michael@0 30 gTrigger = document.getElementById("trigger");
michael@0 31
michael@0 32 gIsMenu = gTrigger.boxObject instanceof Components.interfaces.nsIMenuBoxObject;
michael@0 33
michael@0 34 // a hacky way to get the screen position of the document. Cache the event
michael@0 35 // so that we can use it in calls to openPopup.
michael@0 36 gCachedEvent = cacheEvent({ shiftKey: true });
michael@0 37 gScreenX = gCachedEvent.screenX;
michael@0 38 gScreenY = gCachedEvent.screenY;
michael@0 39 gCachedEvent2 = cacheEvent({ altKey: true, ctrlKey: true, shiftKey: true, metaKey: true });
michael@0 40
michael@0 41 startPopupTests(popupTests);
michael@0 42 }
michael@0 43
michael@0 44 var popupTests = [
michael@0 45 {
michael@0 46 testname: "mouse click on trigger",
michael@0 47 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 48 test: function() {
michael@0 49 // for menus, no trigger will be set. For non-menus using the popup
michael@0 50 // attribute, the trigger will be set to the node with the popup attribute
michael@0 51 gExpectedTriggerNode = gIsMenu ? "notset" : gTrigger;
michael@0 52 synthesizeMouse(gTrigger, 4, 4, { });
michael@0 53 },
michael@0 54 result: function (testname) {
michael@0 55 gExpectedTriggerNode = null;
michael@0 56 // menus are the anchor but non-menus are opened at screen coordinates
michael@0 57 is(gMenuPopup.anchorNode, gIsMenu ? gTrigger : null, testname + " anchorNode");
michael@0 58 // menus are opened internally, but non-menus have a mouse event which
michael@0 59 // triggered them
michael@0 60 is(gMenuPopup.triggerNode, gIsMenu ? null : gTrigger, testname + " triggerNode");
michael@0 61 is(document.popupNode, gIsMenu ? null : gTrigger, testname + " document.popupNode");
michael@0 62 is(document.tooltipNode, null, testname + " document.tooltipNode");
michael@0 63 // check to ensure the popup node for a different document isn't used
michael@0 64 if (window.opener)
michael@0 65 is(window.opener.document.popupNode, null, testname + " opener.document.popupNode");
michael@0 66
michael@0 67 // this will be used in some tests to ensure the size doesn't change
michael@0 68 var popuprect = gMenuPopup.getBoundingClientRect();
michael@0 69 gPopupWidth = Math.round(popuprect.width);
michael@0 70 gPopupHeight = Math.round(popuprect.height);
michael@0 71
michael@0 72 checkActive(gMenuPopup, "", testname);
michael@0 73 checkOpen("trigger", testname);
michael@0 74 // if a menu, the popup should be opened underneath the menu in the
michael@0 75 // 'after_start' position, otherwise it is opened at the mouse position
michael@0 76 if (gIsMenu)
michael@0 77 compareEdge(gTrigger, gMenuPopup, "after_start", 0, 0, testname);
michael@0 78 }
michael@0 79 },
michael@0 80 {
michael@0 81 // check that pressing cursor down while there is no selection
michael@0 82 // highlights the first item
michael@0 83 testname: "cursor down no selection",
michael@0 84 events: [ "DOMMenuItemActive item1" ],
michael@0 85 test: function() { synthesizeKey("VK_DOWN", { }); },
michael@0 86 result: function(testname) { checkActive(gMenuPopup, "item1", testname); }
michael@0 87 },
michael@0 88 {
michael@0 89 // check that pressing cursor up wraps and highlights the last item
michael@0 90 testname: "cursor up wrap",
michael@0 91 events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive last" ],
michael@0 92 test: function() { synthesizeKey("VK_UP", { }); },
michael@0 93 result: function(testname) {
michael@0 94 checkActive(gMenuPopup, "last", testname);
michael@0 95 }
michael@0 96 },
michael@0 97 {
michael@0 98 // check that pressing cursor down wraps and highlights the first item
michael@0 99 testname: "cursor down wrap",
michael@0 100 events: [ "DOMMenuItemInactive last", "DOMMenuItemActive item1" ],
michael@0 101 test: function() { synthesizeKey("VK_DOWN", { }); },
michael@0 102 result: function(testname) { checkActive(gMenuPopup, "item1", testname); }
michael@0 103 },
michael@0 104 {
michael@0 105 // check that pressing cursor down highlights the second item
michael@0 106 testname: "cursor down",
michael@0 107 events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive item2" ],
michael@0 108 test: function() { synthesizeKey("VK_DOWN", { }); },
michael@0 109 result: function(testname) { checkActive(gMenuPopup, "item2", testname); }
michael@0 110 },
michael@0 111 {
michael@0 112 // check that pressing cursor up highlights the second item
michael@0 113 testname: "cursor up",
michael@0 114 events: [ "DOMMenuItemInactive item2", "DOMMenuItemActive item1" ],
michael@0 115 test: function() { synthesizeKey("VK_UP", { }); },
michael@0 116 result: function(testname) { checkActive(gMenuPopup, "item1", testname); }
michael@0 117 },
michael@0 118 {
michael@0 119 // cursor left should not do anything
michael@0 120 testname: "cursor left",
michael@0 121 test: function() { synthesizeKey("VK_LEFT", { }); },
michael@0 122 result: function(testname) { checkActive(gMenuPopup, "item1", testname); }
michael@0 123 },
michael@0 124 {
michael@0 125 // cursor right should not do anything
michael@0 126 testname: "cursor right",
michael@0 127 test: function() { synthesizeKey("VK_RIGHT", { }); },
michael@0 128 result: function(testname) { checkActive(gMenuPopup, "item1", testname); }
michael@0 129 },
michael@0 130 {
michael@0 131 // check cursor down when a disabled item exists in the menu
michael@0 132 testname: "cursor down disabled",
michael@0 133 events: function() {
michael@0 134 // On Windows, disabled items are included when navigating, but on
michael@0 135 // other platforms, disabled items are skipped over
michael@0 136 if (navigator.platform.indexOf("Win") == 0)
michael@0 137 return [ "DOMMenuItemInactive item1", "DOMMenuItemActive item2" ];
michael@0 138 else
michael@0 139 return [ "DOMMenuItemInactive item1", "DOMMenuItemActive amenu" ];
michael@0 140 },
michael@0 141 test: function() {
michael@0 142 document.getElementById("item2").disabled = true;
michael@0 143 synthesizeKey("VK_DOWN", { });
michael@0 144 }
michael@0 145 },
michael@0 146 {
michael@0 147 // check cursor up when a disabled item exists in the menu
michael@0 148 testname: "cursor up disabled",
michael@0 149 events: function() {
michael@0 150 if (navigator.platform.indexOf("Win") == 0)
michael@0 151 return [ "DOMMenuItemInactive item2", "DOMMenuItemActive amenu",
michael@0 152 "DOMMenuItemInactive amenu", "DOMMenuItemActive item2",
michael@0 153 "DOMMenuItemInactive item2", "DOMMenuItemActive item1" ];
michael@0 154 else
michael@0 155 return [ "DOMMenuItemInactive amenu", "DOMMenuItemActive item1" ];
michael@0 156 },
michael@0 157 test: function() {
michael@0 158 if (navigator.platform.indexOf("Win") == 0)
michael@0 159 synthesizeKey("VK_DOWN", { });
michael@0 160 synthesizeKey("VK_UP", { });
michael@0 161 if (navigator.platform.indexOf("Win") == 0)
michael@0 162 synthesizeKey("VK_UP", { });
michael@0 163 }
michael@0 164 },
michael@0 165 {
michael@0 166 testname: "mouse click outside",
michael@0 167 events: [ "popuphiding thepopup", "popuphidden thepopup",
michael@0 168 "DOMMenuItemInactive item1", "DOMMenuInactive thepopup" ],
michael@0 169 test: function() {
michael@0 170 gMenuPopup.hidePopup();
michael@0 171 // XXXndeakin event simulation fires events outside of the platform specific
michael@0 172 // widget code so the popup capturing isn't handled. Thus, the menu won't
michael@0 173 // rollup this way.
michael@0 174 // synthesizeMouse(gTrigger, 0, -12, { });
michael@0 175 },
michael@0 176 result: function(testname, step) {
michael@0 177 is(gMenuPopup.anchorNode, null, testname + " anchorNode");
michael@0 178 is(gMenuPopup.triggerNode, null, testname + " triggerNode");
michael@0 179 is(document.popupNode, null, testname + " document.popupNode");
michael@0 180 checkClosed("trigger", testname);
michael@0 181 }
michael@0 182 },
michael@0 183 {
michael@0 184 // these tests check to ensure that passing an anchor and position
michael@0 185 // puts the popup in the right place
michael@0 186 testname: "open popup anchored",
michael@0 187 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 188 autohide: "thepopup",
michael@0 189 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 190 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap",
michael@0 191 "topleft topleft", "topcenter topleft", "topright topleft",
michael@0 192 "leftcenter topright", "rightcenter topright",
michael@0 193 "bottomleft bottomleft", "bottomcenter bottomleft", "bottomright bottomleft",
michael@0 194 "topleft bottomright", "bottomcenter bottomright", "rightcenter topright"],
michael@0 195 test: function(testname, step) {
michael@0 196 gExpectedTriggerNode = "notset";
michael@0 197 gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false);
michael@0 198 },
michael@0 199 result: function(testname, step) {
michael@0 200 // no triggerNode because it was opened without passing an event
michael@0 201 gExpectedTriggerNode = null;
michael@0 202 is(gMenuPopup.anchorNode, gTrigger, testname + " anchorNode");
michael@0 203 is(gMenuPopup.triggerNode, null, testname + " triggerNode");
michael@0 204 is(document.popupNode, null, testname + " document.popupNode");
michael@0 205 compareEdge(gTrigger, gMenuPopup, step, 0, 0, testname);
michael@0 206 }
michael@0 207 },
michael@0 208 {
michael@0 209 // these tests check the same but with a 10 pixel margin on the popup
michael@0 210 testname: "open popup anchored with margin",
michael@0 211 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 212 autohide: "thepopup",
michael@0 213 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 214 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap",
michael@0 215 "topleft topleft", "topcenter topleft", "topright topleft",
michael@0 216 "leftcenter topright", "rightcenter topright",
michael@0 217 "bottomleft bottomleft", "bottomcenter bottomleft", "bottomright bottomleft",
michael@0 218 "topleft bottomright", "bottomcenter bottomright", "rightcenter topright"],
michael@0 219 test: function(testname, step) {
michael@0 220 gMenuPopup.setAttribute("style", "margin: 10px;");
michael@0 221 gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false);
michael@0 222 },
michael@0 223 result: function(testname, step) {
michael@0 224 var rightmod = step == "before_end" || step == "after_end" ||
michael@0 225 step == "start_before" || step == "start_after" ||
michael@0 226 step.match(/topright$/) || step.match(/bottomright$/);
michael@0 227 var bottommod = step == "before_start" || step == "before_end" ||
michael@0 228 step == "start_after" || step == "end_after" ||
michael@0 229 step.match(/bottomleft$/) || step.match(/bottomright$/);
michael@0 230 compareEdge(gTrigger, gMenuPopup, step, rightmod ? -10 : 10, bottommod ? -10 : 10, testname);
michael@0 231 gMenuPopup.removeAttribute("style");
michael@0 232 }
michael@0 233 },
michael@0 234 {
michael@0 235 // these tests check the same but with a -8 pixel margin on the popup
michael@0 236 testname: "open popup anchored with negative margin",
michael@0 237 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 238 autohide: "thepopup",
michael@0 239 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 240 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"],
michael@0 241 test: function(testname, step) {
michael@0 242 gMenuPopup.setAttribute("style", "margin: -8px;");
michael@0 243 gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false);
michael@0 244 },
michael@0 245 result: function(testname, step) {
michael@0 246 var rightmod = step == "before_end" || step == "after_end" ||
michael@0 247 step == "start_before" || step == "start_after";
michael@0 248 var bottommod = step == "before_start" || step == "before_end" ||
michael@0 249 step == "start_after" || step == "end_after";
michael@0 250 compareEdge(gTrigger, gMenuPopup, step, rightmod ? 8 : -8, bottommod ? 8 : -8, testname);
michael@0 251 gMenuPopup.removeAttribute("style");
michael@0 252 }
michael@0 253 },
michael@0 254 {
michael@0 255 testname: "open popup with large positive margin",
michael@0 256 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 257 autohide: "thepopup",
michael@0 258 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 259 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"],
michael@0 260 test: function(testname, step) {
michael@0 261 gMenuPopup.setAttribute("style", "margin: 1000px;");
michael@0 262 gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false);
michael@0 263 },
michael@0 264 result: function(testname, step) {
michael@0 265 var popuprect = gMenuPopup.getBoundingClientRect();
michael@0 266 // as there is more room on the 'end' or 'after' side, popups will always
michael@0 267 // appear on the right or bottom corners, depending on which side they are
michael@0 268 // allowed to be flipped by.
michael@0 269 var expectedleft = step == "before_end" || step == "after_end" ?
michael@0 270 0 : Math.round(window.innerWidth - gPopupWidth);
michael@0 271 var expectedtop = step == "start_after" || step == "end_after" ?
michael@0 272 0 : Math.round(window.innerHeight - gPopupHeight);
michael@0 273 is(Math.round(popuprect.left), expectedleft, testname + " x position " + step);
michael@0 274 is(Math.round(popuprect.top), expectedtop, testname + " y position " + step);
michael@0 275 gMenuPopup.removeAttribute("style");
michael@0 276 }
michael@0 277 },
michael@0 278 {
michael@0 279 testname: "open popup with large negative margin",
michael@0 280 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 281 autohide: "thepopup",
michael@0 282 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 283 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap"],
michael@0 284 test: function(testname, step) {
michael@0 285 gMenuPopup.setAttribute("style", "margin: -1000px;");
michael@0 286 gMenuPopup.openPopup(gTrigger, step, 0, 0, false, false);
michael@0 287 },
michael@0 288 result: function(testname, step) {
michael@0 289 var popuprect = gMenuPopup.getBoundingClientRect();
michael@0 290 // using negative margins causes the reverse of positive margins, and
michael@0 291 // popups will appear on the left or top corners.
michael@0 292 var expectedleft = step == "before_end" || step == "after_end" ?
michael@0 293 Math.round(window.innerWidth - gPopupWidth) : 0;
michael@0 294 var expectedtop = step == "start_after" || step == "end_after" ?
michael@0 295 Math.round(window.innerHeight - gPopupHeight) : 0;
michael@0 296 is(Math.round(popuprect.left), expectedleft, testname + " x position " + step);
michael@0 297 is(Math.round(popuprect.top), expectedtop, testname + " y position " + step);
michael@0 298 gMenuPopup.removeAttribute("style");
michael@0 299 }
michael@0 300 },
michael@0 301 {
michael@0 302 testname: "popup with unknown step",
michael@0 303 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 304 autohide: "thepopup",
michael@0 305 test: function() {
michael@0 306 gMenuPopup.openPopup(gTrigger, "other", 0, 0, false, false);
michael@0 307 },
michael@0 308 result: function (testname) {
michael@0 309 var triggerrect = gMenuPopup.getBoundingClientRect();
michael@0 310 var popuprect = gMenuPopup.getBoundingClientRect();
michael@0 311 is(Math.round(popuprect.left), triggerrect.left, testname + " x position ");
michael@0 312 is(Math.round(popuprect.top), triggerrect.top, testname + " y position ");
michael@0 313 }
michael@0 314 },
michael@0 315 {
michael@0 316 // these tests check to ensure that the position attribute can be used
michael@0 317 // to set the position of a popup instead of passing it as an argument
michael@0 318 testname: "open popup anchored with attribute",
michael@0 319 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 320 autohide: "thepopup",
michael@0 321 steps: ["before_start", "before_end", "after_start", "after_end",
michael@0 322 "start_before", "start_after", "end_before", "end_after", "after_pointer", "overlap",
michael@0 323 "topcenter topleft", "topright bottomright", "leftcenter topright"],
michael@0 324 test: function(testname, step) {
michael@0 325 gMenuPopup.setAttribute("position", step);
michael@0 326 gMenuPopup.openPopup(gTrigger, "", 0, 0, false, false);
michael@0 327 },
michael@0 328 result: function(testname, step) { compareEdge(gTrigger, gMenuPopup, step, 0, 0, testname); }
michael@0 329 },
michael@0 330 {
michael@0 331 // this test checks to ensure that the attributes override flag to openPopup
michael@0 332 // can be used to override the popup's position. This test also passes an
michael@0 333 // event to openPopup to check the trigger node.
michael@0 334 testname: "open popup anchored with override",
michael@0 335 events: [ "popupshowing thepopup 0010", "popupshown thepopup" ],
michael@0 336 test: function(testname, step) {
michael@0 337 // attribute overrides the position passed in
michael@0 338 gMenuPopup.setAttribute("position", "end_after");
michael@0 339 gExpectedTriggerNode = gCachedEvent.target;
michael@0 340 gMenuPopup.openPopup(gTrigger, "before_start", 0, 0, false, true, gCachedEvent);
michael@0 341 },
michael@0 342 result: function(testname, step) {
michael@0 343 gExpectedTriggerNode = null;
michael@0 344 is(gMenuPopup.anchorNode, gTrigger, testname + " anchorNode");
michael@0 345 is(gMenuPopup.triggerNode, gCachedEvent.target, testname + " triggerNode");
michael@0 346 is(document.popupNode, gCachedEvent.target, testname + " document.popupNode");
michael@0 347 compareEdge(gTrigger, gMenuPopup, "end_after", 0, 0, testname);
michael@0 348 }
michael@0 349 },
michael@0 350 {
michael@0 351 testname: "close popup with escape",
michael@0 352 events: [ "popuphiding thepopup", "popuphidden thepopup",
michael@0 353 "DOMMenuInactive thepopup", ],
michael@0 354 test: function(testname, step) {
michael@0 355 synthesizeKey("VK_ESCAPE", { });
michael@0 356 checkClosed("trigger", testname);
michael@0 357 }
michael@0 358 },
michael@0 359 {
michael@0 360 // check that offsets may be supplied to the openPopup method
michael@0 361 testname: "open popup anchored with offsets",
michael@0 362 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 363 autohide: "thepopup",
michael@0 364 test: function(testname, step) {
michael@0 365 // attribute is empty so does not override
michael@0 366 gMenuPopup.setAttribute("position", "");
michael@0 367 gMenuPopup.openPopup(gTrigger, "before_start", 5, 10, true, true);
michael@0 368 },
michael@0 369 result: function(testname, step) { compareEdge(gTrigger, gMenuPopup, "before_start", 5, 10, testname); }
michael@0 370 },
michael@0 371 {
michael@0 372 // these tests check to ensure that passing an anchor and position
michael@0 373 // puts the popup in the right place
michael@0 374 testname: "show popup anchored",
michael@0 375 condition: function() {
michael@0 376 // only perform this test for popups not in a menu, such as those using
michael@0 377 // the popup attribute, as the showPopup implementation in popup.xml
michael@0 378 // calls openMenu if the popup is inside a menu
michael@0 379 return !gIsMenu;
michael@0 380 },
michael@0 381 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 382 autohide: "thepopup",
michael@0 383 steps: [["topleft", "topleft"],
michael@0 384 ["topleft", "topright"], ["topleft", "bottomleft"],
michael@0 385 ["topright", "topleft"], ["topright", "bottomright"],
michael@0 386 ["bottomleft", "bottomright"], ["bottomleft", "topleft"],
michael@0 387 ["bottomright", "bottomleft"], ["bottomright", "topright"]],
michael@0 388 test: function(testname, step) {
michael@0 389 // the attributes should be ignored
michael@0 390 gMenuPopup.setAttribute("popupanchor", "topright");
michael@0 391 gMenuPopup.setAttribute("popupalign", "bottomright");
michael@0 392 gMenuPopup.setAttribute("position", "end_after");
michael@0 393 gMenuPopup.showPopup(gTrigger, -1, -1, "popup", step[0], step[1]);
michael@0 394 },
michael@0 395 result: function(testname, step) {
michael@0 396 var pos = convertPosition(step[0], step[1]);
michael@0 397 compareEdge(gTrigger, gMenuPopup, pos, 0, 0, testname);
michael@0 398 gMenuPopup.removeAttribute("popupanchor");
michael@0 399 gMenuPopup.removeAttribute("popupalign");
michael@0 400 gMenuPopup.removeAttribute("position");
michael@0 401 }
michael@0 402 },
michael@0 403 {
michael@0 404 testname: "show popup with position",
michael@0 405 condition: function() { return !gIsMenu; },
michael@0 406 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 407 autohide: "thepopup",
michael@0 408 test: function(testname, step) {
michael@0 409 gMenuPopup.showPopup(gTrigger, gScreenX + 60, gScreenY + 15,
michael@0 410 "context", "topleft", "bottomright");
michael@0 411 },
michael@0 412 result: function(testname, step) {
michael@0 413 var rect = gMenuPopup.getBoundingClientRect();
michael@0 414 ok(true, gScreenX + "," + gScreenY);
michael@0 415 is(rect.left, 60, testname + " left");
michael@0 416 is(rect.top, 15, testname + " top");
michael@0 417 ok(rect.right, testname + " right is " + rect.right);
michael@0 418 ok(rect.bottom, testname + " bottom is " + rect.bottom);
michael@0 419 }
michael@0 420 },
michael@0 421 {
michael@0 422 // if no anchor is supplied to openPopup, it should be opened relative
michael@0 423 // to the viewport.
michael@0 424 testname: "open popup unanchored",
michael@0 425 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 426 test: function(testname, step) { gMenuPopup.openPopup(null, "after_start", 6, 8, false); },
michael@0 427 result: function(testname, step) {
michael@0 428 var rect = gMenuPopup.getBoundingClientRect();
michael@0 429 ok(rect.left == 6 && rect.top == 8 && rect.right && rect.bottom, testname);
michael@0 430 }
michael@0 431 },
michael@0 432 {
michael@0 433 testname: "activate menuitem with mouse",
michael@0 434 events: [ "DOMMenuInactive thepopup", "command item3",
michael@0 435 "popuphiding thepopup", "popuphidden thepopup",
michael@0 436 "DOMMenuItemInactive item3" ],
michael@0 437 test: function(testname, step) {
michael@0 438 var item3 = document.getElementById("item3");
michael@0 439 synthesizeMouse(item3, 4, 4, { });
michael@0 440 },
michael@0 441 result: function(testname, step) { checkClosed("trigger", testname); }
michael@0 442 },
michael@0 443 {
michael@0 444 testname: "close popup",
michael@0 445 condition: function() { return false; },
michael@0 446 events: [ "popuphiding thepopup", "popuphidden thepopup",
michael@0 447 "DOMMenuInactive thepopup" ],
michael@0 448 test: function(testname, step) { gMenuPopup.hidePopup(); }
michael@0 449 },
michael@0 450 {
michael@0 451 testname: "open popup at screen",
michael@0 452 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 453 test: function(testname, step) {
michael@0 454 gExpectedTriggerNode = "notset";
michael@0 455 gMenuPopup.openPopupAtScreen(gScreenX + 24, gScreenY + 20, false);
michael@0 456 },
michael@0 457 result: function(testname, step) {
michael@0 458 gExpectedTriggerNode = null;
michael@0 459 is(gMenuPopup.anchorNode, null, testname + " anchorNode");
michael@0 460 is(gMenuPopup.triggerNode, null, testname + " triggerNode");
michael@0 461 is(document.popupNode, null, testname + " document.popupNode");
michael@0 462 var rect = gMenuPopup.getBoundingClientRect();
michael@0 463 is(rect.left, 24, testname + " left");
michael@0 464 is(rect.top, 20, testname + " top");
michael@0 465 ok(rect.right, testname + " right is " + rect.right);
michael@0 466 ok(rect.bottom, testname + " bottom is " + rect.bottom);
michael@0 467 }
michael@0 468 },
michael@0 469 {
michael@0 470 // check that pressing a menuitem's accelerator selects it. Note that
michael@0 471 // the menuitem with the M accesskey overrides the earlier menuitem that
michael@0 472 // begins with M.
michael@0 473 testname: "menuitem accelerator",
michael@0 474 events: [ "DOMMenuItemActive amenu", "DOMMenuItemInactive amenu",
michael@0 475 "DOMMenuInactive thepopup",
michael@0 476 "command amenu", "popuphiding thepopup", "popuphidden thepopup",
michael@0 477 "DOMMenuItemInactive amenu"
michael@0 478 ],
michael@0 479 test: function() { synthesizeKey("M", { }); },
michael@0 480 result: function(testname) { checkClosed("trigger", testname); }
michael@0 481 },
michael@0 482 {
michael@0 483 testname: "open context popup at screen",
michael@0 484 events: [ "popupshowing thepopup 0010", "popupshown thepopup" ],
michael@0 485 test: function(testname, step) {
michael@0 486 gExpectedTriggerNode = gCachedEvent.target;
michael@0 487 gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent);
michael@0 488 },
michael@0 489 result: function(testname, step) {
michael@0 490 gExpectedTriggerNode = null;
michael@0 491 is(gMenuPopup.anchorNode, null, testname + " anchorNode");
michael@0 492 is(gMenuPopup.triggerNode, gCachedEvent.target, testname + " triggerNode");
michael@0 493 is(document.popupNode, gCachedEvent.target, testname + " document.popupNode");
michael@0 494
michael@0 495 var childframe = document.getElementById("childframe");
michael@0 496 if (childframe) {
michael@0 497 for (var t = 0; t < 2; t++) {
michael@0 498 var child = childframe.contentDocument;
michael@0 499 var evt = child.createEvent("Event");
michael@0 500 evt.initEvent("click", true, true);
michael@0 501 child.documentElement.dispatchEvent(evt);
michael@0 502 is(child.documentElement.getAttribute("data"), "xnull",
michael@0 503 "cannot get popupNode from other document");
michael@0 504 child.documentElement.setAttribute("data", "none");
michael@0 505 // now try again with document.popupNode set explicitly
michael@0 506 document.popupNode = gCachedEvent.target;
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 var rect = gMenuPopup.getBoundingClientRect();
michael@0 511 is(rect.left, 10, testname + " left");
michael@0 512 is(rect.top, 18, testname + " top");
michael@0 513 ok(rect.right, testname + " right is " + rect.right);
michael@0 514 ok(rect.bottom, testname + " bottom is " + rect.bottom);
michael@0 515 }
michael@0 516 },
michael@0 517 {
michael@0 518 // pressing a letter that doesn't correspond to an accelerator, but does
michael@0 519 // correspond to the first letter in a menu's label. The menu should not
michael@0 520 // close because there is more than one item corresponding to that letter
michael@0 521 testname: "menuitem with non accelerator",
michael@0 522 events: [ "DOMMenuItemActive one" ],
michael@0 523 test: function() { synthesizeKey("O", { }); },
michael@0 524 result: function(testname) {
michael@0 525 checkOpen("trigger", testname);
michael@0 526 checkActive(gMenuPopup, "one", testname);
michael@0 527 }
michael@0 528 },
michael@0 529 {
michael@0 530 // pressing the letter again should select the next one that starts with
michael@0 531 // that letter
michael@0 532 testname: "menuitem with non accelerator again",
michael@0 533 events: [ "DOMMenuItemInactive one", "DOMMenuItemActive submenu" ],
michael@0 534 test: function() { synthesizeKey("O", { }); },
michael@0 535 result: function(testname) {
michael@0 536 // 'submenu' is a menu but it should not be open
michael@0 537 checkOpen("trigger", testname);
michael@0 538 checkClosed("submenu", testname);
michael@0 539 checkActive(gMenuPopup, "submenu", testname);
michael@0 540 }
michael@0 541 },
michael@0 542 {
michael@0 543 // open the submenu with the cursor right key
michael@0 544 testname: "open submenu with cursor right",
michael@0 545 events: [ "popupshowing submenupopup", "DOMMenuItemActive submenuitem",
michael@0 546 "popupshown submenupopup" ],
michael@0 547 test: function() { synthesizeKey("VK_RIGHT", { }); },
michael@0 548 result: function(testname) {
michael@0 549 checkOpen("trigger", testname);
michael@0 550 checkOpen("submenu", testname);
michael@0 551 checkActive(gMenuPopup, "submenu", testname);
michael@0 552 checkActive(document.getElementById("submenupopup"), "submenuitem", testname);
michael@0 553 }
michael@0 554 },
michael@0 555 {
michael@0 556 // close the submenu with the cursor left key
michael@0 557 testname: "close submenu with cursor left",
michael@0 558 events: [ "popuphiding submenupopup", "popuphidden submenupopup",
michael@0 559 "DOMMenuItemInactive submenuitem", "DOMMenuInactive submenupopup",
michael@0 560 "DOMMenuItemActive submenu" ],
michael@0 561 test: function() { synthesizeKey("VK_LEFT", { }); },
michael@0 562 result: function(testname) {
michael@0 563 checkOpen("trigger", testname);
michael@0 564 checkClosed("submenu", testname);
michael@0 565 checkActive(gMenuPopup, "submenu", testname);
michael@0 566 checkActive(document.getElementById("submenupopup"), "", testname);
michael@0 567 }
michael@0 568 },
michael@0 569 {
michael@0 570 // open the submenu with the enter key
michael@0 571 testname: "open submenu with enter",
michael@0 572 events: [ "popupshowing submenupopup", "DOMMenuItemActive submenuitem",
michael@0 573 "popupshown submenupopup" ],
michael@0 574 test: function() { synthesizeKey("VK_RETURN", { }); },
michael@0 575 result: function(testname) {
michael@0 576 checkOpen("trigger", testname);
michael@0 577 checkOpen("submenu", testname);
michael@0 578 checkActive(gMenuPopup, "submenu", testname);
michael@0 579 checkActive(document.getElementById("submenupopup"), "submenuitem", testname);
michael@0 580 }
michael@0 581 },
michael@0 582 {
michael@0 583 // close the submenu with the escape key
michael@0 584 testname: "close submenu with escape",
michael@0 585 events: [ "popuphiding submenupopup", "popuphidden submenupopup",
michael@0 586 "DOMMenuItemInactive submenuitem", "DOMMenuInactive submenupopup",
michael@0 587 "DOMMenuItemActive submenu" ],
michael@0 588 test: function() { synthesizeKey("VK_ESCAPE", { }); },
michael@0 589 result: function(testname) {
michael@0 590 checkOpen("trigger", testname);
michael@0 591 checkClosed("submenu", testname);
michael@0 592 checkActive(gMenuPopup, "submenu", testname);
michael@0 593 checkActive(document.getElementById("submenupopup"), "", testname);
michael@0 594 }
michael@0 595 },
michael@0 596 {
michael@0 597 // pressing the letter again when the next item is disabled should still
michael@0 598 // select the disabled item on Windows, but select the next item on other
michael@0 599 // platforms
michael@0 600 testname: "menuitem with non accelerator disabled",
michael@0 601 events: function() {
michael@0 602 if (navigator.platform.indexOf("Win") == 0)
michael@0 603 return [ "DOMMenuItemInactive submenu", "DOMMenuItemActive other",
michael@0 604 "DOMMenuItemInactive other", "DOMMenuItemActive item1" ];
michael@0 605 else
michael@0 606 return [ "DOMMenuItemInactive submenu", "DOMMenuItemActive last",
michael@0 607 "DOMMenuItemInactive last", "DOMMenuItemActive item1" ];
michael@0 608 },
michael@0 609 test: function() { synthesizeKey("O", { }); synthesizeKey("F", { }); },
michael@0 610 result: function(testname) {
michael@0 611 checkActive(gMenuPopup, "item1", testname);
michael@0 612 }
michael@0 613 },
michael@0 614 {
michael@0 615 // pressing a letter that doesn't correspond to an accelerator nor the
michael@0 616 // first letter of a menu. This should have no effect.
michael@0 617 testname: "menuitem with keypress no accelerator found",
michael@0 618 test: function() { synthesizeKey("G", { }); },
michael@0 619 result: function(testname) {
michael@0 620 checkOpen("trigger", testname);
michael@0 621 checkActive(gMenuPopup, "item1", testname);
michael@0 622 }
michael@0 623 },
michael@0 624 {
michael@0 625 // when only one menuitem starting with that letter exists, it should be
michael@0 626 // selected and the menu closed
michael@0 627 testname: "menuitem with non accelerator single",
michael@0 628 events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive amenu",
michael@0 629 "DOMMenuItemInactive amenu", "DOMMenuInactive thepopup",
michael@0 630 "command amenu", "popuphiding thepopup", "popuphidden thepopup",
michael@0 631 "DOMMenuItemInactive amenu",
michael@0 632 ],
michael@0 633 test: function() { synthesizeKey("M", { }); },
michael@0 634 result: function(testname) {
michael@0 635 checkClosed("trigger", testname);
michael@0 636 checkActive(gMenuPopup, "", testname);
michael@0 637 }
michael@0 638 },
michael@0 639 {
michael@0 640 testname: "open context popup at screen with all modifiers set",
michael@0 641 events: [ "popupshowing thepopup 1111", "popupshown thepopup" ],
michael@0 642 autohide: "thepopup",
michael@0 643 test: function(testname, step) {
michael@0 644 gMenuPopup.openPopupAtScreen(gScreenX + 8, gScreenY + 16, true, gCachedEvent2);
michael@0 645 }
michael@0 646 },
michael@0 647 {
michael@0 648 testname: "open popup with open property",
michael@0 649 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 650 test: function(testname, step) { openMenu(gTrigger); },
michael@0 651 result: function(testname, step) {
michael@0 652 checkOpen("trigger", testname);
michael@0 653 if (gIsMenu)
michael@0 654 compareEdge(gTrigger, gMenuPopup, "after_start", 0, 0, testname);
michael@0 655 }
michael@0 656 },
michael@0 657 {
michael@0 658 testname: "open submenu with open property",
michael@0 659 events: [ "popupshowing submenupopup", "DOMMenuItemActive submenu",
michael@0 660 "popupshown submenupopup" ],
michael@0 661 test: function(testname, step) { openMenu(document.getElementById("submenu")); },
michael@0 662 result: function(testname, step) {
michael@0 663 checkOpen("trigger", testname);
michael@0 664 checkOpen("submenu", testname);
michael@0 665 // XXXndeakin
michael@0 666 // getBoundingClientRect doesn't seem to working right for submenus
michael@0 667 // so disable this test for now
michael@0 668 // compareEdge(document.getElementById("submenu"),
michael@0 669 // document.getElementById("submenupopup"), "end_before", 0, 0, testname);
michael@0 670 }
michael@0 671 },
michael@0 672 {
michael@0 673 testname: "hidePopup hides entire chain",
michael@0 674 events: [ "popuphiding submenupopup", "popuphidden submenupopup",
michael@0 675 "popuphiding thepopup", "popuphidden thepopup",
michael@0 676 "DOMMenuInactive submenupopup",
michael@0 677 "DOMMenuItemInactive submenu", "DOMMenuItemInactive submenu",
michael@0 678 "DOMMenuInactive thepopup", ],
michael@0 679 test: function() { gMenuPopup.hidePopup(); },
michael@0 680 result: function(testname, step) {
michael@0 681 checkClosed("trigger", testname);
michael@0 682 checkClosed("submenu", testname);
michael@0 683 }
michael@0 684 },
michael@0 685 {
michael@0 686 testname: "open submenu with open property without parent open",
michael@0 687 test: function(testname, step) { openMenu(document.getElementById("submenu")); },
michael@0 688 result: function(testname, step) {
michael@0 689 checkClosed("trigger", testname);
michael@0 690 checkClosed("submenu", testname);
michael@0 691 }
michael@0 692 },
michael@0 693 {
michael@0 694 testname: "open popup with open property and position",
michael@0 695 condition: function() { return gIsMenu; },
michael@0 696 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 697 test: function(testname, step) {
michael@0 698 gMenuPopup.setAttribute("position", "before_start");
michael@0 699 openMenu(gTrigger);
michael@0 700 },
michael@0 701 result: function(testname, step) {
michael@0 702 compareEdge(gTrigger, gMenuPopup, "before_start", 0, 0, testname);
michael@0 703 }
michael@0 704 },
michael@0 705 {
michael@0 706 testname: "close popup with open property",
michael@0 707 condition: function() { return gIsMenu; },
michael@0 708 events: [ "popuphiding thepopup", "popuphidden thepopup",
michael@0 709 "DOMMenuInactive thepopup" ],
michael@0 710 test: function(testname, step) { closeMenu(gTrigger, gMenuPopup); },
michael@0 711 result: function(testname, step) { checkClosed("trigger", testname); }
michael@0 712 },
michael@0 713 {
michael@0 714 testname: "open popup with open property, position, anchor and alignment",
michael@0 715 condition: function() { return gIsMenu; },
michael@0 716 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 717 autohide: "thepopup",
michael@0 718 test: function(testname, step) {
michael@0 719 gMenuPopup.setAttribute("position", "start_after");
michael@0 720 gMenuPopup.setAttribute("popupanchor", "topright");
michael@0 721 gMenuPopup.setAttribute("popupalign", "bottomright");
michael@0 722 openMenu(gTrigger);
michael@0 723 },
michael@0 724 result: function(testname, step) {
michael@0 725 compareEdge(gTrigger, gMenuPopup, "start_after", 0, 0, testname);
michael@0 726 }
michael@0 727 },
michael@0 728 {
michael@0 729 testname: "open popup with open property, anchor and alignment",
michael@0 730 condition: function() { return gIsMenu; },
michael@0 731 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 732 autohide: "thepopup",
michael@0 733 test: function(testname, step) {
michael@0 734 gMenuPopup.removeAttribute("position");
michael@0 735 gMenuPopup.setAttribute("popupanchor", "bottomright");
michael@0 736 gMenuPopup.setAttribute("popupalign", "topright");
michael@0 737 openMenu(gTrigger);
michael@0 738 },
michael@0 739 result: function(testname, step) {
michael@0 740 compareEdge(gTrigger, gMenuPopup, "after_end", 0, 0, testname);
michael@0 741 gMenuPopup.removeAttribute("popupanchor");
michael@0 742 gMenuPopup.removeAttribute("popupalign");
michael@0 743 }
michael@0 744 },
michael@0 745 {
michael@0 746 testname: "focus and cursor down on trigger",
michael@0 747 condition: function() { return gIsMenu; },
michael@0 748 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 749 autohide: "thepopup",
michael@0 750 test: function(testname, step) {
michael@0 751 gTrigger.focus();
michael@0 752 synthesizeKey("VK_DOWN", { altKey: (navigator.platform.indexOf("Mac") == -1) });
michael@0 753 },
michael@0 754 result: function(testname, step) {
michael@0 755 checkOpen("trigger", testname);
michael@0 756 checkActive(gMenuPopup, "", testname);
michael@0 757 }
michael@0 758 },
michael@0 759 {
michael@0 760 testname: "focus and cursor up on trigger",
michael@0 761 condition: function() { return gIsMenu; },
michael@0 762 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 763 test: function(testname, step) {
michael@0 764 gTrigger.focus();
michael@0 765 synthesizeKey("VK_UP", { altKey: (navigator.platform.indexOf("Mac") == -1) });
michael@0 766 },
michael@0 767 result: function(testname, step) {
michael@0 768 checkOpen("trigger", testname);
michael@0 769 checkActive(gMenuPopup, "", testname);
michael@0 770 }
michael@0 771 },
michael@0 772 {
michael@0 773 testname: "select and enter on menuitem",
michael@0 774 condition: function() { return gIsMenu; },
michael@0 775 events: [ "DOMMenuItemActive item1", "DOMMenuItemInactive item1",
michael@0 776 "DOMMenuInactive thepopup", "command item1",
michael@0 777 "popuphiding thepopup", "popuphidden thepopup",
michael@0 778 "DOMMenuItemInactive item1" ],
michael@0 779 test: function(testname, step) {
michael@0 780 synthesizeKey("VK_DOWN", { });
michael@0 781 synthesizeKey("VK_RETURN", { });
michael@0 782 },
michael@0 783 result: function(testname, step) { checkClosed("trigger", testname); }
michael@0 784 },
michael@0 785 {
michael@0 786 testname: "focus trigger and key to open",
michael@0 787 condition: function() { return gIsMenu; },
michael@0 788 events: [ "popupshowing thepopup", "popupshown thepopup" ],
michael@0 789 autohide: "thepopup",
michael@0 790 test: function(testname, step) {
michael@0 791 gTrigger.focus();
michael@0 792 synthesizeKey((navigator.platform.indexOf("Mac") == -1) ? "VK_F4" : " ", { });
michael@0 793 },
michael@0 794 result: function(testname, step) {
michael@0 795 checkOpen("trigger", testname);
michael@0 796 checkActive(gMenuPopup, "", testname);
michael@0 797 }
michael@0 798 },
michael@0 799 {
michael@0 800 // the menu should only open when the meta or alt key is not pressed
michael@0 801 testname: "focus trigger and key wrong modifier",
michael@0 802 condition: function() { return gIsMenu; },
michael@0 803 test: function(testname, step) {
michael@0 804 gTrigger.focus();
michael@0 805 if (navigator.platform.indexOf("Mac") == -1)
michael@0 806 synthesizeKey("", { metaKey: true });
michael@0 807 else
michael@0 808 synthesizeKey("VK_F4", { altKey: true });
michael@0 809 },
michael@0 810 result: function(testname, step) {
michael@0 811 checkClosed("trigger", testname);
michael@0 812 }
michael@0 813 },
michael@0 814 {
michael@0 815 testname: "mouse click on disabled menu",
michael@0 816 condition: function() { return gIsMenu; },
michael@0 817 test: function(testname, step) {
michael@0 818 gTrigger.setAttribute("disabled", "true");
michael@0 819 synthesizeMouse(gTrigger, 4, 4, { });
michael@0 820 },
michael@0 821 result: function(testname, step) {
michael@0 822 checkClosed("trigger", testname);
michael@0 823 gTrigger.removeAttribute("disabled");
michael@0 824 }
michael@0 825 },
michael@0 826 {
michael@0 827 // openPopup should open the menu synchronously, however popupshown
michael@0 828 // is fired asynchronously
michael@0 829 testname: "openPopup synchronous",
michael@0 830 events: [ "popupshowing thepopup", "popupshowing submenupopup",
michael@0 831 "popupshown thepopup", "DOMMenuItemActive submenu",
michael@0 832 "popupshown submenupopup" ],
michael@0 833 test: function(testname, step) {
michael@0 834 gMenuPopup.openPopup(gTrigger, "after_start", 0, 0, false, true);
michael@0 835 document.getElementById("submenupopup").
michael@0 836 openPopup(gTrigger, "end_before", 0, 0, false, true);
michael@0 837 checkOpen("trigger", testname);
michael@0 838 checkOpen("submenu", testname);
michael@0 839 }
michael@0 840 },
michael@0 841 {
michael@0 842 // remove the content nodes for the popup
michael@0 843 testname: "remove content",
michael@0 844 test: function(testname, step) {
michael@0 845 var submenupopup = document.getElementById("submenupopup");
michael@0 846 submenupopup.parentNode.removeChild(submenupopup);
michael@0 847 var popup = document.getElementById("thepopup");
michael@0 848 popup.parentNode.removeChild(popup);
michael@0 849 }
michael@0 850 }
michael@0 851
michael@0 852 ];

mercurial