dom/tests/mochitest/general/test_offsets.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/tests/mochitest/general/test_offsets.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,209 @@
     1.4 +var scrollbarWidth = 17, scrollbarHeight = 17;
     1.5 +
     1.6 +function testElements(baseid, callback)
     1.7 +{
     1.8 +  scrollbarWidth = scrollbarHeight = gcs($("scrollbox-test"), "width");
     1.9 +
    1.10 +  var elements = $(baseid).getElementsByTagName("*");
    1.11 +  for (var t = 0; t < elements.length; t++) {
    1.12 +    var element = elements[t];
    1.13 +    testElement(element);
    1.14 +  }
    1.15 +
    1.16 +  var nonappended = document.createElement("div");
    1.17 +  nonappended.id = "nonappended";
    1.18 +  nonappended.setAttribute("_offsetParent", "null");
    1.19 +  testElement(nonappended);
    1.20 +
    1.21 +  checkScrolledElement($("scrollbox"), $("scrollchild"));
    1.22 +
    1.23 +  var div = $("noscroll");
    1.24 +  div.scrollLeft = 10;
    1.25 +  div.scrollTop = 10;
    1.26 +  is(element.scrollLeft, 0, element.id + " scrollLeft after nonscroll");
    1.27 +  is(element.scrollTop, 0, element.id + " scrollTop after nonscroll");
    1.28 +
    1.29 +  callback();
    1.30 +}
    1.31 +
    1.32 +function toNearestAppunit(v)
    1.33 +{
    1.34 +  // 60 appunits per CSS pixel; round result to the nearest appunit
    1.35 +  return Math.round(v*60)/60;
    1.36 +}
    1.37 +
    1.38 +function isEqualAppunits(a, b, msg)
    1.39 +{
    1.40 +  is(toNearestAppunit(a), toNearestAppunit(b), msg);
    1.41 +}
    1.42 +
    1.43 +function testElement(element)
    1.44 +{
    1.45 +  var offsetParent = element.getAttribute("_offsetParent");
    1.46 +  offsetParent = $(offsetParent == "null" ? null: (offsetParent ? offsetParent : "body"));
    1.47 +
    1.48 +  var borderLeft = gcs(element, "borderLeftWidth");
    1.49 +  var borderTop = gcs(element, "borderTopWidth");
    1.50 +  var borderRight = gcs(element, "borderRightWidth");
    1.51 +  var borderBottom = gcs(element, "borderBottomWidth");
    1.52 +  var paddingLeft = gcs(element, "paddingLeft");
    1.53 +  var paddingTop = gcs(element, "paddingTop");
    1.54 +  var paddingRight = gcs(element, "paddingRight");
    1.55 +  var paddingBottom = gcs(element, "paddingBottom");
    1.56 +  var width = gcs(element, "width");
    1.57 +  var height = gcs(element, "height");
    1.58 +
    1.59 +  if (element instanceof HTMLElement)
    1.60 +    checkOffsetState(element, -10000, -10000,
    1.61 +                              borderLeft + paddingLeft + width + paddingRight + borderRight,
    1.62 +                              borderTop + paddingTop + height + paddingBottom + borderBottom,
    1.63 +                              offsetParent, element.id);
    1.64 +
    1.65 +  var scrollWidth, scrollHeight, clientWidth, clientHeight;
    1.66 +  var doScrollCheck = true;
    1.67 +  if (element.id == "scrollbox") {
    1.68 +    var lastchild = $("lastline");
    1.69 +    scrollWidth = lastchild.getBoundingClientRect().width + paddingLeft + paddingRight;
    1.70 +    var top = element.firstChild.getBoundingClientRect().top;
    1.71 +    var bottom = element.lastChild.getBoundingClientRect().bottom;
    1.72 +    var contentsHeight = bottom - top;
    1.73 +    scrollHeight = contentsHeight + paddingTop + paddingBottom;
    1.74 +    clientWidth = paddingLeft + width + paddingRight - scrollbarWidth;
    1.75 +    clientHeight = paddingTop + height + paddingBottom - scrollbarHeight;
    1.76 +  } else {
    1.77 +    clientWidth = paddingLeft + width + paddingRight;
    1.78 +    clientHeight = paddingTop + height + paddingBottom;
    1.79 +    if (element.id == "overflow-visible") {
    1.80 +      scrollWidth = 200;
    1.81 +      scrollHeight = 201;
    1.82 +    } else if (element.scrollWidth > clientWidth ||
    1.83 +               element.scrollHeight > clientHeight) {
    1.84 +      // The element overflows. Don't check scrollWidth/scrollHeight since the
    1.85 +      // above calculation is not correct.
    1.86 +      doScrollCheck = false;
    1.87 +    } else {
    1.88 +      scrollWidth = clientWidth;
    1.89 +      scrollHeight = clientHeight;
    1.90 +    }
    1.91 +  }
    1.92 +
    1.93 +  if (doScrollCheck) {
    1.94 +    if (element instanceof SVGElement)
    1.95 +      checkScrollState(element, 0, 0, 0, 0, element.id);
    1.96 +     else
    1.97 +      checkScrollState(element, 0, 0, scrollWidth, scrollHeight, element.id);
    1.98 +  }
    1.99 +
   1.100 +  if (element instanceof SVGElement)
   1.101 +    checkClientState(element, 0, 0, 0, 0, element.id);
   1.102 +  else
   1.103 +    checkClientState(element, borderLeft, borderTop, clientWidth, clientHeight, element.id);
   1.104 +
   1.105 +  var boundingrect = element.getBoundingClientRect();
   1.106 +  isEqualAppunits(boundingrect.width, borderLeft + paddingLeft + width + paddingRight + borderRight,
   1.107 +     element.id + " bounding rect width");
   1.108 +  isEqualAppunits(boundingrect.height, borderTop + paddingTop + height + paddingBottom + borderBottom,
   1.109 +     element.id + " bounding rect height");
   1.110 +  isEqualAppunits(boundingrect.right - boundingrect.left, boundingrect.width,
   1.111 +     element.id + " bounding rect right");
   1.112 +  isEqualAppunits(boundingrect.bottom - boundingrect.top, boundingrect.height,
   1.113 +     element.id + " bounding rect bottom");
   1.114 +
   1.115 +  var rects = element.getClientRects();
   1.116 +  if (element.id == "div-displaynone" || element.id == "nonappended") {
   1.117 +    is(rects.length, 0, element.id + " getClientRects empty");
   1.118 +  }
   1.119 +  else {
   1.120 +    is(rects[0].left, boundingrect.left, element.id + " getClientRects left");
   1.121 +    is(rects[0].top, boundingrect.top, element.id + " getClientRects top");
   1.122 +    is(rects[0].right, boundingrect.right, element.id + " getClientRects right");
   1.123 +    is(rects[0].bottom, boundingrect.bottom, element.id + " getClientRects bottom");
   1.124 +  }
   1.125 +}
   1.126 +
   1.127 +function checkScrolledElement(element, child)
   1.128 +{
   1.129 +  var elemrect = element.getBoundingClientRect();
   1.130 +  var childrect = child.getBoundingClientRect();
   1.131 +
   1.132 +  var topdiff = childrect.top - elemrect.top;
   1.133 +
   1.134 +  element.scrollTop = 20;
   1.135 +  is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll");
   1.136 +  is(element.scrollTop, 20, element.id + " scrollTop after vertical scroll");
   1.137 +  // If the viewport has been transformed, then we might have scrolled to a subpixel value
   1.138 +  // that's slightly different from what we requested. After rounding, however, it should
   1.139 +  // be the same.
   1.140 +  is(Math.round(childrect.top - child.getBoundingClientRect().top), 20, "child position after vertical scroll");
   1.141 +
   1.142 +  element.scrollTop = 0;
   1.143 +  is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll reset");
   1.144 +  is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll reset");
   1.145 +  // Scrolling back to the top should work precisely.
   1.146 +  is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll reset");
   1.147 +
   1.148 +  element.scrollTop = 10;
   1.149 +  element.scrollTop = -30;
   1.150 +  is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll negative");
   1.151 +  is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll negative");
   1.152 +  is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll negative");
   1.153 +
   1.154 +  element.scrollLeft = 18;
   1.155 +  is(element.scrollLeft, 18, element.id + " scrollLeft after horizontal scroll");
   1.156 +  is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll");
   1.157 +  is(Math.round(childrect.left - child.getBoundingClientRect().left), 18, "child position after horizontal scroll");
   1.158 +
   1.159 +  element.scrollLeft = -30;
   1.160 +  is(element.scrollLeft, 0, element.id + " scrollLeft after horizontal scroll reset");
   1.161 +  is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll reset");
   1.162 +  is(child.getBoundingClientRect().left, childrect.left, "child position after horizontal scroll reset");
   1.163 +}
   1.164 +
   1.165 +function checkOffsetState(element, left, top, width, height, parent, testname)
   1.166 +{
   1.167 +  checkCoords(element, "offset", left, top, width, height, testname);
   1.168 +  is(element.offsetParent, parent, testname + " offsetParent");
   1.169 +}
   1.170 +
   1.171 +function checkScrollState(element, left, top, width, height, testname)
   1.172 +{
   1.173 +  checkCoords(element, "scroll", left, top, width, height, testname);
   1.174 +}
   1.175 +
   1.176 +function checkClientState(element, left, top, width, height, testname)
   1.177 +{
   1.178 +  checkCoords(element, "client", left, top, width, height, testname);
   1.179 +}
   1.180 +
   1.181 +function checkCoord(element, type, val, testname)
   1.182 +{
   1.183 +  if (val != -10000)
   1.184 +    is(element[type], Math.round(val), testname + " " + type);
   1.185 +}
   1.186 +
   1.187 +function checkCoords(element, type, left, top, width, height, testname)
   1.188 +{
   1.189 +  checkCoord(element, type + "Left", left, testname);
   1.190 +  checkCoord(element, type + "Top", top, testname);
   1.191 +  checkCoord(element, type + "Width", width, testname);
   1.192 +  checkCoord(element, type + "Height", height, testname);
   1.193 +
   1.194 +  if (element instanceof SVGElement)
   1.195 +    return;
   1.196 +
   1.197 +  if (element.id == "outerpopup" && !element.parentNode.open) // closed popup
   1.198 +    return;
   1.199 +
   1.200 +  if (element.id == "div-displaynone" || element.id == "nonappended") // hidden elements
   1.201 +    ok(element[type + "Width"] == 0 && element[type + "Height"] == 0,
   1.202 +       element.id + " has zero " + type + " width and height");
   1.203 +}
   1.204 +
   1.205 +function gcs(element, prop)
   1.206 +{
   1.207 +  var propVal = (element instanceof SVGElement && (prop == "width" || prop == "height")) ?
   1.208 +                   element.getAttribute(prop) : getComputedStyle(element, "")[prop];
   1.209 +  if (propVal == "auto")
   1.210 +    return 0;
   1.211 +  return parseFloat(propVal);
   1.212 +}

mercurial