diff options
Diffstat (limited to 'accessible/tests/browser/Layout.sys.mjs')
-rw-r--r-- | accessible/tests/browser/Layout.sys.mjs | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/accessible/tests/browser/Layout.sys.mjs b/accessible/tests/browser/Layout.sys.mjs new file mode 100644 index 0000000000..15b0060717 --- /dev/null +++ b/accessible/tests/browser/Layout.sys.mjs @@ -0,0 +1,178 @@ +/* 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/. */ + +import { Assert } from "resource://testing-common/Assert.sys.mjs"; + +import { CommonUtils } from "chrome://mochitests/content/browser/accessible/tests/browser/Common.sys.mjs"; + +export const Layout = { + /** + * Zoom the given document. + */ + zoomDocument(doc, zoom) { + const bc = BrowsingContext.getFromWindow(doc.defaultView); + // To mirror the behaviour of the UI, we set the zoom + // value on the top level browsing context. This value automatically + // propagates down to iframes. + bc.top.fullZoom = zoom; + }, + + /** + * Set the relative resolution of this document. This is what apz does. + * On non-mobile platforms you won't see a visible change. + */ + setResolution(doc, zoom) { + const windowUtils = doc.defaultView.windowUtils; + windowUtils.setResolutionAndScaleTo(zoom); + }, + + /** + * Assert.is() function checking the expected value is within the range. + */ + isWithin(expected, got, within, msg) { + if (Math.abs(got - expected) <= within) { + Assert.ok(true, `${msg} - Got ${got}`); + } else { + Assert.ok( + false, + `${msg} - Got ${got}, expected ${expected} with error of ${within}` + ); + } + }, + + /** + * Return the accessible coordinates relative to the screen in device pixels. + */ + getPos(id) { + const accessible = CommonUtils.getAccessible(id); + const x = {}; + const y = {}; + accessible.getBounds(x, y, {}, {}); + + return [x.value, y.value]; + }, + + /** + * Return the accessible coordinates and size relative to the screen in device + * pixels. This methods also retrieves coordinates in CSS pixels and ensures that they + * match Dev pixels with a given device pixel ratio. + */ + getBounds(id, dpr) { + const accessible = CommonUtils.getAccessible(id); + const x = {}; + const y = {}; + const width = {}; + const height = {}; + const xInCSS = {}; + const yInCSS = {}; + const widthInCSS = {}; + const heightInCSS = {}; + accessible.getBounds(x, y, width, height); + accessible.getBoundsInCSSPixels(xInCSS, yInCSS, widthInCSS, heightInCSS); + + this.isWithin( + x.value / dpr, + xInCSS.value, + 1, + "X in CSS pixels is calculated correctly" + ); + this.isWithin( + y.value / dpr, + yInCSS.value, + 1, + "Y in CSS pixels is calculated correctly" + ); + this.isWithin( + width.value / dpr, + widthInCSS.value, + 1, + "Width in CSS pixels is calculated correctly" + ); + this.isWithin( + height.value / dpr, + heightInCSS.value, + 1, + "Height in CSS pixels is calculated correctly" + ); + + return [x.value, y.value, width.value, height.value]; + }, + + getRangeExtents(id, startOffset, endOffset, coordOrigin) { + const hyperText = CommonUtils.getAccessible(id, [Ci.nsIAccessibleText]); + const x = {}; + const y = {}; + const width = {}; + const height = {}; + hyperText.getRangeExtents( + startOffset, + endOffset, + x, + y, + width, + height, + coordOrigin + ); + + return [x.value, y.value, width.value, height.value]; + }, + + CSSToDevicePixels(win, x, y, width, height) { + const ratio = win.devicePixelRatio; + + // CSS pixels and ratio can be not integer. Device pixels are always integer. + // Do our best and hope it works. + return [ + Math.round(x * ratio), + Math.round(y * ratio), + Math.round(width * ratio), + Math.round(height * ratio), + ]; + }, + + /** + * Return DOM node coordinates relative the screen and its size in device + * pixels. + */ + getBoundsForDOMElm(id, doc) { + let x = 0; + let y = 0; + let width = 0; + let height = 0; + + const elm = CommonUtils.getNode(id, doc); + const elmWindow = elm.ownerGlobal; + if (elm.localName == "area") { + const mapName = elm.parentNode.getAttribute("name"); + const selector = `[usemap="#${mapName}"]`; + const img = elm.ownerDocument.querySelector(selector); + + const areaCoords = elm.coords.split(","); + const areaX = parseInt(areaCoords[0], 10); + const areaY = parseInt(areaCoords[1], 10); + const areaWidth = parseInt(areaCoords[2], 10) - areaX; + const areaHeight = parseInt(areaCoords[3], 10) - areaY; + + const rect = img.getBoundingClientRect(); + x = rect.left + areaX; + y = rect.top + areaY; + width = areaWidth; + height = areaHeight; + } else { + const rect = elm.getBoundingClientRect(); + x = rect.left; + y = rect.top; + width = rect.width; + height = rect.height; + } + + return this.CSSToDevicePixels( + elmWindow, + x + elmWindow.mozInnerScreenX, + y + elmWindow.mozInnerScreenY, + width, + height + ); + }, +}; |