11cb0ef41Sopenharmony_ci(function() {
21cb0ef41Sopenharmony_ci// Test is initiated from body.onload, so explicit done() call is required.
31cb0ef41Sopenharmony_cisetup({ explicit_done: true });
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cifunction checkSubtreeExpectedValues(t, parent, prefix)
61cb0ef41Sopenharmony_ci{
71cb0ef41Sopenharmony_ci    var checkedLayout = checkExpectedValues(t, parent, prefix);
81cb0ef41Sopenharmony_ci    Array.prototype.forEach.call(parent.childNodes, function(node) {
91cb0ef41Sopenharmony_ci        checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
101cb0ef41Sopenharmony_ci    });
111cb0ef41Sopenharmony_ci    return checkedLayout;
121cb0ef41Sopenharmony_ci}
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cifunction checkAttribute(output, node, attribute)
151cb0ef41Sopenharmony_ci{
161cb0ef41Sopenharmony_ci    var result = node.getAttribute && node.getAttribute(attribute);
171cb0ef41Sopenharmony_ci    output.checked |= !!result;
181cb0ef41Sopenharmony_ci    return result;
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_cifunction assert_tolerance(actual, expected, message)
221cb0ef41Sopenharmony_ci{
231cb0ef41Sopenharmony_ci    if (isNaN(expected) || isNaN(actual) || Math.abs(actual - expected) >= 1) {
241cb0ef41Sopenharmony_ci        assert_equals(actual, Number(expected), message);
251cb0ef41Sopenharmony_ci    }
261cb0ef41Sopenharmony_ci}
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cifunction checkDataKeys(node) {
291cb0ef41Sopenharmony_ci    var validData = new Set([
301cb0ef41Sopenharmony_ci        "data-expected-width",
311cb0ef41Sopenharmony_ci        "data-expected-height",
321cb0ef41Sopenharmony_ci        "data-offset-x",
331cb0ef41Sopenharmony_ci        "data-offset-y",
341cb0ef41Sopenharmony_ci        "data-expected-client-width",
351cb0ef41Sopenharmony_ci        "data-expected-client-height",
361cb0ef41Sopenharmony_ci        "data-expected-scroll-width",
371cb0ef41Sopenharmony_ci        "data-expected-scroll-height",
381cb0ef41Sopenharmony_ci        "data-expected-bounding-client-rect-width",
391cb0ef41Sopenharmony_ci        "data-expected-bounding-client-rect-height",
401cb0ef41Sopenharmony_ci        "data-total-x",
411cb0ef41Sopenharmony_ci        "data-total-y",
421cb0ef41Sopenharmony_ci        "data-expected-display",
431cb0ef41Sopenharmony_ci        "data-expected-padding-top",
441cb0ef41Sopenharmony_ci        "data-expected-padding-bottom",
451cb0ef41Sopenharmony_ci        "data-expected-padding-left",
461cb0ef41Sopenharmony_ci        "data-expected-padding-right",
471cb0ef41Sopenharmony_ci        "data-expected-margin-top",
481cb0ef41Sopenharmony_ci        "data-expected-margin-bottom",
491cb0ef41Sopenharmony_ci        "data-expected-margin-left",
501cb0ef41Sopenharmony_ci        "data-expected-margin-right"
511cb0ef41Sopenharmony_ci    ]);
521cb0ef41Sopenharmony_ci    if (!node || !node.getAttributeNames)
531cb0ef41Sopenharmony_ci        return;
541cb0ef41Sopenharmony_ci    // Use "data-test" prefix if you need custom-named data elements.
551cb0ef41Sopenharmony_ci    for (let name of node.getAttributeNames()) {
561cb0ef41Sopenharmony_ci        if (name.startsWith("data-") && !name.startsWith("data-test"))
571cb0ef41Sopenharmony_ci            assert_true(validData.has(name), name + " is a valid data attribute");
581cb0ef41Sopenharmony_ci    }
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_cifunction checkExpectedValues(t, node, prefix)
621cb0ef41Sopenharmony_ci{
631cb0ef41Sopenharmony_ci    checkDataKeys(node);
641cb0ef41Sopenharmony_ci    var output = { checked: false };
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    var expectedWidth = checkAttribute(output, node, "data-expected-width");
671cb0ef41Sopenharmony_ci    if (expectedWidth) {
681cb0ef41Sopenharmony_ci        assert_tolerance(node.offsetWidth, expectedWidth, prefix + "width");
691cb0ef41Sopenharmony_ci    }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci    var expectedHeight = checkAttribute(output, node, "data-expected-height");
721cb0ef41Sopenharmony_ci    if (expectedHeight) {
731cb0ef41Sopenharmony_ci        assert_tolerance(node.offsetHeight, expectedHeight, prefix + "height");
741cb0ef41Sopenharmony_ci    }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci    var expectedOffset = checkAttribute(output, node, "data-offset-x");
771cb0ef41Sopenharmony_ci    if (expectedOffset) {
781cb0ef41Sopenharmony_ci        assert_tolerance(node.offsetLeft, expectedOffset, prefix + "offsetLeft");
791cb0ef41Sopenharmony_ci    }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci    var expectedOffset = checkAttribute(output, node, "data-offset-y");
821cb0ef41Sopenharmony_ci    if (expectedOffset) {
831cb0ef41Sopenharmony_ci        assert_tolerance(node.offsetTop, expectedOffset, prefix + "offsetTop");
841cb0ef41Sopenharmony_ci    }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci    var expectedWidth = checkAttribute(output, node, "data-expected-client-width");
871cb0ef41Sopenharmony_ci    if (expectedWidth) {
881cb0ef41Sopenharmony_ci        assert_tolerance(node.clientWidth, expectedWidth, prefix + "clientWidth");
891cb0ef41Sopenharmony_ci    }
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci    var expectedHeight = checkAttribute(output, node, "data-expected-client-height");
921cb0ef41Sopenharmony_ci    if (expectedHeight) {
931cb0ef41Sopenharmony_ci        assert_tolerance(node.clientHeight, expectedHeight, prefix + "clientHeight");
941cb0ef41Sopenharmony_ci    }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci    var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width");
971cb0ef41Sopenharmony_ci    if (expectedWidth) {
981cb0ef41Sopenharmony_ci        assert_tolerance(node.scrollWidth, expectedWidth, prefix + "scrollWidth");
991cb0ef41Sopenharmony_ci    }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci    var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height");
1021cb0ef41Sopenharmony_ci    if (expectedHeight) {
1031cb0ef41Sopenharmony_ci        assert_tolerance(node.scrollHeight, expectedHeight, prefix + "scrollHeight");
1041cb0ef41Sopenharmony_ci    }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    var expectedWidth = checkAttribute(output, node, "data-expected-bounding-client-rect-width");
1071cb0ef41Sopenharmony_ci    if (expectedWidth) {
1081cb0ef41Sopenharmony_ci        assert_tolerance(node.getBoundingClientRect().width, expectedWidth, prefix + "getBoundingClientRect().width");
1091cb0ef41Sopenharmony_ci    }
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci    var expectedHeight = checkAttribute(output, node, "data-expected-bounding-client-rect-height");
1121cb0ef41Sopenharmony_ci    if (expectedHeight) {
1131cb0ef41Sopenharmony_ci        assert_tolerance(node.getBoundingClientRect().height, expectedHeight, prefix + "getBoundingClientRect().height");
1141cb0ef41Sopenharmony_ci    }
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci    var expectedOffset = checkAttribute(output, node, "data-total-x");
1171cb0ef41Sopenharmony_ci    if (expectedOffset) {
1181cb0ef41Sopenharmony_ci        var totalLeft = node.clientLeft + node.offsetLeft;
1191cb0ef41Sopenharmony_ci        assert_tolerance(totalLeft, expectedOffset, prefix +
1201cb0ef41Sopenharmony_ci                         "clientLeft+offsetLeft (" + node.clientLeft + " + " + node.offsetLeft + ")");
1211cb0ef41Sopenharmony_ci    }
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci    var expectedOffset = checkAttribute(output, node, "data-total-y");
1241cb0ef41Sopenharmony_ci    if (expectedOffset) {
1251cb0ef41Sopenharmony_ci        var totalTop = node.clientTop + node.offsetTop;
1261cb0ef41Sopenharmony_ci        assert_tolerance(totalTop, expectedOffset, prefix +
1271cb0ef41Sopenharmony_ci                         "clientTop+offsetTop (" + node.clientTop + " + " + node.offsetTop + ")");
1281cb0ef41Sopenharmony_ci    }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci    var expectedDisplay = checkAttribute(output, node, "data-expected-display");
1311cb0ef41Sopenharmony_ci    if (expectedDisplay) {
1321cb0ef41Sopenharmony_ci        var actualDisplay = getComputedStyle(node).display;
1331cb0ef41Sopenharmony_ci        assert_equals(actualDisplay, expectedDisplay, prefix + "display");
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci    var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top");
1371cb0ef41Sopenharmony_ci    if (expectedPaddingTop) {
1381cb0ef41Sopenharmony_ci        var actualPaddingTop = getComputedStyle(node).paddingTop;
1391cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1401cb0ef41Sopenharmony_ci        actualPaddingTop = actualPaddingTop.slice(0, -2);
1411cb0ef41Sopenharmony_ci        assert_equals(actualPaddingTop, expectedPaddingTop, prefix + "padding-top");
1421cb0ef41Sopenharmony_ci    }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci    var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom");
1451cb0ef41Sopenharmony_ci    if (expectedPaddingBottom) {
1461cb0ef41Sopenharmony_ci        var actualPaddingBottom = getComputedStyle(node).paddingBottom;
1471cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1481cb0ef41Sopenharmony_ci        actualPaddingBottom = actualPaddingBottom.slice(0, -2);
1491cb0ef41Sopenharmony_ci        assert_equals(actualPaddingBottom, expectedPaddingBottom, prefix + "padding-bottom");
1501cb0ef41Sopenharmony_ci    }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci    var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left");
1531cb0ef41Sopenharmony_ci    if (expectedPaddingLeft) {
1541cb0ef41Sopenharmony_ci        var actualPaddingLeft = getComputedStyle(node).paddingLeft;
1551cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1561cb0ef41Sopenharmony_ci        actualPaddingLeft = actualPaddingLeft.slice(0, -2);
1571cb0ef41Sopenharmony_ci        assert_equals(actualPaddingLeft, expectedPaddingLeft, prefix + "padding-left");
1581cb0ef41Sopenharmony_ci    }
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci    var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right");
1611cb0ef41Sopenharmony_ci    if (expectedPaddingRight) {
1621cb0ef41Sopenharmony_ci        var actualPaddingRight = getComputedStyle(node).paddingRight;
1631cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1641cb0ef41Sopenharmony_ci        actualPaddingRight = actualPaddingRight.slice(0, -2);
1651cb0ef41Sopenharmony_ci        assert_equals(actualPaddingRight, expectedPaddingRight, prefix + "padding-right");
1661cb0ef41Sopenharmony_ci    }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci    var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top");
1691cb0ef41Sopenharmony_ci    if (expectedMarginTop) {
1701cb0ef41Sopenharmony_ci        var actualMarginTop = getComputedStyle(node).marginTop;
1711cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1721cb0ef41Sopenharmony_ci        actualMarginTop = actualMarginTop.slice(0, -2);
1731cb0ef41Sopenharmony_ci        assert_equals(actualMarginTop, expectedMarginTop, prefix + "margin-top");
1741cb0ef41Sopenharmony_ci    }
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci    var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom");
1771cb0ef41Sopenharmony_ci    if (expectedMarginBottom) {
1781cb0ef41Sopenharmony_ci        var actualMarginBottom = getComputedStyle(node).marginBottom;
1791cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1801cb0ef41Sopenharmony_ci        actualMarginBottom = actualMarginBottom.slice(0, -2);
1811cb0ef41Sopenharmony_ci        assert_equals(actualMarginBottom, expectedMarginBottom, prefix + "margin-bottom");
1821cb0ef41Sopenharmony_ci    }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci    var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left");
1851cb0ef41Sopenharmony_ci    if (expectedMarginLeft) {
1861cb0ef41Sopenharmony_ci        var actualMarginLeft = getComputedStyle(node).marginLeft;
1871cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1881cb0ef41Sopenharmony_ci        actualMarginLeft = actualMarginLeft.slice(0, -2);
1891cb0ef41Sopenharmony_ci        assert_equals(actualMarginLeft, expectedMarginLeft, prefix + "margin-left");
1901cb0ef41Sopenharmony_ci    }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci    var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right");
1931cb0ef41Sopenharmony_ci    if (expectedMarginRight) {
1941cb0ef41Sopenharmony_ci        var actualMarginRight = getComputedStyle(node).marginRight;
1951cb0ef41Sopenharmony_ci        // Trim the unit "px" from the output.
1961cb0ef41Sopenharmony_ci        actualMarginRight = actualMarginRight.slice(0, -2);
1971cb0ef41Sopenharmony_ci        assert_equals(actualMarginRight, expectedMarginRight, prefix + "margin-right");
1981cb0ef41Sopenharmony_ci    }
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci    return output.checked;
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_civar testNumber = 0;
2041cb0ef41Sopenharmony_civar highlightError = false; // displays outline around failed test element.
2051cb0ef41Sopenharmony_civar printDomOnError = true; // prints dom when test fails.
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ciwindow.checkLayout = function(selectorList, callDone = true)
2081cb0ef41Sopenharmony_ci{
2091cb0ef41Sopenharmony_ci    if (!selectorList) {
2101cb0ef41Sopenharmony_ci        console.error("You must provide a CSS selector of nodes to check.");
2111cb0ef41Sopenharmony_ci        return;
2121cb0ef41Sopenharmony_ci    }
2131cb0ef41Sopenharmony_ci    var nodes = document.querySelectorAll(selectorList);
2141cb0ef41Sopenharmony_ci    nodes = Array.prototype.slice.call(nodes);
2151cb0ef41Sopenharmony_ci    var checkedLayout = false;
2161cb0ef41Sopenharmony_ci    Array.prototype.forEach.call(nodes, function(node) {
2171cb0ef41Sopenharmony_ci        test(function(t) {
2181cb0ef41Sopenharmony_ci            var container = node.parentNode.className == 'container' ? node.parentNode : node;
2191cb0ef41Sopenharmony_ci            var prefix =
2201cb0ef41Sopenharmony_ci                printDomOnError ? '\n' + container.outerHTML + '\n' : '';
2211cb0ef41Sopenharmony_ci            var passed = false;
2221cb0ef41Sopenharmony_ci            try {
2231cb0ef41Sopenharmony_ci                checkedLayout |= checkExpectedValues(t, node.parentNode, prefix);
2241cb0ef41Sopenharmony_ci                checkedLayout |= checkSubtreeExpectedValues(t, node, prefix);
2251cb0ef41Sopenharmony_ci                passed = true;
2261cb0ef41Sopenharmony_ci            } finally {
2271cb0ef41Sopenharmony_ci              if (!passed && highlightError) {
2281cb0ef41Sopenharmony_ci                if (!document.getElementById('testharness_error_css')) {
2291cb0ef41Sopenharmony_ci                  var style = document.createElement('style');
2301cb0ef41Sopenharmony_ci                  style.id = 'testharness_error_css';
2311cb0ef41Sopenharmony_ci                  style.textContent = '.testharness_error { outline: red dotted 2px !important; }';
2321cb0ef41Sopenharmony_ci                  document.body.appendChild(style);
2331cb0ef41Sopenharmony_ci                }
2341cb0ef41Sopenharmony_ci                if (node)
2351cb0ef41Sopenharmony_ci                  node.classList.add('testharness_error');
2361cb0ef41Sopenharmony_ci              }
2371cb0ef41Sopenharmony_ci                checkedLayout |= !passed;
2381cb0ef41Sopenharmony_ci            }
2391cb0ef41Sopenharmony_ci        }, selectorList + ' ' + String(++testNumber));
2401cb0ef41Sopenharmony_ci    });
2411cb0ef41Sopenharmony_ci    if (!checkedLayout) {
2421cb0ef41Sopenharmony_ci        console.error("No valid data-* attributes found in selector list : " + selectorList);
2431cb0ef41Sopenharmony_ci    }
2441cb0ef41Sopenharmony_ci    if (callDone)
2451cb0ef41Sopenharmony_ci        done();
2461cb0ef41Sopenharmony_ci};
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci})();
249