toolkit/content/tests/chrome/window_largemenu.xul

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/content/tests/chrome/window_largemenu.xul	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,379 @@
     1.4 +<?xml version="1.0"?>
     1.5 +<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
     1.6 +
     1.7 +<window title="Large Menu Tests"
     1.8 +        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
     1.9 +
    1.10 +  <script type="application/javascript"
    1.11 +          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
    1.12 +
    1.13 +<!--
    1.14 +  This test checks that a large menu is displayed with arrow buttons
    1.15 +  and is on the screen.
    1.16 +  -->
    1.17 +
    1.18 +<script>
    1.19 +<![CDATA[
    1.20 +
    1.21 +var gOverflowed = false, gUnderflowed = false;
    1.22 +var gContextMenuTests = false;
    1.23 +var gScreenY = -1;
    1.24 +var gTestIndex = 0;
    1.25 +var gTests = ["open normal", "open flipped position", "open with scrolling",
    1.26 +              "open after scrolling", "open small again",
    1.27 +              "menu movement", "panel movement",
    1.28 +              "context menu enough space below",
    1.29 +              "context menu more space above",
    1.30 +              "context menu too big either side",
    1.31 +              "context menu larger than screen"];
    1.32 +
    1.33 +function getScreenXY(element)
    1.34 +{
    1.35 +  var screenX, screenY;
    1.36 +  var mouseFn = function(event) {
    1.37 +    screenX = event.screenX - 1;
    1.38 +    screenY = event.screenY - 1;
    1.39 +  }
    1.40 +
    1.41 +  // a hacky way to get the screen position of an element without using the box object
    1.42 +  window.addEventListener("mousedown", mouseFn, false);
    1.43 +  synthesizeMouse(element, 1, 1, { });
    1.44 +  window.removeEventListener("mousedown", mouseFn, false);
    1.45 +
    1.46 +  return [screenX, screenY];
    1.47 +}
    1.48 +
    1.49 +function hidePopup() {
    1.50 +  window.requestAnimationFrame(
    1.51 +    function() {
    1.52 +      setTimeout(
    1.53 +        function() {
    1.54 +          document.getElementById("popup").hidePopup();
    1.55 +        }, 0);
    1.56 +    });
    1.57 +}
    1.58 +
    1.59 +function runTests()
    1.60 +{
    1.61 +  [, gScreenY] = getScreenXY(document.documentElement);
    1.62 +  nextTest();
    1.63 +}
    1.64 +
    1.65 +function nextTest()
    1.66 +{
    1.67 +  gOverflowed = false, gUnderflowed = false;
    1.68 +
    1.69 +  var y = screen.height;
    1.70 +  if (gTestIndex == 1) // open flipped position test:
    1.71 +    y -= 100;
    1.72 +  else
    1.73 +    y /= 2;
    1.74 +
    1.75 +  var popup = document.getElementById("popup");
    1.76 +  if (gTestIndex == 2) {
    1.77 +    // add some more menuitems so that scrolling will be necessary
    1.78 +    for (var t = 1; t <= 30; t++) {
    1.79 +      var menu = document.createElement("menuitem");
    1.80 +      menu.setAttribute("label", "More" + t);
    1.81 +      popup.appendChild(menu);
    1.82 +    }
    1.83 +  }
    1.84 +  else if (gTestIndex == 4) {
    1.85 +    for (var t = 1; t <= 30; t++)
    1.86 +      popup.removeChild(popup.lastChild);
    1.87 +  }
    1.88 +
    1.89 +  window.requestAnimationFrame(function() {
    1.90 +    setTimeout(
    1.91 +      function() {
    1.92 +        popup.openPopupAtScreen(100, y, false);
    1.93 +      }, 0);
    1.94 +  });
    1.95 +}
    1.96 +
    1.97 +function popupShown()
    1.98 +{
    1.99 +  if (gTests[gTestIndex] == "menu movement")
   1.100 +    return testPopupMovement();
   1.101 +
   1.102 +  if (gContextMenuTests)
   1.103 +    return contextMenuPopupShown();
   1.104 +
   1.105 +  var popup = document.getElementById("popup");
   1.106 +  var rect = popup.getBoundingClientRect();
   1.107 +  var sbo = document.getAnonymousNodes(popup)[0].scrollBoxObject;
   1.108 +  var expectedScrollPos = 0;
   1.109 +
   1.110 +  if (gTestIndex == 0) {
   1.111 +    // the popup should be in the center of the screen
   1.112 +    // note that if the height is odd, the y-offset will have been rounded
   1.113 +    // down when we pass the fractional value to openPopupAtScreen above.
   1.114 +    is(Math.round(rect.top) + gScreenY, Math.floor(screen.height / 2),
   1.115 +                              gTests[gTestIndex] + " top");
   1.116 +    ok(Math.round(rect.bottom) + gScreenY < screen.height,
   1.117 +                                gTests[gTestIndex] + " bottom");
   1.118 +    ok(!gOverflowed && !gUnderflowed, gTests[gTestIndex] + " overflow")
   1.119 +  }
   1.120 +  else if (gTestIndex == 1) {
   1.121 +    // the popup was supposed to open 100 pixels from the bottom, but that
   1.122 +    // would put it off screen so it should be flipped to have its bottom
   1.123 +    // edge 100 pixels from the bottom
   1.124 +    ok(Math.round(rect.top) + gScreenY >= screen.top, gTests[gTestIndex] + " top");
   1.125 +    is(Math.round(rect.bottom) + gScreenY, screen.height - 100,
   1.126 +                                gTests[gTestIndex] + " bottom");
   1.127 +    ok(!gOverflowed && !gUnderflowed, gTests[gTestIndex] + " overflow")
   1.128 +  }
   1.129 +  else if (gTestIndex == 2) {
   1.130 +    // the popup is too large so ensure that it is on screen
   1.131 +    ok(Math.round(rect.top) + gScreenY >= screen.top, gTests[gTestIndex] + " top");
   1.132 +    ok(Math.round(rect.bottom) + gScreenY <= screen.height, gTests[gTestIndex] + " bottom");
   1.133 +    ok(gOverflowed && !gUnderflowed, gTests[gTestIndex] + " overflow")
   1.134 +
   1.135 +    sbo.scrollTo(0, 40);
   1.136 +    expectedScrollPos = 40;
   1.137 +  }
   1.138 +  else if (gTestIndex == 3) {
   1.139 +    expectedScrollPos = 40;
   1.140 +  }
   1.141 +  else if (gTestIndex == 4) {
   1.142 +    // note that if the height is odd, the y-offset will have been rounded
   1.143 +    // down when we pass the fractional value to openPopupAtScreen above.
   1.144 +    is(Math.round(rect.top) + gScreenY, Math.floor(screen.height / 2),
   1.145 +                              gTests[gTestIndex] + " top");
   1.146 +    ok(Math.round(rect.bottom) + gScreenY < screen.height,
   1.147 +                                gTests[gTestIndex] + " bottom");
   1.148 +    ok(!gOverflowed && gUnderflowed, gTests[gTestIndex] + " overflow")
   1.149 +  }
   1.150 +
   1.151 +  var sx = { }, sy = { };
   1.152 +  sbo.getPosition(sx, sy);
   1.153 +  is(sy.value, expectedScrollPos, "menu scroll position");
   1.154 +
   1.155 +  hidePopup();
   1.156 +}
   1.157 +
   1.158 +function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
   1.159 +function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
   1.160 +
   1.161 +var oldx, oldy, waitSteps = 0;
   1.162 +function moveWindowTo(x, y, callback, arg)
   1.163 +{
   1.164 +  if (!waitSteps) {
   1.165 +    oldx = window.screenX;
   1.166 +    oldy = window.screenY;
   1.167 +    window.moveTo(x, y);
   1.168 +
   1.169 +    waitSteps++;
   1.170 +    setTimeout(moveWindowTo, 100, x, y, callback, arg);
   1.171 +    return;
   1.172 +  }
   1.173 +
   1.174 +  if (window.screenX == oldx && window.screenY == oldy) {
   1.175 +    if (waitSteps++ > 10) {
   1.176 +      ok(false, "Window never moved properly to " + x + "," + y);
   1.177 +      window.opener.wrappedJSObject.SimpleTest.finish();
   1.178 +      window.close();
   1.179 +    }
   1.180 +
   1.181 +    setTimeout(moveWindowTo, 100, x, y, callback, arg);
   1.182 +  }
   1.183 +  else {
   1.184 +    waitSteps = 0;
   1.185 +    callback(arg);
   1.186 +  }
   1.187 +}
   1.188 +
   1.189 +function popupHidden()
   1.190 +{
   1.191 +  gTestIndex++;
   1.192 +  if (gTestIndex == gTests.length) {
   1.193 +    window.opener.wrappedJSObject.SimpleTest.finish();
   1.194 +    window.close();
   1.195 +  }
   1.196 +  else if (gTests[gTestIndex] == "context menu enough space below") {
   1.197 +    gContextMenuTests = true;
   1.198 +    moveWindowTo(window.screenX, screen.availTop + 10,
   1.199 +      function () synthesizeMouse(document.getElementById("label"), 4, 4, { type: "contextmenu", button: 2 }));
   1.200 +  }
   1.201 +  else if (gTests[gTestIndex] == "menu movement") {
   1.202 +    document.getElementById("popup").openPopup(
   1.203 +      document.getElementById("label"), "after_start", 0, 0, false, false);
   1.204 +  }
   1.205 +  else if (gTests[gTestIndex] == "panel movement") {
   1.206 +    document.getElementById("panel").openPopup(
   1.207 +      document.getElementById("label"), "after_start", 0, 0, false, false);
   1.208 +  }
   1.209 +  else if (gContextMenuTests) {
   1.210 +    contextMenuPopupHidden();
   1.211 +  }
   1.212 +  else {
   1.213 +    nextTest();
   1.214 +  }
   1.215 +}
   1.216 +
   1.217 +function contextMenuPopupShown()
   1.218 +{
   1.219 +  var popup = document.getElementById("popup");
   1.220 +  var rect = popup.getBoundingClientRect();
   1.221 +  var labelrect = document.getElementById("label").getBoundingClientRect();
   1.222 +
   1.223 +  is(rect.left, labelrect.left + 6, gTests[gTestIndex] + " left");
   1.224 +  switch (gTests[gTestIndex]) {
   1.225 +    case "context menu enough space below":
   1.226 +      is(rect.top, labelrect.top + 6, gTests[gTestIndex] + " top");
   1.227 +      break;
   1.228 +    case "context menu more space above":
   1.229 +      is(rect.top, labelrect.top - rect.height + 2, gTests[gTestIndex] + " top");
   1.230 +      break;
   1.231 +    case "context menu too big either side":
   1.232 +      [, gScreenY] = getScreenXY(document.documentElement);
   1.233 +      // compare against the available size as well as the total size, as some
   1.234 +      // platforms allow the menu to overlap os chrome and others do not
   1.235 +      var pos = (screen.availTop + screen.availHeight - rect.height) - gScreenY;
   1.236 +      var availPos = (screen.top + screen.height - rect.height) - gScreenY;
   1.237 +      ok(rect.top == pos || rect.top == availPos,
   1.238 +         gTests[gTestIndex] + " top");
   1.239 +      break;
   1.240 +    case "context menu larger than screen":
   1.241 +      ok(rect.top == -(gScreenY - screen.availTop) || rect.top == -(gScreenY - screen.top), gTests[gTestIndex] + " top");
   1.242 +      break;
   1.243 +  }
   1.244 +
   1.245 +  hidePopup();
   1.246 +}
   1.247 +
   1.248 +function contextMenuPopupHidden()
   1.249 +{
   1.250 +  var screenAvailBottom = screen.availTop + screen.availHeight;
   1.251 +
   1.252 +  if (gTests[gTestIndex] == "context menu more space above") {
   1.253 +    moveWindowTo(window.screenX, screenAvailBottom - 80, nextContextMenuTest, -1);
   1.254 +  }
   1.255 +  else if (gTests[gTestIndex] == "context menu too big either side") {
   1.256 +    moveWindowTo(window.screenX, screenAvailBottom / 2 - 80, nextContextMenuTest, screenAvailBottom / 2 + 120);
   1.257 +  }
   1.258 +  else if (gTests[gTestIndex] == "context menu larger than screen") {
   1.259 +    nextContextMenuTest(screen.availHeight + 80);
   1.260 +  }
   1.261 +}
   1.262 +
   1.263 +function nextContextMenuTest(desiredHeight)
   1.264 +{
   1.265 +  if (desiredHeight >= 0) {
   1.266 +    var popup = document.getElementById("popup");
   1.267 +    var height = popup.getBoundingClientRect().height;
   1.268 +    var itemheight = document.getElementById("firstitem").getBoundingClientRect().height;
   1.269 +    while (height < desiredHeight) {
   1.270 +      var menu = document.createElement("menuitem");
   1.271 +      menu.setAttribute("label", "Item");
   1.272 +      popup.appendChild(menu);
   1.273 +      height += itemheight;
   1.274 +    }
   1.275 +  }
   1.276 +
   1.277 +  synthesizeMouse(document.getElementById("label"), 4, 4, { type: "contextmenu", button: 2 });
   1.278 +}
   1.279 +
   1.280 +function testPopupMovement()
   1.281 +{
   1.282 +  var button = document.getElementById("label");
   1.283 +  var isPanelTest = (gTests[gTestIndex] == "panel movement");
   1.284 +  var popup = document.getElementById(isPanelTest ? "panel" : "popup");
   1.285 +
   1.286 +  var screenX, screenY, buttonScreenX, buttonScreenY;
   1.287 +  var rect = popup.getBoundingClientRect();
   1.288 +
   1.289 +  var overlapOSChrome = (navigator.platform.indexOf("Mac") == -1);
   1.290 +  popup.moveTo(1, 1);
   1.291 +  [screenX, screenY] = getScreenXY(popup);
   1.292 +
   1.293 +  var expectedx = 1, expectedy = 1;
   1.294 +  if (!isPanelTest && !overlapOSChrome) {
   1.295 +    if (screen.availLeft >= 1) expectedx = screen.availLeft;
   1.296 +    if (screen.availTop >= 1) expectedy = screen.availTop;
   1.297 +  }
   1.298 +  is(screenX, expectedx, gTests[gTestIndex] + " (1, 1) x");
   1.299 +  is(screenY, expectedy, gTests[gTestIndex] + " (1, 1) y");
   1.300 +
   1.301 +  popup.moveTo(100, 8000);
   1.302 +  if (isPanelTest) {
   1.303 +    expectedy = 8000;
   1.304 +  }
   1.305 +  else {
   1.306 +    expectedy = (overlapOSChrome ? screen.height + screen.top : screen.availHeight + screen.availTop) -
   1.307 +                Math.round(rect.height);
   1.308 +  }
   1.309 +
   1.310 +  [screenX, screenY] = getScreenXY(popup);
   1.311 +  is(screenX, 100, gTests[gTestIndex] + " (100, 8000) x");
   1.312 +  is(screenY, expectedy, gTests[gTestIndex] + " (100, 8000) y");
   1.313 +
   1.314 +  popup.moveTo(6000, 100);
   1.315 +
   1.316 +  if (isPanelTest) {
   1.317 +    expectedx = 6000;
   1.318 +  }
   1.319 +  else {
   1.320 +    expectedx = (overlapOSChrome ? screen.width + screen.left : screen.availWidth + screen.availLeft) -
   1.321 +                Math.round(rect.width);
   1.322 +  }
   1.323 +
   1.324 +  [screenX, screenY] = getScreenXY(popup);
   1.325 +  is(screenX, expectedx, gTests[gTestIndex] + " (6000, 100) x");
   1.326 +  is(screenY, 100, gTests[gTestIndex] + " (6000, 100) y");
   1.327 +
   1.328 +  is(popup.left, "", gTests[gTestIndex] + " left is empty after moving");
   1.329 +  is(popup.top, "", gTests[gTestIndex] + " top is empty after moving");
   1.330 +  popup.setAttribute("left", "80");
   1.331 +  popup.setAttribute("top", "82");
   1.332 +  [screenX, screenY] = getScreenXY(popup);
   1.333 +  is(screenX, 80, gTests[gTestIndex] + " set left and top x");
   1.334 +  is(screenY, 82, gTests[gTestIndex] + " set left and top y");
   1.335 +  popup.moveTo(95, 98);
   1.336 +  [screenX, screenY] = getScreenXY(popup);
   1.337 +  is(screenX, 95, gTests[gTestIndex] + " move after set left and top x");
   1.338 +  is(screenY, 98, gTests[gTestIndex] + " move after set left and top y");
   1.339 +  is(popup.left, "95", gTests[gTestIndex] + " left is set after moving");
   1.340 +  is(popup.top, "98", gTests[gTestIndex] + " top is set after moving");
   1.341 +  popup.removeAttribute("left");
   1.342 +  popup.removeAttribute("top");
   1.343 +
   1.344 +  popup.moveTo(-1, -1);
   1.345 +  [screenX, screenY] = getScreenXY(popup);
   1.346 +  [buttonScreenX, buttonScreenY] = getScreenXY(button);
   1.347 +  is(screenX, buttonScreenX, gTests[gTestIndex] + " original x");
   1.348 +  is(screenY, buttonScreenY + button.getBoundingClientRect().height, gTests[gTestIndex] + " original y");
   1.349 +
   1.350 +  popup.hidePopup();
   1.351 +}
   1.352 +
   1.353 +window.opener.wrappedJSObject.SimpleTest.waitForFocus(runTests, window);
   1.354 +
   1.355 +]]>
   1.356 +</script>
   1.357 +
   1.358 +<button id="label" label="OK" context="popup"/>
   1.359 +<menupopup id="popup" onpopupshown="popupShown();" onpopuphidden="popupHidden();"
   1.360 +                      onoverflow="gOverflowed = true" onunderflow="gUnderflowed = true;">
   1.361 +  <menuitem id="firstitem" label="1"/>
   1.362 +  <menuitem label="2"/>
   1.363 +  <menuitem label="3"/>
   1.364 +  <menuitem label="4"/>
   1.365 +  <menuitem label="5"/>
   1.366 +  <menuitem label="6"/>
   1.367 +  <menuitem label="7"/>
   1.368 +  <menuitem label="8"/>
   1.369 +  <menuitem label="9"/>
   1.370 +  <menuitem label="10"/>
   1.371 +  <menuitem label="11"/>
   1.372 +  <menuitem label="12"/>
   1.373 +  <menuitem label="13"/>
   1.374 +  <menuitem label="14"/>
   1.375 +  <menuitem label="15"/>
   1.376 +</menupopup>
   1.377 +
   1.378 +<panel id="panel" onpopupshown="testPopupMovement();" onpopuphidden="popupHidden();" style="margin: 0">
   1.379 +  <button label="OK"/>
   1.380 +</panel>
   1.381 +
   1.382 +</window>

mercurial