UNPKG

@progress/kendo-e2e

Version:

Kendo UI end-to-end test utilities.

269 lines 15.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWCTSpecViolations = getWCTSpecViolations; /* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ const selenium_webdriver_1 = require("selenium-webdriver"); /** * Check current page for violations against WCT A11y Spec. * * @example * await getWCTSpecViolations(browser, spec, ['k-multiselect-autocomplete']}); * * @param driver WebDriver instance * @param spec A spec object (like https://unpkg.com/@progress/wct-a11y-spec@1.0.3/dist/jquery/test-def/test-definitions.json). * @param excludeErrors Array of validation IDs that will be skipped. * @param componentsToTest Array of validation components that need to be tested. * @param excludeSelectors Array of validation CSS selectors that will be skipped. */ function getWCTSpecViolations(driver_1, spec_1) { return __awaiter(this, arguments, void 0, function* (driver, spec, excludeErrors = [], componentsToTest = [], excludeSelectors = []) { const passed = []; const skipped = []; const errors = []; const notFoundSelectors = []; const result = { passed, skipped, errors, notFoundSelectors }; const RULES = 'rules'; const SELECTOR = 'selector'; const CHECKS = 'checks'; const ID = 'id'; const WHEN = 'when'; const ATTRIBUTE = 'attribute'; const VALUE = 'value'; const STRING = 'string'; const TABINDEX = 'tabindex'; const INPUT = 'INPUT'; const BUTTON = 'BUTTON'; const ANCHOR = 'A'; const ZERO = '0'; const COMMA = ','; const EMPTY = ' '; const ANIMATION_CONTAINER = '.k-animation-container'; const LIST = '.k-list-ul'; const LIST_ITEM = '.k-list-item'; const LIST_FILTER = '.k-list-filter'; const DISABLED = '.k-disabled'; const ELMENTS_MAP = { buttongroup: '.k-button-group', floatingactionbutton: '.k-fab', pager: '.k-pager-wrap' }; for (const key of Object.keys(spec)) { const areComponentsToTest = componentsToTest.length > 0; const requestedComponent = componentsToTest.includes(key) ? componentsToTest[componentsToTest.indexOf(key)] : undefined; const component = areComponentsToTest ? spec[requestedComponent] : spec[key]; if (component) { const rules = component[RULES]; const keySelector = ELMENTS_MAP[key] || `.k-${key}`; const testingElement = yield driver.findElements(selenium_webdriver_1.By.css(keySelector)); if (testingElement.length > 0) { for (const rule of rules) { const selector = rule[SELECTOR]; let arraySelector; const re = /\((.*)\)/; const stringBetweenBrackets = selector.match(re); const hasCommaBetweenBrackets = stringBetweenBrackets !== null && stringBetweenBrackets[1].includes(COMMA); if (selector.indexOf('px,') > -1) { arraySelector = [selector]; } else if (hasCommaBetweenBrackets) { arraySelector = [selector]; } else { arraySelector = selector.split(COMMA); } if (selector.indexOf(DISABLED) > -1) { if (selector.indexOf(keySelector) === -1) { arraySelector = arraySelector.map((s) => keySelector + s); } } else if (selector !== keySelector && selector.indexOf(ANIMATION_CONTAINER) === -1 && selector.indexOf(LIST) === -1 && selector.indexOf(LIST_ITEM) === -1 && selector.indexOf(LIST_FILTER) === -1) { arraySelector = arraySelector.map((s) => { if (s.startsWith(`${keySelector}.`) || s.startsWith(`${keySelector}:`)) { return s; } else { return keySelector + EMPTY + s; } }); } for (const sel of arraySelector) { const arraySelectorElement = yield driver.findElements(selenium_webdriver_1.By.css(sel)); if (arraySelectorElement.length > 0) { const checks = rule[CHECKS]; for (const check of checks) { const checkId = check[ID]; const conditionalCheck = check[WHEN]; const attribute = check[ATTRIBUTE]; let expectedValue = check[VALUE]; if (typeof expectedValue === STRING && expectedValue.includes(EMPTY)) { const refElementSelector = expectedValue.split(EMPTY)[0]; const refElementAttribute = expectedValue.split(EMPTY)[1]; if ((yield driver.findElements(selenium_webdriver_1.By.css(refElementSelector))).length > 0) { expectedValue = yield Promise.all((yield driver.findElements(selenium_webdriver_1.By.css(refElementSelector))).map((el) => __awaiter(this, void 0, void 0, function* () { return yield el.getAttribute(refElementAttribute); }))); } else { skipped.push(`[${checkId}]: Skip check for ${sel}, as no ${refElementSelector} was found.`); continue; } } if (conditionalCheck !== undefined) { skipped.push(`[${checkId}]: Skip check for ${sel}, conditional checks not supported.`); } else if (excludeErrors.includes(checkId)) { skipped.push(`[${checkId}]: Skip check for ${sel}, explicitly excluded.`); } else if (Array.isArray(attribute)) { const elements = yield driver.findElements(selenium_webdriver_1.By.css(sel)); for (const el of elements) { const pass = yield asyncSome(attribute, (attr) => __awaiter(this, void 0, void 0, function* () { return yield iterateAttributeArray(driver, attr, expectedValue, el); })); if (pass) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute.`); } else { errors.push(`[${checkId}]: ${sel} has no "${attribute}"`); } } } else { const elements = yield driver.findElements(selenium_webdriver_1.By.css(sel)); for (const el of elements) { let attributeValue; try { attributeValue = yield el.getAttribute(attribute); } catch (err) { attributeValue = undefined; } const elType = yield el.getTagName(); if (attributeValue === undefined) { passed.push(`[${checkId}]: ${sel} dos not have ${attribute} attribute, but that is fine, we only check if element exist.`); } else if (attribute === TABINDEX && expectedValue === ZERO) { if ((elType === INPUT || elType === BUTTON || elType === ANCHOR) && (attributeValue === ZERO || attributeValue === null)) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } else if (attributeValue === expectedValue) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } else { errors.push(`[${checkId}]: ${sel} does not have "${attribute}" attribute with "${expectedValue}" value.`); } } else if (attribute === TABINDEX && expectedValue === '-1') { if (elType !== INPUT && elType !== BUTTON && elType !== ANCHOR && attributeValue === null) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } else if (attributeValue === expectedValue) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } else { errors.push(`[${checkId}]: ${sel} does not have "${attribute}" attribute with "${expectedValue}" value.`); } } else if (Array.isArray(expectedValue)) { if (expectedValue.includes(attributeValue)) { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } else { errors.push(`[${checkId}]: ${sel} has "${attribute}" which does not contain any of "${expectedValue}".`); } } else { if (expectedValue === undefined && !attributeValue) { errors.push(`[${checkId}]: ${sel} does not have "${attribute}" attribute with value.`); } else if (attributeValue !== expectedValue && expectedValue !== undefined) { errors.push(`[${checkId}]: ${sel} does not have "${attribute}" attribute with "${expectedValue}" value.`); } else { passed.push(`[${checkId}]: ${sel} has ${attribute} attribute with ${expectedValue} value.`); } } } } } } else { if (arraySelectorElement.length === 0 && areComponentsToTest) { notFoundSelectors.push(sel); } } } } } if (testingElement.length === 0 && areComponentsToTest) { notFoundSelectors.push(keySelector); } } } for (const error of excludeErrors) { result.errors = result.errors.filter(item => !item.includes(error)); } for (const selector of excludeSelectors) { result.notFoundSelectors = result.notFoundSelectors.filter(item => !item.includes(selector)); } return result; }); } function asyncSome(arr, predicate) { return __awaiter(this, void 0, void 0, function* () { for (const e of arr) { if (yield predicate(e)) { return true; } } return false; }); } function iterateAttributeArray(driver, attr, expectedValue, el) { return __awaiter(this, void 0, void 0, function* () { const ID = 'id'; const LABEL_FOR = 'label for'; const EQUALS = '='; let attributeValue; if (attr.indexOf(EQUALS) > -1) { expectedValue = attr.split(EQUALS)[1]; attr = attr.split(EQUALS)[0]; } if (attr === LABEL_FOR) { attributeValue = yield el.getAttribute(ID); if (attributeValue) { if ((yield driver.findElements(selenium_webdriver_1.By.css(`label[for="${attributeValue}"]`))).length > 0) { return true; } } } else if (attr === 'nodeName') { attributeValue = (yield el.getTagName()).toLowerCase(); } else { attributeValue = yield el.getAttribute(attr); } if (expectedValue) { return attributeValue === expectedValue; } else { return attributeValue !== null; } }); } //# sourceMappingURL=a11y-wct-spec.js.map