@wdio/image-comparison-core 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/CHANGELOG.md +82 -0
- package/LICENSE +21 -0
- package/README.md +12 -0
- package/assets/ios/ipadair4th.ipadair5th-bottom.png +0 -0
- package/assets/ios/ipadair4th.ipadair5th-top.png +0 -0
- package/assets/ios/ipadmini6th-bottom.png +0 -0
- package/assets/ios/ipadmini6th-top.png +0 -0
- package/assets/ios/ipadpro11-bottom.png +0 -0
- package/assets/ios/ipadpro11-top.png +0 -0
- package/assets/ios/ipadpro129-bottom.png +0 -0
- package/assets/ios/ipadpro129-top.png +0 -0
- package/assets/ios/iphone11promax-bottom.png +0 -0
- package/assets/ios/iphone11promax-top.png +0 -0
- package/assets/ios/iphone12.iphone12pro-top.png +0 -0
- package/assets/ios/iphone12.iphone12pro.iphone13.iphone13pro.iphone14-bottom.png +0 -0
- package/assets/ios/iphone12mini-top.png +0 -0
- package/assets/ios/iphone12mini.iphone13mini-bottom.png +0 -0
- package/assets/ios/iphone12promax-top.png +0 -0
- package/assets/ios/iphone12promax.iphone13promax.iphone14plus-bottom.png +0 -0
- package/assets/ios/iphone13.iphone13pro.iphone14-top.png +0 -0
- package/assets/ios/iphone13mini-top.png +0 -0
- package/assets/ios/iphone13promax.iphone14plus-top.png +0 -0
- package/assets/ios/iphone14pro-bottom.png +0 -0
- package/assets/ios/iphone14pro-top.png +0 -0
- package/assets/ios/iphone14promax-bottom.png +0 -0
- package/assets/ios/iphone14promax-top.png +0 -0
- package/assets/ios/iphone15-bottom.png +0 -0
- package/assets/ios/iphone15-top.png +0 -0
- package/assets/ios/iphonex.iphonexs.iphone11pro-bottom.png +0 -0
- package/assets/ios/iphonex.iphonexs.iphone11pro-top.png +0 -0
- package/assets/ios/iphonexr.iphone11-bottom.png +0 -0
- package/assets/ios/iphonexr.iphone11-top.png +0 -0
- package/assets/ios/iphonexsmax-bottom.png +0 -0
- package/assets/ios/iphonexsmax-top.png +0 -0
- package/dist/base.d.ts +18 -0
- package/dist/base.d.ts.map +1 -0
- package/dist/base.interfaces.d.ts +200 -0
- package/dist/base.interfaces.d.ts.map +1 -0
- package/dist/base.interfaces.js +1 -0
- package/dist/base.js +58 -0
- package/dist/base.test.d.ts +2 -0
- package/dist/base.test.d.ts.map +1 -0
- package/dist/base.test.js +45 -0
- package/dist/clientSideScripts/checkMetaTag.d.ts +2 -0
- package/dist/clientSideScripts/checkMetaTag.d.ts.map +1 -0
- package/dist/clientSideScripts/checkMetaTag.js +9 -0
- package/dist/clientSideScripts/checkMetaTag.test.d.ts +2 -0
- package/dist/clientSideScripts/checkMetaTag.test.d.ts.map +1 -0
- package/dist/clientSideScripts/checkMetaTag.test.js +25 -0
- package/dist/clientSideScripts/customCss.interfaces.d.ts +8 -0
- package/dist/clientSideScripts/customCss.interfaces.d.ts.map +1 -0
- package/dist/clientSideScripts/customCss.interfaces.js +1 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.d.ts +8 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.d.ts.map +1 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.interfaces.d.ts +4 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.interfaces.d.ts.map +1 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.interfaces.js +1 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.js +275 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.test.d.ts +2 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.test.d.ts.map +1 -0
- package/dist/clientSideScripts/drawTabbableOnCanvas.test.js +251 -0
- package/dist/clientSideScripts/elementPosition.interfaces.d.ts +3 -0
- package/dist/clientSideScripts/elementPosition.interfaces.d.ts.map +1 -0
- package/dist/clientSideScripts/elementPosition.interfaces.js +1 -0
- package/dist/clientSideScripts/getBoundingClientRect.d.ts +6 -0
- package/dist/clientSideScripts/getBoundingClientRect.d.ts.map +1 -0
- package/dist/clientSideScripts/getBoundingClientRect.js +12 -0
- package/dist/clientSideScripts/getBoundingClientRect.test.d.ts +2 -0
- package/dist/clientSideScripts/getBoundingClientRect.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getBoundingClientRect.test.js +28 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.d.ts +5 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.d.ts.map +1 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.js +48 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.test.d.ts +2 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getDocumentScrollHeight.test.js +30 -0
- package/dist/clientSideScripts/getElementPositionTopDom.d.ts +6 -0
- package/dist/clientSideScripts/getElementPositionTopDom.d.ts.map +1 -0
- package/dist/clientSideScripts/getElementPositionTopDom.js +11 -0
- package/dist/clientSideScripts/getElementPositionTopDom.test.d.ts +2 -0
- package/dist/clientSideScripts/getElementPositionTopDom.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getElementPositionTopDom.test.js +11 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.d.ts +14 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.d.ts.map +1 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.js +19 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.test.d.ts +2 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getElementPositionTopScreenNativeMobile.test.js +52 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.d.ts +6 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.d.ts.map +1 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.js +17 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.test.d.ts +2 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getMobileWebviewClickAndDimensions.test.js +47 -0
- package/dist/clientSideScripts/getScreenDimensions.d.ts +6 -0
- package/dist/clientSideScripts/getScreenDimensions.d.ts.map +1 -0
- package/dist/clientSideScripts/getScreenDimensions.js +104 -0
- package/dist/clientSideScripts/getScreenDimensions.test.d.ts +2 -0
- package/dist/clientSideScripts/getScreenDimensions.test.d.ts.map +1 -0
- package/dist/clientSideScripts/getScreenDimensions.test.js +161 -0
- package/dist/clientSideScripts/hideRemoveElements.d.ts +8 -0
- package/dist/clientSideScripts/hideRemoveElements.d.ts.map +1 -0
- package/dist/clientSideScripts/hideRemoveElements.js +60 -0
- package/dist/clientSideScripts/hideRemoveElements.test.d.ts +2 -0
- package/dist/clientSideScripts/hideRemoveElements.test.d.ts.map +1 -0
- package/dist/clientSideScripts/hideRemoveElements.test.js +199 -0
- package/dist/clientSideScripts/hideScrollbars.d.ts +9 -0
- package/dist/clientSideScripts/hideScrollbars.d.ts.map +1 -0
- package/dist/clientSideScripts/hideScrollbars.js +15 -0
- package/dist/clientSideScripts/hideScrollbars.test.d.ts +2 -0
- package/dist/clientSideScripts/hideScrollbars.test.d.ts.map +1 -0
- package/dist/clientSideScripts/hideScrollbars.test.js +12 -0
- package/dist/clientSideScripts/injectWebviewOverlay.d.ts +5 -0
- package/dist/clientSideScripts/injectWebviewOverlay.d.ts.map +1 -0
- package/dist/clientSideScripts/injectWebviewOverlay.js +35 -0
- package/dist/clientSideScripts/injectWebviewOverlay.test.d.ts +2 -0
- package/dist/clientSideScripts/injectWebviewOverlay.test.d.ts.map +1 -0
- package/dist/clientSideScripts/injectWebviewOverlay.test.js +74 -0
- package/dist/clientSideScripts/removeElementFromDom.d.ts +5 -0
- package/dist/clientSideScripts/removeElementFromDom.d.ts.map +1 -0
- package/dist/clientSideScripts/removeElementFromDom.js +9 -0
- package/dist/clientSideScripts/removeElementFromDom.test.d.ts +2 -0
- package/dist/clientSideScripts/removeElementFromDom.test.d.ts.map +1 -0
- package/dist/clientSideScripts/removeElementFromDom.test.js +43 -0
- package/dist/clientSideScripts/screenDimensions.interfaces.d.ts +96 -0
- package/dist/clientSideScripts/screenDimensions.interfaces.d.ts.map +1 -0
- package/dist/clientSideScripts/screenDimensions.interfaces.js +1 -0
- package/dist/clientSideScripts/scrollElementIntoView.d.ts +5 -0
- package/dist/clientSideScripts/scrollElementIntoView.d.ts.map +1 -0
- package/dist/clientSideScripts/scrollElementIntoView.js +31 -0
- package/dist/clientSideScripts/scrollElementIntoView.test.d.ts +2 -0
- package/dist/clientSideScripts/scrollElementIntoView.test.d.ts.map +1 -0
- package/dist/clientSideScripts/scrollElementIntoView.test.js +79 -0
- package/dist/clientSideScripts/scrollToPosition.d.ts +5 -0
- package/dist/clientSideScripts/scrollToPosition.d.ts.map +1 -0
- package/dist/clientSideScripts/scrollToPosition.js +25 -0
- package/dist/clientSideScripts/scrollToPosition.test.d.ts +2 -0
- package/dist/clientSideScripts/scrollToPosition.test.d.ts.map +1 -0
- package/dist/clientSideScripts/scrollToPosition.test.js +72 -0
- package/dist/clientSideScripts/setCustomCss.d.ts +6 -0
- package/dist/clientSideScripts/setCustomCss.d.ts.map +1 -0
- package/dist/clientSideScripts/setCustomCss.js +36 -0
- package/dist/clientSideScripts/setCustomCss.test.d.ts +2 -0
- package/dist/clientSideScripts/setCustomCss.test.d.ts.map +1 -0
- package/dist/clientSideScripts/setCustomCss.test.js +68 -0
- package/dist/clientSideScripts/statusAddressToolBarOffsets.interfaces.d.ts +11 -0
- package/dist/clientSideScripts/statusAddressToolBarOffsets.interfaces.d.ts.map +1 -0
- package/dist/clientSideScripts/statusAddressToolBarOffsets.interfaces.js +1 -0
- package/dist/clientSideScripts/toggleTextTransparency.d.ts +5 -0
- package/dist/clientSideScripts/toggleTextTransparency.d.ts.map +1 -0
- package/dist/clientSideScripts/toggleTextTransparency.js +16 -0
- package/dist/clientSideScripts/toggleTextTransparency.test.d.ts +2 -0
- package/dist/clientSideScripts/toggleTextTransparency.test.d.ts.map +1 -0
- package/dist/clientSideScripts/toggleTextTransparency.test.js +35 -0
- package/dist/clientSideScripts/waitForFonts.d.ts +8 -0
- package/dist/clientSideScripts/waitForFonts.d.ts.map +1 -0
- package/dist/clientSideScripts/waitForFonts.js +20 -0
- package/dist/clientSideScripts/waitForFonts.test.d.ts +2 -0
- package/dist/clientSideScripts/waitForFonts.test.d.ts.map +1 -0
- package/dist/clientSideScripts/waitForFonts.test.js +37 -0
- package/dist/commands/check.interfaces.d.ts +35 -0
- package/dist/commands/check.interfaces.d.ts.map +1 -0
- package/dist/commands/check.interfaces.js +1 -0
- package/dist/commands/checkAppElement.d.ts +7 -0
- package/dist/commands/checkAppElement.d.ts.map +1 -0
- package/dist/commands/checkAppElement.js +44 -0
- package/dist/commands/checkAppElement.test.d.ts +2 -0
- package/dist/commands/checkAppElement.test.d.ts.map +1 -0
- package/dist/commands/checkAppElement.test.js +241 -0
- package/dist/commands/checkAppScreen.d.ts +7 -0
- package/dist/commands/checkAppScreen.d.ts.map +1 -0
- package/dist/commands/checkAppScreen.js +73 -0
- package/dist/commands/checkAppScreen.test.d.ts +2 -0
- package/dist/commands/checkAppScreen.test.d.ts.map +1 -0
- package/dist/commands/checkAppScreen.test.js +295 -0
- package/dist/commands/checkElement.d.ts +7 -0
- package/dist/commands/checkElement.d.ts.map +1 -0
- package/dist/commands/checkElement.js +10 -0
- package/dist/commands/checkElement.test.d.ts +2 -0
- package/dist/commands/checkElement.test.d.ts.map +1 -0
- package/dist/commands/checkElement.test.js +66 -0
- package/dist/commands/checkFullPageScreen.d.ts +7 -0
- package/dist/commands/checkFullPageScreen.d.ts.map +1 -0
- package/dist/commands/checkFullPageScreen.js +56 -0
- package/dist/commands/checkFullPageScreen.test.d.ts +2 -0
- package/dist/commands/checkFullPageScreen.test.d.ts.map +1 -0
- package/dist/commands/checkFullPageScreen.test.js +259 -0
- package/dist/commands/checkScreen.d.ts +7 -0
- package/dist/commands/checkScreen.d.ts.map +1 -0
- package/dist/commands/checkScreen.js +10 -0
- package/dist/commands/checkScreen.test.d.ts +2 -0
- package/dist/commands/checkScreen.test.d.ts.map +1 -0
- package/dist/commands/checkScreen.test.js +62 -0
- package/dist/commands/checkTabbablePage.d.ts +7 -0
- package/dist/commands/checkTabbablePage.d.ts.map +1 -0
- package/dist/commands/checkTabbablePage.js +28 -0
- package/dist/commands/checkTabbablePage.test.d.ts +2 -0
- package/dist/commands/checkTabbablePage.test.d.ts.map +1 -0
- package/dist/commands/checkTabbablePage.test.js +200 -0
- package/dist/commands/checkWebElement.d.ts +7 -0
- package/dist/commands/checkWebElement.d.ts.map +1 -0
- package/dist/commands/checkWebElement.js +52 -0
- package/dist/commands/checkWebElement.test.d.ts +2 -0
- package/dist/commands/checkWebElement.test.d.ts.map +1 -0
- package/dist/commands/checkWebElement.test.js +278 -0
- package/dist/commands/checkWebScreen.d.ts +7 -0
- package/dist/commands/checkWebScreen.d.ts.map +1 -0
- package/dist/commands/checkWebScreen.js +50 -0
- package/dist/commands/checkWebScreen.test.d.ts +2 -0
- package/dist/commands/checkWebScreen.test.d.ts.map +1 -0
- package/dist/commands/checkWebScreen.test.js +227 -0
- package/dist/commands/element.interfaces.d.ts +27 -0
- package/dist/commands/element.interfaces.d.ts.map +1 -0
- package/dist/commands/element.interfaces.js +1 -0
- package/dist/commands/fullPage.interfaces.d.ts +38 -0
- package/dist/commands/fullPage.interfaces.d.ts.map +1 -0
- package/dist/commands/fullPage.interfaces.js +1 -0
- package/dist/commands/save.interfaces.d.ts +27 -0
- package/dist/commands/save.interfaces.d.ts.map +1 -0
- package/dist/commands/save.interfaces.js +1 -0
- package/dist/commands/saveAppElement.d.ts +7 -0
- package/dist/commands/saveAppElement.d.ts.map +1 -0
- package/dist/commands/saveAppElement.js +30 -0
- package/dist/commands/saveAppElement.test.d.ts +2 -0
- package/dist/commands/saveAppElement.test.d.ts.map +1 -0
- package/dist/commands/saveAppElement.test.js +199 -0
- package/dist/commands/saveAppScreen.d.ts +7 -0
- package/dist/commands/saveAppScreen.d.ts.map +1 -0
- package/dist/commands/saveAppScreen.js +43 -0
- package/dist/commands/saveAppScreen.test.d.ts +2 -0
- package/dist/commands/saveAppScreen.test.d.ts.map +1 -0
- package/dist/commands/saveAppScreen.test.js +221 -0
- package/dist/commands/saveElement.d.ts +7 -0
- package/dist/commands/saveElement.d.ts.map +1 -0
- package/dist/commands/saveElement.js +10 -0
- package/dist/commands/saveElement.test.d.ts +2 -0
- package/dist/commands/saveElement.test.d.ts.map +1 -0
- package/dist/commands/saveElement.test.js +62 -0
- package/dist/commands/saveFullPageScreen.d.ts +7 -0
- package/dist/commands/saveFullPageScreen.d.ts.map +1 -0
- package/dist/commands/saveFullPageScreen.js +60 -0
- package/dist/commands/saveFullPageScreen.test.d.ts +2 -0
- package/dist/commands/saveFullPageScreen.test.d.ts.map +1 -0
- package/dist/commands/saveFullPageScreen.test.js +293 -0
- package/dist/commands/saveScreen.d.ts +7 -0
- package/dist/commands/saveScreen.d.ts.map +1 -0
- package/dist/commands/saveScreen.js +10 -0
- package/dist/commands/saveScreen.test.d.ts +2 -0
- package/dist/commands/saveScreen.test.d.ts.map +1 -0
- package/dist/commands/saveScreen.test.js +47 -0
- package/dist/commands/saveTabbablePage.d.ts +7 -0
- package/dist/commands/saveTabbablePage.d.ts.map +1 -0
- package/dist/commands/saveTabbablePage.js +20 -0
- package/dist/commands/saveTabbablePage.test.d.ts +2 -0
- package/dist/commands/saveTabbablePage.test.d.ts.map +1 -0
- package/dist/commands/saveTabbablePage.test.js +74 -0
- package/dist/commands/saveWebElement.d.ts +7 -0
- package/dist/commands/saveWebElement.d.ts.map +1 -0
- package/dist/commands/saveWebElement.js +53 -0
- package/dist/commands/saveWebElement.test.d.ts +2 -0
- package/dist/commands/saveWebElement.test.d.ts.map +1 -0
- package/dist/commands/saveWebElement.test.js +253 -0
- package/dist/commands/saveWebScreen.d.ts +7 -0
- package/dist/commands/saveWebScreen.d.ts.map +1 -0
- package/dist/commands/saveWebScreen.js +48 -0
- package/dist/commands/saveWebScreen.test.d.ts +2 -0
- package/dist/commands/saveWebScreen.test.d.ts.map +1 -0
- package/dist/commands/saveWebScreen.test.js +222 -0
- package/dist/commands/screen.interfaces.d.ts +16 -0
- package/dist/commands/screen.interfaces.d.ts.map +1 -0
- package/dist/commands/screen.interfaces.js +1 -0
- package/dist/commands/tabbable.interfaces.d.ts +29 -0
- package/dist/commands/tabbable.interfaces.d.ts.map +1 -0
- package/dist/commands/tabbable.interfaces.js +1 -0
- package/dist/helpers/afterScreenshot.d.ts +7 -0
- package/dist/helpers/afterScreenshot.d.ts.map +1 -0
- package/dist/helpers/afterScreenshot.interfaces.d.ts +46 -0
- package/dist/helpers/afterScreenshot.interfaces.d.ts.map +1 -0
- package/dist/helpers/afterScreenshot.interfaces.js +1 -0
- package/dist/helpers/afterScreenshot.js +55 -0
- package/dist/helpers/afterScreenshot.test.d.ts +2 -0
- package/dist/helpers/afterScreenshot.test.d.ts.map +1 -0
- package/dist/helpers/afterScreenshot.test.js +241 -0
- package/dist/helpers/beforeScreenshot.d.ts +6 -0
- package/dist/helpers/beforeScreenshot.d.ts.map +1 -0
- package/dist/helpers/beforeScreenshot.interfaces.d.ts +15 -0
- package/dist/helpers/beforeScreenshot.interfaces.d.ts.map +1 -0
- package/dist/helpers/beforeScreenshot.interfaces.js +1 -0
- package/dist/helpers/beforeScreenshot.js +79 -0
- package/dist/helpers/beforeScreenshot.test.d.ts +2 -0
- package/dist/helpers/beforeScreenshot.test.d.ts.map +1 -0
- package/dist/helpers/beforeScreenshot.test.js +261 -0
- package/dist/helpers/compare.interfaces.d.ts +16 -0
- package/dist/helpers/compare.interfaces.d.ts.map +1 -0
- package/dist/helpers/compare.interfaces.js +1 -0
- package/dist/helpers/constants.d.ts +108 -0
- package/dist/helpers/constants.d.ts.map +1 -0
- package/dist/helpers/constants.interfaces.d.ts +30 -0
- package/dist/helpers/constants.interfaces.d.ts.map +1 -0
- package/dist/helpers/constants.interfaces.js +11 -0
- package/dist/helpers/constants.js +436 -0
- package/dist/helpers/options.d.ts +64 -0
- package/dist/helpers/options.d.ts.map +1 -0
- package/dist/helpers/options.interfaces.d.ts +363 -0
- package/dist/helpers/options.interfaces.d.ts.map +1 -0
- package/dist/helpers/options.interfaces.js +1 -0
- package/dist/helpers/options.js +184 -0
- package/dist/helpers/options.test.d.ts +2 -0
- package/dist/helpers/options.test.d.ts.map +1 -0
- package/dist/helpers/options.test.js +428 -0
- package/dist/helpers/utils.d.ts +134 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/helpers/utils.interfaces.d.ts +254 -0
- package/dist/helpers/utils.interfaces.d.ts.map +1 -0
- package/dist/helpers/utils.interfaces.js +1 -0
- package/dist/helpers/utils.js +566 -0
- package/dist/helpers/utils.test.d.ts +2 -0
- package/dist/helpers/utils.test.d.ts.map +1 -0
- package/dist/helpers/utils.test.js +900 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/methods/compareReport.interfaces.d.ts +109 -0
- package/dist/methods/compareReport.interfaces.d.ts.map +1 -0
- package/dist/methods/compareReport.interfaces.js +1 -0
- package/dist/methods/createCompareReport.d.ts +7 -0
- package/dist/methods/createCompareReport.d.ts.map +1 -0
- package/dist/methods/createCompareReport.js +61 -0
- package/dist/methods/createCompareReport.test.d.ts +2 -0
- package/dist/methods/createCompareReport.test.d.ts.map +1 -0
- package/dist/methods/createCompareReport.test.js +236 -0
- package/dist/methods/elementPosition.d.ts +18 -0
- package/dist/methods/elementPosition.d.ts.map +1 -0
- package/dist/methods/elementPosition.interfaces.d.ts +14 -0
- package/dist/methods/elementPosition.interfaces.d.ts.map +1 -0
- package/dist/methods/elementPosition.interfaces.js +1 -0
- package/dist/methods/elementPosition.js +34 -0
- package/dist/methods/images.d.ts +69 -0
- package/dist/methods/images.d.ts.map +1 -0
- package/dist/methods/images.executeImageCompare.test.d.ts +2 -0
- package/dist/methods/images.executeImageCompare.test.d.ts.map +1 -0
- package/dist/methods/images.executeImageCompare.test.js +770 -0
- package/dist/methods/images.interfaces.d.ts +214 -0
- package/dist/methods/images.interfaces.d.ts.map +1 -0
- package/dist/methods/images.interfaces.js +1 -0
- package/dist/methods/images.js +428 -0
- package/dist/methods/images.test.d.ts +2 -0
- package/dist/methods/images.test.d.ts.map +1 -0
- package/dist/methods/images.test.js +1465 -0
- package/dist/methods/instanceData.d.ts +6 -0
- package/dist/methods/instanceData.d.ts.map +1 -0
- package/dist/methods/instanceData.interfaces.d.ts +57 -0
- package/dist/methods/instanceData.interfaces.d.ts.map +1 -0
- package/dist/methods/instanceData.interfaces.js +1 -0
- package/dist/methods/instanceData.js +42 -0
- package/dist/methods/instanceData.test.d.ts +2 -0
- package/dist/methods/instanceData.test.d.ts.map +1 -0
- package/dist/methods/instanceData.test.js +224 -0
- package/dist/methods/processDiffPixels.d.ts +59 -0
- package/dist/methods/processDiffPixels.d.ts.map +1 -0
- package/dist/methods/processDiffPixels.js +242 -0
- package/dist/methods/processDiffPixels.test.d.ts +2 -0
- package/dist/methods/processDiffPixels.test.d.ts.map +1 -0
- package/dist/methods/processDiffPixels.test.js +122 -0
- package/dist/methods/rectangles.d.ts +51 -0
- package/dist/methods/rectangles.d.ts.map +1 -0
- package/dist/methods/rectangles.interfaces.d.ts +146 -0
- package/dist/methods/rectangles.interfaces.d.ts.map +1 -0
- package/dist/methods/rectangles.interfaces.js +1 -0
- package/dist/methods/rectangles.js +266 -0
- package/dist/methods/rectangles.test.d.ts +2 -0
- package/dist/methods/rectangles.test.d.ts.map +1 -0
- package/dist/methods/rectangles.test.js +853 -0
- package/dist/methods/screenshots.d.ts +37 -0
- package/dist/methods/screenshots.d.ts.map +1 -0
- package/dist/methods/screenshots.interfaces.d.ts +203 -0
- package/dist/methods/screenshots.interfaces.d.ts.map +1 -0
- package/dist/methods/screenshots.interfaces.js +1 -0
- package/dist/methods/screenshots.js +394 -0
- package/dist/methods/screenshots.test.d.ts +2 -0
- package/dist/methods/screenshots.test.d.ts.map +1 -0
- package/dist/methods/screenshots.test.js +656 -0
- package/dist/methods/takeElementScreenshots.d.ts +3 -0
- package/dist/methods/takeElementScreenshots.d.ts.map +1 -0
- package/dist/methods/takeElementScreenshots.js +104 -0
- package/dist/methods/takeElementScreenshots.test.d.ts +2 -0
- package/dist/methods/takeElementScreenshots.test.d.ts.map +1 -0
- package/dist/methods/takeElementScreenshots.test.js +314 -0
- package/dist/methods/takeFullPageScreenshots.d.ts +3 -0
- package/dist/methods/takeFullPageScreenshots.d.ts.map +1 -0
- package/dist/methods/takeFullPageScreenshots.js +56 -0
- package/dist/methods/takeFullPageScreenshots.test.d.ts +2 -0
- package/dist/methods/takeFullPageScreenshots.test.d.ts.map +1 -0
- package/dist/methods/takeFullPageScreenshots.test.js +72 -0
- package/dist/methods/takeWebScreenshots.d.ts +3 -0
- package/dist/methods/takeWebScreenshots.d.ts.map +1 -0
- package/dist/methods/takeWebScreenshots.js +41 -0
- package/dist/methods/takeWebScreenshots.test.d.ts +2 -0
- package/dist/methods/takeWebScreenshots.test.d.ts.map +1 -0
- package/dist/methods/takeWebScreenshots.test.js +149 -0
- package/dist/mocks/image.d.ts +4 -0
- package/dist/mocks/image.d.ts.map +1 -0
- package/dist/mocks/image.js +3 -0
- package/dist/mocks/mocks.d.ts +745 -0
- package/dist/mocks/mocks.d.ts.map +1 -0
- package/dist/mocks/mocks.js +392 -0
- package/dist/resemble/compare.interfaces.d.ts +136 -0
- package/dist/resemble/compare.interfaces.d.ts.map +1 -0
- package/dist/resemble/compare.interfaces.js +1 -0
- package/dist/resemble/compareImages.d.ts +3 -0
- package/dist/resemble/compareImages.d.ts.map +1 -0
- package/dist/resemble/compareImages.js +21 -0
- package/dist/resemble/resemble.jimp.cjs +981 -0
- package/dist/resemble/resemble.jimp.d.cts +46 -0
- package/dist/resemble/resemble.jimp.d.cts.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This method is based on this blog post
|
|
3
|
+
* https://vivrichards.co.uk/accessibility/automating-page-tab-flows-using-visual-testing-and-javascript
|
|
4
|
+
* by Viv Richards and optimized for using Canvas
|
|
5
|
+
*/
|
|
6
|
+
export default function drawTabbableOnCanvas(drawOptions) {
|
|
7
|
+
// 1. Scroll to top of page
|
|
8
|
+
window.scrollTo(0, 0);
|
|
9
|
+
// 2. Insert canvas
|
|
10
|
+
const width = window.innerWidth;
|
|
11
|
+
const height = getDocumentScrollHeight();
|
|
12
|
+
const canvasNode = `<canvas id="wic-tabbable-canvas" width="${width}" height="${height}" style="position:absolute;top:0;left:0;z-index:999999;">`;
|
|
13
|
+
document.body.insertAdjacentHTML('afterbegin', canvasNode);
|
|
14
|
+
// 3. Get all the elements
|
|
15
|
+
const accessibleElements = tabbable();
|
|
16
|
+
// 4a. Iterate over all accessibleElements and get the coordinates
|
|
17
|
+
const elementCoordinates = accessibleElements.map((node) => {
|
|
18
|
+
const currentElement = node.getBoundingClientRect();
|
|
19
|
+
return {
|
|
20
|
+
x: currentElement.left + currentElement.width / 2,
|
|
21
|
+
y: currentElement.top + currentElement.height / 2,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
// 4b. Add the starting coordinates
|
|
25
|
+
elementCoordinates.unshift({ x: 0, y: 0 });
|
|
26
|
+
// 4c. Iterate over all coordinates and draw lines and circles
|
|
27
|
+
elementCoordinates.forEach((elementCoordinate, i) => {
|
|
28
|
+
if (i === 0) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
drawLine(drawOptions.line, elementCoordinates[i - 1], elementCoordinate);
|
|
32
|
+
drawCircleAndNumber(drawOptions.circle, elementCoordinate, i);
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Draw a line
|
|
36
|
+
*/
|
|
37
|
+
function drawLine(options, start, end) {
|
|
38
|
+
const tabbableCanvasContext = document.getElementById('wic-tabbable-canvas').getContext('2d');
|
|
39
|
+
if (!tabbableCanvasContext) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Draw the line
|
|
43
|
+
tabbableCanvasContext.beginPath();
|
|
44
|
+
tabbableCanvasContext.globalCompositeOperation = 'destination-over';
|
|
45
|
+
tabbableCanvasContext.lineWidth = options.width;
|
|
46
|
+
tabbableCanvasContext.strokeStyle = options.color;
|
|
47
|
+
tabbableCanvasContext.moveTo(start.x, start.y);
|
|
48
|
+
tabbableCanvasContext.lineTo(end.x, end.y);
|
|
49
|
+
tabbableCanvasContext.stroke();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Draw a circle
|
|
53
|
+
*/
|
|
54
|
+
function drawCircleAndNumber(options, position, i) {
|
|
55
|
+
const tabbableCanvasContext = document.getElementById('wic-tabbable-canvas').getContext('2d');
|
|
56
|
+
if (!tabbableCanvasContext) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Draw circle
|
|
60
|
+
tabbableCanvasContext.beginPath();
|
|
61
|
+
tabbableCanvasContext.globalCompositeOperation = 'source-over';
|
|
62
|
+
tabbableCanvasContext.fillStyle = options.backgroundColor;
|
|
63
|
+
tabbableCanvasContext.arc(position.x, position.y, options.size, 0, Math.PI * 2, true);
|
|
64
|
+
tabbableCanvasContext.fill();
|
|
65
|
+
// Draw border
|
|
66
|
+
tabbableCanvasContext.lineWidth = options.borderWidth;
|
|
67
|
+
tabbableCanvasContext.strokeStyle = options.borderColor;
|
|
68
|
+
tabbableCanvasContext.stroke();
|
|
69
|
+
if (options.showNumber) {
|
|
70
|
+
// Set the text
|
|
71
|
+
tabbableCanvasContext.font = `${options.fontSize}px ${options.fontFamily}`;
|
|
72
|
+
tabbableCanvasContext.textAlign = 'center';
|
|
73
|
+
tabbableCanvasContext.textBaseline = 'middle';
|
|
74
|
+
tabbableCanvasContext.fillStyle = options.fontColor;
|
|
75
|
+
tabbableCanvasContext.fillText(i.toString(), position.x, position.y);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Below code is coming from https://github.com/davidtheclark/tabbable
|
|
80
|
+
* and is modified a bit to work inside the browser.
|
|
81
|
+
* The original module couldn't be used for injection and didn't support TypeScript
|
|
82
|
+
*/
|
|
83
|
+
/**
|
|
84
|
+
* Get all tabbable elements based on tabindex and then regular dom order
|
|
85
|
+
*/
|
|
86
|
+
function tabbable() {
|
|
87
|
+
const regularTabbables = [];
|
|
88
|
+
const orderedTabbables = [];
|
|
89
|
+
const candidateSelectors = [
|
|
90
|
+
'input',
|
|
91
|
+
'select',
|
|
92
|
+
'textarea',
|
|
93
|
+
'a[href]',
|
|
94
|
+
'button',
|
|
95
|
+
'[tabindex]',
|
|
96
|
+
'audio[controls]',
|
|
97
|
+
'video[controls]',
|
|
98
|
+
'[contenteditable]:not([contenteditable="false"])',
|
|
99
|
+
].join(',');
|
|
100
|
+
const candidates = document.querySelectorAll(candidateSelectors);
|
|
101
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
102
|
+
const candidate = candidates[i];
|
|
103
|
+
if (!isNodeMatchingSelectorTabbable(candidate)) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const candidateTabindex = getTabindex(candidate);
|
|
107
|
+
if (candidateTabindex === 0) {
|
|
108
|
+
regularTabbables.push(candidate);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
orderedTabbables.push({
|
|
112
|
+
documentOrder: i,
|
|
113
|
+
tabIndex: candidateTabindex,
|
|
114
|
+
node: candidate,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Array.prototype.slice.call(orderedTabbables
|
|
119
|
+
.sort(sortOrderedTabbables)
|
|
120
|
+
.map((a) => a.node)
|
|
121
|
+
.concat(regularTabbables));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Is the node tabbable
|
|
125
|
+
*/
|
|
126
|
+
function isNodeMatchingSelectorTabbable(node) {
|
|
127
|
+
return !(!isNodeMatchingSelectorFocusable(node) || isNonTabbableRadio(node) || getTabindex(node) < 0);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if the node has a focused state
|
|
131
|
+
*/
|
|
132
|
+
function isNodeMatchingSelectorFocusable(node) {
|
|
133
|
+
return !(node.hasAttribute('disabled') || node.getAttribute('disabled') || isHiddenInput(node) || isHidden(node));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get the tab index of the node
|
|
137
|
+
*/
|
|
138
|
+
function getTabindex(node) {
|
|
139
|
+
const tabindexAttr = parseInt(node.getAttribute('tabindex'), 10);
|
|
140
|
+
if (!isNaN(tabindexAttr)) {
|
|
141
|
+
return tabindexAttr;
|
|
142
|
+
}
|
|
143
|
+
// Browsers do not return `tabIndex` correctly for contentEditable nodes;
|
|
144
|
+
// so if they don't have a tabindex attribute specifically set, assume it's 0.
|
|
145
|
+
// TODO: Lines 173-174 are currently untestable with the current setup
|
|
146
|
+
// The radio input with no name case is hard to test through the public API
|
|
147
|
+
if (isContentEditable(node)) {
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
return node.tabIndex;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Return ordered tabbable nodes
|
|
154
|
+
*/
|
|
155
|
+
function sortOrderedTabbables(nodeA, nodeB) {
|
|
156
|
+
// TODO: Lines 187-191 are currently untestable with the current setup
|
|
157
|
+
// The findHighestNode function is hard to test through the public API
|
|
158
|
+
return nodeA.tabIndex === nodeB.tabIndex
|
|
159
|
+
? // This is so bad :(, fix this!
|
|
160
|
+
nodeA.documentOrder - nodeB.documentOrder
|
|
161
|
+
: nodeA.tabIndex - nodeB.tabIndex;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Is the content editable
|
|
165
|
+
*/
|
|
166
|
+
function isContentEditable(node) {
|
|
167
|
+
return node.contentEditable === 'true';
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Is the node an input
|
|
171
|
+
*/
|
|
172
|
+
function isInput(node) {
|
|
173
|
+
return node.tagName === 'INPUT';
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Is the input hidden
|
|
177
|
+
*/
|
|
178
|
+
function isHiddenInput(node) {
|
|
179
|
+
return isInput(node) && node.type === 'hidden';
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Is the node a radio input
|
|
183
|
+
*/
|
|
184
|
+
function isRadio(node) {
|
|
185
|
+
return isInput(node) && node.type === 'radio';
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Is the node a radio input and can it be tabbed
|
|
189
|
+
*/
|
|
190
|
+
function isNonTabbableRadio(node) {
|
|
191
|
+
return isRadio(node) && !isTabbableRadio(node);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get the checked radio input
|
|
195
|
+
*/
|
|
196
|
+
// @ts-ignore
|
|
197
|
+
function getCheckedRadio(nodes) {
|
|
198
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
199
|
+
if (nodes[i].checked) {
|
|
200
|
+
return nodes[i];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Is the radio input tabbable
|
|
206
|
+
*/
|
|
207
|
+
function isTabbableRadio(node) {
|
|
208
|
+
if (!node.name) {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
// This won't account for the edge case where you have radio groups with the same
|
|
212
|
+
// in separate forms on the same page.
|
|
213
|
+
// This is bad :(, but don't know how to fix this typing
|
|
214
|
+
const radioSet = node.ownerDocument.querySelectorAll(`input[type="radio"][name="${node.name}"]`);
|
|
215
|
+
const checked = getCheckedRadio(radioSet);
|
|
216
|
+
return !checked || checked === node;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Is the node hidden
|
|
220
|
+
*/
|
|
221
|
+
function isHidden(node) {
|
|
222
|
+
// offsetParent being null will allow detecting cases where an element is invisible or inside an invisible element,
|
|
223
|
+
// as long as the element does not use position: fixed. For them, their visibility has to be checked directly as well.
|
|
224
|
+
return node.offsetParent === null || getComputedStyle(node).visibility === 'hidden';
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get the document scroll height
|
|
228
|
+
*/
|
|
229
|
+
function getDocumentScrollHeight() {
|
|
230
|
+
const viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
231
|
+
const scrollHeight = document.documentElement.scrollHeight;
|
|
232
|
+
const bodyScrollHeight = document.body.scrollHeight;
|
|
233
|
+
// In some situations the default scrollheight can be equal to the viewport height
|
|
234
|
+
// but the body scroll height can be different, then return that one
|
|
235
|
+
if (viewPortHeight === scrollHeight && bodyScrollHeight > scrollHeight) {
|
|
236
|
+
return bodyScrollHeight;
|
|
237
|
+
}
|
|
238
|
+
// In some cases we can have a challenge determining the height of the page
|
|
239
|
+
// due to for example a `vh` property on the body element.
|
|
240
|
+
// If that is the case we need to walk over all the elements and determine the highest element
|
|
241
|
+
// this is a very time consuming thing, so our last hope :(
|
|
242
|
+
let pageHeight = 0;
|
|
243
|
+
let largestNodeElement = document.querySelector('body');
|
|
244
|
+
// TODO: Lines 288-293 are currently untestable with the current setup
|
|
245
|
+
if (bodyScrollHeight === scrollHeight && bodyScrollHeight === viewPortHeight) {
|
|
246
|
+
findHighestNode(document.documentElement.childNodes);
|
|
247
|
+
// There could be some elements above this largest element,
|
|
248
|
+
// add that on top
|
|
249
|
+
return pageHeight + largestNodeElement?.getBoundingClientRect().top;
|
|
250
|
+
}
|
|
251
|
+
// The scrollHeight is good enough
|
|
252
|
+
return scrollHeight;
|
|
253
|
+
/**
|
|
254
|
+
* Find the largest html element on the page
|
|
255
|
+
*/
|
|
256
|
+
// This is so bad :(, fix the typings!!!
|
|
257
|
+
function findHighestNode(nodesList) {
|
|
258
|
+
// TODO: Lines 304-319 are currently untestable with the current setup
|
|
259
|
+
for (let i = nodesList.length - 1; i >= 0; i--) {
|
|
260
|
+
const currentNode = nodesList[i];
|
|
261
|
+
/* istanbul ignore next */
|
|
262
|
+
if (currentNode.scrollHeight && currentNode.clientHeight) {
|
|
263
|
+
const elHeight = Math.max(currentNode.scrollHeight, currentNode.clientHeight);
|
|
264
|
+
pageHeight = Math.max(elHeight, pageHeight);
|
|
265
|
+
if (elHeight === pageHeight) {
|
|
266
|
+
largestNodeElement = currentNode;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (currentNode.childNodes.length) {
|
|
270
|
+
findHighestNode(currentNode.childNodes);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawTabbableOnCanvas.test.d.ts","sourceRoot":"","sources":["../../src/clientSideScripts/drawTabbableOnCanvas.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
3
|
+
import drawTabbableOnCanvas from './drawTabbableOnCanvas.js';
|
|
4
|
+
describe('drawTabbableOnCanvas', () => {
|
|
5
|
+
const mockCanvasContext = {
|
|
6
|
+
beginPath: vi.fn(),
|
|
7
|
+
globalCompositeOperation: '',
|
|
8
|
+
lineWidth: 0,
|
|
9
|
+
strokeStyle: '',
|
|
10
|
+
moveTo: vi.fn(),
|
|
11
|
+
lineTo: vi.fn(),
|
|
12
|
+
stroke: vi.fn(),
|
|
13
|
+
fillStyle: '',
|
|
14
|
+
arc: vi.fn(),
|
|
15
|
+
fill: vi.fn(),
|
|
16
|
+
font: '',
|
|
17
|
+
textAlign: '',
|
|
18
|
+
textBaseline: '',
|
|
19
|
+
fillText: vi.fn(),
|
|
20
|
+
};
|
|
21
|
+
const defaultOptions = {
|
|
22
|
+
line: {
|
|
23
|
+
color: '#ff0000',
|
|
24
|
+
width: 2,
|
|
25
|
+
},
|
|
26
|
+
circle: {
|
|
27
|
+
backgroundColor: '#ffffff',
|
|
28
|
+
borderColor: '#ff0000',
|
|
29
|
+
borderWidth: 2,
|
|
30
|
+
size: 10,
|
|
31
|
+
showNumber: true,
|
|
32
|
+
fontSize: 12,
|
|
33
|
+
fontFamily: 'Arial',
|
|
34
|
+
fontColor: '#000000',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
document.body.innerHTML = '';
|
|
39
|
+
Object.defineProperty(window, 'innerWidth', { value: 1024, configurable: true });
|
|
40
|
+
Object.defineProperty(window, 'innerHeight', { value: 768, configurable: true });
|
|
41
|
+
Object.defineProperty(document.documentElement, 'clientHeight', { value: 768, configurable: true });
|
|
42
|
+
Object.defineProperty(document.documentElement, 'scrollHeight', { value: 1000, configurable: true });
|
|
43
|
+
Object.defineProperty(document.body, 'scrollHeight', { value: 1000, configurable: true });
|
|
44
|
+
window.scrollTo = vi.fn();
|
|
45
|
+
const mockGetContext = vi.fn().mockReturnValue(mockCanvasContext);
|
|
46
|
+
HTMLCanvasElement.prototype.getContext = mockGetContext;
|
|
47
|
+
vi.clearAllMocks();
|
|
48
|
+
});
|
|
49
|
+
it('should create a canvas element with correct dimensions', () => {
|
|
50
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
51
|
+
const canvas = document.getElementById('wic-tabbable-canvas');
|
|
52
|
+
expect(canvas).toBeTruthy();
|
|
53
|
+
expect(canvas.width).toBe(1024);
|
|
54
|
+
expect(canvas.height).toBe(1000);
|
|
55
|
+
expect(canvas.style.position).toBe('absolute');
|
|
56
|
+
expect(canvas.style.top).toBe('0px');
|
|
57
|
+
expect(canvas.style.left).toBe('0px');
|
|
58
|
+
expect(canvas.style.zIndex).toBe('999999');
|
|
59
|
+
});
|
|
60
|
+
it('should draw lines and circles for tabbable elements', () => {
|
|
61
|
+
const button = document.createElement('button');
|
|
62
|
+
button.textContent = 'Test Button';
|
|
63
|
+
button.tabIndex = 0;
|
|
64
|
+
document.body.appendChild(button);
|
|
65
|
+
const input = document.createElement('input');
|
|
66
|
+
input.type = 'text';
|
|
67
|
+
input.tabIndex = 0;
|
|
68
|
+
document.body.appendChild(input);
|
|
69
|
+
const mockRect = {
|
|
70
|
+
left: 100,
|
|
71
|
+
top: 100,
|
|
72
|
+
width: 100,
|
|
73
|
+
height: 50,
|
|
74
|
+
right: 200,
|
|
75
|
+
bottom: 150,
|
|
76
|
+
};
|
|
77
|
+
Element.prototype.getBoundingClientRect = vi.fn().mockReturnValue(mockRect);
|
|
78
|
+
Object.defineProperty(button, 'offsetParent', { value: document.body, configurable: true });
|
|
79
|
+
Object.defineProperty(input, 'offsetParent', { value: document.body, configurable: true });
|
|
80
|
+
const beginPathSpy = vi.spyOn(mockCanvasContext, 'beginPath');
|
|
81
|
+
const globalCompositeOperationSpy = vi.spyOn(mockCanvasContext, 'globalCompositeOperation', 'set');
|
|
82
|
+
const fillStyleSpy = vi.spyOn(mockCanvasContext, 'fillStyle', 'set');
|
|
83
|
+
const strokeStyleSpy = vi.spyOn(mockCanvasContext, 'strokeStyle', 'set');
|
|
84
|
+
const lineWidthSpy = vi.spyOn(mockCanvasContext, 'lineWidth', 'set');
|
|
85
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
86
|
+
expect(beginPathSpy).toHaveBeenCalled();
|
|
87
|
+
expect(globalCompositeOperationSpy).toHaveBeenNthCalledWith(1, 'destination-over');
|
|
88
|
+
expect(lineWidthSpy).toHaveBeenNthCalledWith(1, defaultOptions.line.width);
|
|
89
|
+
expect(strokeStyleSpy).toHaveBeenNthCalledWith(1, defaultOptions.line.color);
|
|
90
|
+
expect(mockCanvasContext.moveTo).toHaveBeenCalled();
|
|
91
|
+
expect(mockCanvasContext.lineTo).toHaveBeenCalled();
|
|
92
|
+
expect(mockCanvasContext.stroke).toHaveBeenCalled();
|
|
93
|
+
expect(globalCompositeOperationSpy).toHaveBeenNthCalledWith(2, 'source-over');
|
|
94
|
+
expect(fillStyleSpy).toHaveBeenNthCalledWith(1, defaultOptions.circle.backgroundColor);
|
|
95
|
+
expect(lineWidthSpy).toHaveBeenNthCalledWith(2, defaultOptions.circle.borderWidth);
|
|
96
|
+
expect(strokeStyleSpy).toHaveBeenNthCalledWith(2, defaultOptions.circle.borderColor);
|
|
97
|
+
expect(mockCanvasContext.arc).toHaveBeenCalled();
|
|
98
|
+
expect(mockCanvasContext.fill).toHaveBeenCalled();
|
|
99
|
+
expect(mockCanvasContext.stroke).toHaveBeenCalled();
|
|
100
|
+
expect(fillStyleSpy).toHaveBeenNthCalledWith(2, defaultOptions.circle.fontColor);
|
|
101
|
+
expect(mockCanvasContext.font).toBe(`${defaultOptions.circle.fontSize}px ${defaultOptions.circle.fontFamily}`);
|
|
102
|
+
expect(mockCanvasContext.textAlign).toBe('center');
|
|
103
|
+
expect(mockCanvasContext.textBaseline).toBe('middle');
|
|
104
|
+
expect(mockCanvasContext.fillText).toHaveBeenCalled();
|
|
105
|
+
});
|
|
106
|
+
it('should handle empty tabbable elements', () => {
|
|
107
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
108
|
+
const canvas = document.getElementById('wic-tabbable-canvas');
|
|
109
|
+
expect(canvas).toBeTruthy();
|
|
110
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
|
+
it('should handle hidden elements', () => {
|
|
113
|
+
const button = document.createElement('button');
|
|
114
|
+
button.style.visibility = 'hidden';
|
|
115
|
+
document.body.appendChild(button);
|
|
116
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
117
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
118
|
+
});
|
|
119
|
+
it('should handle disabled elements', () => {
|
|
120
|
+
const button = document.createElement('button');
|
|
121
|
+
button.disabled = true;
|
|
122
|
+
document.body.appendChild(button);
|
|
123
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
124
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
it('should not include elements with negative tabindex', () => {
|
|
127
|
+
const div = document.createElement('div');
|
|
128
|
+
div.tabIndex = -1;
|
|
129
|
+
document.body.appendChild(div);
|
|
130
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
131
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
132
|
+
});
|
|
133
|
+
it('should not include disabled elements', () => {
|
|
134
|
+
const input = document.createElement('input');
|
|
135
|
+
input.disabled = true;
|
|
136
|
+
document.body.appendChild(input);
|
|
137
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
138
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
139
|
+
});
|
|
140
|
+
it('should not include hidden elements (visibility: hidden)', () => {
|
|
141
|
+
const input = document.createElement('input');
|
|
142
|
+
input.style.visibility = 'hidden';
|
|
143
|
+
document.body.appendChild(input);
|
|
144
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
145
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
146
|
+
});
|
|
147
|
+
it('should only include checked radio in group as tabbable', () => {
|
|
148
|
+
const radio1 = document.createElement('input');
|
|
149
|
+
radio1.type = 'radio';
|
|
150
|
+
radio1.name = 'group1';
|
|
151
|
+
document.body.appendChild(radio1);
|
|
152
|
+
const radio2 = document.createElement('input');
|
|
153
|
+
radio2.type = 'radio';
|
|
154
|
+
radio2.name = 'group1';
|
|
155
|
+
radio2.checked = true;
|
|
156
|
+
document.body.appendChild(radio2);
|
|
157
|
+
Object.defineProperty(radio1, 'offsetParent', { value: document.body, configurable: true });
|
|
158
|
+
Object.defineProperty(radio2, 'offsetParent', { value: document.body, configurable: true });
|
|
159
|
+
radio2.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
160
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
161
|
+
expect(mockCanvasContext.beginPath).toHaveBeenCalled();
|
|
162
|
+
});
|
|
163
|
+
it('should sort tabbable elements correctly (tabIndex 0 vs non-zero)', () => {
|
|
164
|
+
const btn1 = document.createElement('button');
|
|
165
|
+
btn1.tabIndex = 0;
|
|
166
|
+
document.body.appendChild(btn1);
|
|
167
|
+
const btn2 = document.createElement('button');
|
|
168
|
+
btn2.tabIndex = 1;
|
|
169
|
+
document.body.appendChild(btn2);
|
|
170
|
+
Object.defineProperty(btn1, 'offsetParent', { value: document.body, configurable: true });
|
|
171
|
+
Object.defineProperty(btn2, 'offsetParent', { value: document.body, configurable: true });
|
|
172
|
+
btn1.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
173
|
+
btn2.getBoundingClientRect = vi.fn().mockReturnValue({ left: 20, top: 20, width: 10, height: 10, right: 30, bottom: 30 });
|
|
174
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
175
|
+
expect(mockCanvasContext.beginPath).toHaveBeenCalled();
|
|
176
|
+
});
|
|
177
|
+
it('should treat radio with no name as tabbable', () => {
|
|
178
|
+
const radio = document.createElement('input');
|
|
179
|
+
radio.type = 'radio';
|
|
180
|
+
document.body.appendChild(radio);
|
|
181
|
+
Object.defineProperty(radio, 'offsetParent', { value: document.body, configurable: true });
|
|
182
|
+
radio.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
183
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
184
|
+
expect(mockCanvasContext.beginPath).toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
it('should treat contentEditable as tabbable', () => {
|
|
187
|
+
const div = document.createElement('div');
|
|
188
|
+
div.contentEditable = 'true';
|
|
189
|
+
div.tabIndex = 0;
|
|
190
|
+
document.body.appendChild(div);
|
|
191
|
+
Object.defineProperty(div, 'offsetParent', { value: document.body, configurable: true });
|
|
192
|
+
div.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
193
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
194
|
+
expect(mockCanvasContext.beginPath).toHaveBeenCalled();
|
|
195
|
+
});
|
|
196
|
+
it('should use body scrollHeight if it is greater than document scrollHeight', () => {
|
|
197
|
+
Object.defineProperty(document.documentElement, 'clientHeight', { value: 100, configurable: true });
|
|
198
|
+
Object.defineProperty(document.documentElement, 'scrollHeight', { value: 100, configurable: true });
|
|
199
|
+
Object.defineProperty(document.body, 'scrollHeight', { value: 200, configurable: true });
|
|
200
|
+
Object.defineProperty(window, 'innerHeight', { value: 100, configurable: true });
|
|
201
|
+
const btn = document.createElement('button');
|
|
202
|
+
btn.tabIndex = 0;
|
|
203
|
+
Object.defineProperty(btn, 'offsetParent', { value: document.body, configurable: true });
|
|
204
|
+
btn.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
205
|
+
document.body.appendChild(btn);
|
|
206
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
207
|
+
const canvas = document.getElementById('wic-tabbable-canvas');
|
|
208
|
+
expect(canvas.height).toBe(200);
|
|
209
|
+
});
|
|
210
|
+
it('should walk DOM to find highest node if scrollHeight and bodyScrollHeight equal clientHeight', () => {
|
|
211
|
+
Object.defineProperty(document.documentElement, 'clientHeight', { value: 100, configurable: true });
|
|
212
|
+
Object.defineProperty(document.documentElement, 'scrollHeight', { value: 100, configurable: true });
|
|
213
|
+
Object.defineProperty(document.body, 'scrollHeight', { value: 100, configurable: true });
|
|
214
|
+
const tallDiv = document.createElement('div');
|
|
215
|
+
tallDiv.style.height = '300px';
|
|
216
|
+
document.body.appendChild(tallDiv);
|
|
217
|
+
tallDiv.getBoundingClientRect = vi.fn().mockReturnValue({ top: 0 });
|
|
218
|
+
drawTabbableOnCanvas(defaultOptions);
|
|
219
|
+
const canvas = document.getElementById('wic-tabbable-canvas');
|
|
220
|
+
expect(canvas.height).toBeGreaterThanOrEqual(100);
|
|
221
|
+
});
|
|
222
|
+
it('should not throw or attempt to draw if getContext returns null (drawLine)', () => {
|
|
223
|
+
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
|
224
|
+
HTMLCanvasElement.prototype.getContext = vi.fn().mockReturnValue(null);
|
|
225
|
+
const btn1 = document.createElement('button');
|
|
226
|
+
btn1.tabIndex = 0;
|
|
227
|
+
Object.defineProperty(btn1, 'offsetParent', { value: document.body, configurable: true });
|
|
228
|
+
btn1.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
229
|
+
document.body.appendChild(btn1);
|
|
230
|
+
const btn2 = document.createElement('button');
|
|
231
|
+
btn2.tabIndex = 0;
|
|
232
|
+
Object.defineProperty(btn2, 'offsetParent', { value: document.body, configurable: true });
|
|
233
|
+
btn2.getBoundingClientRect = vi.fn().mockReturnValue({ left: 20, top: 20, width: 10, height: 10, right: 30, bottom: 30 });
|
|
234
|
+
document.body.appendChild(btn2);
|
|
235
|
+
expect(() => drawTabbableOnCanvas(defaultOptions)).not.toThrow();
|
|
236
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
237
|
+
HTMLCanvasElement.prototype.getContext = originalGetContext;
|
|
238
|
+
});
|
|
239
|
+
it('should not throw or attempt to draw if getContext returns null (drawCircleAndNumber)', () => {
|
|
240
|
+
const originalGetContext = HTMLCanvasElement.prototype.getContext;
|
|
241
|
+
HTMLCanvasElement.prototype.getContext = vi.fn().mockReturnValue(null);
|
|
242
|
+
const btn = document.createElement('button');
|
|
243
|
+
btn.tabIndex = 0;
|
|
244
|
+
Object.defineProperty(btn, 'offsetParent', { value: document.body, configurable: true });
|
|
245
|
+
btn.getBoundingClientRect = vi.fn().mockReturnValue({ left: 0, top: 0, width: 10, height: 10, right: 10, bottom: 10 });
|
|
246
|
+
document.body.appendChild(btn);
|
|
247
|
+
expect(() => drawTabbableOnCanvas(defaultOptions)).not.toThrow();
|
|
248
|
+
expect(mockCanvasContext.beginPath).not.toHaveBeenCalled();
|
|
249
|
+
HTMLCanvasElement.prototype.getContext = originalGetContext;
|
|
250
|
+
});
|
|
251
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elementPosition.interfaces.d.ts","sourceRoot":"","sources":["../../src/clientSideScripts/elementPosition.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAE3E,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ElementPosition } from './elementPosition.interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get the element position relative to the viewport
|
|
4
|
+
*/
|
|
5
|
+
export declare function getBoundingClientRect(element: HTMLElement): ElementPosition;
|
|
6
|
+
//# sourceMappingURL=getBoundingClientRect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBoundingClientRect.d.ts","sourceRoot":"","sources":["../../src/clientSideScripts/getBoundingClientRect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAEtE;;GAEG;AACH,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,WAAW,GACrB,eAAe,CASjB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the element position relative to the viewport
|
|
3
|
+
*/
|
|
4
|
+
export function getBoundingClientRect(element) {
|
|
5
|
+
const { height, width, x, y } = element.getBoundingClientRect();
|
|
6
|
+
return {
|
|
7
|
+
height: Math.round(height),
|
|
8
|
+
width: Math.round(width),
|
|
9
|
+
x: Math.round(x),
|
|
10
|
+
y: Math.round(y),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBoundingClientRect.test.d.ts","sourceRoot":"","sources":["../../src/clientSideScripts/getBoundingClientRect.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { getBoundingClientRect } from './getBoundingClientRect.js';
|
|
4
|
+
describe('getBoundingClientRect', () => {
|
|
5
|
+
it('should return rounded values of the bounding client rect', () => {
|
|
6
|
+
const element = document.createElement('div');
|
|
7
|
+
Object.defineProperty(element, 'getBoundingClientRect', {
|
|
8
|
+
value: () => ({
|
|
9
|
+
x: 10.7,
|
|
10
|
+
y: 20.4,
|
|
11
|
+
width: 100.9,
|
|
12
|
+
height: 200.3,
|
|
13
|
+
top: 20.4,
|
|
14
|
+
left: 10.7,
|
|
15
|
+
bottom: 220.7,
|
|
16
|
+
right: 110.9,
|
|
17
|
+
toJSON: () => { },
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
const result = getBoundingClientRect(element);
|
|
21
|
+
expect(result).toEqual({
|
|
22
|
+
x: 11,
|
|
23
|
+
y: 20,
|
|
24
|
+
width: 101,
|
|
25
|
+
height: 200,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDocumentScrollHeight.d.ts","sourceRoot":"","sources":["../../src/clientSideScripts/getDocumentScrollHeight.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,uBAAuB,IAAI,MAAM,CAoDxD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the document scroll height, this means the actual height of the page from the top to the bottom of the DOM
|
|
3
|
+
*/
|
|
4
|
+
export default function getDocumentScrollHeight() {
|
|
5
|
+
const viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
6
|
+
const scrollHeight = document.documentElement.scrollHeight;
|
|
7
|
+
const bodyScrollHeight = document.body.scrollHeight;
|
|
8
|
+
// In some situations the default scrollheight can be equal to the viewport height
|
|
9
|
+
// but the body scroll height can be different, then return that one
|
|
10
|
+
if (viewPortHeight === scrollHeight && bodyScrollHeight > scrollHeight) {
|
|
11
|
+
return bodyScrollHeight;
|
|
12
|
+
}
|
|
13
|
+
// In some cases we can have a challenge determining the height of the page
|
|
14
|
+
// due to for example a `vh` property on the body element.
|
|
15
|
+
// If that is the case we need to walk over all the elements and determine the highest element
|
|
16
|
+
// this is a very time consuming thing, so our last hope :(
|
|
17
|
+
let pageHeight = 0;
|
|
18
|
+
let largestNodeElement = document.querySelector('body');
|
|
19
|
+
if (bodyScrollHeight === scrollHeight && bodyScrollHeight === viewPortHeight) {
|
|
20
|
+
findHighestNode(document.documentElement.childNodes);
|
|
21
|
+
// There could be some elements above this largest element,
|
|
22
|
+
// add that on top
|
|
23
|
+
/* istanbul ignore next */
|
|
24
|
+
return pageHeight + largestNodeElement.getBoundingClientRect().top;
|
|
25
|
+
}
|
|
26
|
+
// The scrollHeight is good enough
|
|
27
|
+
return scrollHeight;
|
|
28
|
+
/**
|
|
29
|
+
* Find the largest html element on the page
|
|
30
|
+
* @param nodesList
|
|
31
|
+
*/
|
|
32
|
+
function findHighestNode(nodesList) {
|
|
33
|
+
for (let i = nodesList.length - 1; i >= 0; i--) {
|
|
34
|
+
const currentNode = nodesList[i];
|
|
35
|
+
/* istanbul ignore next */
|
|
36
|
+
if (currentNode.scrollHeight && currentNode.clientHeight) {
|
|
37
|
+
const elHeight = Math.max(currentNode.scrollHeight, currentNode.clientHeight);
|
|
38
|
+
pageHeight = Math.max(elHeight, pageHeight);
|
|
39
|
+
if (elHeight === pageHeight) {
|
|
40
|
+
largestNodeElement = currentNode;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (currentNode.childNodes.length) {
|
|
44
|
+
findHighestNode(currentNode.childNodes);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|