@afixt/test-utils 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +13 -0
- package/.eslintrc +78 -0
- package/.gitattributes +5 -0
- package/.nvmrc +1 -0
- package/CLAUDE.md +33 -0
- package/README.md +72 -0
- package/docs/arrayUtils.js.html +69 -0
- package/docs/data/search.json +1 -0
- package/docs/domUtils.js.html +182 -0
- package/docs/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/getAccessibleName.js.html +456 -0
- package/docs/getAccessibleText.js.html +65 -0
- package/docs/getAriaAttributesByElement.js.html +22 -0
- package/docs/getCSSGeneratedContent.js.html +62 -0
- package/docs/getComputedRole.js.html +172 -0
- package/docs/getFocusableElements.js.html +29 -0
- package/docs/getGeneratedContent.js.html +18 -0
- package/docs/getImageText.js.html +28 -0
- package/docs/getStyleObject.js.html +48 -0
- package/docs/global.html +3 -0
- package/docs/hasAccessibleName.js.html +30 -0
- package/docs/hasAttribute.js.html +18 -0
- package/docs/hasCSSGeneratedContent.js.html +23 -0
- package/docs/hasHiddenParent.js.html +32 -0
- package/docs/hasParent.js.html +57 -0
- package/docs/hasValidAriaAttributes.js.html +33 -0
- package/docs/hasValidAriaRole.js.html +32 -0
- package/docs/index.html +3 -0
- package/docs/index.js.html +66 -0
- package/docs/isAriaAttributesValid.js.html +76 -0
- package/docs/isComplexTable.js.html +112 -0
- package/docs/isDataTable.js.html +241 -0
- package/docs/isFocusable.js.html +37 -0
- package/docs/isHidden.js.html +20 -0
- package/docs/isOffScreen.js.html +19 -0
- package/docs/isValidUrl.js.html +16 -0
- package/docs/isVisible.js.html +65 -0
- package/docs/module-afixt-test-utils.html +3 -0
- package/docs/scripts/core.js +726 -0
- package/docs/scripts/core.min.js +23 -0
- package/docs/scripts/resize.js +90 -0
- package/docs/scripts/search.js +265 -0
- package/docs/scripts/search.min.js +6 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/scripts/third-party/fuse.js +9 -0
- package/docs/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/scripts/third-party/hljs-original.js +5171 -0
- package/docs/scripts/third-party/hljs.js +1 -0
- package/docs/scripts/third-party/popper.js +5 -0
- package/docs/scripts/third-party/tippy.js +1 -0
- package/docs/scripts/third-party/tocbot.js +672 -0
- package/docs/scripts/third-party/tocbot.min.js +1 -0
- package/docs/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/testContrast.js.html +236 -0
- package/docs/testLang.js.html +578 -0
- package/docs/testOrder.js.html +93 -0
- package/jsdoc.json +67 -0
- package/package.json +32 -0
- package/src/arrayUtils.js +67 -0
- package/src/domUtils.js +179 -0
- package/src/getAccessibleName.js +454 -0
- package/src/getAccessibleText.js +63 -0
- package/src/getAriaAttributesByElement.js +19 -0
- package/src/getCSSGeneratedContent.js +60 -0
- package/src/getComputedRole.js +169 -0
- package/src/getFocusableElements.js +26 -0
- package/src/getGeneratedContent.js +15 -0
- package/src/getImageText.js +25 -0
- package/src/getStyleObject.js +45 -0
- package/src/hasAccessibleName.js +28 -0
- package/src/hasAttribute.js +15 -0
- package/src/hasCSSGeneratedContent.js +20 -0
- package/src/hasHiddenParent.js +29 -0
- package/src/hasParent.js +54 -0
- package/src/hasValidAriaAttributes.js +30 -0
- package/src/hasValidAriaRole.js +29 -0
- package/src/index.js +64 -0
- package/src/interactiveRoles.js +20 -0
- package/src/isAriaAttributesValid.js +74 -0
- package/src/isComplexTable.js +109 -0
- package/src/isDataTable.js +239 -0
- package/src/isFocusable.js +34 -0
- package/src/isHidden.js +17 -0
- package/src/isOffScreen.js +16 -0
- package/src/isValidUrl.js +13 -0
- package/src/isVisible.js +62 -0
- package/src/stringUtils.js +150 -0
- package/src/testContrast.js +233 -0
- package/src/testLang.js +575 -0
- package/src/testOrder.js +90 -0
- package/test/_template.test.js +21 -0
- package/test/arrayUtils.test.js +84 -0
- package/test/domUtils.test.js +147 -0
- package/test/generate-test-stubs.js +37 -0
- package/test/getAccessibleName.test.js +113 -0
- package/test/getAccessibleText.test.js +94 -0
- package/test/getAriaAttributesByElement.test.js +112 -0
- package/test/getCSSGeneratedContent.test.js +102 -0
- package/test/getComputedRole.test.js +180 -0
- package/test/getFocusableElements.test.js +134 -0
- package/test/getGeneratedContent.test.js +321 -0
- package/test/getImageText.test.js +21 -0
- package/test/getStyleObject.test.js +134 -0
- package/test/hasAccessibleName.test.js +59 -0
- package/test/hasAttribute.test.js +132 -0
- package/test/hasCSSGeneratedContent.test.js +143 -0
- package/test/hasHiddenParent.test.js +176 -0
- package/test/hasParent.test.js +266 -0
- package/test/hasValidAriaAttributes.test.js +79 -0
- package/test/hasValidAriaRole.test.js +98 -0
- package/test/isAriaAttributesValid.test.js +83 -0
- package/test/isComplexTable.test.js +363 -0
- package/test/isDataTable.test.js +948 -0
- package/test/isFocusable.test.js +182 -0
- package/test/isHidden.test.js +157 -0
- package/test/isOffScreen.test.js +249 -0
- package/test/isValidUrl.test.js +63 -0
- package/test/isVisible.test.js +104 -0
- package/test/setup.js +11 -0
- package/test/stringUtils.test.js +106 -0
- package/test/testContrast.test.js +77 -0
- package/test/testLang.test.js +21 -0
- package/test/testOrder.test.js +157 -0
- package/vitest.config.js +25 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: testOrder.js</title><!--[if lt IE 9]>
|
|
2
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
3
|
+
<![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-afixt-test-utils.html">afixt-test-utils</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#arrayCount">arrayCount</a></div><div class="sidebar-section-children"><a href="global.html#arrayRemoveByValue">arrayRemoveByValue</a></div><div class="sidebar-section-children"><a href="global.html#arrayUnique">arrayUnique</a></div><div class="sidebar-section-children"><a href="global.html#cellColorDiffs">cellColorDiffs</a></div><div class="sidebar-section-children"><a href="global.html#cellCount">cellCount</a></div><div class="sidebar-section-children"><a href="global.html#checkInconsistent">checkInconsistent</a></div><div class="sidebar-section-children"><a href="global.html#checkMultiRowsInHeader">checkMultiRowsInHeader</a></div><div class="sidebar-section-children"><a href="global.html#checkMultiRowsWithColspan">checkMultiRowsWithColspan</a></div><div class="sidebar-section-children"><a href="global.html#cleanBlank">cleanBlank</a></div><div class="sidebar-section-children"><a href="global.html#colCount">colCount</a></div><div class="sidebar-section-children"><a href="global.html#countBordersPct">countBordersPct</a></div><div class="sidebar-section-children"><a href="global.html#getAccessibleName">getAccessibleName</a></div><div class="sidebar-section-children"><a href="global.html#getAccessibleText">getAccessibleText</a></div><div class="sidebar-section-children"><a href="global.html#getAriaAttributes">getAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#getCSSGeneratedContent">getCSSGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#getColorContrast">getColorContrast</a></div><div class="sidebar-section-children"><a href="global.html#getComputedBackgroundColor">getComputedBackgroundColor</a></div><div class="sidebar-section-children"><a href="global.html#getComputedRole">getComputedRole</a></div><div class="sidebar-section-children"><a href="global.html#getFocusableElements">getFocusableElements</a></div><div class="sidebar-section-children"><a href="global.html#getGeneratedContent">getGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#getImageText">getImageText</a></div><div class="sidebar-section-children"><a href="global.html#getStyleObject">getStyleObject</a></div><div class="sidebar-section-children"><a href="global.html#getTwoLetterCode">getTwoLetterCode</a></div><div class="sidebar-section-children"><a href="global.html#hasAccessibleName">hasAccessibleName</a></div><div class="sidebar-section-children"><a href="global.html#hasAttribute">hasAttribute</a></div><div class="sidebar-section-children"><a href="global.html#hasCSSGeneratedContent">hasCSSGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#hasHiddenParent">hasHiddenParent</a></div><div class="sidebar-section-children"><a href="global.html#hasParent">hasParent</a></div><div class="sidebar-section-children"><a href="global.html#hasValidAriaAttributes">hasValidAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#hasValidAriaRole">hasValidAriaRole</a></div><div class="sidebar-section-children"><a href="global.html#isAriaAttributeValid">isAriaAttributeValid</a></div><div class="sidebar-section-children"><a href="global.html#isComplexTable">isComplexTable</a></div><div class="sidebar-section-children"><a href="global.html#isDataTable">isDataTable</a></div><div class="sidebar-section-children"><a href="global.html#isFocusable">isFocusable</a></div><div class="sidebar-section-children"><a href="global.html#isHidden">isHidden</a></div><div class="sidebar-section-children"><a href="global.html#isNotVisible">isNotVisible</a></div><div class="sidebar-section-children"><a href="global.html#isOffScreen">isOffScreen</a></div><div class="sidebar-section-children"><a href="global.html#isValidUrl">isValidUrl</a></div><div class="sidebar-section-children"><a href="global.html#isVisible">isVisible</a></div><div class="sidebar-section-children"><a href="global.html#langCodes">langCodes</a></div><div class="sidebar-section-children"><a href="global.html#luminance">luminance</a></div><div class="sidebar-section-children"><a href="global.html#matchesSelector">matchesSelector</a></div><div class="sidebar-section-children"><a href="global.html#parseRGB">parseRGB</a></div><div class="sidebar-section-children"><a href="global.html#rowCount">rowCount</a></div><div class="sidebar-section-children"><a href="global.html#rtls">rtls</a></div><div class="sidebar-section-children"><a href="global.html#sortByVisualOrder">sortByVisualOrder</a></div><div class="sidebar-section-children"><a href="global.html#strlen">strlen</a></div><div class="sidebar-section-children"><a href="global.html#testContrast">testContrast</a></div><div class="sidebar-section-children"><a href="global.html#testLang">testLang</a></div><div class="sidebar-section-children"><a href="global.html#testOrder">testOrder</a></div><div class="sidebar-section-children"><a href="global.html#validAriaAttributes">validAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#validLangCodes">validLangCodes</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">testOrder.js</h1></header><article><pre class="prettyprint source lang-js"><code>import { getFocusableElements } from "./getFocusableElements.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {Element} a - First element to compare
|
|
8
|
+
* @param {Element} b - Second element to compare
|
|
9
|
+
* @returns {number} - Sorting order based on visual position
|
|
10
|
+
*/
|
|
11
|
+
export function sortByVisualOrder(a, b) {
|
|
12
|
+
const rectA = a.getBoundingClientRect();
|
|
13
|
+
const rectB = b.getBoundingClientRect();
|
|
14
|
+
|
|
15
|
+
if (rectA.top !== rectB.top) {
|
|
16
|
+
return rectA.top - rectB.top;
|
|
17
|
+
}
|
|
18
|
+
return rectA.left - rectB.left;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param {Element} el - The container element to test focus order
|
|
24
|
+
* @returns {boolean} - True if the focus order matches visual order
|
|
25
|
+
*/
|
|
26
|
+
export function testOrder(el) {
|
|
27
|
+
const els = getFocusableElements(el);
|
|
28
|
+
let focusOrder = [...els];
|
|
29
|
+
|
|
30
|
+
// Sort by tabindex
|
|
31
|
+
const elsIndex = focusOrder.map((el, index) => ({ index, el }));
|
|
32
|
+
elsIndex.sort((a, b) => {
|
|
33
|
+
const tabindexA = parseInt(a.el.getAttribute("tabindex")) || 0;
|
|
34
|
+
const tabindexB = parseInt(b.el.getAttribute("tabindex")) || 0;
|
|
35
|
+
|
|
36
|
+
const definedA = tabindexA > 0;
|
|
37
|
+
const definedB = tabindexB > 0;
|
|
38
|
+
|
|
39
|
+
if (!definedA && !definedB) {
|
|
40
|
+
return a.index - b.index;
|
|
41
|
+
}
|
|
42
|
+
if (definedA && !definedB) {
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
if (!definedA && definedB) {
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
return tabindexA - tabindexB;
|
|
49
|
+
});
|
|
50
|
+
focusOrder = elsIndex.map((obj) => obj.el);
|
|
51
|
+
|
|
52
|
+
const visualOrder = [...els].sort(sortByVisualOrder);
|
|
53
|
+
const visualOrderNoCSS = [...els];
|
|
54
|
+
|
|
55
|
+
// Remove CSS and inline styles
|
|
56
|
+
const styleEls = Array.from(
|
|
57
|
+
document.querySelectorAll('link[rel="stylesheet"], style')
|
|
58
|
+
).map((style) => style.cloneNode(true));
|
|
59
|
+
document
|
|
60
|
+
.querySelectorAll('link[rel="stylesheet"], style')
|
|
61
|
+
.forEach((style) => style.remove());
|
|
62
|
+
|
|
63
|
+
const inlineStyles = visualOrderNoCSS.map((el) => {
|
|
64
|
+
const style = el.getAttribute("style");
|
|
65
|
+
el.setAttribute("style", "");
|
|
66
|
+
return style;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Sort with no styles
|
|
70
|
+
visualOrderNoCSS.sort(sortByVisualOrder);
|
|
71
|
+
|
|
72
|
+
// Restore styles
|
|
73
|
+
visualOrderNoCSS.forEach((el, i) => {
|
|
74
|
+
if (inlineStyles[i]) {
|
|
75
|
+
el.setAttribute("style", inlineStyles[i]);
|
|
76
|
+
} else {
|
|
77
|
+
el.removeAttribute("style");
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
styleEls.forEach((style) => document.head.appendChild(style));
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < focusOrder.length; i++) {
|
|
84
|
+
if (focusOrder[i] !== visualOrder[i]) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (focusOrder[i] !== visualOrderNoCSS[i]) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
</code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-afixt-test-utils.html">afixt-test-utils</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#arrayCount">arrayCount</a></div><div class="sidebar-section-children"><a href="global.html#arrayRemoveByValue">arrayRemoveByValue</a></div><div class="sidebar-section-children"><a href="global.html#arrayUnique">arrayUnique</a></div><div class="sidebar-section-children"><a href="global.html#cellColorDiffs">cellColorDiffs</a></div><div class="sidebar-section-children"><a href="global.html#cellCount">cellCount</a></div><div class="sidebar-section-children"><a href="global.html#checkInconsistent">checkInconsistent</a></div><div class="sidebar-section-children"><a href="global.html#checkMultiRowsInHeader">checkMultiRowsInHeader</a></div><div class="sidebar-section-children"><a href="global.html#checkMultiRowsWithColspan">checkMultiRowsWithColspan</a></div><div class="sidebar-section-children"><a href="global.html#cleanBlank">cleanBlank</a></div><div class="sidebar-section-children"><a href="global.html#colCount">colCount</a></div><div class="sidebar-section-children"><a href="global.html#countBordersPct">countBordersPct</a></div><div class="sidebar-section-children"><a href="global.html#getAccessibleName">getAccessibleName</a></div><div class="sidebar-section-children"><a href="global.html#getAccessibleText">getAccessibleText</a></div><div class="sidebar-section-children"><a href="global.html#getAriaAttributes">getAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#getCSSGeneratedContent">getCSSGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#getColorContrast">getColorContrast</a></div><div class="sidebar-section-children"><a href="global.html#getComputedBackgroundColor">getComputedBackgroundColor</a></div><div class="sidebar-section-children"><a href="global.html#getComputedRole">getComputedRole</a></div><div class="sidebar-section-children"><a href="global.html#getFocusableElements">getFocusableElements</a></div><div class="sidebar-section-children"><a href="global.html#getGeneratedContent">getGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#getImageText">getImageText</a></div><div class="sidebar-section-children"><a href="global.html#getStyleObject">getStyleObject</a></div><div class="sidebar-section-children"><a href="global.html#getTwoLetterCode">getTwoLetterCode</a></div><div class="sidebar-section-children"><a href="global.html#hasAccessibleName">hasAccessibleName</a></div><div class="sidebar-section-children"><a href="global.html#hasAttribute">hasAttribute</a></div><div class="sidebar-section-children"><a href="global.html#hasCSSGeneratedContent">hasCSSGeneratedContent</a></div><div class="sidebar-section-children"><a href="global.html#hasHiddenParent">hasHiddenParent</a></div><div class="sidebar-section-children"><a href="global.html#hasParent">hasParent</a></div><div class="sidebar-section-children"><a href="global.html#hasValidAriaAttributes">hasValidAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#hasValidAriaRole">hasValidAriaRole</a></div><div class="sidebar-section-children"><a href="global.html#isAriaAttributeValid">isAriaAttributeValid</a></div><div class="sidebar-section-children"><a href="global.html#isComplexTable">isComplexTable</a></div><div class="sidebar-section-children"><a href="global.html#isDataTable">isDataTable</a></div><div class="sidebar-section-children"><a href="global.html#isFocusable">isFocusable</a></div><div class="sidebar-section-children"><a href="global.html#isHidden">isHidden</a></div><div class="sidebar-section-children"><a href="global.html#isNotVisible">isNotVisible</a></div><div class="sidebar-section-children"><a href="global.html#isOffScreen">isOffScreen</a></div><div class="sidebar-section-children"><a href="global.html#isValidUrl">isValidUrl</a></div><div class="sidebar-section-children"><a href="global.html#isVisible">isVisible</a></div><div class="sidebar-section-children"><a href="global.html#langCodes">langCodes</a></div><div class="sidebar-section-children"><a href="global.html#luminance">luminance</a></div><div class="sidebar-section-children"><a href="global.html#matchesSelector">matchesSelector</a></div><div class="sidebar-section-children"><a href="global.html#parseRGB">parseRGB</a></div><div class="sidebar-section-children"><a href="global.html#rowCount">rowCount</a></div><div class="sidebar-section-children"><a href="global.html#rtls">rtls</a></div><div class="sidebar-section-children"><a href="global.html#sortByVisualOrder">sortByVisualOrder</a></div><div class="sidebar-section-children"><a href="global.html#strlen">strlen</a></div><div class="sidebar-section-children"><a href="global.html#testContrast">testContrast</a></div><div class="sidebar-section-children"><a href="global.html#testLang">testLang</a></div><div class="sidebar-section-children"><a href="global.html#testOrder">testOrder</a></div><div class="sidebar-section-children"><a href="global.html#validAriaAttributes">validAriaAttributes</a></div><div class="sidebar-section-children"><a href="global.html#validLangCodes">validLangCodes</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>
|
package/jsdoc.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tags": {
|
|
3
|
+
"allowUnknownTags": true,
|
|
4
|
+
"dictionaries": ["jsdoc"]
|
|
5
|
+
},
|
|
6
|
+
"source": {
|
|
7
|
+
"include": ["src"],
|
|
8
|
+
"includePattern": ".+\\.js(doc|x)?$",
|
|
9
|
+
"excludePattern": "(^|\\/|\\\\)_"
|
|
10
|
+
},
|
|
11
|
+
"plugins": ["plugins/markdown"],
|
|
12
|
+
"templates": {
|
|
13
|
+
"cleverLinks": false,
|
|
14
|
+
"monospaceLinks": false,
|
|
15
|
+
"default": {
|
|
16
|
+
"outputSourceFiles": true,
|
|
17
|
+
"includeDate": false
|
|
18
|
+
},
|
|
19
|
+
"clean-jsdoc-theme": {
|
|
20
|
+
"name": "AFixt Test Utilities",
|
|
21
|
+
"homepageTitle": "AFixt Test Utilities",
|
|
22
|
+
"title": "AFixt Test Utilities Documentation",
|
|
23
|
+
"meta": {
|
|
24
|
+
"title": "AFixt Test Utilities Documentation",
|
|
25
|
+
"description": "Documentation for the AFixt test utilities library",
|
|
26
|
+
"keyword": "accessibility, testing, javascript, utilities"
|
|
27
|
+
},
|
|
28
|
+
"menu": {
|
|
29
|
+
"GitHub": {
|
|
30
|
+
"href": "https://github.com/AFixt/test-utils",
|
|
31
|
+
"target": "_blank"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"sections": [
|
|
35
|
+
"Classes",
|
|
36
|
+
"Modules",
|
|
37
|
+
"Externals",
|
|
38
|
+
"Events",
|
|
39
|
+
"Namespaces",
|
|
40
|
+
"Mixins",
|
|
41
|
+
"Tutorials",
|
|
42
|
+
"Interfaces",
|
|
43
|
+
"Global"
|
|
44
|
+
],
|
|
45
|
+
"theme_opts": {
|
|
46
|
+
"default_theme": "light",
|
|
47
|
+
"search": true,
|
|
48
|
+
"create_style": true,
|
|
49
|
+
"footer": "Generated with JSDoc and Clean Theme",
|
|
50
|
+
"codepen": {
|
|
51
|
+
"enable_for": ["examples"],
|
|
52
|
+
"options": {
|
|
53
|
+
"js_external": "https://code.jquery.com/jquery-3.6.0.min.js",
|
|
54
|
+
"js_pre_processor": "babel"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"opts": {
|
|
61
|
+
"destination": "./docs/",
|
|
62
|
+
"encoding": "utf8",
|
|
63
|
+
"private": true,
|
|
64
|
+
"recurse": true,
|
|
65
|
+
"template": "node_modules/clean-jsdoc-theme"
|
|
66
|
+
}
|
|
67
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@afixt/test-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Various utilities for accessibility testing",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "vitest run",
|
|
7
|
+
"test:watch": "vitest",
|
|
8
|
+
"test:coverage": "vitest run --coverage",
|
|
9
|
+
"test:single": "vitest run --testNamePattern",
|
|
10
|
+
"test:generate-stubs": "node test/generate-test-stubs.js",
|
|
11
|
+
"docs": "jsdoc -c jsdoc.json",
|
|
12
|
+
"docs:serve": "npx http-server ./docs"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git@github.com:AFixt/test-utils.git"
|
|
17
|
+
},
|
|
18
|
+
"author": "Karl Groves <karl.groves@afixt.com>",
|
|
19
|
+
"license": "UNLICENSED",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"franc": "^6.2.0",
|
|
22
|
+
"tesseract.js": "^6.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@testing-library/dom": "^10.4.0",
|
|
26
|
+
"@vitest/coverage-v8": "^3.0.9",
|
|
27
|
+
"clean-jsdoc-theme": "^4.3.0",
|
|
28
|
+
"jsdoc": "^4.0.4",
|
|
29
|
+
"jsdom": "^26.0.0",
|
|
30
|
+
"vitest": "^3.0.9"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for working with arrays and objects.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reduce an array to only the unique items.
|
|
7
|
+
* @param {Array} array - Array of items
|
|
8
|
+
* @returns {Array} - Array with unique items
|
|
9
|
+
*/
|
|
10
|
+
function arrayUnique(array) {
|
|
11
|
+
return Array.from(new Set(array));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Remove specified items by value from an array.
|
|
16
|
+
* @param {Array} array - Array of items
|
|
17
|
+
* @param {String} value - Value to remove
|
|
18
|
+
* @returns {Array} - Array without the specified value
|
|
19
|
+
*/
|
|
20
|
+
function arrayRemoveByValue(array, value) {
|
|
21
|
+
return array.filter(item => String(item) !== String(value));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get a count of each occurrence for items in an array.
|
|
26
|
+
* @param {Array} array - Array of items
|
|
27
|
+
* @returns {Object} - Object containing key/value pairs where key is array value and value is occurrence count
|
|
28
|
+
*/
|
|
29
|
+
function arrayCount(array) {
|
|
30
|
+
return array.reduce((acc, item) => {
|
|
31
|
+
acc[item] = (acc[item] || 0) + 1;
|
|
32
|
+
return acc;
|
|
33
|
+
}, {});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Remove items from an object that do not have a value.
|
|
38
|
+
* @param {Object} obj - Object to remove empty values from
|
|
39
|
+
* @returns {Object} - Cleaned object
|
|
40
|
+
*/
|
|
41
|
+
function cleanBlank(obj) {
|
|
42
|
+
return Object.fromEntries(
|
|
43
|
+
Object.entries(obj).filter(([_, value]) => value && value.length > 0)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create arrayUtils object with all functions
|
|
48
|
+
const arrayUtils = {
|
|
49
|
+
arrayUnique,
|
|
50
|
+
arrayRemoveByValue,
|
|
51
|
+
arrayCount,
|
|
52
|
+
cleanBlank
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Export for ES modules
|
|
56
|
+
export { arrayUnique, arrayRemoveByValue, arrayCount, cleanBlank, arrayUtils };
|
|
57
|
+
|
|
58
|
+
// Export for CommonJS
|
|
59
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
60
|
+
module.exports = {
|
|
61
|
+
arrayUnique,
|
|
62
|
+
arrayRemoveByValue,
|
|
63
|
+
arrayCount,
|
|
64
|
+
cleanBlank,
|
|
65
|
+
arrayUtils
|
|
66
|
+
};
|
|
67
|
+
}
|
package/src/domUtils.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const domUtils = {
|
|
2
|
+
/**
|
|
3
|
+
* Checks if the specified element has the given attribute.
|
|
4
|
+
*
|
|
5
|
+
* @param {HTMLElement} element - The DOM element to check.
|
|
6
|
+
* @param {string} name - The name of the attribute to look for.
|
|
7
|
+
* @returns {boolean} True if the element has the attribute, false otherwise.
|
|
8
|
+
*/
|
|
9
|
+
hasAttr(element, attrName) {
|
|
10
|
+
return element.hasAttribute(attrName);
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Filters a list of elements to include only those whose attributes begin with a specified prefix.
|
|
15
|
+
*
|
|
16
|
+
* @param {NodeList | Array} elements - The list of elements to filter.
|
|
17
|
+
* @param {string} prefix - The prefix to match against the attribute names.
|
|
18
|
+
* @returns {Array} - An array of elements that have at least one attribute starting with the specified prefix.
|
|
19
|
+
*/
|
|
20
|
+
attrBegins(elements, prefix) {
|
|
21
|
+
return Array.from(elements).filter((element) => {
|
|
22
|
+
return Array.from(element.attributes).some((attr) =>
|
|
23
|
+
attr.name.startsWith(prefix)
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Checks if the text content of a given DOM element contains a specified string, case-insensitively.
|
|
30
|
+
*
|
|
31
|
+
* @param {HTMLElement} element - The DOM element whose text content will be checked.
|
|
32
|
+
* @param {string} str - The string to search for within the element's text content.
|
|
33
|
+
* @returns {boolean} - Returns true if the element's text content contains the specified string, case-insensitively; otherwise, false.
|
|
34
|
+
*/
|
|
35
|
+
containsNoCase(element, str) {
|
|
36
|
+
return element.textContent.toLowerCase().includes(str.toLowerCase());
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves all attributes of a given DOM element as an object.
|
|
41
|
+
*
|
|
42
|
+
* @param {Element} element - The DOM element from which to get the attributes.
|
|
43
|
+
* @returns {Object} An object containing the element's attributes as key-value pairs.
|
|
44
|
+
*/
|
|
45
|
+
getAttributes(element) {
|
|
46
|
+
if (!element) return {};
|
|
47
|
+
return [...element.attributes].reduce((attrs, attr) => {
|
|
48
|
+
attrs[attr.name] = attr.value;
|
|
49
|
+
return attrs;
|
|
50
|
+
}, {});
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves the attributes of a given DOM element as a JSON string.
|
|
55
|
+
*
|
|
56
|
+
* @param {HTMLElement} element - The DOM element from which to retrieve attributes.
|
|
57
|
+
* @returns {string|boolean} A JSON string representing the attributes of the element, or false if no attributes are found.
|
|
58
|
+
*/
|
|
59
|
+
getAttributesAsString(element) {
|
|
60
|
+
const attrs = getAttributes(element);
|
|
61
|
+
return attrs ? JSON.stringify(attrs) : false;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets the constructor name of a given DOM element.
|
|
66
|
+
*
|
|
67
|
+
* @param {HTMLElement} element - The DOM element to get the constructor name from.
|
|
68
|
+
* @returns {string} The name of the constructor of the element.
|
|
69
|
+
*/
|
|
70
|
+
getConstructor(element) {
|
|
71
|
+
return element.constructor.name;
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Calculates the size of the document's HTML content.
|
|
76
|
+
*
|
|
77
|
+
* This function retrieves the outer HTML of the document's root element,
|
|
78
|
+
* removes all whitespace characters, and returns the length of the resulting string.
|
|
79
|
+
*
|
|
80
|
+
* @returns {number} The length of the document's HTML content without whitespace.
|
|
81
|
+
*/
|
|
82
|
+
getDocumentSize() {
|
|
83
|
+
return document.documentElement.outerHTML.replace(/\s+/g, "").length;
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Finds and returns an array of elements that have duplicate IDs in the document.
|
|
88
|
+
*
|
|
89
|
+
* @returns {Element[]} An array of elements that have duplicate IDs.
|
|
90
|
+
*/
|
|
91
|
+
getElementsWithDuplicateIds() {
|
|
92
|
+
const nodes = document.querySelectorAll("[id]");
|
|
93
|
+
const ids = {};
|
|
94
|
+
const duplicates = [];
|
|
95
|
+
nodes.forEach((node) => {
|
|
96
|
+
const id = node.id.trim();
|
|
97
|
+
ids[id] = (ids[id] || 0) + 1;
|
|
98
|
+
if (ids[id] > 1 && !duplicates.includes(id)) {
|
|
99
|
+
duplicates.push(id);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return duplicates.map((id) => document.querySelector(`#${id}`));
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Returns the outer HTML of the given element.
|
|
107
|
+
*
|
|
108
|
+
* @param {Element} element - The DOM element to get the outer HTML from.
|
|
109
|
+
* @returns {string} The outer HTML of the element.
|
|
110
|
+
*/
|
|
111
|
+
getOuterHTML(element) {
|
|
112
|
+
return element.outerHTML;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Generates an XPath string for a given DOM element.
|
|
117
|
+
*
|
|
118
|
+
* @param {Element} element - The DOM element for which to generate the XPath.
|
|
119
|
+
* @returns {string} The XPath string representing the element's location in the DOM.
|
|
120
|
+
*/
|
|
121
|
+
getXPath(element) {
|
|
122
|
+
if (!element) return "";
|
|
123
|
+
let path = "";
|
|
124
|
+
while (element && element.nodeType === Node.ELEMENT_NODE) {
|
|
125
|
+
let index = 1;
|
|
126
|
+
let sibling = element.previousElementSibling;
|
|
127
|
+
while (sibling) {
|
|
128
|
+
if (sibling.nodeName === element.nodeName) index++;
|
|
129
|
+
sibling = sibling.previousElementSibling;
|
|
130
|
+
}
|
|
131
|
+
path = `/${element.nodeName.toLowerCase()}[${index}]` + path;
|
|
132
|
+
element = element.parentElement;
|
|
133
|
+
}
|
|
134
|
+
return path;
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Checks if the given element has focus.
|
|
139
|
+
*
|
|
140
|
+
* @param {HTMLElement} element - The DOM element to check for focus.
|
|
141
|
+
* @returns {boolean} True if the element has focus, otherwise false.
|
|
142
|
+
*/
|
|
143
|
+
hasFocus(element) {
|
|
144
|
+
return document.activeElement === element;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Checks if the given element is fully visible within the viewport.
|
|
149
|
+
*
|
|
150
|
+
* @param {Element} element - The DOM element to check for visibility.
|
|
151
|
+
* @returns {boolean} True if the element is fully visible, false otherwise.
|
|
152
|
+
*/
|
|
153
|
+
isFullyVisible(element) {
|
|
154
|
+
const rect = element.getBoundingClientRect();
|
|
155
|
+
return (
|
|
156
|
+
rect.top >= 0 &&
|
|
157
|
+
rect.left >= 0 &&
|
|
158
|
+
rect.bottom <= window.innerHeight &&
|
|
159
|
+
rect.right <= window.innerWidth
|
|
160
|
+
);
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
module.exports = {
|
|
165
|
+
hasAttr: domUtils.hasAttr,
|
|
166
|
+
attrBegins: domUtils.attrBegins,
|
|
167
|
+
containsNoCase: domUtils.containsNoCase,
|
|
168
|
+
getAttributes: domUtils.getAttributes,
|
|
169
|
+
getAttributesAsString: domUtils.getAttributesAsString,
|
|
170
|
+
getConstructor: domUtils.getConstructor,
|
|
171
|
+
getDocumentSize: domUtils.getDocumentSize,
|
|
172
|
+
getElementsWithDuplicateIds: domUtils.getElementsWithDuplicateIds,
|
|
173
|
+
getOuterHTML: domUtils.getOuterHTML,
|
|
174
|
+
getXPath: domUtils.getXPath,
|
|
175
|
+
hasFocus: domUtils.hasFocus,
|
|
176
|
+
isFullyVisible: domUtils.isFullyVisible,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
module.exports = domUtils;
|