From 83f7cca5886ba370e1865adcc6bbcb0b969a07af Mon Sep 17 00:00:00 2001 From: Utkarsh Chaudhary Date: Thu, 14 Nov 2024 15:10:13 +0530 Subject: [PATCH 1/8] Update in getOverflowHiddenAncestors for accessible text --- lib/commons/dom/get-overflow-hidden-ancestors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commons/dom/get-overflow-hidden-ancestors.js b/lib/commons/dom/get-overflow-hidden-ancestors.js index 79ca04ce..4a2bbcf8 100644 --- a/lib/commons/dom/get-overflow-hidden-ancestors.js +++ b/lib/commons/dom/get-overflow-hidden-ancestors.js @@ -28,7 +28,7 @@ const getOverflowHiddenAncestors = memoize( ancestors.push(vNode); } } else { - if (overflow.includes('hidden')) { + if (overflow.includes('hidden') || overflow.includes('clip')) { ancestors.push(vNode); } } From 024fd300185c5b3cb8bbc67ff7a6514f5b7d4cbb Mon Sep 17 00:00:00 2001 From: Utkarsh Chaudhary Date: Wed, 4 Dec 2024 14:18:18 +0530 Subject: [PATCH 2/8] Added node count --- lib/core/base/rule.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/core/base/rule.js b/lib/core/base/rule.js index e42c7429..8432760a 100644 --- a/lib/core/base/rule.js +++ b/lib/core/base/rule.js @@ -12,6 +12,7 @@ import { } from '../utils'; import { isVisibleToScreenReaders } from '../../commons/dom'; import constants from '../constants'; +import cache from './cache'; export default function Rule(spec, parentAudit) { this._audit = parentAudit; @@ -245,6 +246,7 @@ Rule.prototype.run = function run(context, options = {}, resolve, reject) { try { // Matches throws an error when it lacks support for document methods nodes = this.gatherAndMatchNodes(context, options); + cache.set(this.id, nodes.length); } catch (error) { // Exit the rule execution if matches fails reject(new SupportError({ cause: error, ruleId: this.id })); From 0a1c14b6ca42bb9c308c4615a00ec380e1355140 Mon Sep 17 00:00:00 2001 From: Arjun Chikara <106317740+chikara1608@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:09:13 +0530 Subject: [PATCH 3/8] Fix: Revert back to original get overflown hidden ancestors else case (#113) * Update in getOverflowHiddenAncestors for accessible text * Added node count * Back to original get overflown hidden ancestors --------- Co-authored-by: Utkarsh Chaudhary --- lib/commons/dom/get-overflow-hidden-ancestors.js | 2 +- lib/core/base/rule.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/commons/dom/get-overflow-hidden-ancestors.js b/lib/commons/dom/get-overflow-hidden-ancestors.js index 79ca04ce..8ace4290 100644 --- a/lib/commons/dom/get-overflow-hidden-ancestors.js +++ b/lib/commons/dom/get-overflow-hidden-ancestors.js @@ -28,7 +28,7 @@ const getOverflowHiddenAncestors = memoize( ancestors.push(vNode); } } else { - if (overflow.includes('hidden')) { + if (overflow === 'hidden' || overflow.includes('clip')) { ancestors.push(vNode); } } diff --git a/lib/core/base/rule.js b/lib/core/base/rule.js index e42c7429..8432760a 100644 --- a/lib/core/base/rule.js +++ b/lib/core/base/rule.js @@ -12,6 +12,7 @@ import { } from '../utils'; import { isVisibleToScreenReaders } from '../../commons/dom'; import constants from '../constants'; +import cache from './cache'; export default function Rule(spec, parentAudit) { this._audit = parentAudit; @@ -245,6 +246,7 @@ Rule.prototype.run = function run(context, options = {}, resolve, reject) { try { // Matches throws an error when it lacks support for document methods nodes = this.gatherAndMatchNodes(context, options); + cache.set(this.id, nodes.length); } catch (error) { // Exit the rule execution if matches fails reject(new SupportError({ cause: error, ruleId: this.id })); From ac57923db7aa72f0b420cbd5244c4e59c6c0a15c Mon Sep 17 00:00:00 2001 From: Utkarsh Chaudhary Date: Thu, 5 Dec 2024 20:26:14 +0530 Subject: [PATCH 4/8] Added a function in checkHelper to getCheckData --- lib/core/utils/check-helper.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/core/utils/check-helper.js b/lib/core/utils/check-helper.js index fbedf364..71960bac 100644 --- a/lib/core/utils/check-helper.js +++ b/lib/core/utils/check-helper.js @@ -25,6 +25,9 @@ function checkHelper(checkResult, options, resolve, reject) { data(data) { checkResult.data = data; }, + getCheckData() { + return checkResult.data; + }, relatedNodes(nodes) { if (!window.Node) { return; From 8243a88faaf329621116de3b7d993cbb4935bc55 Mon Sep 17 00:00:00 2001 From: Pooja Jadhav Date: Fri, 13 Dec 2024 18:24:25 +0530 Subject: [PATCH 5/8] AXE-789 : fixed color issue --- lib/checks/color/link-in-text-block-evaluate.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/checks/color/link-in-text-block-evaluate.js b/lib/checks/color/link-in-text-block-evaluate.js index be872cd7..0cb89893 100644 --- a/lib/checks/color/link-in-text-block-evaluate.js +++ b/lib/checks/color/link-in-text-block-evaluate.js @@ -136,6 +136,14 @@ function getColorContrast(node, parentBlock) { nodeColor = getForegroundColor(node); parentColor = getForegroundColor(parentBlock); + if (!nodeColor) { + nodeColor = new axe.commons.color.Color(0, 0, 0, 0); + } + + if (!parentColor) { + parentColor = new axe.commons.color.Color(0, 0, 0, 0); + } + if (!nodeColor || !parentColor) { return undefined; } From 74dc2c95940cdf890535d9dc278ccdcd01a4eec4 Mon Sep 17 00:00:00 2001 From: Utkarsh Chaudhary Date: Mon, 16 Dec 2024 10:33:23 +0530 Subject: [PATCH 6/8] Added ariadescribedbyText --- lib/commons/aria/ariadescribedby-text.js | 46 ++++++++++++++++++++++++ lib/commons/aria/index.js | 1 + 2 files changed, 47 insertions(+) create mode 100644 lib/commons/aria/ariadescribedby-text.js diff --git a/lib/commons/aria/ariadescribedby-text.js b/lib/commons/aria/ariadescribedby-text.js new file mode 100644 index 00000000..d81252d5 --- /dev/null +++ b/lib/commons/aria/ariadescribedby-text.js @@ -0,0 +1,46 @@ +/** + * Get the accessible name based on aria-describedby + * + * @deprecated Do not use Element directly. Pass VirtualNode instead + * @param {VirtualNode|Element} element + * @param {Object} context + * @property {Bool} inLabelledByContext Whether or not the lookup is part of aria-describedby reference + * @property {Bool} inControlContext Whether or not the lookup is part of a native label reference + * @property {Element} startNode First node in accessible name computation + * @property {Bool} debug Enable logging for formControlValue + * @return {string} Concatenated text value for referenced elements + */ +function ariadescribedbyText(element, context = {}) { + const { vNode } = axe.utils.nodeLookup(element); + if (vNode?.props.nodeType !== 1) { + return ''; + } + + if ( + vNode.props.nodeType !== 1 || + context.inLabelledByContext || + context.inControlContext || + !vNode.attr('aria-describedby') + ) { + return ''; + } + + const refs = axe.commons.dom + .idrefs(vNode, 'aria-describedby') + .filter(elm => elm); + return refs.reduce((accessibleName, elm) => { + const accessibleNameAdd = axe.commons.text.accessibleText(elm, { + // Prevent the infinite reference loop: + inLabelledByContext: true, + startNode: context.startNode || vNode, + ...context + }); + + if (!accessibleName) { + return accessibleNameAdd; + } + return `${accessibleName} ${accessibleNameAdd}`; + }, ''); +} + +export default ariadescribedbyText; diff --git a/lib/commons/aria/index.js b/lib/commons/aria/index.js index 9eb5bb3a..86d310ee 100644 --- a/lib/commons/aria/index.js +++ b/lib/commons/aria/index.js @@ -6,6 +6,7 @@ export { default as allowedAttr } from './allowed-attr'; export { default as arialabelText } from './arialabel-text'; export { default as arialabelledbyText } from './arialabelledby-text'; +export { default as ariadescribedbyText } from './ariadescribedby-text'; export { default as getAccessibleRefs } from './get-accessible-refs'; export { default as getElementUnallowedRoles } from './get-element-unallowed-roles'; export { default as getExplicitRole } from './get-explicit-role'; From 9607bd88f3a0c1f16fa088ebff41b3dd7a679d0d Mon Sep 17 00:00:00 2001 From: Utkarsh Chaudhary Date: Mon, 16 Dec 2024 10:35:29 +0530 Subject: [PATCH 7/8] Added ariadescribedbyText --- lib/commons/aria/ariadescribedby-text.js | 46 ++++++++++++++++++++++++ lib/commons/aria/index.js | 1 + 2 files changed, 47 insertions(+) create mode 100644 lib/commons/aria/ariadescribedby-text.js diff --git a/lib/commons/aria/ariadescribedby-text.js b/lib/commons/aria/ariadescribedby-text.js new file mode 100644 index 00000000..d81252d5 --- /dev/null +++ b/lib/commons/aria/ariadescribedby-text.js @@ -0,0 +1,46 @@ +/** + * Get the accessible name based on aria-describedby + * + * @deprecated Do not use Element directly. Pass VirtualNode instead + * @param {VirtualNode|Element} element + * @param {Object} context + * @property {Bool} inLabelledByContext Whether or not the lookup is part of aria-describedby reference + * @property {Bool} inControlContext Whether or not the lookup is part of a native label reference + * @property {Element} startNode First node in accessible name computation + * @property {Bool} debug Enable logging for formControlValue + * @return {string} Concatenated text value for referenced elements + */ +function ariadescribedbyText(element, context = {}) { + const { vNode } = axe.utils.nodeLookup(element); + if (vNode?.props.nodeType !== 1) { + return ''; + } + + if ( + vNode.props.nodeType !== 1 || + context.inLabelledByContext || + context.inControlContext || + !vNode.attr('aria-describedby') + ) { + return ''; + } + + const refs = axe.commons.dom + .idrefs(vNode, 'aria-describedby') + .filter(elm => elm); + return refs.reduce((accessibleName, elm) => { + const accessibleNameAdd = axe.commons.text.accessibleText(elm, { + // Prevent the infinite reference loop: + inLabelledByContext: true, + startNode: context.startNode || vNode, + ...context + }); + + if (!accessibleName) { + return accessibleNameAdd; + } + return `${accessibleName} ${accessibleNameAdd}`; + }, ''); +} + +export default ariadescribedbyText; diff --git a/lib/commons/aria/index.js b/lib/commons/aria/index.js index 9eb5bb3a..86d310ee 100644 --- a/lib/commons/aria/index.js +++ b/lib/commons/aria/index.js @@ -6,6 +6,7 @@ export { default as allowedAttr } from './allowed-attr'; export { default as arialabelText } from './arialabel-text'; export { default as arialabelledbyText } from './arialabelledby-text'; +export { default as ariadescribedbyText } from './ariadescribedby-text'; export { default as getAccessibleRefs } from './get-accessible-refs'; export { default as getElementUnallowedRoles } from './get-element-unallowed-roles'; export { default as getExplicitRole } from './get-explicit-role'; From 1be13b9c926c82efb3463789844ba6b385ff1d82 Mon Sep 17 00:00:00 2001 From: Abhishek Bindra Date: Mon, 23 Dec 2024 14:44:24 +0530 Subject: [PATCH 8/8] remove unwanted attributes from html string (#120) --- lib/core/utils/dq-element.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core/utils/dq-element.js b/lib/core/utils/dq-element.js index 3cf790fe..47bcc64e 100644 --- a/lib/core/utils/dq-element.js +++ b/lib/core/utils/dq-element.js @@ -26,7 +26,11 @@ function getSource(element) { if (!source && typeof window.XMLSerializer === 'function') { source = new window.XMLSerializer().serializeToString(element); } - return truncate(source || ''); + let htmlString = truncate(source || ''); + // Remove unwanted attributes + const regex = /\s*data-percy-[^=]+="[^"]*"/g; + htmlString = htmlString.replace(regex, ''); + return htmlString; } /**