From 9df849ffae108df492ef49cbc4353ea3bbfb15de Mon Sep 17 00:00:00 2001 From: balesniy Date: Mon, 10 Jun 2024 20:23:00 +0200 Subject: [PATCH] update tests --- engine_scripts/childrenDecrease.js | 94 ++++++++++++++ engine_scripts/childrenIncrease.js | 94 ++++++++++++++ engine_scripts/clickAndHoverHelper.cjs | 89 +++++++++++++ engine_scripts/contentOverflow.js | 94 ++++++++++++++ engine_scripts/fill-email.js | 11 ++ engine_scripts/fillInput.js | 20 +++ engine_scripts/hide-bg.js | 18 +++ engine_scripts/highlight-required.js | 21 +++ engine_scripts/imgDecrease.js | 94 ++++++++++++++ engine_scripts/imgIncrease.js | 96 ++++++++++++++ engine_scripts/imgLandscape.js | 96 ++++++++++++++ engine_scripts/imgPortrait.js | 96 ++++++++++++++ engine_scripts/interaction.js | 62 +++++++++ engine_scripts/interceptImages.js | 37 ++++++ engine_scripts/jsDisable.js | 10 ++ engine_scripts/markup-interaction-active.js | 134 +++++++++++++++++++ engine_scripts/markup-interaction-hover.js | 136 ++++++++++++++++++++ engine_scripts/onBefore.js | 3 + engine_scripts/onReady.cjs | 36 ++++++ engine_scripts/overrideCSS.js | 14 ++ engine_scripts/textDecrease.js | 94 ++++++++++++++ engine_scripts/textIncrease.js | 95 ++++++++++++++ engine_scripts/textStylesOnly.js | 59 +++++++++ run-test.js | 102 +++++++-------- test-config/backstop-html-03.config.js | 2 +- test-config/backstop-html-04.config.js | 2 +- test-config/backstop-img-01.config.js | 2 +- test-config/backstop-test-03.config.js | 2 +- test-config/backstop-test-04.config.js | 2 +- test-config/backstop-test-05.config.js | 2 +- test-config/backstop-test-06.config.js | 4 +- test-config/backstop-test-07.config.js | 2 +- test-config/backstop-test-08.config.js | 2 +- test-config/backstop-test-ff.config.js | 2 +- test-config/backstop-test-logo.config.js | 2 +- test-config/backstop-test-menu.config.js | 2 +- test-config/backstop-test-swiper.config.js | 2 +- 37 files changed, 1567 insertions(+), 66 deletions(-) create mode 100644 engine_scripts/childrenDecrease.js create mode 100644 engine_scripts/childrenIncrease.js create mode 100644 engine_scripts/clickAndHoverHelper.cjs create mode 100644 engine_scripts/contentOverflow.js create mode 100644 engine_scripts/fill-email.js create mode 100644 engine_scripts/fillInput.js create mode 100644 engine_scripts/hide-bg.js create mode 100644 engine_scripts/highlight-required.js create mode 100644 engine_scripts/imgDecrease.js create mode 100644 engine_scripts/imgIncrease.js create mode 100644 engine_scripts/imgLandscape.js create mode 100644 engine_scripts/imgPortrait.js create mode 100644 engine_scripts/interaction.js create mode 100644 engine_scripts/interceptImages.js create mode 100644 engine_scripts/jsDisable.js create mode 100644 engine_scripts/markup-interaction-active.js create mode 100644 engine_scripts/markup-interaction-hover.js create mode 100644 engine_scripts/onBefore.js create mode 100644 engine_scripts/onReady.cjs create mode 100644 engine_scripts/overrideCSS.js create mode 100644 engine_scripts/textDecrease.js create mode 100644 engine_scripts/textIncrease.js create mode 100644 engine_scripts/textStylesOnly.js diff --git a/engine_scripts/childrenDecrease.js b/engine_scripts/childrenDecrease.js new file mode 100644 index 00000000..99f165b0 --- /dev/null +++ b/engine_scripts/childrenDecrease.js @@ -0,0 +1,94 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.6; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["fieldset", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyChildrenAmount, scenario.multiplier || defaultChildrenDecreaseMultiplier, defaultChildrenSelectors) + +}; diff --git a/engine_scripts/childrenIncrease.js b/engine_scripts/childrenIncrease.js new file mode 100644 index 00000000..f13ff75b --- /dev/null +++ b/engine_scripts/childrenIncrease.js @@ -0,0 +1,94 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["fieldset", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyChildrenAmount, scenario.multiplier || defaultChildrenIncreaseMultiplier, defaultChildrenSelectors) + +}; diff --git a/engine_scripts/clickAndHoverHelper.cjs b/engine_scripts/clickAndHoverHelper.cjs new file mode 100644 index 00000000..b32b5b99 --- /dev/null +++ b/engine_scripts/clickAndHoverHelper.cjs @@ -0,0 +1,89 @@ +module.exports = async (page, scenario) => { + const hoverSelector = scenario.hoverSelectors || scenario.hoverSelector; + const clickSelector = scenario.clickSelectors || scenario.clickSelector; + const activeSelector = scenario.activeSelectors || scenario.activeSelector; + const disableSelector = scenario.disableSelectors || scenario.disableSelector; + const focusSelector = scenario.focusSelectors || scenario.focusSelector; + const keyPressSelector = scenario.keyPressSelectors || scenario.keyPressSelector; + const scrollToSelector = scenario.scrollToSelector; + const postInteractionWait = scenario.postInteractionWait; // ms [int] + + const interactiveElsSelector = "a, button, input[type='radio'], input[type='checkbox'], label"; + const content = ` + const preventer = (e) => e.preventDefault(); + const els = document.querySelectorAll("${interactiveElsSelector}"); + const mouseEvts = ["mouseup", "mousedown", "click"]; + + els.forEach((el) => { + mouseEvts.forEach((me) => el.addEventListener(me, preventer)); + }); + `; + + // await page.addScriptTag({ content }); + + if (disableSelector) { + await Promise.all( + [].concat(disableSelector).map(async (selector) => { + await page + .evaluate((sel) => { + document.querySelectorAll(sel).forEach(s => { + if (s.tagName === 'LABEL') { + s = s.control + } + s.disabled = true; + s.classList.add('disabled'); + }); + }, selector); + }) + ); + } + + if (keyPressSelector) { + for (const keyPressSelectorItem of [].concat(keyPressSelector)) { + await page.waitFor(keyPressSelectorItem.selector); + await page.type(keyPressSelectorItem.selector, keyPressSelectorItem.keyPress); + } + } + + if (hoverSelector) { + for (const hoverSelectorIndex of [].concat(hoverSelector)) { + await page.waitForSelector(hoverSelectorIndex); + await page.hover(hoverSelectorIndex); + } + } + + if (activeSelector) { + for (const activeSelectorIndex of [].concat(activeSelector)) { + await page.waitForSelector(activeSelectorIndex); + await page.hover(activeSelectorIndex); + await page.mouse.down(); + } + } + + if (clickSelector) { + for (const clickSelectorIndex of [].concat(clickSelector)) { + await page.waitForSelector(clickSelectorIndex); + await page.click(clickSelectorIndex); + } + } + + if (focusSelector) { + for (const focusSelectorIndex of [].concat(focusSelector)) { + await page.waitForSelector(focusSelectorIndex); + await page.focus(focusSelectorIndex); + } + } + + if (postInteractionWait) { + await page.waitForTimeout(postInteractionWait); + } + + if (scrollToSelector) { + await page.waitForSelector(scrollToSelector); + await page.evaluate(scrollToSelector => { + document.querySelector(scrollToSelector).scrollIntoView({ + behavior: "instant", block: "center", inline: "center" + }); + }, scrollToSelector); + } +}; diff --git a/engine_scripts/contentOverflow.js b/engine_scripts/contentOverflow.js new file mode 100644 index 00000000..12e4c547 --- /dev/null +++ b/engine_scripts/contentOverflow.js @@ -0,0 +1,94 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyTextAmount, defaultTextIncreaseMultiplier, defaultTextSelectors) + +}; diff --git a/engine_scripts/fill-email.js b/engine_scripts/fill-email.js new file mode 100644 index 00000000..1b503395 --- /dev/null +++ b/engine_scripts/fill-email.js @@ -0,0 +1,11 @@ +module.exports = async (page, scenario, vp, isReference) => { + console.log('SCENARIO > ' + scenario.label); + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + await page.type(scenario.field, scenario.email); + await require('./clickAndHoverHelper')(page, scenario); +}; diff --git a/engine_scripts/fillInput.js b/engine_scripts/fillInput.js new file mode 100644 index 00000000..7314e84e --- /dev/null +++ b/engine_scripts/fillInput.js @@ -0,0 +1,20 @@ +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + await page.evaluate(() => { + const $textEls = [...document.querySelectorAll('input[type="text"],input[type="email"]')]; + $textEls.forEach((el) => { + el.value = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.'; + }); + const $numberEls = [...document.querySelectorAll('input[type="number"]')]; + $numberEls.forEach((el) => { + el.value = 999999999999999; + }); + }); +}; diff --git a/engine_scripts/hide-bg.js b/engine_scripts/hide-bg.js new file mode 100644 index 00000000..26706c3e --- /dev/null +++ b/engine_scripts/hide-bg.js @@ -0,0 +1,18 @@ +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + const BACKSTOP_TEST_CSS_OVERRIDE = ` + *, *::before, *::after { + background-image: unset !important; + } + `; + + await require('./overrideCSS')(page, scenario, BACKSTOP_TEST_CSS_OVERRIDE); +}; diff --git a/engine_scripts/highlight-required.js b/engine_scripts/highlight-required.js new file mode 100644 index 00000000..5545fd30 --- /dev/null +++ b/engine_scripts/highlight-required.js @@ -0,0 +1,21 @@ +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + + const BACKSTOP_TEST_CSS_OVERRIDE = ` + input[required] { + outline: solid 10px red !important; + outline-offset: -10px !important; + } + `; + + await require('./overrideCSS')(page, scenario, BACKSTOP_TEST_CSS_OVERRIDE); + + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + +}; diff --git a/engine_scripts/imgDecrease.js b/engine_scripts/imgDecrease.js new file mode 100644 index 00000000..ce7bae6b --- /dev/null +++ b/engine_scripts/imgDecrease.js @@ -0,0 +1,94 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyImages, false, defaultImgSelectors) + +}; diff --git a/engine_scripts/imgIncrease.js b/engine_scripts/imgIncrease.js new file mode 100644 index 00000000..971235ef --- /dev/null +++ b/engine_scripts/imgIncrease.js @@ -0,0 +1,96 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + const portraitImgSrc = + "data:image/png;base64,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" + const landscapeImgSrc = + "data:image/png;base64,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" + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyImages, true, defaultImgSelectors) +}; diff --git a/engine_scripts/imgLandscape.js b/engine_scripts/imgLandscape.js new file mode 100644 index 00000000..fefb2ff1 --- /dev/null +++ b/engine_scripts/imgLandscape.js @@ -0,0 +1,96 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isLandscape, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + const portraitImgSrc = + "data:image/png;base64,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" + const landscapeImgSrc = + "data:image/png;base64,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" + $el.src = isLandscape ? landscapeImgSrc : portraitImgSrc; + $el.width = isLandscape ? 500 : 300; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyImages, true, defaultImgSelectors) +}; diff --git a/engine_scripts/imgPortrait.js b/engine_scripts/imgPortrait.js new file mode 100644 index 00000000..7231d684 --- /dev/null +++ b/engine_scripts/imgPortrait.js @@ -0,0 +1,96 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isLandscape, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + const portraitImgSrc = + "data:image/png;base64,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" + const landscapeImgSrc = + "data:image/png;base64,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" + $el.src = isLandscape ? landscapeImgSrc : portraitImgSrc; + $el.width = isLandscape ? 500 : 300; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyImages, false, defaultImgSelectors) +}; diff --git a/engine_scripts/interaction.js b/engine_scripts/interaction.js new file mode 100644 index 00000000..d1eb5520 --- /dev/null +++ b/engine_scripts/interaction.js @@ -0,0 +1,62 @@ +module.exports = async (page, scenario, vp, isReference) => { + console.log('SCENARIO > ' + scenario.label); + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + if (scenario.content) { + function xpathPrepare(xpath, searchString) { + return xpath.replace("$u", searchString.toUpperCase()) + .replace("$l", searchString.toLowerCase()) + .replace("$s", searchString.toLowerCase()); + } + + const ancestor = `*[@data-test="${scenario.section}"]` + + const [elementHandle] = await page.$x(`//${ancestor}//${xpathPrepare("*[text()[contains(translate(., '$u', '$l'), '$s')]]", scenario.content)}`); + if (!elementHandle) { + throw new Error('Element not found with text "' + scenario.content + '"'); + } + const selector = await page.evaluate((element, text) => { + const closest = element.closest('a, button, label, select'); + if (!closest) { + return null; + } + closest.dataset.testText = text + return closest.tagName + '[data-test-text="' + text + '"]' + (closest.classList.length ? '.' + Array.from(closest.classList).join('.') : '') + }, elementHandle, scenario.content) + if (!selector) { + throw new Error('Selector not found for text "' + scenario.content + '"'); + } + + // const parentSelector = await page.evaluate((element) => { + // const closest = element.closest('a, button, label, select'); + // let parent = closest.parentElement || document.body; + // while (parent.clientWidth < (closest.clientWidth + 10) || parent.clientHeight < (closest.clientHeight + 10)) { + // parent = parent.parentElement + // } + // parent.dataset.testText = 'parent' + // return parent.tagName + '[data-test-text="parent"]' + '.' + Array.from(parent.classList).join('.') + // }, elementHandle) + scenario.selectors = [`[data-test="${scenario.section}"] ${selector}`] + + // scenario.scrollToSelector = selector + console.log({ selector }) + + if (scenario.hoverSelectors || scenario.hoverSelector) { + scenario.hoverSelectors = [selector] + } + if (scenario.activeSelectors || scenario.activeSelector) { + scenario.activeSelectors = [selector] + } + if (scenario.focusSelectors || scenario.focusSelector) { + scenario.focusSelectors = [selector] + } + if (scenario.disableSelectors || scenario.disableSelector) { + scenario.disableSelectors = [selector] + } + } + await require('./clickAndHoverHelper')(page, scenario); +}; diff --git a/engine_scripts/interceptImages.js b/engine_scripts/interceptImages.js new file mode 100644 index 00000000..2b02be91 --- /dev/null +++ b/engine_scripts/interceptImages.js @@ -0,0 +1,37 @@ +/** + * INTERCEPT IMAGES + * Listen to all requests. If a request matches IMAGE_URL_RE + * then stub the image with data from IMAGE_STUB_URL + * + * Use this in an onBefore script E.G. + ``` + module.exports = async function(page, scenario) { + require('./interceptImages')(page, scenario); + } + ``` + * + */ + +const fs = require('fs'); +const path = require('path'); + +const IMAGE_URL_RE = /\.gif|\.jpg|\.png/i; +const IMAGE_STUB_URL = path.resolve(__dirname, '../imageStub.jpg'); +const IMAGE_DATA_BUFFER = fs.readFileSync(IMAGE_STUB_URL); +const HEADERS_STUB = {}; + +module.exports = async function (page, scenario) { + const intercept = async (request, targetUrl) => { + if (IMAGE_URL_RE.test(request.url())) { + await request.respond({ + body: IMAGE_DATA_BUFFER, + headers: HEADERS_STUB, + status: 200 + }); + } else { + request.continue(); + } + }; + await page.setRequestInterception(true); + page.on('request', intercept); +}; diff --git a/engine_scripts/jsDisable.js b/engine_scripts/jsDisable.js new file mode 100644 index 00000000..4820f42f --- /dev/null +++ b/engine_scripts/jsDisable.js @@ -0,0 +1,10 @@ +module.exports = async (page, scenario, vp) => { + await page.setRequestInterception(true) + //check resourceType is script + page.on('request', request => { + if (request.resourceType() === 'script') + request.abort(); + else + request.continue(); + }) +}; diff --git a/engine_scripts/markup-interaction-active.js b/engine_scripts/markup-interaction-active.js new file mode 100644 index 00000000..dfb5fb42 --- /dev/null +++ b/engine_scripts/markup-interaction-active.js @@ -0,0 +1,134 @@ +module.exports = async (page, { section = 'body' }, vp) => { + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + const interactiveElsSelector = `${section} :is(a, button, label, input[type='radio'], input[type='checkbox'])`; + const content = ` + const preventer = (e) => e.preventDefault(); + const els = document.querySelectorAll("${interactiveElsSelector}"); + const mouseEvts = ["mouseup", "mousedown", "click"]; + + els.forEach((el) => { + mouseEvts.forEach((me) => el.addEventListener(me, preventer)); + }); + `; + await page.addScriptTag({ content }); + + // 1. Получаем список интерактивных элементов: a, button, input[radio, checkbox] + const elts = await page.$$(interactiveElsSelector); + + const eq = (l, r) => { + if (l === null && r === null) { + return true; + } + if (l === null || r === null) { + return false; + } + + return l.x === r.x && l.y === r.y && l.width === r.width && l.height === r.height; + }; + const diff = (l, r) => { + if (l === null && r === null) { + return true; + } + if (l === null || r === null) { + return false; + } + return { + x: l.x - r.x, + y: l.y - r.y, + width: l.width - r.width, + height: l.height - r.height + } + } + const results = []; + for await (const el of elts) { + const isVisibleHandle = await page.evaluateHandle((e) => { + const style = window.getComputedStyle(e); + return (style && style.display !== 'none' && + style.visibility !== 'hidden' && style.opacity !== '0' && !e.classList.contains('visually-hidden')); + }, el); + const visible = await isVisibleHandle.jsonValue(); + const box = await el.boxModel(); + if (!visible || !box) { + continue; + } + + await el.evaluate((element) => { + element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'}); + }) + const bb = await el.boundingBox(); + if (bb.width === 0 || bb.height === 0) { + // await el.evaluate((h) => h.style.visibility = 'visible'); + continue; + } + + // JSHandle следующего элемента + const nh = await el.evaluateHandle((e) => e.nextElementSibling || e.parentElement, el); + // ElementHandle + const ne = nh.asElement(); + const nb = ne ? await ne.boundingBox() : null; + const code = await el.evaluate((h) => h.outerHTML); + if (!nb) { + console.log("no next element", code); + } + + // эмулируем page.mouse.move(координаты элемента), + // el.hover() тоже подойдёт + await el.hover(); + + const bbHover = await el.boundingBox(); + const nbHover = ne ? await ne.boundingBox() : null; + + // затем page.mouse.down() + await page.mouse.down(); + + const bbActive = await el.boundingBox(); + const nbActive = ne ? await ne.boundingBox() : null; + + // чтобы можно было кликнуть следующий элемент, поднимаем палец с кнопки + await page.mouse.up(); + + // 3. После каждой эмуляции + // 3.1. Смотрим размеры и позицию самого элемента + // 3.2. Смотрим размеры и позицию следующего элемента (надеюсь, этого хватит) + // Если размеры какого-то элемента меняются, репортим + if (!eq(bbActive, bbHover)) { + results.push({ + code, + diff: diff(bbActive, bbHover), + title: "В состоянии «:hover» позиция/размеры меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } else if (!eq(nbActive, nbHover)) { + results.push({ + code, + diff: diff(nbActive, nbHover), + title: "В состоянии «:hover» позиция/размеры следующего элемента меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } else if (!eq(bb, bbActive)) { + results.push({ + code, + diff: diff(bb, bbActive), + title: "В состоянии «:active» позиция/размеры меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } else if (!eq(nb, nbActive)) { + results.push({ + code, + diff: diff(nb, nbActive), + title: "В состоянии «:active» позиция/размеры следующего элемента меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } + + nh.dispose(); + } + if (results.length) { + // throw new Error(results.map((r) => r.title + '\n' + r.code + '\n' + JSON.stringify(r.diff)).join('\n')); + } +} diff --git a/engine_scripts/markup-interaction-hover.js b/engine_scripts/markup-interaction-hover.js new file mode 100644 index 00000000..900b40cc --- /dev/null +++ b/engine_scripts/markup-interaction-hover.js @@ -0,0 +1,136 @@ +module.exports = async (page, { section = 'body' }, scenario) => { + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + const interactiveElsSelector = `${section} :is(a, button, label, input[type='radio'], input[type='checkbox'])`; + const content = ` + const preventer = (e) => e.preventDefault(); + const els = document.querySelectorAll("${interactiveElsSelector}"); + const mouseEvts = ["mouseup", "mousedown", "click"]; + + els.forEach((el) => { + mouseEvts.forEach((me) => el.addEventListener(me, preventer)); + }); + `; + + await page.addScriptTag({ content }); + + // 1. Получаем список интерактивных элементов: a, button, input[radio, checkbox] + const elts = await page.$$(interactiveElsSelector); + + const eq = (l, r) => { + if (l === null && r === null) { + return true; + } + if (l === null || r === null) { + return false; + } + + return l.x === r.x && l.y === r.y && l.width === r.width && l.height === r.height; + }; + const diff = (l, r) => { + if (l === null && r === null) { + return true; + } + if (l === null || r === null) { + return false; + } + return { + x: l.x - r.x, + y: l.y - r.y, + width: l.width - r.width, + height: l.height - r.height + } + } + const results = []; + for await (const el of elts) { + const isVisibleHandle = await page.evaluateHandle((e) => { + const style = window.getComputedStyle(e); + return (style && style.display !== 'none' && + style.visibility !== 'hidden' && style.opacity !== '0' && !e.classList.contains('visually-hidden')); + }, el); + const visible = await isVisibleHandle.jsonValue(); + const box = await el.boxModel(); + if (!visible || !box) { + continue; + } + + await el.evaluate((element) => { + element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'}); + }) + const bb = await el.boundingBox(); + if (bb.width === 0 || bb.height === 0) { + // await el.evaluate((h) => h.style.visibility = 'visible'); + continue; + } + + // JSHandle следующего элемента + const nh = await el.evaluateHandle((e) => e.nextElementSibling || e.parentElement, el); + // ElementHandle + const ne = nh.asElement(); + const nb = ne ? await ne.boundingBox() : null; + const code = await el.evaluate((h) => h.outerHTML); + if (!nb) { + console.log("no next element", code); + } + + // эмулируем page.mouse.move(координаты элемента), + // el.hover() тоже подойдёт + await el.hover(); + + const bbHover = await el.boundingBox(); + const nbHover = ne ? await ne.boundingBox() : null; + + // затем page.mouse.down() + // await page.mouse.down(); + // + // const bbActive = await el.boundingBox(); + // const nbActive = ne ? await ne.boundingBox() : null; + + // чтобы можно было кликнуть следующий элемент, поднимаем палец с кнопки + // await page.mouse.up(); + + // 3. После каждой эмуляции + // 3.1. Смотрим размеры и позицию самого элемента + // 3.2. Смотрим размеры и позицию следующего элемента (надеюсь, этого хватит) + // Если размеры какого-то элемента меняются, репортим + if (!eq(bb, bbHover)) { + results.push({ + code, + diff: diff(bb, bbHover), + title: "В состоянии «:hover» позиция/размеры меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } else if (!eq(nb, nbHover)) { + results.push({ + code, + diff: diff(nb, nbHover), + title: "В состоянии «:hover» позиция/размеры следующего элемента меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } + /*else if (!eq(bb, bbActive)) { + results.push({ + code, + diff: diff(bb, bbActive), + title: "В состоянии «:active» позиция/размеры меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + } else if (!eq(nb, nbActive)) { + results.push({ + code, + diff: diff(nb, nbActive), + title: "В состоянии «:active» позиция/размеры следующего элемента меняются" + }); + await el.evaluate((h) => h.style.visibility = 'visible'); + }*/ + + nh.dispose(); + } + if (results.length) { + // throw new Error(results.map((r) => r.title + '\n' + r.code + '\n' + JSON.stringify(r.diff)).join('\n')); + } +} diff --git a/engine_scripts/onBefore.js b/engine_scripts/onBefore.js new file mode 100644 index 00000000..c0ed9cb2 --- /dev/null +++ b/engine_scripts/onBefore.js @@ -0,0 +1,3 @@ +module.exports = async (page, scenario, vp) => { + await require('./interceptImages.cjs')(page, scenario); +}; diff --git a/engine_scripts/onReady.cjs b/engine_scripts/onReady.cjs new file mode 100644 index 00000000..0e42875e --- /dev/null +++ b/engine_scripts/onReady.cjs @@ -0,0 +1,36 @@ +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + // await page.waitForSelector('.leaflet-marker-icon'); + // await page.waitForSelector('.leaflet-tile-loaded'); + + await require('./clickAndHoverHelper.cjs')(page, scenario); + + if (scenario.content) { + const [elementHandle] = await page.$x(`//*[contains(text(), '${scenario.content}')]`); + const selector = await page.evaluate((element) => { + return element.tagName + '.' + element.className + }, elementHandle) + console.log(selector) + scenario.selectors = [selector] + } + if (scenario.showSelectors) { + await Promise.all( + scenario.showSelectors.map(async (selector) => { + await page + .evaluate((sel) => { + document.querySelectorAll(sel).forEach(s => { + s.style.visibility = 'visible'; + }); + }, selector); + }) + ); + } +}; diff --git a/engine_scripts/overrideCSS.js b/engine_scripts/overrideCSS.js new file mode 100644 index 00000000..c5f9da2f --- /dev/null +++ b/engine_scripts/overrideCSS.js @@ -0,0 +1,14 @@ +module.exports = async (page, scenario, BACKSTOP_TEST_CSS_OVERRIDE = 'html {background-image: none;}') => { + // inject arbitrary css to override styles + await page.evaluate(`window._styleData = '${BACKSTOP_TEST_CSS_OVERRIDE.replace(/\n/g, '')}';`); + + await page.evaluate(() => { + const style = document.createElement('style'); + style.type = 'text/css'; + const styleNode = document.createTextNode(window._styleData); + style.appendChild(styleNode); + document.head.appendChild(style); + }); + + console.log('BACKSTOP_TEST_CSS_OVERRIDE injected for: ' + scenario.label); +}; diff --git a/engine_scripts/textDecrease.js b/engine_scripts/textDecrease.js new file mode 100644 index 00000000..693b0cf7 --- /dev/null +++ b/engine_scripts/textDecrease.js @@ -0,0 +1,94 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(""); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyTextAmount, defaultTextDecreaseMultiplier, defaultTextSelectors) + +}; diff --git a/engine_scripts/textIncrease.js b/engine_scripts/textIncrease.js new file mode 100644 index 00000000..42b4368e --- /dev/null +++ b/engine_scripts/textIncrease.js @@ -0,0 +1,95 @@ +const modifyTextAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))].flatMap((el) => [...el.childNodes]); + for (const $el of $els) { + if ($el.nodeType !== $el.TEXT_NODE) continue; + if (!$el.textContent) continue; + + const text = $el.textContent.trim(); + if (!text) continue; + + // Умножим строку на меньшее целое число множителя + const intCnt = Math.floor(multiplier); + $el.textContent = Array.from({ length: intCnt }) + .map(() => text) + .join(", "); + + // Добавим остаток строки из множителя + const tailMultiplier = multiplier % 1; + $el.textContent += text.slice(0, Math.floor(text.length * tailMultiplier)); + } +}; + +const modifyChildrenAmount = (multiplier, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + const getRandomIntBetween = (min, max, seed = 0.5) => { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(seed * (max - min + 1) + min); + }; + for (const $el of $els) { + if ($el.nodeType !== $el.ELEMENT_NODE) { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным nodeType равным ${$el.nodeType}` + ); + } + if ($el.childElementCount < 2) continue; + const newLength = Math.ceil($el.childElementCount * multiplier); + + if (newLength === $el.childElementCount) continue; + while ($el.childElementCount !== newLength) { + const idx = getRandomIntBetween(0, $el.childElementCount - 1); + const $child = $el.children[idx]; + if (newLength < $el.childElementCount) { + $el.removeChild($child); + } else if (newLength > $el.childElementCount) { + $el.appendChild($child.cloneNode(true)); + } + } + } +}; + +const modifyImages = (isBig, selectors) => { + const $els = [...document.querySelectorAll(selectors.join(","))]; + for (const $el of $els) { + if ($el.tagName !== "IMG") { + throw new Error( + `По одному из селекторов «${selectors.join("», «")}» найден элемент с неверным tagName равным ${ + $el.tagName + }, должен быть IMG` + ); + } + // 1500x1500 + const largeImgSrc = + "data:image/png;base64,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"; + // 15x15 + const smallImgSrc = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAG1BMVEXMzMyWlpaqqqq3t7ejo6OcnJyxsbG+vr7FxcXPXVcRAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAN0lEQVQImWNgIAswKTMwcAQoGTAwAznMAgYMDCxhbOYMAq4JDOyFHA4MAuUCDGxqIJGkBGLMAwAMYQT0Tdpz9wAAAABJRU5ErkJggg=="; + + $el.src = isBig ? largeImgSrc : smallImgSrc; + $el.width = isBig ? 1500 : 15; + } +}; + +const defaultTextIncreaseMultiplier = 2.1; +const defaultTextDecreaseMultiplier = 0.4; + +const defaultChildrenIncreaseMultiplier = 1.5; +const defaultChildrenDecreaseMultiplier = 0.5; + +const defaultTextSelectors = ["a", "button", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "label", "legend", "li"]; +const defaultChildrenSelectors = ["section", "article", "ul", "ol", "dl"]; +const defaultImgSelectors = ["img"]; + +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + + await page.evaluate(modifyTextAmount, defaultTextIncreaseMultiplier, defaultTextSelectors) + +}; diff --git a/engine_scripts/textStylesOnly.js b/engine_scripts/textStylesOnly.js new file mode 100644 index 00000000..0da3e432 --- /dev/null +++ b/engine_scripts/textStylesOnly.js @@ -0,0 +1,59 @@ +module.exports = async (page, scenario, vp) => { + console.log('SCENARIO > ' + scenario.label); + + const BACKSTOP_TEST_CSS_OVERRIDE = ` + *:where(:not(.visually-hidden, :root, head, script)) { + background-image: unset !important; + transform: unset !important; + margin: unset !important; + padding: unset !important; + border: unset !important; + border-radius: unset !important; + width: auto !important; + max-width: unset !important; + height: auto !important; + min-height: unset !important; + min-width: unset !important; + text-align: unset !important; + display: inline-block !important; + position: static !important; + } + img, svg, *::before, *::after { + display: none !important; + } + `; + + await require('./overrideCSS')(page, scenario, BACKSTOP_TEST_CSS_OVERRIDE); + + // add more ready handlers here... + await page.waitForFunction(() => { + return document.fonts.ready.then(() => { + console.log('Fonts loaded'); + return true; + }); + }); + await page.evaluate(() => { + document.querySelectorAll('br').forEach(s => { + s.remove(); + }) + }); + if (scenario.content) { + function xpathPrepare(xpath, searchString) { + return xpath.replace("$u", searchString.toUpperCase()) + .replace("$l", searchString.toLowerCase()) + .replace("$s", searchString.toLowerCase()); + } + const selectors = [] + for (const text of [].concat(scenario.content)) { + const [elementHandle] = await page.$x(`//${xpathPrepare("*[text()[contains(translate(., '$u', '$l'), '$s')]]", text)}`); + if (!elementHandle) { + throw new Error('Element not found with text "' + text + '"'); + } + await page.evaluate((element, text) => { + element.dataset.testText = `${text}` + }, elementHandle, text) + selectors.push(`[data-test-text="${text}"]`) + } + scenario.selectors = selectors + } +}; diff --git a/run-test.js b/run-test.js index 369d258e..d810ae2c 100644 --- a/run-test.js +++ b/run-test.js @@ -1,56 +1,54 @@ -const fs = require('node:fs/promises'); -const backstop = require('htmlacademy-backstopjs'); -const fontsConfig = require('./test-config/backstop-test-05.config'); -const ppConfig = require('./test-config/backstop-test-06.config'); -const styleguideConfig = require('./test-config/backstop-test-07.config'); -const interactionConfig = require('./test-config/backstop-test-08.config'); +import fs from 'node:fs/promises'; +import backstop from 'htmlacademy-backstopjs'; +import fontsConfig from './test-config/backstop-test-05.config.js'; +import ppConfig from './test-config/backstop-test-06.config.js'; +import styleguideConfig from './test-config/backstop-test-07.config.js'; +import interactionConfig from './test-config/backstop-test-08.config.js'; -(async () => { - let passedSelectors - try { - await backstop('test', { config: ppConfig }); - console.log('All blocks passed') - } catch (e) { - console.log('mismatch blocks detected') - } finally { - const reportFile = await fs.readFile('./backstop_data/json_report/jsonReport.json', 'utf8') - const report = JSON.parse(reportFile) - const passed = report.tests - .filter(({ status }) => status === 'pass') - .map(({ - pair: { - viewportLabel, - selector, - }, - }) => ({ selector, viewportLabel })) - .reduce((acc, { viewportLabel, selector }) => { - acc[selector] = acc[selector]?.add(viewportLabel) ?? new Set([viewportLabel]); - return acc; - }, {}) - passedSelectors = Object.entries(passed) - .filter(([, set]) => set.size === 3) - .map(([selector]) => { - let pattern = /data-test="(\w+)"/; - let match = selector.match(pattern); - return (match[1]); - }).join('|') || 'nothing good found' - } - const config05 = { - ...fontsConfig, - scenarios: fontsConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), - } - await fs.writeFile('./test-config/backstop-test-05.config.json', JSON.stringify(config05, null, 2), 'utf8') +let passedSelectors +try { + await backstop('test', { config: ppConfig }); + console.log('All blocks passed') +} catch (e) { + console.log('mismatch blocks detected') +} finally { + const reportFile = await fs.readFile('./backstop_data/json_report/jsonReport.json', 'utf8') + const report = JSON.parse(reportFile) + const passed = report.tests + .filter(({ status }) => status === 'pass') + .map(({ + pair: { + viewportLabel, + selector, + }, + }) => ({ selector, viewportLabel })) + .reduce((acc, { viewportLabel, selector }) => { + acc[selector] = acc[selector]?.add(viewportLabel) ?? new Set([viewportLabel]); + return acc; + }, {}) + passedSelectors = Object.entries(passed) + .filter(([, set]) => set.size === 3) + .map(([selector]) => { + let pattern = /data-test="(\w+)"/; + let match = selector.match(pattern); + return (match[1]); + }).join('|') || 'nothing good found' +} +const config05 = { + ...fontsConfig, + scenarios: fontsConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), +} +await fs.writeFile('./test-config/backstop-test-05.config.json', JSON.stringify(config05, null, 2), 'utf8') - const config08 = { - ...interactionConfig, - scenarios: interactionConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), - } - await fs.writeFile('./test-config/backstop-test-08.config.json', JSON.stringify(config08, null, 2), 'utf8') +const config08 = { + ...interactionConfig, + scenarios: interactionConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), +} +await fs.writeFile('./test-config/backstop-test-08.config.json', JSON.stringify(config08, null, 2), 'utf8') - const config07 = { - ...styleguideConfig, - scenarios: styleguideConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), - } - await fs.writeFile('./test-config/backstop-test-07.config.json', JSON.stringify(config07, null, 2), 'utf8') +const config07 = { + ...styleguideConfig, + scenarios: styleguideConfig.scenarios.filter(({ label }) => !!label.match(passedSelectors)), +} +await fs.writeFile('./test-config/backstop-test-07.config.json', JSON.stringify(config07, null, 2), 'utf8') -})() diff --git a/test-config/backstop-html-03.config.js b/test-config/backstop-html-03.config.js index e5393a7c..3efc9c35 100644 --- a/test-config/backstop-html-03.config.js +++ b/test-config/backstop-html-03.config.js @@ -1,4 +1,4 @@ -module.exports = { +export default { "id": "drink2go html-03", "viewports": [ { diff --git a/test-config/backstop-html-04.config.js b/test-config/backstop-html-04.config.js index 74e07c30..7e9f3a18 100644 --- a/test-config/backstop-html-04.config.js +++ b/test-config/backstop-html-04.config.js @@ -3,7 +3,7 @@ * todo прокликать контролы формы * */ -module.exports = { +export default { "id": "drink2go form", "viewports": [ { diff --git a/test-config/backstop-img-01.config.js b/test-config/backstop-img-01.config.js index baaade30..06281bf6 100644 --- a/test-config/backstop-img-01.config.js +++ b/test-config/backstop-img-01.config.js @@ -1,4 +1,4 @@ -module.exports = { +export default { "id": "drink2go img", "viewports": [ { diff --git a/test-config/backstop-test-03.config.js b/test-config/backstop-test-03.config.js index c95d4d41..0ea95ea6 100644 --- a/test-config/backstop-test-03.config.js +++ b/test-config/backstop-test-03.config.js @@ -18,7 +18,7 @@ */ -module.exports = { +export default { "id": "drink2go test-03", "viewports": [ { diff --git a/test-config/backstop-test-04.config.js b/test-config/backstop-test-04.config.js index f6c98b94..ba6cb0eb 100644 --- a/test-config/backstop-test-04.config.js +++ b/test-config/backstop-test-04.config.js @@ -19,7 +19,7 @@ */ const indexSections = ['header', 'main', 'hero', 'features', 'catalog', 'map', 'footer']; -module.exports = { +export default { "id": "drink2go test-04", "viewports": [ { diff --git a/test-config/backstop-test-05.config.js b/test-config/backstop-test-05.config.js index 761621fc..5d10ac51 100644 --- a/test-config/backstop-test-05.config.js +++ b/test-config/backstop-test-05.config.js @@ -17,7 +17,7 @@ const indexSections = [ { section: 'catalog', content: ['Каталог кофейных напитков', 'Цена', 'Наличие молока', 'Неважно', 'Страна произрастания', 'Бразилия', 'Эфиопия', 'Перу', 'Применить', 'Сбросить', 'Сортировка', 'Кофе без кофеина из Эфиопии', 'В корзину'] }, { section: 'footer', content: ['Способы оплаты', 'Медиа', 'Санкт-Петербург', 'Разработано', 'HTML Academy'] } ]; -module.exports = { +export default { "id": "drink2go test-05", "viewports": [ { diff --git a/test-config/backstop-test-06.config.js b/test-config/backstop-test-06.config.js index 5e765ae5..3212f13e 100644 --- a/test-config/backstop-test-06.config.js +++ b/test-config/backstop-test-06.config.js @@ -7,7 +7,7 @@ const indexSections = [ { section: 'footer', misMatchThreshold: 3 } ]; -module.exports = { +export default { "id": "drink2go test-06", "viewports": [ { @@ -26,7 +26,7 @@ module.exports = { "height": 800, }, ], - "onReadyScript": "onReady.js", + "onReadyScript": "onReady.cjs", "resembleOutputOptions": { "ignoreAntialiasing": true, "errorType": "movementDifferenceIntensity", diff --git a/test-config/backstop-test-07.config.js b/test-config/backstop-test-07.config.js index 62131551..7506959a 100644 --- a/test-config/backstop-test-07.config.js +++ b/test-config/backstop-test-07.config.js @@ -20,7 +20,7 @@ const indexSections = [ ] } ].flatMap(item => item.content.map(content => ({ ...item, content }))); -module.exports = { +export default { "id": "drink2go test-07", "viewports": [ { diff --git a/test-config/backstop-test-08.config.js b/test-config/backstop-test-08.config.js index 0823c455..92497999 100644 --- a/test-config/backstop-test-08.config.js +++ b/test-config/backstop-test-08.config.js @@ -11,7 +11,7 @@ const indexSections = [ { section: 'footer' } ]; -module.exports = { +export default { "id": "drink2go test-08", "viewports": [{ "label": "desktop", diff --git a/test-config/backstop-test-ff.config.js b/test-config/backstop-test-ff.config.js index d93b047d..959bbb7d 100644 --- a/test-config/backstop-test-ff.config.js +++ b/test-config/backstop-test-ff.config.js @@ -1,6 +1,6 @@ const indexSections = ['header', 'main', 'hero', 'features', 'catalog', 'map', 'footer']; -module.exports = { +export default { "id": "drink2go FF", "viewports": [ { diff --git a/test-config/backstop-test-logo.config.js b/test-config/backstop-test-logo.config.js index d64188f8..1b03279f 100644 --- a/test-config/backstop-test-logo.config.js +++ b/test-config/backstop-test-logo.config.js @@ -1,5 +1,5 @@ -module.exports = { +export default { "id": "drink2go Logo", "viewports": [ { diff --git a/test-config/backstop-test-menu.config.js b/test-config/backstop-test-menu.config.js index 6c61111e..fbbe473a 100644 --- a/test-config/backstop-test-menu.config.js +++ b/test-config/backstop-test-menu.config.js @@ -1,4 +1,4 @@ -module.exports = { +export default { "id": "drink2go menu", "viewports": [ { diff --git a/test-config/backstop-test-swiper.config.js b/test-config/backstop-test-swiper.config.js index 16b89fee..d1bf4b3d 100644 --- a/test-config/backstop-test-swiper.config.js +++ b/test-config/backstop-test-swiper.config.js @@ -1,4 +1,4 @@ -module.exports = { +export default { "id": "drink2go swiper", "viewports": [ {