(function() { // Test is initiated from body.onload, so explicit done() call is required. setup({ explicit_done: true }); function checkSubtreeExpectedValues(t, parent, prefix) { var checkedLayout = checkExpectedValues(t, parent, prefix); Array.prototype.forEach.call(parent.childNodes, function(node) { checkedLayout |= checkSubtreeExpectedValues(t, node, prefix); }); return checkedLayout; } function checkAttribute(output, node, attribute) { var result = node.getAttribute && node.getAttribute(attribute); output.checked |= !!result; return result; } function assert_tolerance(actual, expected, message) { if (isNaN(expected) || Math.abs(actual - expected) >= 1) { assert_equals(actual, Number(expected), message); } } function checkExpectedValues(t, node, prefix) { var output = { checked: false }; var expectedWidth = checkAttribute(output, node, "data-expected-width"); if (expectedWidth) { assert_tolerance(node.offsetWidth, expectedWidth, prefix + "width"); } var expectedHeight = checkAttribute(output, node, "data-expected-height"); if (expectedHeight) { assert_tolerance(node.offsetHeight, expectedHeight, prefix + "height"); } var expectedOffset = checkAttribute(output, node, "data-offset-x"); if (expectedOffset) { assert_tolerance(node.offsetLeft, expectedOffset, prefix + "offsetLeft"); } var expectedOffset = checkAttribute(output, node, "data-offset-y"); if (expectedOffset) { assert_tolerance(node.offsetTop, expectedOffset, prefix + "offsetTop"); } var expectedWidth = checkAttribute(output, node, "data-expected-client-width"); if (expectedWidth) { assert_tolerance(node.clientWidth, expectedWidth, prefix + "clientWidth"); } var expectedHeight = checkAttribute(output, node, "data-expected-client-height"); if (expectedHeight) { assert_tolerance(node.clientHeight, expectedHeight, prefix + "clientHeight"); } var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width"); if (expectedWidth) { assert_tolerance(node.scrollWidth, expectedWidth, prefix + "scrollWidth"); } var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height"); if (expectedHeight) { assert_tolerance(node.scrollHeight, expectedHeight, prefix + "scrollHeight"); } var expectedWidth = checkAttribute(output, node, "data-expected-bounding-client-rect-width"); if (expectedWidth) { assert_tolerance(node.getBoundingClientRect().width, expectedWidth, prefix + "getBoundingClientRect().width"); } var expectedOffset = checkAttribute(output, node, "data-total-x"); if (expectedOffset) { var totalLeft = node.clientLeft + node.offsetLeft; assert_tolerance(totalLeft, expectedOffset, prefix + "clientLeft+offsetLeft (" + node.clientLeft + " + " + node.offsetLeft + ")"); } var expectedOffset = checkAttribute(output, node, "data-total-y"); if (expectedOffset) { var totalTop = node.clientTop + node.offsetTop; assert_tolerance(totalTop, expectedOffset, prefix + "clientTop+offsetTop (" + node.clientTop + " + " + node.offsetTop + ")"); } var expectedDisplay = checkAttribute(output, node, "data-expected-display"); if (expectedDisplay) { var actualDisplay = getComputedStyle(node).display; assert_equals(actualDisplay, expectedDisplay, prefix + "display"); } var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top"); if (expectedPaddingTop) { var actualPaddingTop = getComputedStyle(node).paddingTop; // Trim the unit "px" from the output. actualPaddingTop = actualPaddingTop.slice(0, -2); assert_equals(actualPaddingTop, expectedPaddingTop, prefix + "padding-top"); } var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom"); if (expectedPaddingBottom) { var actualPaddingBottom = getComputedStyle(node).paddingBottom; // Trim the unit "px" from the output. actualPaddingBottom = actualPaddingBottom.slice(0, -2); assert_equals(actualPaddingBottom, expectedPaddingBottom, prefix + "padding-bottom"); } var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left"); if (expectedPaddingLeft) { var actualPaddingLeft = getComputedStyle(node).paddingLeft; // Trim the unit "px" from the output. actualPaddingLeft = actualPaddingLeft.slice(0, -2); assert_equals(actualPaddingLeft, expectedPaddingLeft, prefix + "padding-left"); } var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right"); if (expectedPaddingRight) { var actualPaddingRight = getComputedStyle(node).paddingRight; // Trim the unit "px" from the output. actualPaddingRight = actualPaddingRight.slice(0, -2); assert_equals(actualPaddingRight, expectedPaddingRight, prefix + "padding-right"); } var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top"); if (expectedMarginTop) { var actualMarginTop = getComputedStyle(node).marginTop; // Trim the unit "px" from the output. actualMarginTop = actualMarginTop.slice(0, -2); assert_equals(actualMarginTop, expectedMarginTop, prefix + "margin-top"); } var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom"); if (expectedMarginBottom) { var actualMarginBottom = getComputedStyle(node).marginBottom; // Trim the unit "px" from the output. actualMarginBottom = actualMarginBottom.slice(0, -2); assert_equals(actualMarginBottom, expectedMarginBottom, prefix + "margin-bottom"); } var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left"); if (expectedMarginLeft) { var actualMarginLeft = getComputedStyle(node).marginLeft; // Trim the unit "px" from the output. actualMarginLeft = actualMarginLeft.slice(0, -2); assert_equals(actualMarginLeft, expectedMarginLeft, prefix + "margin-left"); } var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right"); if (expectedMarginRight) { var actualMarginRight = getComputedStyle(node).marginRight; // Trim the unit "px" from the output. actualMarginRight = actualMarginRight.slice(0, -2); assert_equals(actualMarginRight, expectedMarginRight, prefix + "margin-right"); } return output.checked; } let testNumbers = new Map(); window.checkLayout = function(selectorList, outputContainer) { if (!selectorList) { console.error("You must provide a CSS selector of nodes to check."); return; } var nodes = document.querySelectorAll(selectorList); let testNumber = 0; if (testNumbers.has("" + selectorList)) testNumber = testNumbers.get("" + selectorList); nodes = Array.prototype.slice.call(nodes); nodes.reverse(); var checkedLayout = false; Array.prototype.forEach.call(nodes, function(node) { test(function(t) { var container = node.parentNode.className == 'container' ? node.parentNode : node; var prefix = "\n" + container.outerHTML + "\n"; var passed = false; try { checkedLayout |= checkExpectedValues(t, node.parentNode, prefix); checkedLayout |= checkSubtreeExpectedValues(t, node, prefix); passed = true; } finally { checkedLayout |= !passed; } }, selectorList + ' ' + String(++testNumber)); }); if (!checkedLayout) { console.error("No valid data-* attributes found in selector list : " + selectorList); } testNumbers.set("" + selectorList, testNumber); done(); }; })();