| <!DOCTYPE HTML> |
| <script src="../resources/testharness.js"></script> |
| <script src="../resources/testharnessreport.js"></script> |
| |
| <!-- |
| This is a test of the new (June 2016) bounds calculation code, |
| in which every node in the accessibility tree specifies its |
| bounding box and optional matrix transform relative to an |
| ancestor object in the tree. |
| |
| This representation means that when a container element |
| scrolls, animates, or otherwise changes position on screen, |
| its descendants don't need to be updated because their |
| coordinates are all relative. |
| |
| This test asserts that the bounding box we compute is the |
| same as what's computed by the DOM getBoundingClientRect |
| interface. |
| --> |
| |
| <style> |
| .hideAllContainers .container { |
| display: none; |
| } |
| </style> |
| |
| <div class="container"> |
| <input type="text" id="input"> |
| <input type="checkbox" id="checkbox"> |
| <input type="radio" id="radio"> |
| <select id="select"> |
| <option>Apple |
| <option>Orange |
| </select> |
| <button id="button">Button</button> |
| <h1 id="heading">Heading</h1> |
| <p id="para">Para</p> |
| <p>This para has one <span id="span" role="group">span</span></p> |
| <ul id="ul"> |
| <li id="li1">List item 1</li> |
| <li id="li2">List item 2</li> |
| </ul> |
| <div id="div">Div</div> |
| <div id="border" style="border: 10px solid #ccc;">Border</div> |
| <div id="padding" style="padding: 20px;">Padding</div> |
| <div id="margin" style="margin: 30px;">Margin</div> |
| <div id="border_padding_margin" |
| style="border: 10px solid #eee; padding: 20px; margin: 30px;"> |
| Border Padding Margin |
| </div> |
| <svg id="svg" width="60" height="60"> |
| <circle role="button" id="svg_circle" r="25" cx="30" cy="30" stroke="blue" stroke-width="1"/> |
| </svg> |
| </div> |
| |
| <script> |
| function assertDOMRectSameAsAXRect(id) { |
| var element = document.getElementById(id); |
| var bounds = element.getBoundingClientRect(); |
| var axObject = accessibilityController.accessibleElementById(id); |
| |
| // Due to rounding we won't get identical bounds as getBoundingClientRect(), |
| // so allow the test to pass if we're within 1 pixel. The test examples |
| // deliberately have borders, margins, and padding larger than 1 pixel to |
| // ensure that this epsilon is not masking more serious errors. |
| var epsilon = 1; |
| |
| assert_approx_equals(axObject.boundsX, bounds.left, epsilon, id + " left"); |
| assert_approx_equals(axObject.boundsY, bounds.top, epsilon, id + " top"); |
| assert_approx_equals(axObject.boundsWidth, bounds.width, epsilon, id + " width"); |
| assert_approx_equals(axObject.boundsHeight, bounds.height, epsilon, id + " height"); |
| } |
| |
| function assertStaticTextChildDOMRectSameAsAXRect(id) { |
| var element = document.getElementById(id); |
| var axObject = accessibilityController.accessibleElementById(id); |
| var text = element.firstChild; |
| var axText = axObject.childAtIndex(0); |
| assert_equals(text.nodeType, Node.TEXT_NODE, id + " firstChild nodeType"); |
| assert_equals(axText.role, "AXRole: AXStaticText", id + " AX first child role"); |
| var range = document.createRange(); |
| range.selectNode(text); |
| var bounds = range.getBoundingClientRect(); |
| var axObject = accessibilityController.accessibleElementById(id); |
| var epsilon = 1; |
| assert_approx_equals(axText.boundsX, bounds.left, epsilon, id + " left"); |
| assert_approx_equals(axText.boundsY, bounds.top, epsilon, id + " left"); |
| assert_approx_equals(axText.boundsWidth, bounds.width, epsilon, id + " left"); |
| assert_approx_equals(axText.boundsHeight, bounds.height, epsilon, id + " left"); |
| } |
| |
| function assertOffsetContainerIs(id, containerId, opt_expectedResult) { |
| if (opt_expectedResult === undefined) |
| opt_expectedResult = true; |
| var axObject = accessibilityController.accessibleElementById(id); |
| var axContainer = accessibilityController.accessibleElementById(containerId); |
| if (opt_expectedResult) |
| assert_equals(axObject.offsetContainer(), axContainer, id + " offsetContainer"); |
| else |
| assert_false(axObject.offsetContainer().isEqual(axContainer), id + " offsetContainer (should be false)"); |
| } |
| |
| function assertHasTransform(id, expected) { |
| var axObject = accessibilityController.accessibleElementById(id); |
| assert_equals(axObject.hasNonIdentityTransform(), expected, id + " hasNonIdentityTransform"); |
| } |
| |
| test(function(t) { |
| assertDOMRectSameAsAXRect("input"); |
| assertDOMRectSameAsAXRect("checkbox"); |
| assertDOMRectSameAsAXRect("radio"); |
| assertDOMRectSameAsAXRect("button"); |
| assertDOMRectSameAsAXRect("heading"); |
| assertStaticTextChildDOMRectSameAsAXRect("heading"); |
| assertDOMRectSameAsAXRect("para"); |
| assertStaticTextChildDOMRectSameAsAXRect("para"); |
| assertDOMRectSameAsAXRect("span"); |
| assertStaticTextChildDOMRectSameAsAXRect("span"); |
| assertDOMRectSameAsAXRect("ul"); |
| assertDOMRectSameAsAXRect("li1"); |
| assertDOMRectSameAsAXRect("li2"); |
| assertDOMRectSameAsAXRect("div"); |
| assertStaticTextChildDOMRectSameAsAXRect("div"); |
| assertDOMRectSameAsAXRect("border"); |
| assertStaticTextChildDOMRectSameAsAXRect("border"); |
| assertDOMRectSameAsAXRect("padding"); |
| assertStaticTextChildDOMRectSameAsAXRect("padding"); |
| assertDOMRectSameAsAXRect("margin"); |
| assertStaticTextChildDOMRectSameAsAXRect("margin"); |
| assertDOMRectSameAsAXRect("border_padding_margin"); |
| assertStaticTextChildDOMRectSameAsAXRect("border_padding_margin"); |
| assertDOMRectSameAsAXRect("svg"); |
| assertDOMRectSameAsAXRect("svg_circle"); |
| }, "Test computed AX rect for some common objects"); |
| </script> |
| |
| <div id="container2" class="container" role="group" |
| style="position: absolute; left: 400px; top: 20px; border: 3px solid #eee; margin: 5px; padding: 7px;"> |
| <div id="div2">Absolute-positioned</div> |
| <svg id="svg2" width="60" height="60"> |
| <circle role="button" id="svg_circle2" r="25" cx="30" cy="30" stroke="blue" stroke-width="1"/> |
| </svg> |
| |
| </div> |
| |
| <script> |
| test(function(t) { |
| assertHasTransform("container2", false); |
| |
| assertHasTransform("div2", false); |
| assertDOMRectSameAsAXRect("div2"); |
| assertOffsetContainerIs("div2", "container2"); |
| assertDOMRectSameAsAXRect("svg2"); |
| assertDOMRectSameAsAXRect("svg_circle2"); |
| }, "Test objects inside of absolute-positioned container"); |
| </script> |
| |
| <div id="container3" class="container" style="height: 100px; overflow: scroll;"> |
| <div id="div3" style="height: 500px;">Div</div> |
| <input type="text" id="input3"> |
| </div> |
| |
| <script> |
| test(function(t) { |
| document.getElementById("container3").scrollTop = 200; |
| |
| assertHasTransform("container3", false); |
| |
| assertHasTransform("div3", false); |
| assertDOMRectSameAsAXRect("div3"); |
| assertOffsetContainerIs("div3", "container3"); |
| assertHasTransform("input3", false); |
| assertDOMRectSameAsAXRect("input3"); |
| assertOffsetContainerIs("input3", "container3"); |
| }, "Test objects inside of scrolled container"); |
| </script> |
| |
| <div id="container4" class="container" style="width: 200px; transform: rotateZ(45deg);" role="group"> |
| <div id="div4">Rotated text</div> |
| </div> |
| |
| <script> |
| test(function(t) { |
| assertHasTransform("container4", true); |
| |
| assertHasTransform("div4", false); |
| assertDOMRectSameAsAXRect("div4"); |
| assertOffsetContainerIs("div4", "container4"); |
| }, "Test objects inside of rotated container"); |
| </script> |
| |
| <div class="container"> |
| <div style="margin: 20px; width: 200px; transform: scale(1.5);"> |
| <div id="scroll5" class="container" style="padding: 10px; height: 100px; overflow: scroll;"> |
| <div style="width: 200px; transform: rotateZ(175deg);"> |
| <div id="div5" style="margin: 30px; padding: 40px; border: 2px solid #eee;"> |
| Text with lots of transformations |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <script> |
| test(function(t) { |
| document.getElementById("scroll5").scrollTop = 40; |
| assertDOMRectSameAsAXRect("div5"); |
| }, "Test object inside of several nested containers with transforms and scrolling."); |
| </script> |
| |
| <div id="container6a" class="container" role="group" style="position: relative; left: 10px;" |
| aria-owns="div6d"> |
| <div id="div6a">A</div> |
| <div id="div6b">B</div> |
| </div> |
| |
| <div id="container6b" class="container" role="group" style="position: relative; left: 10px;" |
| aria-owns="div6b"> |
| <div id="div6c">C</div> |
| <div id="div6d">D</div> |
| </div> |
| |
| <script> |
| test(function(t) { |
| // This test uses aria-owns to rearrange children between ancestors, |
| // to ensure that an object's offset container is not a node that's an |
| // ancestor in the accessibility tree but not in the layout tree. |
| // |
| // Access both of these accessibility objects first to make sure that |
| // the owned children are up to date before running assertions, |
| // since aria-owns is processed lazily. |
| var axContainer6a = accessibilityController.accessibleElementById("container6a"); |
| axContainer6a.childrenCount; |
| var axContainer6b = accessibilityController.accessibleElementById("container6b"); |
| axContainer6b.childrenCount; |
| |
| assertOffsetContainerIs("div6a", "container6a", true); |
| assertOffsetContainerIs("div6b", "container6a", false); |
| assertOffsetContainerIs("div6b", "container6b", false); |
| |
| assertOffsetContainerIs("div6c", "container6b", true); |
| assertOffsetContainerIs("div6d", "container6a", false); |
| assertOffsetContainerIs("div6d", "container6b", false); |
| }, "Container must be an ancestor in both the AX tree and layout tree."); |
| </script> |
| |
| <div id="container7" class="container" role="group" |
| style="position: absolute; left: 600px; top: 20px; border: 3px solid #eee; margin: 5px; padding: 7px;"> |
| <span id="span7" role="group"> |
| Before |
| <div style="width: 100px; height: 100px;">Block</div> |
| After |
| </span> |
| </div> |
| |
| <script> |
| test(function(t) { |
| assertHasTransform("container7", false); |
| assertHasTransform("span7", false); |
| assertDOMRectSameAsAXRect("span7"); |
| }, "Test spans inside of absolute-positioned container"); |
| </script> |
| |
| <script> |
| if (window.testRunner) |
| document.body.className = "hideAllContainers"; |
| </script> |