| <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> |
| <html> |
| <head> |
| <script src="../resources/accessibility-helper.js"></script> |
| <script src="../resources/js-test.js"></script> |
| <style> |
| /* Minimal repro: elements share the same static position (top:50%, left:50%) |
| and are distinguished only by CSS transforms. Without using transforms in the |
| path origin computation (localToAbsolute), all elements get identical |
| accessibility paths pinned to the untransformed center. */ |
| .container { |
| position: relative; |
| width: 300px; |
| height: 300px; |
| } |
| .item { |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| width: 80px; |
| height: 80px; |
| margin: -40px; |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| } |
| /* Three items at 120-degree intervals around a circle. */ |
| #item1 { transform: rotate(0deg) translateX(-120px) rotate(0deg); } |
| #item2 { transform: rotate(120deg) translateX(-120px) rotate(-120deg); } |
| #item3 { transform: rotate(240deg) translateX(-120px) rotate(-240deg); } |
| </style> |
| </head> |
| <body> |
| |
| <div id="content"> |
| <div class="container"> |
| <div class="item" id="item1" role="button">A</div> |
| <div class="item" id="item2" role="button">B</div> |
| <div class="item" id="item3" role="button">C</div> |
| </div> |
| </div> |
| |
| <script> |
| var output = "This test verifies that accessibility paths for border-radius elements with CSS transforms are correctly positioned. The three items share the same static position and are placed in a circle purely via CSS transforms. Their path bounds must reflect the transformed positions, not the shared untransformed origin.\n\n"; |
| |
| if (window.accessibilityController) { |
| window.jsTestIsAsync = true; |
| |
| (async () => { |
| // Wait for paths to be cached (they require a paint). |
| await waitUntilIDHasPathWith("item1", 1, "Curve to"); |
| |
| output += "--- All items should have curve paths (border-radius: 50%) ---\n"; |
| output += expect("pathSegmentCountOfID('item1', 'Curve to') > 0", "true"); |
| output += expect("pathSegmentCountOfID('item2', 'Curve to') > 0", "true"); |
| output += expect("pathSegmentCountOfID('item3', 'Curve to') > 0", "true"); |
| |
| window.bounds1 = pathAsBoundsOfID("item1"); |
| window.bounds2 = pathAsBoundsOfID("item2"); |
| window.bounds3 = pathAsBoundsOfID("item3"); |
| |
| // All items are 80x80 circles, so their path sizes should be similar. |
| // But their origins must differ because they're at different transformed |
| // positions. Before the fix, all three had identical path bounds. |
| output += "\n--- Path bounds should have similar sizes (all are 80x80 circles) ---\n"; |
| output += expect("Math.abs(bounds1.width - bounds2.width) < 2", "true"); |
| output += expect("Math.abs(bounds1.height - bounds2.height) < 2", "true"); |
| |
| output += "\n--- Path bounds must have different positions (CSS transforms applied) ---\n"; |
| // Item1 is translated straight up, item2 is at 120deg, item3 is at 240deg. |
| // No two should share the same (x, y) origin. |
| window.tolerance = 5; |
| output += expect("Math.abs(bounds1.x - bounds2.x) > tolerance || Math.abs(bounds1.y - bounds2.y) > tolerance", "true"); |
| output += expect("Math.abs(bounds1.x - bounds3.x) > tolerance || Math.abs(bounds1.y - bounds3.y) > tolerance", "true"); |
| output += expect("Math.abs(bounds2.x - bounds3.x) > tolerance || Math.abs(bounds2.y - bounds3.y) > tolerance", "true"); |
| |
| document.getElementById("content").style.visibility = "hidden"; |
| debug(output); |
| finishJSTest(); |
| })(); |
| } |
| </script> |
| </body> |
| </html> |