@qualweb/wcag-techniques
Advanced tools
Comparing version 0.1.14 to 0.1.15
{ | ||
"name": "@qualweb/wcag-techniques", | ||
"version": "0.1.14", | ||
"version": "0.1.15", | ||
"description": "Implementation of the WCAG 2.1 techniques", | ||
@@ -5,0 +5,0 @@ "main": "dist/wcag.js", |
132
src/index.ts
@@ -1,8 +0,7 @@ | ||
import { WCAGOptions, WCAGTechniquesReport } from '@qualweb/wcag-techniques'; | ||
import { QWPage } from '@qualweb/qw-page'; | ||
import * as techniques from './lib/techniques'; | ||
import mapping from './lib/mapping'; | ||
import { WCAGOptions, WCAGTechniquesReport } from "@qualweb/wcag-techniques"; | ||
import { QWPage } from "@qualweb/qw-page"; | ||
import * as techniques from "./lib/techniques"; | ||
import mapping from "./lib/mapping"; | ||
class WCAGTechniques { | ||
private techniques: any; | ||
@@ -16,3 +15,3 @@ private techniquesToExecute: any; | ||
for (const technique of Object.keys(techniques) || []) { | ||
const _technique = technique.replace(/_/g, '-'); | ||
const _technique = technique.replace(/_/g, "-"); | ||
this.techniques[_technique] = new techniques[technique](); | ||
@@ -31,10 +30,21 @@ this.techniquesToExecute[_technique] = true; | ||
if (options.principles) { | ||
options.principles = options.principles.map(p => (p.charAt(0).toUpperCase() + p.toLowerCase().slice(1)).trim()); | ||
options.principles = options.principles.map((p) => | ||
(p.charAt(0).toUpperCase() + p.toLowerCase().slice(1)).trim() | ||
); | ||
} | ||
if (options.levels) { | ||
options.levels = options.levels.map(l => l.toUpperCase().trim()); | ||
options.levels = options.levels.map((l) => l.toUpperCase().trim()); | ||
} | ||
if (options.techniques) { | ||
options.techniques = options.techniques.map(t => t.toUpperCase().trim()); | ||
options.techniques = options.techniques.map((t) => | ||
t.toUpperCase().trim() | ||
); | ||
} | ||
if (options.exclude) { | ||
options.exclude = options.exclude.map((t: string) => { | ||
return t.toLowerCase().startsWith("qw") | ||
? t.toUpperCase().trim() | ||
: t.trim(); | ||
}); | ||
} | ||
@@ -46,10 +56,25 @@ for (const technique of Object.keys(this.techniques) || []) { | ||
if (options.levels && options.levels.length !== 0) { | ||
if (!this.techniques[technique].hasPrincipleAndLevels(options.principles, options.levels)) { | ||
if ( | ||
!this.techniques[technique].hasPrincipleAndLevels( | ||
options.principles, | ||
options.levels | ||
) | ||
) { | ||
this.techniquesToExecute[technique] = false; | ||
} | ||
} else if (!this.techniques[technique].hasPrincipleAndLevels(options.principles, ['A', 'AA', 'AAA'])) { | ||
} else if ( | ||
!this.techniques[technique].hasPrincipleAndLevels( | ||
options.principles, | ||
["A", "AA", "AAA"] | ||
) | ||
) { | ||
this.techniquesToExecute[technique] = false; | ||
} | ||
} else if (options.levels && options.levels.length !== 0) { | ||
if (!this.techniques[technique].hasPrincipleAndLevels(['Perceivable', 'Operable', 'Understandable', 'Robust'], options.levels)) { | ||
if ( | ||
!this.techniques[technique].hasPrincipleAndLevels( | ||
["Perceivable", "Operable", "Understandable", "Robust"], | ||
options.levels | ||
) | ||
) { | ||
this.techniquesToExecute[technique] = false; | ||
@@ -60,3 +85,8 @@ } | ||
if (options.techniques && options.techniques.length !== 0) { | ||
if (!options.techniques.includes(technique) && !options.techniques.includes(this.techniques[technique].getTechniqueMapping())) { | ||
if ( | ||
!options.techniques.includes(technique) && | ||
!options.techniques.includes( | ||
this.techniques[technique].getTechniqueMapping() | ||
) | ||
) { | ||
this.techniquesToExecute[technique] = false; | ||
@@ -67,3 +97,8 @@ } | ||
if (options.techniques && options.techniques.length !== 0) { | ||
if (options.techniques.includes(technique) || options.techniques.includes(this.techniques[technique].getTechniqueMapping())) { | ||
if ( | ||
options.techniques.includes(technique) || | ||
options.techniques.includes( | ||
this.techniques[technique].getTechniqueMapping() | ||
) | ||
) { | ||
this.techniquesToExecute[technique] = true; | ||
@@ -73,2 +108,10 @@ } | ||
} | ||
if (options.exclude && options.exclude.length !== 0) { | ||
if ( | ||
options.exclude.includes(technique) || | ||
options.exclude.includes(this.techniques[technique].getRuleMapping()) | ||
) { | ||
this.techniquesToExecute[technique] = false; | ||
} | ||
} | ||
} | ||
@@ -83,3 +126,8 @@ } | ||
private executeTechnique(technique: string, selector: string, page: QWPage, report: WCAGTechniquesReport): void { | ||
private executeTechnique( | ||
technique: string, | ||
selector: string, | ||
page: QWPage, | ||
report: WCAGTechniquesReport | ||
): void { | ||
const elements = page.getElements(selector); | ||
@@ -107,7 +155,12 @@ if (elements.length > 0) { | ||
private executeMappedTechniques(report: WCAGTechniquesReport, page: QWPage, selectors: string[], mappedTechniques: any): void { | ||
private executeMappedTechniques( | ||
report: WCAGTechniquesReport, | ||
page: QWPage, | ||
selectors: string[], | ||
mappedTechniques: any | ||
): void { | ||
for (const selector of selectors || []) { | ||
for (const technique of mappedTechniques[selector] || []) { | ||
if (this.techniquesToExecute[technique]) { | ||
this.executeTechnique(technique, selector, page, report) | ||
this.executeTechnique(technique, selector, page, report); | ||
} | ||
@@ -118,22 +171,33 @@ } | ||
private executeNotMappedTechniques(report: WCAGTechniquesReport, newTabWasOpen: boolean, validation): void { | ||
if (this.techniquesToExecute['QW-WCAG-T16']) { | ||
this.techniques['QW-WCAG-T16'].validate(validation); | ||
report.assertions['QW-WCAG-T16'] = this.techniques['QW-WCAG-T16'].getFinalResults(); | ||
report.metadata[report.assertions['QW-WCAG-T16'].metadata.outcome]++; | ||
this.techniques['QW-WCAG-T16'].reset(); | ||
private executeNotMappedTechniques( | ||
report: WCAGTechniquesReport, | ||
newTabWasOpen: boolean, | ||
validation | ||
): void { | ||
if (this.techniquesToExecute["QW-WCAG-T16"]) { | ||
this.techniques["QW-WCAG-T16"].validate(validation); | ||
report.assertions["QW-WCAG-T16"] = this.techniques[ | ||
"QW-WCAG-T16" | ||
].getFinalResults(); | ||
report.metadata[report.assertions["QW-WCAG-T16"].metadata.outcome]++; | ||
this.techniques["QW-WCAG-T16"].reset(); | ||
} | ||
if (this.techniquesToExecute['QW-WCAG-T22']) { | ||
this.techniques['QW-WCAG-T22'].validate(newTabWasOpen); | ||
report.assertions['QW-WCAG-T22'] = this.techniques['QW-WCAG-T22'].getFinalResults(); | ||
report.metadata[report.assertions['QW-WCAG-T22'].metadata.outcome]++; | ||
this.techniques['QW-WCAG-T22'].reset(); | ||
if (this.techniquesToExecute["QW-WCAG-T22"]) { | ||
this.techniques["QW-WCAG-T22"].validate(newTabWasOpen); | ||
report.assertions["QW-WCAG-T22"] = this.techniques[ | ||
"QW-WCAG-T22" | ||
].getFinalResults(); | ||
report.metadata[report.assertions["QW-WCAG-T22"].metadata.outcome]++; | ||
this.techniques["QW-WCAG-T22"].reset(); | ||
} | ||
} | ||
public execute(page: QWPage, newTabWasOpen: boolean, validation: any): WCAGTechniquesReport { | ||
public execute( | ||
page: QWPage, | ||
newTabWasOpen: boolean, | ||
validation: any | ||
): WCAGTechniquesReport { | ||
const report: WCAGTechniquesReport = { | ||
type: 'wcag-techniques', | ||
type: "wcag-techniques", | ||
metadata: { | ||
@@ -143,8 +207,8 @@ passed: 0, | ||
failed: 0, | ||
inapplicable: 0 | ||
inapplicable: 0, | ||
}, | ||
assertions: {} | ||
assertions: {}, | ||
}; | ||
this.executeMappedTechniques(report, page, Object.keys(mapping), mapping) | ||
this.executeMappedTechniques(report, page, Object.keys(mapping), mapping); | ||
this.executeNotMappedTechniques(report, newTabWasOpen, validation); | ||
@@ -151,0 +215,0 @@ |
@@ -1,8 +0,7 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { WCAGTechnique } from '../lib/decorators'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { WCAGTechnique } from "../lib/decorators"; | ||
@WCAGTechnique | ||
class QW_WCAG_T22 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -13,21 +12,20 @@ super(technique); | ||
execute(): void { | ||
throw new Error('Method not implemented.'); | ||
throw new Error("Method not implemented."); | ||
} | ||
validate(newTabWasOpen: boolean): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
if (!newTabWasOpen) { | ||
evaluation.verdict = 'passed'; | ||
evaluation.verdict = "passed"; | ||
evaluation.description = `Browser didn't open new tab`; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = `Browser opened a new tab`; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
@@ -34,0 +32,0 @@ |
@@ -1,11 +0,10 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { QWPage } from '@qualweb/qw-page'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { AccessibilityUtils } from '@qualweb/util'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
import { QWPage } from "@qualweb/qw-page"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
import { AccessibilityUtils } from "@qualweb/util"; | ||
@WCAGTechnique | ||
class QW_WCAG_T23 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -17,61 +16,78 @@ super(technique); | ||
execute(element: QWElement, page: QWPage): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
let children = element.getElementChildren(); | ||
if (children !== null && children.length > 0) { | ||
let firstFocusableElem = findFirstFocusableElement(element,page); | ||
let firstFocusableElem = findFirstFocusableElement(element, page); | ||
if (!!firstFocusableElem) { | ||
const firstFocusableElemName = firstFocusableElem.getElementTagName(); | ||
//const firstFocusableElemAttribs = await DomUtils.getElementAttributes(firstFocusableElem); | ||
const firstFocusableElemHREF = firstFocusableElem.getElementAttribute('href'); | ||
if (firstFocusableElemName === 'a' && firstFocusableElemHREF && firstFocusableElemHREF.trim()) { | ||
const firstFocusableElemHREF = firstFocusableElem.getElementAttribute( | ||
"href" | ||
); | ||
if ( | ||
firstFocusableElemName === "a" && | ||
firstFocusableElemHREF && | ||
firstFocusableElemHREF.trim() | ||
) { | ||
let url = page.getURL(); | ||
let urlConcatWithId = url + '#'; | ||
let lastSlash = url.lastIndexOf('/'); | ||
let urlConcatWithId = url + "#"; | ||
let lastSlash = url.lastIndexOf("/"); | ||
let filename = url.substring(lastSlash + 1); | ||
if (firstFocusableElemHREF.startsWith('#') || firstFocusableElemHREF.startsWith(urlConcatWithId) || | ||
firstFocusableElemHREF.startsWith(filename)) { | ||
let idSymbol = firstFocusableElemHREF.indexOf('#'); | ||
if ( | ||
firstFocusableElemHREF.startsWith("#") || | ||
firstFocusableElemHREF.startsWith(urlConcatWithId) || | ||
firstFocusableElemHREF.startsWith(filename) | ||
) { | ||
let idSymbol = firstFocusableElemHREF.indexOf("#"); | ||
let idReferenced = firstFocusableElemHREF.substring(idSymbol + 1); | ||
if (idReferenced.length > 0) { | ||
let idElementReferenced = element.getElement('[id="' + idReferenced + '"]') | ||
let idElementReferenced = element.getElement( | ||
'[id="' + idReferenced + '"]' | ||
); | ||
if (idElementReferenced !== null) { | ||
if (hasMainElementAsParent(idElementReferenced)) { | ||
evaluation.verdict = 'warning'; | ||
evaluation.description = 'The first focusable control is a visible link to a <main> element.'; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.verdict = "warning"; | ||
evaluation.description = | ||
"The first focusable control is a visible link to a <main> element."; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'warning'; | ||
evaluation.description = 'The first focusable control is a visible link to some content in the Web Page. Verify if it links to the main content.'; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.verdict = "warning"; | ||
evaluation.description = | ||
"The first focusable control is a visible link to some content in the Web Page. Verify if it links to the main content."; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'The first focusable control on the Web page links to an inexistent element'; | ||
evaluation.resultCode = 'RC3'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"The first focusable control on the Web page links to an inexistent element"; | ||
evaluation.resultCode = "RC3"; | ||
} | ||
} else { | ||
//todo failed ou inapplicable? | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'The first focusable control on the Web page links to the top of the page'; | ||
evaluation.resultCode = 'RC4'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"The first focusable control on the Web page links to the top of the page"; | ||
evaluation.resultCode = "RC4"; | ||
} | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'The first focusable control on the Web page does not links to local content'; | ||
evaluation.resultCode = 'RC5'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"The first focusable control on the Web page does not links to local content"; | ||
evaluation.resultCode = "RC5"; | ||
} | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'The first focusable control on the Web page is not a link'; | ||
evaluation.resultCode = 'RC6'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"The first focusable control on the Web page is not a link"; | ||
evaluation.resultCode = "RC6"; | ||
} | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'This Web page does not have focusable controls'; | ||
evaluation.resultCode = 'RC7'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"This Web page does not have focusable controls"; | ||
evaluation.resultCode = "RC7"; | ||
} | ||
@@ -84,3 +100,6 @@ | ||
function findFirstFocusableElement(element: QWElement,page:QWPage): QWElement | undefined { | ||
function findFirstFocusableElement( | ||
element: QWElement, | ||
page: QWPage | ||
): QWElement | undefined { | ||
let foundFirstFocusableElem = false; | ||
@@ -94,8 +113,8 @@ let firstFocusableElem: QWElement | undefined; | ||
if (!!children[i]) { | ||
if (AccessibilityUtils.isElementFocusable(children[i],page)) { | ||
if (AccessibilityUtils.isElementFocusable(children[i], page)) { | ||
firstFocusableElem = children[i]; | ||
foundFirstFocusableElem = true; | ||
} else { | ||
firstFocusableElem = findFirstFocusableElement(children[i],page); | ||
if(!!firstFocusableElem){ | ||
firstFocusableElem = findFirstFocusableElement(children[i], page); | ||
if (!!firstFocusableElem) { | ||
foundFirstFocusableElem = true; | ||
@@ -116,3 +135,3 @@ } | ||
let pointer = element.getElementSelector(); | ||
return pointer.indexOf('main:') > 0; | ||
return pointer.indexOf("main:") > 0; | ||
} | ||
@@ -119,0 +138,0 @@ |
@@ -1,11 +0,10 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import { AccessibilityUtils } from '@qualweb/util'; | ||
import Technique from '../lib/Technique.object'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { QWPage } from '@qualweb/qw-page'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import { AccessibilityUtils } from "@qualweb/util"; | ||
import Technique from "../lib/Technique.object"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
import { QWPage } from "@qualweb/qw-page"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
@WCAGTechnique | ||
class QW_WCAG_T24 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -17,10 +16,9 @@ super(technique); | ||
execute(element: QWElement, page: QWPage): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
const isFocusable = AccessibilityUtils.isElementFocusable(element,page); | ||
const isFocusable = AccessibilityUtils.isElementFocusable(element, page); | ||
@@ -30,9 +28,9 @@ if (isFocusable) { | ||
if (keepsFocus) { | ||
evaluation.verdict = 'passed'; | ||
evaluation.verdict = "passed"; | ||
evaluation.description = `Element kept focus`; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = `Element didn't keep focus`; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
@@ -39,0 +37,0 @@ |
@@ -1,9 +0,8 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
@WCAGTechnique | ||
class QW_WCAG_T25 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,7 +14,6 @@ super(technique); | ||
execute(element: QWElement): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
@@ -25,21 +23,26 @@ | ||
const hasScope = element.elementHasAttribute('scope'); | ||
const scope = element.getElementAttribute('scope'); | ||
const hasScope = element.elementHasAttribute("scope"); | ||
const scope = element.getElementAttribute("scope"); | ||
if (name === 'th' && !hasScope) { | ||
evaluation.verdict = 'failed'; | ||
if (name === "th" && !hasScope) { | ||
evaluation.verdict = "failed"; | ||
evaluation.description = `The element doesn't contain a scope attribute`; | ||
evaluation.resultCode = 'RC1'; | ||
} else if (name === 'th' && scope === '') { | ||
evaluation.verdict = 'failed'; | ||
evaluation.resultCode = "RC1"; | ||
} else if (name === "th" && scope === "") { | ||
evaluation.verdict = "failed"; | ||
evaluation.description = `The element's scope attribute is empty`; | ||
evaluation.resultCode = 'RC2'; | ||
} else if (scope && ['col', 'row', 'colgroup', 'rowgroup'].includes(scope)) { | ||
evaluation.verdict = 'passed'; | ||
evaluation.description = 'The element\'s scope attribute matches the following values: col, row, colgroup, rowgroup'; | ||
evaluation.resultCode = 'RC3'; | ||
evaluation.resultCode = "RC2"; | ||
} else if ( | ||
scope && | ||
["col", "row", "colgroup", "rowgroup"].includes(scope) | ||
) { | ||
evaluation.verdict = "passed"; | ||
evaluation.description = | ||
"The element's scope attribute matches the following values: col, row, colgroup, rowgroup"; | ||
evaluation.resultCode = "RC3"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'The element\'s scope attribute doesn\'t match any of the following values: col, row, colgroup, rowgroup'; | ||
evaluation.resultCode = 'RC4'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"The element's scope attribute doesn't match any of the following values: col, row, colgroup, rowgroup"; | ||
evaluation.resultCode = "RC4"; | ||
} | ||
@@ -46,0 +49,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { HTMLTechniqueResult } from "@qualweb/html-techniques"; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import { AccessibilityUtils } from "@qualweb/util"; | ||
@@ -23,3 +23,3 @@ import Technique from "../lib/Technique.object"; | ||
execute(element: QWElement, page: QWPage): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
@@ -26,0 +26,0 @@ description: "", |
@@ -1,9 +0,8 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
@WCAGTechnique | ||
class QW_WCAG_T27 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,20 +14,19 @@ super(technique); | ||
execute(element: QWElement): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
const alignAttribute = element.getElementStyleProperty('text-align', null); | ||
const alignAttribute = element.getElementStyleProperty("text-align", null); | ||
if (alignAttribute) { | ||
if (alignAttribute.includes('justify')) { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'This content shouldn\'t be justified'; | ||
evaluation.resultCode = 'RC1'; | ||
if (alignAttribute.includes("justify")) { | ||
evaluation.verdict = "failed"; | ||
evaluation.description = "This content shouldn't be justified"; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'passed'; | ||
evaluation.description = 'This content is not justified'; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.verdict = "passed"; | ||
evaluation.description = "This content is not justified"; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
@@ -35,0 +33,0 @@ |
@@ -1,9 +0,8 @@ | ||
import { CSSTechniqueResult } from '@qualweb/css-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
@WCAGTechnique | ||
class QW_WCAG_T28 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,5 +14,4 @@ super(technique); | ||
execute(element: QWElement): void { | ||
if (element.getElementTagName() === 'style') { | ||
const sheet = <any> element.getElementProperty('sheet'); | ||
if (element.getElementTagName() === "style") { | ||
const sheet = <any>element.getElementProperty("sheet"); | ||
for (const rule of sheet.cssRules || []) { | ||
@@ -26,3 +24,3 @@ const style = rule?.style?.cssText; | ||
} else { | ||
const style = <string> element.getElementAttribute('style'); | ||
const style = <string>element.getElementAttribute("style"); | ||
this.checkCssProperty(style, element); | ||
@@ -33,32 +31,44 @@ } | ||
private checkCssProperty(style: string, element: QWElement): void { | ||
const evaluation: CSSTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
const properties = style.split(';').filter(p => p.trim() !== '') || [style]; | ||
const properties = style.split(";").filter((p) => p.trim() !== "") || [ | ||
style, | ||
]; | ||
for (const property of properties) { | ||
if (property.includes('font-size')) { | ||
const fontSize = property.split(':')[1]; | ||
const hasImportant = fontSize.includes('!important'); | ||
if (property.includes("font-size")) { | ||
const fontSize = property.split(":")[1]; | ||
const hasImportant = fontSize.includes("!important"); | ||
if (hasImportant) { | ||
const value = fontSize.replace('!important', '').trim(); | ||
const hasAbsoluteUnit = value.endsWith('cm') || value.endsWith('mm') || value.endsWith('in') || value.endsWith('px') || value.endsWith('pt') || value.endsWith('pc'); | ||
const value = fontSize.replace("!important", "").trim(); | ||
const hasAbsoluteUnit = | ||
value.endsWith("cm") || | ||
value.endsWith("mm") || | ||
value.endsWith("in") || | ||
value.endsWith("px") || | ||
value.endsWith("pt") || | ||
value.endsWith("pc"); | ||
if (!hasAbsoluteUnit) { | ||
evaluation.verdict = 'passed'; | ||
evaluation.description = 'This test target has a font-size css property using an relative unit value with the important flag.'; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.verdict = "passed"; | ||
evaluation.description = | ||
"This test target has a font-size css property using an relative unit value with the important flag."; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'This test target has a font-size css property using an absolute unit value with the important flag.'; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"This test target has a font-size css property using an absolute unit value with the important flag."; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
evaluation.pointer = element.getElementSelector(); | ||
evaluation.htmlCode = element.getElementHtmlCode(true, true); | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, true), | ||
}, | ||
]; | ||
evaluation.attributes = property; | ||
@@ -65,0 +75,0 @@ |
@@ -1,9 +0,8 @@ | ||
import { CSSTechniqueResult } from '@qualweb/css-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
@WCAGTechnique | ||
class QW_WCAG_T29 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,5 +14,4 @@ super(technique); | ||
execute(element: QWElement): void { | ||
if (element.getElementTagName() === 'style') { | ||
const sheet = <any> element.getElementProperty('sheet'); | ||
if (element.getElementTagName() === "style") { | ||
const sheet = <any>element.getElementProperty("sheet"); | ||
for (const rule of sheet.cssRules || []) { | ||
@@ -26,3 +24,3 @@ const style = rule?.style?.cssText; | ||
} else { | ||
const style = <string> element.getElementAttribute('style'); | ||
const style = <string>element.getElementAttribute("style"); | ||
this.checkCssProperty(style, element); | ||
@@ -33,28 +31,35 @@ } | ||
private checkCssProperty(style: string, element: QWElement): void { | ||
const evaluation: CSSTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
const properties = style.split(';').filter(p => p.trim() !== '') || [style]; | ||
const properties = style.split(";").filter((p) => p.trim() !== "") || [ | ||
style, | ||
]; | ||
for (const property of properties) { | ||
if (property.includes('text-align')) { | ||
const textAlign = property.split(':')[1]; | ||
const isJustified = textAlign.includes('justify'); | ||
if (property.includes("text-align")) { | ||
const textAlign = property.split(":")[1]; | ||
const isJustified = textAlign.includes("justify"); | ||
if (!isJustified) { | ||
evaluation.verdict = 'passed'; | ||
evaluation.description = 'This test target has a text-align css property equal to justify.'; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.verdict = "passed"; | ||
evaluation.description = | ||
"This test target has a text-align css property equal to justify."; | ||
evaluation.resultCode = "RC1"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'This test target has a text-align css property not equal to justify.'; | ||
evaluation.resultCode = 'RC2'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"This test target has a text-align css property not equal to justify."; | ||
evaluation.resultCode = "RC2"; | ||
} | ||
evaluation.pointer =element.getElementSelector(); | ||
evaluation.htmlCode = element.getElementHtmlCode(true, false); | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, false), | ||
}, | ||
]; | ||
evaluation.attributes = property; | ||
@@ -61,0 +66,0 @@ |
@@ -1,9 +0,8 @@ | ||
import { CSSTechniqueResult } from '@qualweb/css-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
@WCAGTechnique | ||
class QW_WCAG_T30 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,10 +14,9 @@ super(technique); | ||
execute(element: QWElement): void { | ||
const evaluation: CSSTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
if (element.elementHasAttribute('_cssRules')) { | ||
if (element.elementHasAttribute("_cssRules")) { | ||
const cssRules = element.getCSSRules(); | ||
@@ -29,12 +27,17 @@ | ||
if (property !== undefined) { | ||
evaluation.verdict = 'failed'; | ||
evaluation.description = 'This test target has a `text-decoration` property with the value `blink'; | ||
evaluation.resultCode = 'RC1'; | ||
evaluation.htmlCode = element.getElementHtmlCode(true, true); | ||
evaluation.pointer = element.getElementSelector(); | ||
evaluation.property = { | ||
name: 'text-decoration', | ||
value: 'blink' | ||
}; | ||
evaluation.stylesheetFile = property.pointer; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = | ||
"This test target has a `text-decoration` property with the value `blink"; | ||
evaluation.resultCode = "RC1"; | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, true), | ||
property: { | ||
name: "text-decoration", | ||
value: "blink", | ||
}, | ||
stylesheetFile: property.pointer, | ||
}, | ||
]; | ||
@@ -48,9 +51,9 @@ super.addEvaluationResult(evaluation); | ||
for (const property in properties || {}) { | ||
if (property === 'media') { | ||
const mediaRule = this.findInMediaRules(properties['media']); | ||
if (property === "media") { | ||
const mediaRule = this.findInMediaRules(properties["media"]); | ||
if (mediaRule !== undefined) { | ||
return mediaRule; | ||
} | ||
} else if (property === 'text-decoration') { | ||
if (properties[property]['value'] === 'blink') { | ||
} else if (property === "text-decoration") { | ||
if (properties[property]["value"] === "blink") { | ||
return properties[property]; | ||
@@ -67,4 +70,4 @@ } | ||
for (const property in media[condition] || {}) { | ||
if (property === 'text-decoration') { | ||
if (media[condition][property]['value'] === 'blink') { | ||
if (property === "text-decoration") { | ||
if (media[condition][property]["value"] === "blink") { | ||
return media[condition][property]; | ||
@@ -80,2 +83,2 @@ } | ||
export = QW_WCAG_T30; | ||
export = QW_WCAG_T30; |
import Technique from "../lib/Technique.object"; | ||
import { CSSTechniqueResult } from "@qualweb/css-techniques"; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
@@ -22,3 +22,3 @@ import { QWElement } from "@qualweb/qw-element"; | ||
const evaluation: CSSTechniqueResult = { | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
@@ -62,4 +62,8 @@ description: "", | ||
evaluation.pointer = element.getElementSelector(); | ||
evaluation.htmlCode = element.getElementHtmlCode(true, true); | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, false), | ||
}, | ||
]; | ||
@@ -72,4 +76,8 @@ super.addEvaluationResult(evaluation); | ||
evaluation.pointer = element.getElementSelector(); | ||
evaluation.htmlCode = element.getElementHtmlCode(true, true); | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, false), | ||
}, | ||
]; | ||
@@ -82,4 +90,8 @@ super.addEvaluationResult(evaluation); | ||
evaluation.pointer = element.getElementSelector(); | ||
evaluation.htmlCode = element.getElementHtmlCode(true, true); | ||
evaluation.elements = [ | ||
{ | ||
pointer: element.getElementSelector(), | ||
htmlCode: element.getElementHtmlCode(true, false), | ||
}, | ||
]; | ||
@@ -86,0 +98,0 @@ super.addEvaluationResult(evaluation); |
@@ -1,9 +0,8 @@ | ||
import { HTMLTechniqueResult } from '@qualweb/html-techniques'; | ||
import Technique from '../lib/Technique.object'; | ||
import { QWElement } from '@qualweb/qw-element'; | ||
import { WCAGTechnique, ElementExists } from '../lib/decorators'; | ||
import { WCAGTechniqueResult } from "@qualweb/wcag-techniques"; | ||
import Technique from "../lib/Technique.object"; | ||
import { QWElement } from "@qualweb/qw-element"; | ||
import { WCAGTechnique, ElementExists } from "../lib/decorators"; | ||
@WCAGTechnique | ||
class QW_WCAG_T32 extends Technique { | ||
constructor(technique?: any) { | ||
@@ -15,31 +14,34 @@ super(technique); | ||
execute(element: QWElement): void { | ||
const evaluation: HTMLTechniqueResult = { | ||
verdict: '', | ||
description: '', | ||
resultCode: '' | ||
const evaluation: WCAGTechniqueResult = { | ||
verdict: "", | ||
description: "", | ||
resultCode: "", | ||
}; | ||
const hasLi = (element.getElements('li')).length !== 0; | ||
const hasDd = (element.getElements('dd')).length !== 0; | ||
const hasDt = (element.getElements('dt')).length !== 0; | ||
const hasLi = element.getElements("li").length !== 0; | ||
const hasDd = element.getElements("dd").length !== 0; | ||
const hasDt = element.getElements("dt").length !== 0; | ||
const name = element.getElementTagName(); | ||
if (hasLi && name === 'ul') { // fails if the element doesn't contain an alt attribute | ||
evaluation.verdict = 'warning'; | ||
evaluation.description = 'Check that content that has the visual appearance of a list (with or without bullets) is marked as an unordered list'; | ||
evaluation.resultCode = 'RC1'; | ||
} else if (hasLi && name === 'ol') { | ||
evaluation.verdict = 'warning'; | ||
evaluation.description = 'Check that content that has the visual appearance of a numbered list is marked as an ordered list.'; | ||
evaluation.resultCode = 'RC2'; | ||
} else if (name === 'dl' && (hasDt || hasDd)) { | ||
evaluation.verdict = 'warning'; | ||
evaluation.description = 'Check that content is marked as a definition list when terms and their definitions are presented in the form of a list.'; | ||
evaluation.resultCode = 'RC3'; | ||
if (hasLi && name === "ul") { | ||
// fails if the element doesn't contain an alt attribute | ||
evaluation.verdict = "warning"; | ||
evaluation.description = | ||
"Check that content that has the visual appearance of a list (with or without bullets) is marked as an unordered list"; | ||
evaluation.resultCode = "RC1"; | ||
} else if (hasLi && name === "ol") { | ||
evaluation.verdict = "warning"; | ||
evaluation.description = | ||
"Check that content that has the visual appearance of a numbered list is marked as an ordered list."; | ||
evaluation.resultCode = "RC2"; | ||
} else if (name === "dl" && (hasDt || hasDd)) { | ||
evaluation.verdict = "warning"; | ||
evaluation.description = | ||
"Check that content is marked as a definition list when terms and their definitions are presented in the form of a list."; | ||
evaluation.resultCode = "RC3"; | ||
} else { | ||
evaluation.verdict = 'failed'; | ||
evaluation.verdict = "failed"; | ||
evaluation.description = `A list item is not contained in a correct list element`; | ||
evaluation.resultCode = 'RC4'; | ||
evaluation.resultCode = "RC4"; | ||
} | ||
@@ -46,0 +48,0 @@ |
Sorry, the diff of this file is too big to display
363257
3257