From 26dbef434510d47fc9bf2662ebaacaa2a3d21b4f Mon Sep 17 00:00:00 2001 From: Martin Forstner Date: Wed, 25 Aug 2021 18:21:11 +0200 Subject: [PATCH] feat: add possibility to close cookie consents (or other popus); fix: some bugfixes for scroll elements in view --- README.md | 3 +- lib/models/config.ts | 2 + lib/utils/analyze-url.ts | 4 ++ .../make-sreenshots-with-errors-borderd.ts | 38 +++++++++++------ lib/utils/mark-all-tabable-items.ts | 22 +++++----- lib/utils/save-results-to-file.ts | 41 +++---------------- lib/utils/setup-config.ts | 6 +++ 7 files changed, 57 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 85b5ae4..eb8ec8e 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,8 @@ export interface Config { runOnly: RunOnly | TagValue[] | string[]; crawl: boolean; name: string; - + cookieSelector?: string; // provide a selector for clicking cookie consent button (example: "[id*=cookie] a, [class*=cookie] a, [id*=cookie] button, [class*=cookie] button, [id*=didomi] button") + cookieText?: string; //provides a text for cookie consent text (example: "^(Alle akzeptieren|Akzeptieren|Verstanden|Zustimmen|Okay|OK|Alle Cookies akzeptieren)$") } ``` diff --git a/lib/models/config.ts b/lib/models/config.ts index 121a31d..f907661 100644 --- a/lib/models/config.ts +++ b/lib/models/config.ts @@ -24,6 +24,8 @@ export interface Config { runOnly: RunOnly | TagValue[] | string[]; crawl: boolean; name: string; + cookieText?: string; + cookieSelector?: string; } interface AxeConfig { diff --git a/lib/utils/analyze-url.ts b/lib/utils/analyze-url.ts index fcbeead..6253933 100644 --- a/lib/utils/analyze-url.ts +++ b/lib/utils/analyze-url.ts @@ -7,6 +7,7 @@ import { Page } from 'puppeteer'; import { ResultByUrl } from '../models/a11y-sitechecker-result'; import { makeScreenshotsWithErrorsBorderd } from './make-sreenshots-with-errors-borderd'; import { createUrlResult } from './create-url-result'; +import { acceptCookieConsent } from './accept-cookies'; const savedScreenshotHtmls: string[] = []; @@ -19,6 +20,9 @@ export async function analyzeUrl( ): Promise { if ((await page.url()) !== url) { await page.goto(url, { waitUntil: 'load' }); + if(config.cookieText && config.cookieSelector) { + await acceptCookieConsent(page, config); + } await waitForHTML(page, config.timeout, config.debugMode); } else { debug(config.debugMode, 'URL already open.' + url); diff --git a/lib/utils/make-sreenshots-with-errors-borderd.ts b/lib/utils/make-sreenshots-with-errors-borderd.ts index 12dbf86..fc57fc9 100644 --- a/lib/utils/make-sreenshots-with-errors-borderd.ts +++ b/lib/utils/make-sreenshots-with-errors-borderd.ts @@ -4,12 +4,18 @@ import { Config } from '../models/config'; import { debug, saveScreenshot } from './helper-functions'; import { v4 as uuidv4 } from 'uuid'; +const uniqueNamePerUrl: Map = new Map(); + export async function makeScreenshotsWithErrorsBorderd( resultByUrl: ResultByUrl, page: Page, config: Config, savedScreenshotHtmls: string[], ): Promise { + if(!uniqueNamePerUrl.get(resultByUrl.url)) { + uniqueNamePerUrl.set(resultByUrl.url, {id: uuidv4(), count: 0}); + } + const currentMapObject = uniqueNamePerUrl.get(resultByUrl.url)!; debug(config.debugMode, 'make screenshots with border'); page.on('console', (log) => { debug(config.debugMode, log.text()); @@ -20,19 +26,19 @@ export async function makeScreenshotsWithErrorsBorderd( debug( config.debugMode, e.message + - '. Ignored because normally it means that Function already there. (Adding debug to winwo in expose object)', + '. Ignored because normally it means that the function is already exposed. (Adding debug to window in expose object)', ); } for (const result of resultByUrl.violations) { for (const node of result.nodes) { if (!savedScreenshotHtmls.includes(node.html)) { - debug(config.debugMode, 'Adding border to: ' + JSON.stringify(node.target[0])); - await page.evaluate( + debug(config.debugMode, '(Count:' + currentMapObject.count + ')Adding border to: ' + JSON.stringify(node.target[0])); + const isVisible = await page.evaluate( async (elementSelector, debugMode) => { const dom: Element = document.querySelector(elementSelector); + let elementVisible = false; if (dom) { let currentDom = dom; - let elementVisible = false; let k = 0; const tolerance = 0.01; const percentX = 90; @@ -43,10 +49,9 @@ export async function makeScreenshotsWithErrorsBorderd( const elementRect = currentDom.getBoundingClientRect(); const parentRects: DOMRect[] = []; - while (currentDom.parentElement != null) { parentRects.push(currentDom.parentElement.getBoundingClientRect()); - currentDom = currentDom.parentElement; + currentDom = currentDom.parentElement; } elementVisible = parentRects.every(function (parentRect) { @@ -61,10 +66,12 @@ export async function makeScreenshotsWithErrorsBorderd( return ( visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY - ); + ) && elementRect.top < window.innerHeight && elementRect.bottom >= 0; }); - - if (!elementVisible) dom.scrollIntoView(); + if (!elementVisible) { + dom.scrollIntoView(); + currentDom = dom; + } k++; } if (dom.tagName === 'A') { @@ -89,13 +96,20 @@ export async function makeScreenshotsWithErrorsBorderd( } else { window.debug(debugMode, 'No element found with selector ' + elementSelector); } + return elementVisible; }, node.target[0], config.debugMode, ); - const image = uuidv4() + '.png'; - await saveScreenshot(page, config.imagesPath, image, config.saveImages); - node.image = image; + if(isVisible) { + const image = currentMapObject.id + '_' + currentMapObject.count + '.png'; + await saveScreenshot(page, config.imagesPath, image, config.saveImages); + node.image = image; + currentMapObject.count++; + } else { + debug(config.debugMode, JSON.stringify(node.target[0]) + ' is not visible anytime'); + } + await page.evaluate((element) => { const dom = document.querySelector(element); if (dom) { diff --git a/lib/utils/mark-all-tabable-items.ts b/lib/utils/mark-all-tabable-items.ts index c5b19df..9eefb0e 100644 --- a/lib/utils/mark-all-tabable-items.ts +++ b/lib/utils/mark-all-tabable-items.ts @@ -68,8 +68,8 @@ export async function markAllTabableItems( }; const isElementVisible = async (element): Promise => { const tolerance = 0.01; - const percentX = 70; - const percentY = 70; + const percentX = 90; + const percentY = 90; let currentDom = element; const elementRect = currentDom.getBoundingClientRect(); @@ -169,19 +169,20 @@ export async function markAllTabableItems( } } tabbingNumber++; + elementsFromEvaluationParsed.elementsByVisibility.push({ + element: element.id, + visible: elementVisible, + }); } if (elementVisible && !firstVisibleElement) { firstVisibleElement = true; } - elementsFromEvaluationParsed.elementsByVisibility.push({ - element: element.id, - visible: elementVisible, - }); - await window.debug( + + window.debug( debugMode, - element.tagName + ' is visible: ' + elementVisible + 'and got number' + i, + element.tagName + ' is visible: ' + elementVisible + ' and got number ' + i, ); } i++; @@ -192,6 +193,7 @@ export async function markAllTabableItems( let firstVisibleElement = false; let i = 0; let tabbingNumber = elementsFromEvaluationParsed.currentIndex; + console.log('yessinger: ' + tabbingNumber) for (const elementSelector of elementsFromEvaluationParsed.elementsByVisibility) { const element = document.getElementById(elementSelector.element); if (element) { @@ -205,13 +207,11 @@ export async function markAllTabableItems( if (!elementVisible) element.scrollIntoView(); k++; - console.log('step: ' + k); } - console.log('elementSelector' + elementSelector + 'visibility' + elementVisible); + console.log('elementSelector: ' + JSON.stringify(elementSelector) + ', visibility ' + elementVisible); if (elementVisible && !firstVisibleElement) { firstVisibleElement = true; - console.log('i am here elementnumer:' + tabbingNumber); const oldElementsToRemove = Array.from(document.querySelectorAll('[id^=span_id]')); for (const oldElement of oldElementsToRemove) { oldElement.remove(); diff --git a/lib/utils/save-results-to-file.ts b/lib/utils/save-results-to-file.ts index 2a12799..8ba367d 100644 --- a/lib/utils/save-results-to-file.ts +++ b/lib/utils/save-results-to-file.ts @@ -75,44 +75,15 @@ export async function saveResultsToFile(config: Config, sitecheckerResult: A11yS defineExtraTags(sitecheckerResult, config); fs.writeFileSync(fileToSave, JSON.stringify(siteResult, null, 4)); fs.writeFileSync(config.resultsPath + 'files.json', JSON.stringify(fileObject, null, 4)); + const basePath = config.resultsPathPerUrl + getEscaped(id) + '_' + sitecheckerResult.testEnvironment?.windowWidth + '_' + sitecheckerResult.testEnvironment?.windowHeight; - const violationsPath = - config.resultsPathPerUrl + - getEscaped(id) + - '_' + - sitecheckerResult.testEnvironment?.windowWidth + - '_' + - sitecheckerResult.testEnvironment?.windowHeight + - '_violations.json'; - fs.writeFileSync(violationsPath, JSON.stringify(sitecheckerResult.violations, null, 4)); + const violationsPath = basePath + '_violations.json'; + const incompletesPath = basePath + '_incompletes.json'; + const passesPath = basePath + '_passes.json'; + const inapplicablesPath = basePath + '_inapplicables.json'; - const incompletesPath = - config.resultsPathPerUrl + - getEscaped(id) + - '_' + - sitecheckerResult.testEnvironment?.windowWidth + - '_' + - sitecheckerResult.testEnvironment?.windowHeight + - '_incompletes.json'; + fs.writeFileSync(violationsPath, JSON.stringify(sitecheckerResult.violations, null, 4)); fs.writeFileSync(incompletesPath, JSON.stringify(sitecheckerResult.incomplete, null, 4)); - - const passesPath = - config.resultsPathPerUrl + - getEscaped(id) + - '_' + - sitecheckerResult.testEnvironment?.windowWidth + - '_' + - sitecheckerResult.testEnvironment?.windowHeight + - '_passes.json'; fs.writeFileSync(passesPath, JSON.stringify(sitecheckerResult.passes, null, 4)); - - const inapplicablesPath = - config.resultsPathPerUrl + - getEscaped(id) + - '_' + - sitecheckerResult.testEnvironment?.windowWidth + - '_' + - sitecheckerResult.testEnvironment?.windowHeight + - '_inapplicables.json'; fs.writeFileSync(inapplicablesPath, JSON.stringify(sitecheckerResult.inapplicable, null, 4)); } diff --git a/lib/utils/setup-config.ts b/lib/utils/setup-config.ts index d3ffaaf..95a4131 100644 --- a/lib/utils/setup-config.ts +++ b/lib/utils/setup-config.ts @@ -101,6 +101,12 @@ export function setupConfig(options: OptionValues): Config { if (configFile.clickableItemSelector) { config.clickableItemSelector = configFile.clickableItemSelector; } + if (configFile.cookieSelector) { + config.cookieSelector = configFile.cookieSelector; + } + if (configFile.cookieText) { + config.cookieText = configFile.cookieText; + } if (configFile.crawl) { if(config.urlsToAnalyze?.length === 1 && configFile.crawl) { config.crawl = true;