@progress/kendo-e2e
Version:
Kendo UI end-to-end test utilities.
269 lines • 15.9 kB
JavaScript
;
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