dom/tests/mochitest/general/test_offsets.js

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 var scrollbarWidth = 17, scrollbarHeight = 17;
     3 function testElements(baseid, callback)
     4 {
     5   scrollbarWidth = scrollbarHeight = gcs($("scrollbox-test"), "width");
     7   var elements = $(baseid).getElementsByTagName("*");
     8   for (var t = 0; t < elements.length; t++) {
     9     var element = elements[t];
    10     testElement(element);
    11   }
    13   var nonappended = document.createElement("div");
    14   nonappended.id = "nonappended";
    15   nonappended.setAttribute("_offsetParent", "null");
    16   testElement(nonappended);
    18   checkScrolledElement($("scrollbox"), $("scrollchild"));
    20   var div = $("noscroll");
    21   div.scrollLeft = 10;
    22   div.scrollTop = 10;
    23   is(element.scrollLeft, 0, element.id + " scrollLeft after nonscroll");
    24   is(element.scrollTop, 0, element.id + " scrollTop after nonscroll");
    26   callback();
    27 }
    29 function toNearestAppunit(v)
    30 {
    31   // 60 appunits per CSS pixel; round result to the nearest appunit
    32   return Math.round(v*60)/60;
    33 }
    35 function isEqualAppunits(a, b, msg)
    36 {
    37   is(toNearestAppunit(a), toNearestAppunit(b), msg);
    38 }
    40 function testElement(element)
    41 {
    42   var offsetParent = element.getAttribute("_offsetParent");
    43   offsetParent = $(offsetParent == "null" ? null: (offsetParent ? offsetParent : "body"));
    45   var borderLeft = gcs(element, "borderLeftWidth");
    46   var borderTop = gcs(element, "borderTopWidth");
    47   var borderRight = gcs(element, "borderRightWidth");
    48   var borderBottom = gcs(element, "borderBottomWidth");
    49   var paddingLeft = gcs(element, "paddingLeft");
    50   var paddingTop = gcs(element, "paddingTop");
    51   var paddingRight = gcs(element, "paddingRight");
    52   var paddingBottom = gcs(element, "paddingBottom");
    53   var width = gcs(element, "width");
    54   var height = gcs(element, "height");
    56   if (element instanceof HTMLElement)
    57     checkOffsetState(element, -10000, -10000,
    58                               borderLeft + paddingLeft + width + paddingRight + borderRight,
    59                               borderTop + paddingTop + height + paddingBottom + borderBottom,
    60                               offsetParent, element.id);
    62   var scrollWidth, scrollHeight, clientWidth, clientHeight;
    63   var doScrollCheck = true;
    64   if (element.id == "scrollbox") {
    65     var lastchild = $("lastline");
    66     scrollWidth = lastchild.getBoundingClientRect().width + paddingLeft + paddingRight;
    67     var top = element.firstChild.getBoundingClientRect().top;
    68     var bottom = element.lastChild.getBoundingClientRect().bottom;
    69     var contentsHeight = bottom - top;
    70     scrollHeight = contentsHeight + paddingTop + paddingBottom;
    71     clientWidth = paddingLeft + width + paddingRight - scrollbarWidth;
    72     clientHeight = paddingTop + height + paddingBottom - scrollbarHeight;
    73   } else {
    74     clientWidth = paddingLeft + width + paddingRight;
    75     clientHeight = paddingTop + height + paddingBottom;
    76     if (element.id == "overflow-visible") {
    77       scrollWidth = 200;
    78       scrollHeight = 201;
    79     } else if (element.scrollWidth > clientWidth ||
    80                element.scrollHeight > clientHeight) {
    81       // The element overflows. Don't check scrollWidth/scrollHeight since the
    82       // above calculation is not correct.
    83       doScrollCheck = false;
    84     } else {
    85       scrollWidth = clientWidth;
    86       scrollHeight = clientHeight;
    87     }
    88   }
    90   if (doScrollCheck) {
    91     if (element instanceof SVGElement)
    92       checkScrollState(element, 0, 0, 0, 0, element.id);
    93      else
    94       checkScrollState(element, 0, 0, scrollWidth, scrollHeight, element.id);
    95   }
    97   if (element instanceof SVGElement)
    98     checkClientState(element, 0, 0, 0, 0, element.id);
    99   else
   100     checkClientState(element, borderLeft, borderTop, clientWidth, clientHeight, element.id);
   102   var boundingrect = element.getBoundingClientRect();
   103   isEqualAppunits(boundingrect.width, borderLeft + paddingLeft + width + paddingRight + borderRight,
   104      element.id + " bounding rect width");
   105   isEqualAppunits(boundingrect.height, borderTop + paddingTop + height + paddingBottom + borderBottom,
   106      element.id + " bounding rect height");
   107   isEqualAppunits(boundingrect.right - boundingrect.left, boundingrect.width,
   108      element.id + " bounding rect right");
   109   isEqualAppunits(boundingrect.bottom - boundingrect.top, boundingrect.height,
   110      element.id + " bounding rect bottom");
   112   var rects = element.getClientRects();
   113   if (element.id == "div-displaynone" || element.id == "nonappended") {
   114     is(rects.length, 0, element.id + " getClientRects empty");
   115   }
   116   else {
   117     is(rects[0].left, boundingrect.left, element.id + " getClientRects left");
   118     is(rects[0].top, boundingrect.top, element.id + " getClientRects top");
   119     is(rects[0].right, boundingrect.right, element.id + " getClientRects right");
   120     is(rects[0].bottom, boundingrect.bottom, element.id + " getClientRects bottom");
   121   }
   122 }
   124 function checkScrolledElement(element, child)
   125 {
   126   var elemrect = element.getBoundingClientRect();
   127   var childrect = child.getBoundingClientRect();
   129   var topdiff = childrect.top - elemrect.top;
   131   element.scrollTop = 20;
   132   is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll");
   133   is(element.scrollTop, 20, element.id + " scrollTop after vertical scroll");
   134   // If the viewport has been transformed, then we might have scrolled to a subpixel value
   135   // that's slightly different from what we requested. After rounding, however, it should
   136   // be the same.
   137   is(Math.round(childrect.top - child.getBoundingClientRect().top), 20, "child position after vertical scroll");
   139   element.scrollTop = 0;
   140   is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll reset");
   141   is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll reset");
   142   // Scrolling back to the top should work precisely.
   143   is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll reset");
   145   element.scrollTop = 10;
   146   element.scrollTop = -30;
   147   is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll negative");
   148   is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll negative");
   149   is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll negative");
   151   element.scrollLeft = 18;
   152   is(element.scrollLeft, 18, element.id + " scrollLeft after horizontal scroll");
   153   is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll");
   154   is(Math.round(childrect.left - child.getBoundingClientRect().left), 18, "child position after horizontal scroll");
   156   element.scrollLeft = -30;
   157   is(element.scrollLeft, 0, element.id + " scrollLeft after horizontal scroll reset");
   158   is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll reset");
   159   is(child.getBoundingClientRect().left, childrect.left, "child position after horizontal scroll reset");
   160 }
   162 function checkOffsetState(element, left, top, width, height, parent, testname)
   163 {
   164   checkCoords(element, "offset", left, top, width, height, testname);
   165   is(element.offsetParent, parent, testname + " offsetParent");
   166 }
   168 function checkScrollState(element, left, top, width, height, testname)
   169 {
   170   checkCoords(element, "scroll", left, top, width, height, testname);
   171 }
   173 function checkClientState(element, left, top, width, height, testname)
   174 {
   175   checkCoords(element, "client", left, top, width, height, testname);
   176 }
   178 function checkCoord(element, type, val, testname)
   179 {
   180   if (val != -10000)
   181     is(element[type], Math.round(val), testname + " " + type);
   182 }
   184 function checkCoords(element, type, left, top, width, height, testname)
   185 {
   186   checkCoord(element, type + "Left", left, testname);
   187   checkCoord(element, type + "Top", top, testname);
   188   checkCoord(element, type + "Width", width, testname);
   189   checkCoord(element, type + "Height", height, testname);
   191   if (element instanceof SVGElement)
   192     return;
   194   if (element.id == "outerpopup" && !element.parentNode.open) // closed popup
   195     return;
   197   if (element.id == "div-displaynone" || element.id == "nonappended") // hidden elements
   198     ok(element[type + "Width"] == 0 && element[type + "Height"] == 0,
   199        element.id + " has zero " + type + " width and height");
   200 }
   202 function gcs(element, prop)
   203 {
   204   var propVal = (element instanceof SVGElement && (prop == "width" || prop == "height")) ?
   205                    element.getAttribute(prop) : getComputedStyle(element, "")[prop];
   206   if (propVal == "auto")
   207     return 0;
   208   return parseFloat(propVal);
   209 }

mercurial