toolkit/content/tests/widgets/test_popupanchor.xul

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 <?xml version="1.0"?>
michael@0 2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
michael@0 3 <?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
michael@0 4
michael@0 5 <window title="Popup Anchor Tests"
michael@0 6 xmlns:html="http://www.w3.org/1999/xhtml"
michael@0 7 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
michael@0 8
michael@0 9 <panel id="testPanel"
michael@0 10 type="arrow"
michael@0 11 animate="false"
michael@0 12 noautohide="true">
michael@0 13 </panel>
michael@0 14
michael@0 15 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
michael@0 16
michael@0 17 <script>
michael@0 18 <![CDATA[
michael@0 19 var anchor, panel, arrow;
michael@0 20
michael@0 21 function is_close(got, exp, msg) {
michael@0 22 // on some platforms we see differences of a fraction of a pixel - so
michael@0 23 // allow any difference of < 1 pixels as being OK.
michael@0 24 ok(Math.abs(got - exp) < 1, msg + ": " + got + " should be equal(-ish) to " + exp);
michael@0 25 }
michael@0 26
michael@0 27 function isArrowPositionedOn(side, offset) {
michael@0 28 var arrowRect = arrow.getBoundingClientRect();
michael@0 29 var arrowMidX = (arrowRect.left + arrowRect.right) / 2;
michael@0 30 var arrowMidY = (arrowRect.top + arrowRect.bottom) / 2;
michael@0 31 var panelRect = panel.getBoundingClientRect();
michael@0 32 var panelMidX = (panelRect.left + panelRect.right) / 2;
michael@0 33 var panelMidY = (panelRect.top + panelRect.bottom) / 2;
michael@0 34 // First check the "flip" of the panel is correct. If we are expecting the
michael@0 35 // arrow to be pointing to the left side of the anchor, the arrow must
michael@0 36 // also be on the left side of the panel (and vice-versa)
michael@0 37 // XXX - on OSX, the arrow seems to always be exactly in the center, hence
michael@0 38 // the 'equals' sign in the "<=" and ">=" comparisons. NFI why though...
michael@0 39 switch (side) {
michael@0 40 case "left":
michael@0 41 ok(arrowMidX <= panelMidX, "arrow should be on the left of the panel");
michael@0 42 break;
michael@0 43 case "right":
michael@0 44 ok(arrowMidX >= panelMidX, "arrow should be on the right of the panel");
michael@0 45 break;
michael@0 46 case "top":
michael@0 47 ok(arrowMidY <= panelMidY, "arrow should be on the top of the panel");
michael@0 48 break;
michael@0 49 case "bottom":
michael@0 50 ok(arrowMidY >= panelMidY, "arrow should be on the bottom of the panel");
michael@0 51 break;
michael@0 52 default:
michael@0 53 ok(false, "invalid position " + where);
michael@0 54 break;
michael@0 55 }
michael@0 56 // Now check the arrow really is pointing where we expect. The middle of
michael@0 57 // the arrow should be pointing exactly to the left (or right) side of the
michael@0 58 // anchor rect, +- any offsets.
michael@0 59 if (offset === null) // special case - explicit 'null' means 'don't check offset'
michael@0 60 return;
michael@0 61 offset = offset || 0; // no param means no offset expected.
michael@0 62 var anchorRect = anchor.getBoundingClientRect();
michael@0 63 var anchorPos = anchorRect[side];
michael@0 64 switch (side) {
michael@0 65 case "left":
michael@0 66 case "right":
michael@0 67 is_close(arrowMidX - anchorPos, offset, "arrow should be " + offset + "px from " + side + " side of anchor");
michael@0 68 is_close(panelRect.top, anchorRect.bottom, "top of panel should be at bottom of anchor");
michael@0 69 break;
michael@0 70 case "top":
michael@0 71 case "bottom":
michael@0 72 is_close(arrowMidY - anchorPos, offset, "arrow should be " + offset + "px from " + side + " side of anchor");
michael@0 73 is_close(panelRect.right, anchorRect.left, "right of panel should be left of anchor");
michael@0 74 break;
michael@0 75 default:
michael@0 76 ok(false, "unknown side " + side);
michael@0 77 break;
michael@0 78 }
michael@0 79 }
michael@0 80
michael@0 81 function openSlidingPopup(position, callback) {
michael@0 82 panel.setAttribute("flip", "slide");
michael@0 83 _openPopup(position, callback);
michael@0 84 }
michael@0 85
michael@0 86 function openPopup(position, callback) {
michael@0 87 panel.setAttribute("flip", "both");
michael@0 88 _openPopup(position, callback);
michael@0 89 }
michael@0 90
michael@0 91 function _openPopup(position, callback) {
michael@0 92 // this is very ugly: the panel CSS sets the arrow's list-style-image based
michael@0 93 // on the 'side' attribute. If the setting of the 'side' attribute causes
michael@0 94 // the image to change, we may get the popupshown event before the new
michael@0 95 // image has loaded - which causes the size of the arrow to be incorrect
michael@0 96 // for a brief moment - right when we are measuring it!
michael@0 97 // So we work around this in 2 steps:
michael@0 98 // * Force the 'side' attribute to a value which causes the CSS to not
michael@0 99 // specify an image - then when the popup gets shown, the correct image
michael@0 100 // is set, causing a load() event on the image element.
michael@0 101 // * Listen to *both* popupshown and the image load event. When both have
michael@0 102 // fired (the order is indeterminate) we start the test.
michael@0 103 panel.setAttribute("side", "noside");
michael@0 104 var numEvents = 0;
michael@0 105 function onEvent() {
michael@0 106 if (++numEvents == 2) // after both panel 'popupshown' and image 'load'
michael@0 107 callback();
michael@0 108 };
michael@0 109 panel.addEventListener("popupshown", function popupshown() {
michael@0 110 panel.removeEventListener("popupshown", popupshown);
michael@0 111 onEvent();
michael@0 112 });
michael@0 113 arrow.addEventListener("load", function imageload() {
michael@0 114 arrow.removeEventListener("load", imageload);
michael@0 115 onEvent();
michael@0 116 });
michael@0 117 panel.openPopup(anchor, position);
michael@0 118 }
michael@0 119
michael@0 120 var tests = [
michael@0 121 // A panel with the anchor after_end - the anchor should not move on resize
michael@0 122 ['simpleResizeHorizontal', 'middle', function(next) {
michael@0 123 openPopup("after_end", function() {
michael@0 124 isArrowPositionedOn("right");
michael@0 125 var origPanelRect = panel.getBoundingClientRect();
michael@0 126 panel.sizeTo(100, 100);
michael@0 127 isArrowPositionedOn("right"); // should not have flipped, so still "right"
michael@0 128 panel.sizeTo(origPanelRect.width, origPanelRect.height);
michael@0 129 isArrowPositionedOn("right"); // should not have flipped, so still "right"
michael@0 130 next();
michael@0 131 });
michael@0 132 }],
michael@0 133
michael@0 134 ['simpleResizeVertical', 'middle', function(next) {
michael@0 135 openPopup("start_after", function() {
michael@0 136 isArrowPositionedOn("bottom");
michael@0 137 var origPanelRect = panel.getBoundingClientRect();
michael@0 138 panel.sizeTo(100, 100);
michael@0 139 isArrowPositionedOn("bottom"); // should not have flipped
michael@0 140 panel.sizeTo(origPanelRect.width, origPanelRect.height);
michael@0 141 isArrowPositionedOn("bottom"); // should not have flipped
michael@0 142 next();
michael@0 143 });
michael@0 144 }],
michael@0 145
michael@0 146 ['flippingResizeHorizontal', 'middle', function(next) {
michael@0 147 openPopup("after_end", function() {
michael@0 148 isArrowPositionedOn("right");
michael@0 149 panel.sizeTo(anchor.getBoundingClientRect().left + 50, 50);
michael@0 150 isArrowPositionedOn("left"); // check it flipped and has zero offset.
michael@0 151 next();
michael@0 152 });
michael@0 153 }],
michael@0 154
michael@0 155 ['flippingResizeVertical', 'middle', function(next) {
michael@0 156 openPopup("start_after", function() {
michael@0 157 isArrowPositionedOn("bottom");
michael@0 158 panel.sizeTo(50, anchor.getBoundingClientRect().top + 50);
michael@0 159 isArrowPositionedOn("top"); // check it flipped and has zero offset.
michael@0 160 next();
michael@0 161 });
michael@0 162 }],
michael@0 163
michael@0 164 ['simpleMoveToAnchorHorizontal', 'middle', function(next) {
michael@0 165 openPopup("after_end", function() {
michael@0 166 isArrowPositionedOn("right");
michael@0 167 panel.moveToAnchor(anchor, "after_end", 20, 0);
michael@0 168 // the anchor and the panel should have moved 20px right without flipping.
michael@0 169 isArrowPositionedOn("right", 20);
michael@0 170 panel.moveToAnchor(anchor, "after_end", -20, 0);
michael@0 171 // the anchor and the panel should have moved 20px left without flipping.
michael@0 172 isArrowPositionedOn("right", -20);
michael@0 173 next();
michael@0 174 });
michael@0 175 }],
michael@0 176
michael@0 177 ['simpleMoveToAnchorVertical', 'middle', function(next) {
michael@0 178 openPopup("start_after", function() {
michael@0 179 isArrowPositionedOn("bottom");
michael@0 180 panel.moveToAnchor(anchor, "start_after", 0, 20);
michael@0 181 // the anchor and the panel should have moved 20px down without flipping.
michael@0 182 isArrowPositionedOn("bottom", 20);
michael@0 183 panel.moveToAnchor(anchor, "start_after", 0, -20);
michael@0 184 // the anchor and the panel should have moved 20px up without flipping.
michael@0 185 isArrowPositionedOn("bottom", -20);
michael@0 186 next();
michael@0 187 });
michael@0 188 }],
michael@0 189
michael@0 190 // Do a moveToAnchor that causes the panel to flip horizontally
michael@0 191 ['flippingMoveToAnchorHorizontal', 'middle', function(next) {
michael@0 192 var anchorRight = anchor.getBoundingClientRect().right;
michael@0 193 // Size the panel such that it only just fits from the left-hand side of
michael@0 194 // the window to the right of the anchor - thus, it will fit when
michael@0 195 // anchored to the right-hand side of the anchor.
michael@0 196 panel.sizeTo(anchorRight - 10, 100);
michael@0 197 openPopup("after_end", function() {
michael@0 198 isArrowPositionedOn("right");
michael@0 199 // Ask for it to be anchored 1/2 way between the left edge of the window
michael@0 200 // and the anchor right - it can't fit with the panel on the left/arrow
michael@0 201 // on the right, so it must flip (arrow on the left, panel on the right)
michael@0 202 var offset = Math.floor(-anchorRight / 2);
michael@0 203 panel.moveToAnchor(anchor, "after_end", offset, 0);
michael@0 204 isArrowPositionedOn("left", offset); // should have flipped and have the offset.
michael@0 205 // resize back to original and move to a zero offset - it should flip back.
michael@0 206 panel.sizeTo(anchorRight - 10, 100);
michael@0 207 panel.moveToAnchor(anchor, "after_end", 0, 0);
michael@0 208 isArrowPositionedOn("right"); // should have flipped back and no offset
michael@0 209 next();
michael@0 210 });
michael@0 211 }],
michael@0 212
michael@0 213 // Do a moveToAnchor that causes the panel to flip vertically
michael@0 214 ['flippingMoveToAnchorVertical', 'middle', function(next) {
michael@0 215 var anchorBottom = anchor.getBoundingClientRect().bottom;
michael@0 216 // See comments above in flippingMoveToAnchorHorizontal, but read
michael@0 217 // "top/bottom" instead of "left/right"
michael@0 218 panel.sizeTo(100, anchorBottom - 10);
michael@0 219 openPopup("start_after", function() {
michael@0 220 isArrowPositionedOn("bottom");
michael@0 221 var offset = Math.floor(-anchorBottom / 2);
michael@0 222 panel.moveToAnchor(anchor, "start_after", 0, offset);
michael@0 223 isArrowPositionedOn("top", offset);
michael@0 224 panel.sizeTo(100, anchorBottom - 10);
michael@0 225 panel.moveToAnchor(anchor, "start_after", 0, 0);
michael@0 226 isArrowPositionedOn("bottom");
michael@0 227 next();
michael@0 228 });
michael@0 229 }],
michael@0 230
michael@0 231 ['veryWidePanel-after_end', 'middle', function(next) {
michael@0 232 openSlidingPopup("after_end", function() {
michael@0 233 var origArrowRect = arrow.getBoundingClientRect();
michael@0 234 // Now move it such that the arrow can't be at either end of the panel but
michael@0 235 // instead somewhere in the middle as that is the only way things fit,
michael@0 236 // meaning the arrow should "slide" down the panel.
michael@0 237 panel.sizeTo(window.innerWidth - 10, 60);
michael@0 238 is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested.")
michael@0 239 // the arrow should not have moved.
michael@0 240 var curArrowRect = arrow.getBoundingClientRect();
michael@0 241 is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved");
michael@0 242 is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down");
michael@0 243 next();
michael@0 244 });
michael@0 245 }],
michael@0 246
michael@0 247 ['veryWidePanel-before_start', 'middle', function(next) {
michael@0 248 openSlidingPopup("before_start", function() {
michael@0 249 var origArrowRect = arrow.getBoundingClientRect();
michael@0 250 // Now size it such that the arrow can't be at either end of the panel but
michael@0 251 // instead somewhere in the middle as that is the only way things fit.
michael@0 252 panel.sizeTo(window.innerWidth - 10, 60);
michael@0 253 is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested")
michael@0 254 // the arrow should not have moved.
michael@0 255 var curArrowRect = arrow.getBoundingClientRect();
michael@0 256 is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved");
michael@0 257 is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down");
michael@0 258 next();
michael@0 259 });
michael@0 260 }],
michael@0 261
michael@0 262 ['veryTallPanel-start_after', 'middle', function(next) {
michael@0 263 openSlidingPopup("start_after", function() {
michael@0 264 var origArrowRect = arrow.getBoundingClientRect();
michael@0 265 // Now move it such that the arrow can't be at either end of the panel but
michael@0 266 // instead somewhere in the middle as that is the only way things fit,
michael@0 267 // meaning the arrow should "slide" down the panel.
michael@0 268 panel.sizeTo(100, window.innerHeight - 10);
michael@0 269 is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested.")
michael@0 270 // the arrow should not have moved.
michael@0 271 var curArrowRect = arrow.getBoundingClientRect();
michael@0 272 is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved");
michael@0 273 is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down");
michael@0 274 next();
michael@0 275 });
michael@0 276 }],
michael@0 277
michael@0 278 ['veryTallPanel-start_before', 'middle', function(next) {
michael@0 279 openSlidingPopup("start_before", function() {
michael@0 280 var origArrowRect = arrow.getBoundingClientRect();
michael@0 281 // Now size it such that the arrow can't be at either end of the panel but
michael@0 282 // instead somewhere in the middle as that is the only way things fit.
michael@0 283 panel.sizeTo(100, window.innerHeight - 10);
michael@0 284 is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested")
michael@0 285 // the arrow should not have moved.
michael@0 286 var curArrowRect = arrow.getBoundingClientRect();
michael@0 287 is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved");
michael@0 288 is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down");
michael@0 289 next();
michael@0 290 });
michael@0 291 }],
michael@0 292
michael@0 293 // Tests against the anchor at the right-hand side of the window
michael@0 294 ['afterend', 'right', function(next) {
michael@0 295 openPopup("after_end", function() {
michael@0 296 // when we request too far to the right/bottom, the panel gets shrunk
michael@0 297 // and moved. The amount it is shrunk by is how far it is moved.
michael@0 298 var panelRect = panel.getBoundingClientRect();
michael@0 299 // panel was requested 100px wide - calc offset based on actual width.
michael@0 300 var offset = panelRect.width - 100;
michael@0 301 isArrowPositionedOn("right", offset);
michael@0 302 next();
michael@0 303 });
michael@0 304 }],
michael@0 305
michael@0 306 ['after_start', 'right', function(next) {
michael@0 307 openPopup("after_start", function() {
michael@0 308 // See above - we are still too far to the right, but the anchor is
michael@0 309 // on the other side.
michael@0 310 var panelRect = panel.getBoundingClientRect();
michael@0 311 var offset = panelRect.width - 100;
michael@0 312 isArrowPositionedOn("right", offset);
michael@0 313 next();
michael@0 314 });
michael@0 315 }],
michael@0 316
michael@0 317 // Tests against the anchor at the left-hand side of the window
michael@0 318 ['after_start', 'left', function(next) {
michael@0 319 openPopup("after_start", function() {
michael@0 320 var panelRect = panel.getBoundingClientRect();
michael@0 321 is(panelRect.left, 0, "panel remains within the screen");
michael@0 322 // not sure how to determine the offset here, so given we have checked
michael@0 323 // the panel is as left as possible while still being inside the window,
michael@0 324 // we just don't check the offset.
michael@0 325 isArrowPositionedOn("left", null);
michael@0 326 next();
michael@0 327 });
michael@0 328 }],
michael@0 329 ]
michael@0 330
michael@0 331 function runTests() {
michael@0 332 var testIter = Iterator(tests);
michael@0 333 function runNextTest() {
michael@0 334 let name, anchorPos, test;
michael@0 335 try {
michael@0 336 let index;
michael@0 337 [index, [name, anchorPos, test]] = testIter.next();
michael@0 338 } catch (err if err instanceof StopIteration) {
michael@0 339 // out of tests
michael@0 340 panel.hidePopup();
michael@0 341 SimpleTest.finish();
michael@0 342 return;
michael@0 343 }
michael@0 344 SimpleTest.info("sub-test " + anchorPos + "." + name + " starting");
michael@0 345 // first arrange for the anchor to be where the test requires it.
michael@0 346 panel.hidePopup();
michael@0 347 panel.sizeTo(100, 50);
michael@0 348 // hide all the anchors here, then later we make one of them visible.
michael@0 349 document.getElementById("anchor-left-wrapper").style.display = "none";
michael@0 350 document.getElementById("anchor-middle-wrapper").style.display = "none";
michael@0 351 document.getElementById("anchor-right-wrapper").style.display = "none";
michael@0 352 switch(anchorPos) {
michael@0 353 case 'middle':
michael@0 354 anchor = document.getElementById("anchor-middle");
michael@0 355 document.getElementById("anchor-middle-wrapper").style.display = "block";
michael@0 356 break;
michael@0 357 case 'left':
michael@0 358 anchor = document.getElementById("anchor-left");
michael@0 359 document.getElementById("anchor-left-wrapper").style.display = "block";
michael@0 360 break;
michael@0 361 case 'right':
michael@0 362 anchor = document.getElementById("anchor-right");
michael@0 363 document.getElementById("anchor-right-wrapper").style.display = "block";
michael@0 364 break;
michael@0 365 default:
michael@0 366 SimpleTest.ok(false, "Bad anchorPos: " + anchorPos);
michael@0 367 runNextTest();
michael@0 368 return;
michael@0 369 }
michael@0 370 try {
michael@0 371 test(runNextTest);
michael@0 372 } catch (ex) {
michael@0 373 SimpleTest.ok(false, "sub-test " + anchorPos + "." + name + " failed: " + ex.toString() + "\n" + ex.stack);
michael@0 374 runNextTest();
michael@0 375 }
michael@0 376 }
michael@0 377 runNextTest();
michael@0 378 }
michael@0 379
michael@0 380 SimpleTest.waitForExplicitFinish();
michael@0 381
michael@0 382 addEventListener("load", function() {
michael@0 383 // anchor is set by the test runner above
michael@0 384 panel = document.getElementById("testPanel");
michael@0 385 arrow = SpecialPowers.wrap(document).getAnonymousElementByAttribute(panel, "anonid", "arrow");
michael@0 386 // Cancel the arrow panel slide-in transition (bug 767133) so the size and
michael@0 387 // position are "stable" enough to test without jumping through hoops...
michael@0 388 arrow.style.transition = "none";
michael@0 389 runTests();
michael@0 390 });
michael@0 391
michael@0 392 ]]>
michael@0 393 </script>
michael@0 394
michael@0 395 <body xmlns="http://www.w3.org/1999/xhtml">
michael@0 396 <!-- Our tests assume at least 100px around the anchor on all sides, else the
michael@0 397 panel may flip when we don't expect it to
michael@0 398 -->
michael@0 399 <div id="anchor-middle-wrapper" style="margin: 100px 100px 100px 100px;">
michael@0 400 <p>The anchor --&gt; <span id="anchor-middle">v</span> &lt;--</p>
michael@0 401 </div>
michael@0 402 <div id="anchor-left-wrapper" style="text-align: left; display: none;">
michael@0 403 <p><span id="anchor-left">v</span> &lt;-- The anchor;</p>
michael@0 404 </div>
michael@0 405 <div id="anchor-right-wrapper" style="text-align: right; display: none;">
michael@0 406 <p>The anchor --&gt; <span id="anchor-right">v</span></p>
michael@0 407 </div>
michael@0 408 </body>
michael@0 409
michael@0 410 </window>

mercurial