From 7a669f450b8ffbc803a3206bee36733e06773e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 6 Aug 2019 14:14:21 +0200 Subject: [PATCH] MathML: Add tests for children not participating to their parent layout (#18293) * MathML: Add tests for children not participating to their parent layout This commit adds new tests to verify that children with "display: none", "position: absolute" or "position: fixed" don't affect preferred width calculation or layout of their parents. - mathml/support/mathml-fragments.js: Add function to append a non empty child (optionally making the element invalid) and use that function for forceNonEmptyElement. - mathml/support/layout-comparison.js: Introduce new helpers function to extract the children participating to their parent layout. Modify compareLayout so that it browser that list of children instead and allow comparison in horizontal+LTR mode. * Add feature detection otherwise these tests pass when MathML is disabled. * Add TODO for floats. --- .../not-participating-to-parent-layout.html | 74 +++++++++++++++++++ mathml/support/layout-comparison.js | 46 +++++++----- mathml/support/mathml-fragments.js | 20 +++-- 3 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 mathml/relations/css-styling/not-participating-to-parent-layout.html diff --git a/mathml/relations/css-styling/not-participating-to-parent-layout.html b/mathml/relations/css-styling/not-participating-to-parent-layout.html new file mode 100644 index 00000000000000..89389fc668234c --- /dev/null +++ b/mathml/relations/css-styling/not-participating-to-parent-layout.html @@ -0,0 +1,74 @@ + + + + +Elements not participating to the layout of their parent + + + + + + + + + + +
+ + diff --git a/mathml/support/layout-comparison.js b/mathml/support/layout-comparison.js index b1a68995178410..f9111d02ee3187 100644 --- a/mathml/support/layout-comparison.js +++ b/mathml/support/layout-comparison.js @@ -37,36 +37,46 @@ function compareSize(element, reference, epsilon) { } } -function compareLayout(element, reference, epsilon) { - if (element.children.length != reference.children.length) - throw "Reference should have the same number of children." +function participateToParentLayout(child) { + var style = window.getComputedStyle(child); + return style.getPropertyValue("display") !== "none" && + style.getPropertyValue("position") !== "absolute" && + style.getPropertyValue("position") !== "fixed"; +} + +function childrenParticipatingToLayout(element) { + var children = []; + Array.from(element.children).forEach(child => { + if (participateToParentLayout(child)) + children.push(child); + }) + return children; +} +function compareLayout(element, reference, epsilon) { // Compare sizes of elements and children. var param = getWritingMode(element, reference); compareSize(element, reference, epsilon); var elementBox = element.getBoundingClientRect(); var referenceBox = reference.getBoundingClientRect(); - for (var i = 0; i < element.children.length; i++) { - var childDisplay = window. - getComputedStyle(element.children[i]).getPropertyValue("display"); - var referenceChildDisplay = window. - getComputedStyle(reference.children[i]).getPropertyValue("display"); - if (referenceChildDisplay !== childDisplay) - throw "compareLayout: children of reference should have the same display values."; - if (childDisplay === "none") - continue; - compareSize(element.children[i], reference.children[i], epsilon); + var elementChildren = childrenParticipatingToLayout(element); + var referenceChildren = childrenParticipatingToLayout(reference); + if (elementChildren.length != referenceChildren.length) + throw "Reference should have the same number of children participating to layout." + + for (var i = 0; i < elementChildren.length; i++) { + compareSize(elementChildren[i], referenceChildren[i], epsilon); - var childBox = element.children[i].getBoundingClientRect(); - var referenceChildBox = reference.children[i].getBoundingClientRect(); + var childBox = elementChildren[i].getBoundingClientRect(); + var referenceChildBox = referenceChildren[i].getBoundingClientRect(); switch(param.mode) { case "horizontal-tb": - if (!param.rtl) - throw "compareLayout: unexpected writing-mode value"; - assert_approx_equals(elementBox.right - childBox.right, + assert_approx_equals(param.rtl ? + elementBox.right - childBox.right : + childBox.left - elementBox.left, referenceChildBox.left - referenceBox.left, epsilon, `inline position (child ${i})`); diff --git a/mathml/support/mathml-fragments.js b/mathml/support/mathml-fragments.js index 013171cf8c2af5..7c7b003e9e683a 100644 --- a/mathml/support/mathml-fragments.js +++ b/mathml/support/mathml-fragments.js @@ -138,17 +138,25 @@ var FragmentHelper = { return fragment.getElementsByClassName('element')[0]; }, - forceNonEmptyElement: function(fragment) { + appendChild: function(fragment, allowInvalid) { var element = this.element(fragment) || fragment; - if (element.firstElementChild) - return element.firstElementChild; - if (element.classList.contains("mathml-container")) - return element.appendChild(this.createElement("mrow")); if (element.classList.contains("foreign-container")) { var el = document.createElement("span"); el.textContent = "a"; return element.appendChild(el); } - throw "Cannot make the element nonempty"; + if (element.classList.contains("mathml-container") || allowInvalid) { + var el = this.createElement("mi"); + el.textContent = "a"; + return element.appendChild(el); + } + throw "Cannot append child to the element"; + }, + + forceNonEmptyElement: function(fragment) { + var element = this.element(fragment) || fragment; + if (element.firstElementChild) + return element.firstElementChild; + return this.appendChild(fragment); } }