diff options
Diffstat (limited to '')
7 files changed, 995 insertions, 0 deletions
diff --git a/accessible/tests/browser/scroll/browser.toml b/accessible/tests/browser/scroll/browser.toml new file mode 100644 index 0000000000..ef637fe9a5 --- /dev/null +++ b/accessible/tests/browser/scroll/browser.toml @@ -0,0 +1,19 @@ +[DEFAULT] +subsuite = "a11y" +support-files = [ + "head.js", + "!/accessible/tests/browser/shared-head.js", + "!/accessible/tests/browser/*.jsm", + "!/accessible/tests/mochitest/*.js", +] +prefs = ["javascript.options.asyncstack_capture_debuggee_only=false"] + +["browser_scrollToPoint.js"] + +["browser_test_scrollTo.js"] + +["browser_test_scroll_bounds.js"] + +["browser_test_scroll_substring.js"] + +["browser_test_zoom_text.js"] diff --git a/accessible/tests/browser/scroll/browser_scrollToPoint.js b/accessible/tests/browser/scroll/browser_scrollToPoint.js new file mode 100644 index 0000000000..810478fa76 --- /dev/null +++ b/accessible/tests/browser/scroll/browser_scrollToPoint.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from ../../mochitest/layout.js */ +loadScripts({ name: "layout.js", dir: MOCHITESTS_DIR }); + +/** + * Test nsIAccessible::scrollToPoint. + */ +addAccessibleTask( + ` +<hr style="height: 100vh;"> +<p id="p">hi</p> +<hr style="height: 100vh;"> + `, + async function (browser, docAcc) { + const [docX, docY] = getPos(docAcc); + const p = findAccessibleChildByID(docAcc, "p"); + const [pX] = getPos(p); + info("Scrolling p"); + let scrolled = waitForEvent(EVENT_SCROLLING_END, docAcc); + p.scrollToPoint(COORDTYPE_SCREEN_RELATIVE, docX, docY); + await scrolled; + // We can only scroll this vertically. + testPos(p, [pX, docY]); + }, + { chrome: true, topLevel: true, remoteIframe: true } +); diff --git a/accessible/tests/browser/scroll/browser_test_scrollTo.js b/accessible/tests/browser/scroll/browser_test_scrollTo.js new file mode 100644 index 0000000000..c007c62d82 --- /dev/null +++ b/accessible/tests/browser/scroll/browser_test_scrollTo.js @@ -0,0 +1,53 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +function getCenterY(acc) { + const y = {}; + const h = {}; + acc.getBounds({}, y, {}, h); + return y.value + h.value / 2; +} + +/** + * Test nsIAccessible::scrollTo. + */ +addAccessibleTask( + ` +<div id="scroller" style="height: 100vh; overflow: scroll;"> + <hr style="height: 100vh;"> + <p id="p1" style="height: 10vh;">a</p> + <hr style="height: 100vh;"> + <p id="p2" style="height: 10vh;">b</p> + <hr style="height: 100vh;"> +</div> + `, + async function (browser, docAcc) { + const scroller = findAccessibleChildByID(docAcc, "scroller"); + const scrollerY = getCenterY(scroller); + // scroller can only show one of p1 or p2, not both. + const p1 = findAccessibleChildByID(docAcc, "p1"); + info("scrollTo p1"); + let scrolled = waitForEvent( + nsIAccessibleEvent.EVENT_SCROLLING_END, + scroller + ); + p1.scrollTo(SCROLL_TYPE_ANYWHERE); + await scrolled; + isWithin(getCenterY(p1), scrollerY, 10, "p1 scrolled to center"); + const p2 = findAccessibleChildByID(docAcc, "p2"); + info("scrollTo p2"); + scrolled = waitForEvent(nsIAccessibleEvent.EVENT_SCROLLING_END, scroller); + p2.scrollTo(SCROLL_TYPE_ANYWHERE); + await scrolled; + isWithin(getCenterY(p2), scrollerY, 10, "p2 scrolled to center"); + info("scrollTo p1"); + scrolled = waitForEvent(nsIAccessibleEvent.EVENT_SCROLLING_END, scroller); + p1.scrollTo(SCROLL_TYPE_ANYWHERE); + await scrolled; + isWithin(getCenterY(p1), scrollerY, 10, "p1 scrolled to center"); + }, + { topLevel: true, iframe: true, remoteIframe: true, chrome: true } +); diff --git a/accessible/tests/browser/scroll/browser_test_scroll_bounds.js b/accessible/tests/browser/scroll/browser_test_scroll_bounds.js new file mode 100644 index 0000000000..31de002cda --- /dev/null +++ b/accessible/tests/browser/scroll/browser_test_scroll_bounds.js @@ -0,0 +1,662 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from ../../mochitest/role.js */ +loadScripts( + { name: "layout.js", dir: MOCHITESTS_DIR }, + { name: "role.js", dir: MOCHITESTS_DIR } +); +requestLongerTimeout(2); + +const appUnitsPerDevPixel = 60; + +function testCachedScrollPosition( + acc, + expectedX, + expectedY, + shouldBeEmpty = false +) { + let cachedPosition = ""; + try { + cachedPosition = acc.cache.getStringProperty("scroll-position"); + } catch (e) { + info("Cache was not populated"); + // If the key doesn't exist, this frame is not scrollable. + return shouldBeEmpty; + } + + // The value we retrieve from the cache is in app units, but the values + // passed in are in pixels. Since the retrieved value is a string, + // and harder to modify, adjust our expected x and y values to match its units. + return ( + cachedPosition == + `${expectedX * appUnitsPerDevPixel}, ${expectedY * appUnitsPerDevPixel}` + ); +} + +function getCachedBounds(acc) { + let cachedBounds = ""; + try { + cachedBounds = acc.cache.getStringProperty("relative-bounds"); + } catch (e) { + ok(false, "Unable to fetch cached bounds from cache!"); + } + return cachedBounds; +} + +/** + * Test bounds of accessibles after scrolling + */ +addAccessibleTask( + ` + <div id='square' style='height:100px; width:100px; background:green; margin-top:3000px; margin-bottom:4000px;'> + </div> + + <div id='rect' style='height:40px; width:200px; background:blue; margin-bottom:3400px'> + </div> + `, + async function (browser, docAcc) { + ok(docAcc, "iframe document acc is present"); + await testBoundsWithContent(docAcc, "square", browser); + await testBoundsWithContent(docAcc, "rect", browser); + + await invokeContentTask(browser, [], () => { + content.document.getElementById("square").scrollIntoView(); + }); + + await waitForContentPaint(browser); + + await testBoundsWithContent(docAcc, "square", browser); + await testBoundsWithContent(docAcc, "rect", browser); + + // Scroll rect into view, but also make it reflow so we can be sure the + // bounds are correct for reflowed frames. + await invokeContentTask(browser, [], () => { + const rect = content.document.getElementById("rect"); + rect.scrollIntoView(); + rect.style.width = "300px"; + rect.offsetTop; // Flush layout. + rect.style.width = "200px"; + rect.offsetTop; // Flush layout. + }); + + await waitForContentPaint(browser); + await testBoundsWithContent(docAcc, "square", browser); + await testBoundsWithContent(docAcc, "rect", browser); + }, + { iframe: true, remoteIframe: true, chrome: true } +); + +/** + * Test scroll offset on cached accessibles + */ +addAccessibleTask( + ` + <div id='square' style='height:100px; width:100px; background:green; margin-top:3000px; margin-bottom:4000px;'> + </div> + + <div id='rect' style='height:40px; width:200px; background:blue; margin-bottom:3400px'> + </div> + `, + async function (browser, docAcc) { + ok(docAcc, "iframe document acc is present"); + await untilCacheOk( + () => testCachedScrollPosition(docAcc, 0, 0), + "Correct initial scroll position." + ); + const rectAcc = findAccessibleChildByID(docAcc, "rect"); + const rectInitialBounds = getCachedBounds(rectAcc); + + await invokeContentTask(browser, [], () => { + content.document.getElementById("square").scrollIntoView(); + }); + + await waitForContentPaint(browser); + + // The only content to scroll over is `square`'s top margin + // so our scroll offset here should be 3000px + await untilCacheOk( + () => testCachedScrollPosition(docAcc, 0, 3000), + "Correct scroll position after first scroll." + ); + + // Scroll rect into view, but also make it reflow so we can be sure the + // bounds are correct for reflowed frames. + await invokeContentTask(browser, [], () => { + const rect = content.document.getElementById("rect"); + rect.scrollIntoView(); + rect.style.width = "300px"; + rect.offsetTop; + rect.style.width = "200px"; + }); + + await waitForContentPaint(browser); + // We have to scroll over `square`'s top margin (3000px), + // `square` itself (100px), and `square`'s bottom margin (4000px). + // This should give us a 7100px offset. + await untilCacheOk( + () => testCachedScrollPosition(docAcc, 0, 7100), + "Correct final scroll position." + ); + await untilCacheIs( + () => getCachedBounds(rectAcc), + rectInitialBounds, + "Cached relative bounds don't change when scrolling" + ); + }, + { iframe: true, remoteIframe: true } +); + +/** + * Test scroll offset fixed-pos acc accs + */ +addAccessibleTask( + ` + <div style="margin-top: 100px; margin-left: 75px; border: 1px solid;"> + <div id="d" style="position:fixed;"> + <button id="top">top</button> + </div> + </div> + `, + async function (browser, docAcc) { + const origTopBounds = await testBoundsWithContent(docAcc, "top", browser); + const origDBounds = await testBoundsWithContent(docAcc, "d", browser); + const e = waitForEvent(EVENT_REORDER, docAcc); + await invokeContentTask(browser, [], () => { + for (let i = 0; i < 1000; ++i) { + const div = content.document.createElement("div"); + div.innerHTML = "<button>${i}</button>"; + content.document.body.append(div); + } + }); + await e; + + await invokeContentTask(browser, [], () => { + // scroll to the bottom of the page + content.window.scrollTo(0, content.document.body.scrollHeight); + }); + + await waitForContentPaint(browser); + + let newTopBounds = await testBoundsWithContent(docAcc, "top", browser); + let newDBounds = await testBoundsWithContent(docAcc, "d", browser); + is( + origTopBounds[0], + newTopBounds[0], + "x of fixed elem is unaffected by scrolling" + ); + is( + origTopBounds[1], + newTopBounds[1], + "y of fixed elem is unaffected by scrolling" + ); + is( + origTopBounds[2], + newTopBounds[2], + "width of fixed elem is unaffected by scrolling" + ); + is( + origTopBounds[3], + newTopBounds[3], + "height of fixed elem is unaffected by scrolling" + ); + is( + origDBounds[0], + newTopBounds[0], + "x of fixed elem container is unaffected by scrolling" + ); + is( + origDBounds[1], + newDBounds[1], + "y of fixed elem container is unaffected by scrolling" + ); + is( + origDBounds[2], + newDBounds[2], + "width of fixed container elem is unaffected by scrolling" + ); + is( + origDBounds[3], + newDBounds[3], + "height of fixed container elem is unaffected by scrolling" + ); + + await invokeContentTask(browser, [], () => { + // remove position styling + content.document.getElementById("d").style = ""; + }); + + await waitForContentPaint(browser); + + newTopBounds = await testBoundsWithContent(docAcc, "top", browser); + newDBounds = await testBoundsWithContent(docAcc, "d", browser); + is( + origTopBounds[0], + newTopBounds[0], + "x of non-fixed element remains accurate." + ); + ok(newTopBounds[1] < 0, "y coordinate shows item scrolled off page"); + is( + origTopBounds[2], + newTopBounds[2], + "width of non-fixed element remains accurate." + ); + is( + origTopBounds[3], + newTopBounds[3], + "height of non-fixed element remains accurate." + ); + is( + origDBounds[0], + newDBounds[0], + "x of non-fixed container element remains accurate." + ); + ok(newDBounds[1] < 0, "y coordinate shows container scrolled off page"); + // Removing the position styling on this acc causes it to be bound by + // its parent's bounding box, which alters its width as a block element. + // We don't particularly care about width in this test, so skip it. + is( + origDBounds[3], + newDBounds[3], + "height of non-fixed container element remains accurate." + ); + + await invokeContentTask(browser, [], () => { + // re-add position styling + content.document.getElementById("d").style = "position:fixed;"; + }); + + await waitForContentPaint(browser); + + newTopBounds = await testBoundsWithContent(docAcc, "top", browser); + newDBounds = await testBoundsWithContent(docAcc, "d", browser); + is( + origTopBounds[0], + newTopBounds[0], + "x correct when position:fixed is added." + ); + is( + origTopBounds[1], + newTopBounds[1], + "y correct when position:fixed is added." + ); + is( + origTopBounds[2], + newTopBounds[2], + "width correct when position:fixed is added." + ); + is( + origTopBounds[3], + newTopBounds[3], + "height correct when position:fixed is added." + ); + is( + origDBounds[0], + newDBounds[0], + "x of container correct when position:fixed is added." + ); + is( + origDBounds[1], + newDBounds[1], + "y of container correct when position:fixed is added." + ); + is( + origDBounds[2], + newDBounds[2], + "width of container correct when position:fixed is added." + ); + is( + origDBounds[3], + newDBounds[3], + "height of container correct when position:fixed is added." + ); + }, + { chrome: true, iframe: true, remoteIframe: true } +); + +/** + * Test position: fixed for containers that would otherwise be pruned from the + * a11y tree. + */ +addAccessibleTask( + ` +<table id="fixed" role="presentation" style="position: fixed;"> + <tr><th>fixed</th></tr> +</table> +<div id="mutate" role="presentation">mutate</div> +<hr style="height: 200vh;"> +<p>bottom</p> + `, + async function (browser, docAcc) { + const fixed = findAccessibleChildByID(docAcc, "fixed"); + ok(fixed, "fixed is accessible"); + isnot(fixed.role, ROLE_TABLE, "fixed doesn't have ROLE_TABLE"); + ok(!findAccessibleChildByID(docAcc, "mutate"), "mutate inaccessible"); + info("Setting position: fixed on mutate"); + let shown = waitForEvent(EVENT_SHOW, "mutate"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("mutate").style.position = "fixed"; + }); + await shown; + const origFixedBounds = await testBoundsWithContent( + docAcc, + "fixed", + browser + ); + const origMutateBounds = await testBoundsWithContent( + docAcc, + "mutate", + browser + ); + info("Scrolling to bottom of page"); + await invokeContentTask(browser, [], () => { + content.window.scrollTo(0, content.document.body.scrollHeight); + }); + await waitForContentPaint(browser); + const newFixedBounds = await testBoundsWithContent( + docAcc, + "fixed", + browser + ); + Assert.deepEqual( + newFixedBounds, + origFixedBounds, + "fixed bounds are unchanged" + ); + const newMutateBounds = await testBoundsWithContent( + docAcc, + "mutate", + browser + ); + Assert.deepEqual( + newMutateBounds, + origMutateBounds, + "mutate bounds are unchanged" + ); + }, + { chrome: true, iframe: true, remoteIframe: true } +); + +/** + * Test scroll offset on sticky-pos acc + */ +addAccessibleTask( + ` + <div id="d" style="margin-top: 100px; margin-left: 75px; position:sticky; top:0px;"> + <button id="top">top</button> + </div> + `, + async function (browser, docAcc) { + const containerBounds = await testBoundsWithContent(docAcc, "d", browser); + const e = waitForEvent(EVENT_REORDER, docAcc); + await invokeContentTask(browser, [], () => { + for (let i = 0; i < 1000; ++i) { + const div = content.document.createElement("div"); + div.innerHTML = "<button>${i}</button>"; + content.document.body.append(div); + } + }); + await e; + for (let id of ["d", "top"]) { + info(`Verifying bounds for acc with ID ${id}`); + const origBounds = await testBoundsWithContent(docAcc, id, browser); + + info("Scrolling partially"); + await invokeContentTask(browser, [], () => { + // scroll some of the window + content.window.scrollTo(0, 50); + }); + + await waitForContentPaint(browser); + + let newBounds = await testBoundsWithContent(docAcc, id, browser); + is( + origBounds[0], + newBounds[0], + `x coord of sticky element is unaffected by scrolling` + ); + ok( + origBounds[1] > newBounds[1] && newBounds[1] >= 0, + "sticky element scrolled, but not off the page" + ); + is( + origBounds[2], + newBounds[2], + `width of sticky element is unaffected by scrolling` + ); + is( + origBounds[3], + newBounds[3], + `height of sticky element is unaffected by scrolling` + ); + + info("Scrolling to bottom"); + await invokeContentTask(browser, [], () => { + // scroll to the bottom of the page + content.window.scrollTo(0, content.document.body.scrollHeight); + }); + + await waitForContentPaint(browser); + + newBounds = await testBoundsWithContent(docAcc, id, browser); + is( + origBounds[0], + newBounds[0], + `x coord of sticky element is unaffected by scrolling` + ); + // Subtract margin from container screen coords to get chrome height + // which is where our y pos should be + is( + newBounds[1], + containerBounds[1] - 100, + "Sticky element is top of screen" + ); + is( + origBounds[2], + newBounds[2], + `width of sticky element is unaffected by scrolling` + ); + is( + origBounds[3], + newBounds[3], + `height of sticky element is unaffected by scrolling` + ); + + info("Removing position style on container"); + await invokeContentTask(browser, [], () => { + // remove position styling + content.document.getElementById("d").style = + "margin-top: 100px; margin-left: 75px;"; + }); + + await waitForContentPaint(browser); + + newBounds = await testBoundsWithContent(docAcc, id, browser); + + is( + origBounds[0], + newBounds[0], + `x coord of non-sticky element remains accurate.` + ); + ok(newBounds[1] < 0, "y coordinate shows item scrolled off page"); + + // Removing the position styling on this acc causes it to be bound by + // its parent's bounding box, which alters its width as a block element. + // We don't particularly care about width in this test, so skip it. + is( + origBounds[3], + newBounds[3], + `height of non-sticky element remains accurate.` + ); + + info("Adding position style on container"); + await invokeContentTask(browser, [], () => { + // re-add position styling + content.document.getElementById("d").style = + "margin-top: 100px; margin-left: 75px; position:sticky; top:0px;"; + }); + + await waitForContentPaint(browser); + + newBounds = await testBoundsWithContent(docAcc, id, browser); + is( + origBounds[0], + newBounds[0], + `x coord of sticky element is unaffected by scrolling` + ); + is( + newBounds[1], + containerBounds[1] - 100, + "Sticky element is top of screen" + ); + is( + origBounds[2], + newBounds[2], + `width of sticky element is unaffected by scrolling` + ); + is( + origBounds[3], + newBounds[3], + `height of sticky element is unaffected by scrolling` + ); + + info("Scrolling back up to test next ID"); + await invokeContentTask(browser, [], () => { + // scroll some of the window + content.window.scrollTo(0, 0); + }); + } + }, + { chrome: false, iframe: false, remoteIframe: false } +); + +/** + * Test position: sticky for containers that would otherwise be pruned from the + * a11y tree. + */ +addAccessibleTask( + ` +<hr style="height: 100vh;"> +<div id="stickyContainer"> + <div id="sticky" role="presentation" style="position: sticky; top: 0px;">sticky</div> + <hr style="height: 100vh;"> + <p id="stickyEnd">stickyEnd</p> +</div> +<div id="mutateContainer"> + <div id="mutate" role="presentation" style="top: 0px;">mutate</div> + <hr style="height: 100vh;"> + <p id="mutateEnd">mutateEnd</p> +</div> + `, + async function (browser, docAcc) { + ok(findAccessibleChildByID(docAcc, "sticky"), "sticky is accessible"); + info("Scrolling to sticky"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("sticky").scrollIntoView(); + }); + await waitForContentPaint(browser); + const origStickyBounds = await testBoundsWithContent( + docAcc, + "sticky", + browser + ); + info("Scrolling to stickyEnd"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("stickyEnd").scrollIntoView(); + }); + await waitForContentPaint(browser); + const newStickyBounds = await testBoundsWithContent( + docAcc, + "sticky", + browser + ); + Assert.deepEqual( + newStickyBounds, + origStickyBounds, + "sticky bounds are unchanged" + ); + + ok(!findAccessibleChildByID(docAcc, "mutate"), "mutate inaccessible"); + info("Setting position: sticky on mutate"); + let shown = waitForEvent(EVENT_SHOW, "mutate"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("mutate").style.position = "sticky"; + }); + await shown; + info("Scrolling to mutate"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("mutate").scrollIntoView(); + }); + await waitForContentPaint(browser); + const origMutateBounds = await testBoundsWithContent( + docAcc, + "mutate", + browser + ); + info("Scrolling to mutateEnd"); + await invokeContentTask(browser, [], () => { + content.document.getElementById("mutateEnd").scrollIntoView(); + }); + await waitForContentPaint(browser); + const newMutateBounds = await testBoundsWithContent( + docAcc, + "mutate", + browser + ); + assertBoundsFuzzyEqual(newMutateBounds, origMutateBounds); + }, + { chrome: true, iframe: true, remoteIframe: true } +); + +/** + * Test scroll offset on non-scrollable accs + */ +addAccessibleTask( + ` + <div id='square' style='height:100px; width: 100px; background:green;'>hello world + </div> + `, + async function (browser, docAcc) { + const square = findAccessibleChildByID(docAcc, "square"); + await untilCacheOk( + () => testCachedScrollPosition(square, 0, 0, true), + "Square is not scrollable." + ); + + info("Adding more text content to square"); + await invokeContentTask(browser, [], () => { + const s = content.document.getElementById("square"); + s.textContent = + "hello world I am some text and I should overflow this container because I am very long"; + s.offsetTop; // Flush layout. + }); + + await waitForContentPaint(browser); + + await untilCacheOk( + () => testCachedScrollPosition(square, 0, 0, true), + "Square is not scrollable (still has overflow:visible)." + ); + + info("Adding overflow:auto; styling"); + await invokeContentTask(browser, [], () => { + const s = content.document.getElementById("square"); + s.setAttribute( + "style", + "overflow:auto; height:100px; width: 100px; background:green;" + ); + s.offsetTop; // Flush layout. + }); + + await waitForContentPaint(browser); + + await untilCacheOk( + () => testCachedScrollPosition(square, 0, 0), + "Square is scrollable." + ); + }, + { iframe: true, remoteIframe: true } +); diff --git a/accessible/tests/browser/scroll/browser_test_scroll_substring.js b/accessible/tests/browser/scroll/browser_test_scroll_substring.js new file mode 100644 index 0000000000..e8426d00ca --- /dev/null +++ b/accessible/tests/browser/scroll/browser_test_scroll_substring.js @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from ../../mochitest/layout.js */ +loadScripts({ name: "layout.js", dir: MOCHITESTS_DIR }); + +/** + * Test nsIAccessibleText::scrollSubstringTo. + */ +addAccessibleTask( + ` + <style> + @font-face { + font-family: Ahem; + src: url(${CURRENT_CONTENT_DIR}e10s/fonts/Ahem.sjs); + } + pre { + font: 20px/20px Ahem; + height: 40px; + overflow-y: scroll; + } + </style> + <pre id="text"> + + + + + +It's a jetpack, Michael. What could possibly go wrong? + + + + + +The only thing I found in the fridge was a dead dove in a bag. +</pre>`, + async function (browser, docAcc) { + let text = findAccessibleChildByID(docAcc, "text", [nsIAccessibleText]); + let [, containerY, , containerHeight] = getBounds(text); + let getCharY = () => { + let objY = {}; + text.getCharacterExtents(7, {}, objY, {}, {}, COORDTYPE_SCREEN_RELATIVE); + return objY.value; + }; + ok( + containerHeight < getCharY(), + "Character is outside of container bounds" + ); + text.scrollSubstringTo(7, 8, SCROLL_TYPE_TOP_EDGE); + + await waitForContentPaint(browser); + await untilCacheIs( + getCharY, + containerY, + "Character is scrolled to top of container" + ); + }, + { + topLevel: true, + iframe: true, + remoteIframe: true, + chrome: true, + } +); diff --git a/accessible/tests/browser/scroll/browser_test_zoom_text.js b/accessible/tests/browser/scroll/browser_test_zoom_text.js new file mode 100644 index 0000000000..4fc0a56b43 --- /dev/null +++ b/accessible/tests/browser/scroll/browser_test_zoom_text.js @@ -0,0 +1,145 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from ../../mochitest/layout.js */ +loadScripts({ name: "layout.js", dir: MOCHITESTS_DIR }); + +async function runTests(browser, accDoc) { + await loadContentScripts(browser, { + script: "Layout.sys.mjs", + symbol: "Layout", + }); + + let paragraph = findAccessibleChildByID(accDoc, "paragraph", [ + nsIAccessibleText, + ]); + let offset = 64; // beginning of 4th stanza + + let [x /* ,y*/] = getPos(paragraph); + let [docX, docY] = getPos(accDoc); + + paragraph.scrollSubstringToPoint( + offset, + offset, + COORDTYPE_SCREEN_RELATIVE, + docX, + docY + ); + + await waitForContentPaint(browser); + testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE); + + await SpecialPowers.spawn(browser, [], () => { + content.Layout.zoomDocument(content.document, 2.0); + }); + + paragraph = findAccessibleChildByID(accDoc, "paragraph2", [ + nsIAccessibleText, + ]); + offset = 52; // // beginning of 4th stanza + [x /* ,y*/] = getPos(paragraph); + paragraph.scrollSubstringToPoint( + offset, + offset, + COORDTYPE_SCREEN_RELATIVE, + docX, + docY + ); + + await waitForContentPaint(browser); + testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE); +} + +/** + * Test caching of accessible object states + */ +addAccessibleTask( + ` + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br><hr> + <p id='paragraph'> + Пошел котик на торжок<br> + Купил котик пирожок<br> + Пошел котик на улочку<br> + Купил котик булочку<br> + </p> + <hr><br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br><hr> + <p id='paragraph2'> + Самому ли съесть<br> + Либо Сашеньке снесть<br> + Я и сам укушу<br> + Я и Сашеньке снесу<br> + </p> + <hr><br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br> + <br><br><br><br><br><br><br><br><br><br>`, + runTests +); diff --git a/accessible/tests/browser/scroll/head.js b/accessible/tests/browser/scroll/head.js new file mode 100644 index 0000000000..afc50984bd --- /dev/null +++ b/accessible/tests/browser/scroll/head.js @@ -0,0 +1,18 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Load the shared-head file first. +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js", + this +); + +// Loading and common.js from accessible/tests/mochitest/ for all tests, as +// well as promisified-events.js. +loadScripts( + { name: "common.js", dir: MOCHITESTS_DIR }, + { name: "promisified-events.js", dir: MOCHITESTS_DIR } +); |