From dd42cdea62c1595c92cf64482f2eefe55540952e Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Wed, 6 Oct 2021 13:23:35 +0200 Subject: [PATCH 1/3] fix: Separate Level AAA rules from A and best-practices --- build/configure.js | 8 +++ doc/API.md | 2 + doc/rule-descriptions.md | 74 ++++++++++++--------- lib/rules/identical-links-same-purpose.json | 2 +- lib/rules/meta-refresh.json | 1 - 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/build/configure.js b/build/configure.js index 10a583126c..97939e0455 100644 --- a/build/configure.js +++ b/build/configure.js @@ -62,6 +62,12 @@ function buildRules(grunt, options, commons, callback) { 'Rules that do not necessarily conform to WCAG success criterion but are industry accepted practices that improve the user experience.', rules: [] }, + wcag2aaa: { + title: 'WCAG 2.0 and 2.1 level AAA rules', + intro: + 'Rules that check for conformance to WCAG AAA success criteria that can be fully automated.', + rules: [] + }, experimental: { title: 'Experimental Rules', intro: @@ -335,6 +341,8 @@ function buildRules(grunt, options, commons, callback) { rules = descriptions.deprecated.rules; } else if (rule.tags.includes('experimental')) { rules = descriptions.experimental.rules; + } else if (rule.tags.find(tag => tag.includes('aaa'))) { + rules = descriptions.wcag2aaa.rules; } else if (rule.tags.includes('best-practice')) { rules = descriptions.bestPractice.rules; } else if (rule.tags.find(tag => tag.startsWith('wcag2a'))) { diff --git a/doc/API.md b/doc/API.md index 960d6cebd9..98ee922793 100644 --- a/doc/API.md +++ b/doc/API.md @@ -80,8 +80,10 @@ The `experimental`, `ACT` and `section508` tags are only added to some rules. Ea | ---------------- | ---------------------------------------------------- | | `wcag2a` | WCAG 2.0 Level A | | `wcag2aa` | WCAG 2.0 Level AA | +| `wcag2aaa` | WCAG 2.0 Level AAA | | `wcag21a` | WCAG 2.1 Level A | | `wcag21aa` | WCAG 2.1 Level AA | +| `wcag21aaa` | WCAG 2.1 Level AAA | | `best-practice` | Common accessibility best practices | | `wcag***` | WCAG success criterion e.g. wcag111 maps to SC 1.1.1 | | `ACT` | W3C approved Accessibility Conformance Testing rules | diff --git a/doc/rule-descriptions.md b/doc/rule-descriptions.md index e145658a76..bfd63193fd 100644 --- a/doc/rule-descriptions.md +++ b/doc/rule-descriptions.md @@ -5,6 +5,7 @@ - [WCAG 2.0 Level A & AA Rules](#wcag-20-level-a--aa-rules) - [WCAG 2.1 Level A & AA Rules](#wcag-21-level-a--aa-rules) - [Best Practices Rules](#best-practices-rules) +- [WCAG 2.0 and 2.1 level AAA rules](#wcag-20-and-21-level-aaa-rules) - [Experimental Rules](#experimental-rules) - [Deprecated Rules](#deprecated-rules) @@ -54,7 +55,7 @@ | [list](https://dequeuniversity.com/rules/axe/4.3/list?application=RuleDescription) | Ensures that lists are structured correctly | Serious | cat.structure, wcag2a, wcag131 | failure | | | [listitem](https://dequeuniversity.com/rules/axe/4.3/listitem?application=RuleDescription) | Ensures <li> elements are used semantically | Serious | cat.structure, wcag2a, wcag131 | failure | | | [marquee](https://dequeuniversity.com/rules/axe/4.3/marquee?application=RuleDescription) | Ensures <marquee> elements are not used | Serious | cat.parsing, wcag2a, wcag222 | failure | | -| [meta-refresh](https://dequeuniversity.com/rules/axe/4.3/meta-refresh?application=RuleDescription) | Ensures <meta http-equiv="refresh"> is not used | Critical | cat.time-and-media, wcag2a, wcag2aaa, wcag221, wcag224, wcag325 | failure | | +| [meta-refresh](https://dequeuniversity.com/rules/axe/4.3/meta-refresh?application=RuleDescription) | Ensures <meta http-equiv="refresh"> is not used | Critical | cat.time-and-media, wcag2a, wcag221, wcag224, wcag325 | failure | | | [nested-interactive](https://dequeuniversity.com/rules/axe/4.3/nested-interactive?application=RuleDescription) | Nested interactive controls are not announced by screen readers | Serious | cat.keyboard, wcag2a, wcag412 | failure, needs review | [307n5z](https://act-rules.github.io/rules/307n5z) | | [object-alt](https://dequeuniversity.com/rules/axe/4.3/object-alt?application=RuleDescription) | Ensures <object> elements have alternate text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | failure, needs review | [8fc3b6](https://act-rules.github.io/rules/8fc3b6) | | [role-img-alt](https://dequeuniversity.com/rules/axe/4.3/role-img-alt?application=RuleDescription) | Ensures [role='img'] elements have alternate text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a, ACT | failure, needs review | [23a2a8](https://act-rules.github.io/rules/23a2a8) | @@ -79,38 +80,45 @@ Rules that do not necessarily conform to WCAG success criterion but are industry accepted practices that improve the user experience. -| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules | -| :----------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------- | :----------------- | :---------------------------------------------- | :------------------------- | :----------------------------------------------------------------------------------------------------- | -| [accesskeys](https://dequeuniversity.com/rules/axe/4.3/accesskeys?application=RuleDescription) | Ensures every accesskey attribute value is unique | Serious | cat.keyboard, best-practice | failure | | -| [aria-allowed-role](https://dequeuniversity.com/rules/axe/4.3/aria-allowed-role?application=RuleDescription) | Ensures role attribute has an appropriate value for the element | Minor | cat.aria, best-practice | failure, needs review | | -| [aria-dialog-name](https://dequeuniversity.com/rules/axe/4.3/aria-dialog-name?application=RuleDescription) | Ensures every ARIA dialog and alertdialog node has an accessible name | Serious | cat.aria, best-practice | failure, needs review | | -| [aria-text](https://dequeuniversity.com/rules/axe/4.3/aria-text?application=RuleDescription) | Ensures "role=text" is used on elements with no focusable descendants | Serious | cat.aria, best-practice | failure, needs review | | -| [aria-treeitem-name](https://dequeuniversity.com/rules/axe/4.3/aria-treeitem-name?application=RuleDescription) | Ensures every ARIA treeitem node has an accessible name | Serious | cat.aria, best-practice | failure, needs review | | -| [empty-heading](https://dequeuniversity.com/rules/axe/4.3/empty-heading?application=RuleDescription) | Ensures headings have discernible text | Minor | cat.name-role-value, best-practice | failure, needs review | | -| [frame-tested](https://dequeuniversity.com/rules/axe/4.3/frame-tested?application=RuleDescription) | Ensures <iframe> and <frame> elements contain the axe-core script | Critical | cat.structure, review-item, best-practice | failure, needs review | | -| [frame-title-unique](https://dequeuniversity.com/rules/axe/4.3/frame-title-unique?application=RuleDescription) | Ensures <iframe> and <frame> elements contain a unique title attribute | Serious | cat.text-alternatives, best-practice | failure | | -| [heading-order](https://dequeuniversity.com/rules/axe/4.3/heading-order?application=RuleDescription) | Ensures the order of headings is semantically correct | Moderate | cat.semantics, best-practice | failure, needs review | | -| [identical-links-same-purpose](https://dequeuniversity.com/rules/axe/4.3/identical-links-same-purpose?application=RuleDescription) | Ensure that links with the same accessible name serve a similar purpose | Minor | cat.semantics, wcag2aaa, wcag249, best-practice | needs review | [b20e66](https://act-rules.github.io/rules/b20e66), [fd3a94](https://act-rules.github.io/rules/fd3a94) | -| [image-redundant-alt](https://dequeuniversity.com/rules/axe/4.3/image-redundant-alt?application=RuleDescription) | Ensure image alternative is not repeated as text | Minor | cat.text-alternatives, best-practice | failure | | -| [label-title-only](https://dequeuniversity.com/rules/axe/4.3/label-title-only?application=RuleDescription) | Ensures that every form element is not solely labeled using the title or aria-describedby attributes | Serious | cat.forms, best-practice | failure | | -| [landmark-banner-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-banner-is-top-level?application=RuleDescription) | Ensures the banner landmark is at top level | Moderate | cat.semantics, best-practice | failure | | -| [landmark-complementary-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-complementary-is-top-level?application=RuleDescription) | Ensures the complementary landmark or aside is at top level | Moderate | cat.semantics, best-practice | failure | | -| [landmark-contentinfo-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-contentinfo-is-top-level?application=RuleDescription) | Ensures the contentinfo landmark is at top level | Moderate | cat.semantics, best-practice | failure | | -| [landmark-main-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-main-is-top-level?application=RuleDescription) | Ensures the main landmark is at top level | Moderate | cat.semantics, best-practice | failure | | -| [landmark-no-duplicate-banner](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-banner?application=RuleDescription) | Ensures the document has at most one banner landmark | Moderate | cat.semantics, best-practice | failure | | -| [landmark-no-duplicate-contentinfo](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-contentinfo?application=RuleDescription) | Ensures the document has at most one contentinfo landmark | Moderate | cat.semantics, best-practice | failure | | -| [landmark-no-duplicate-main](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-main?application=RuleDescription) | Ensures the document has at most one main landmark | Moderate | cat.semantics, best-practice | failure | | -| [landmark-one-main](https://dequeuniversity.com/rules/axe/4.3/landmark-one-main?application=RuleDescription) | Ensures the document has a main landmark | Moderate | cat.semantics, best-practice | failure | | -| [landmark-unique](https://dequeuniversity.com/rules/axe/4.3/landmark-unique?application=RuleDescription) | Landmarks should have a unique role or role/label/title (i.e. accessible name) combination | Moderate | cat.semantics, best-practice | failure | | -| [meta-viewport-large](https://dequeuniversity.com/rules/axe/4.3/meta-viewport-large?application=RuleDescription) | Ensures <meta name="viewport"> can scale a significant amount | Minor | cat.sensory-and-visual-cues, best-practice | failure | | -| [meta-viewport](https://dequeuniversity.com/rules/axe/4.3/meta-viewport?application=RuleDescription) | Ensures <meta name="viewport"> does not disable text scaling and zooming | Critical | cat.sensory-and-visual-cues, best-practice, ACT | failure | [b4f0c3](https://act-rules.github.io/rules/b4f0c3) | -| [page-has-heading-one](https://dequeuniversity.com/rules/axe/4.3/page-has-heading-one?application=RuleDescription) | Ensure that the page, or at least one of its frames contains a level-one heading | Moderate | cat.semantics, best-practice | failure | | -| [presentation-role-conflict](https://dequeuniversity.com/rules/axe/4.3/presentation-role-conflict?application=RuleDescription) | Flags elements whose role is none or presentation and which cause the role conflict resolution to trigger. | Minor | cat.aria, best-practice | failure | | -| [region](https://dequeuniversity.com/rules/axe/4.3/region?application=RuleDescription) | Ensures all page content is contained by landmarks | Moderate | cat.keyboard, best-practice | failure | | -| [scope-attr-valid](https://dequeuniversity.com/rules/axe/4.3/scope-attr-valid?application=RuleDescription) | Ensures the scope attribute is used correctly on tables | Moderate, Critical | cat.tables, best-practice | failure | | -| [skip-link](https://dequeuniversity.com/rules/axe/4.3/skip-link?application=RuleDescription) | Ensure all skip links have a focusable target | Moderate | cat.keyboard, best-practice | failure, needs review | | -| [tabindex](https://dequeuniversity.com/rules/axe/4.3/tabindex?application=RuleDescription) | Ensures tabindex attribute values are not greater than 0 | Serious | cat.keyboard, best-practice | failure | | -| [table-duplicate-name](https://dequeuniversity.com/rules/axe/4.3/table-duplicate-name?application=RuleDescription) | Ensure that tables do not have the same summary and caption | Minor | cat.tables, best-practice | failure | | +| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules | +| :----------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------- | :----------------- | :---------------------------------------------- | :------------------------- | :------------------------------------------------- | +| [accesskeys](https://dequeuniversity.com/rules/axe/4.3/accesskeys?application=RuleDescription) | Ensures every accesskey attribute value is unique | Serious | cat.keyboard, best-practice | failure | | +| [aria-allowed-role](https://dequeuniversity.com/rules/axe/4.3/aria-allowed-role?application=RuleDescription) | Ensures role attribute has an appropriate value for the element | Minor | cat.aria, best-practice | failure, needs review | | +| [aria-dialog-name](https://dequeuniversity.com/rules/axe/4.3/aria-dialog-name?application=RuleDescription) | Ensures every ARIA dialog and alertdialog node has an accessible name | Serious | cat.aria, best-practice | failure, needs review | | +| [aria-text](https://dequeuniversity.com/rules/axe/4.3/aria-text?application=RuleDescription) | Ensures "role=text" is used on elements with no focusable descendants | Serious | cat.aria, best-practice | failure, needs review | | +| [aria-treeitem-name](https://dequeuniversity.com/rules/axe/4.3/aria-treeitem-name?application=RuleDescription) | Ensures every ARIA treeitem node has an accessible name | Serious | cat.aria, best-practice | failure, needs review | | +| [empty-heading](https://dequeuniversity.com/rules/axe/4.3/empty-heading?application=RuleDescription) | Ensures headings have discernible text | Minor | cat.name-role-value, best-practice | failure, needs review | | +| [frame-tested](https://dequeuniversity.com/rules/axe/4.3/frame-tested?application=RuleDescription) | Ensures <iframe> and <frame> elements contain the axe-core script | Critical | cat.structure, review-item, best-practice | failure, needs review | | +| [frame-title-unique](https://dequeuniversity.com/rules/axe/4.3/frame-title-unique?application=RuleDescription) | Ensures <iframe> and <frame> elements contain a unique title attribute | Serious | cat.text-alternatives, best-practice | failure | | +| [heading-order](https://dequeuniversity.com/rules/axe/4.3/heading-order?application=RuleDescription) | Ensures the order of headings is semantically correct | Moderate | cat.semantics, best-practice | failure, needs review | | +| [image-redundant-alt](https://dequeuniversity.com/rules/axe/4.3/image-redundant-alt?application=RuleDescription) | Ensure image alternative is not repeated as text | Minor | cat.text-alternatives, best-practice | failure | | +| [label-title-only](https://dequeuniversity.com/rules/axe/4.3/label-title-only?application=RuleDescription) | Ensures that every form element is not solely labeled using the title or aria-describedby attributes | Serious | cat.forms, best-practice | failure | | +| [landmark-banner-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-banner-is-top-level?application=RuleDescription) | Ensures the banner landmark is at top level | Moderate | cat.semantics, best-practice | failure | | +| [landmark-complementary-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-complementary-is-top-level?application=RuleDescription) | Ensures the complementary landmark or aside is at top level | Moderate | cat.semantics, best-practice | failure | | +| [landmark-contentinfo-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-contentinfo-is-top-level?application=RuleDescription) | Ensures the contentinfo landmark is at top level | Moderate | cat.semantics, best-practice | failure | | +| [landmark-main-is-top-level](https://dequeuniversity.com/rules/axe/4.3/landmark-main-is-top-level?application=RuleDescription) | Ensures the main landmark is at top level | Moderate | cat.semantics, best-practice | failure | | +| [landmark-no-duplicate-banner](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-banner?application=RuleDescription) | Ensures the document has at most one banner landmark | Moderate | cat.semantics, best-practice | failure | | +| [landmark-no-duplicate-contentinfo](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-contentinfo?application=RuleDescription) | Ensures the document has at most one contentinfo landmark | Moderate | cat.semantics, best-practice | failure | | +| [landmark-no-duplicate-main](https://dequeuniversity.com/rules/axe/4.3/landmark-no-duplicate-main?application=RuleDescription) | Ensures the document has at most one main landmark | Moderate | cat.semantics, best-practice | failure | | +| [landmark-one-main](https://dequeuniversity.com/rules/axe/4.3/landmark-one-main?application=RuleDescription) | Ensures the document has a main landmark | Moderate | cat.semantics, best-practice | failure | | +| [landmark-unique](https://dequeuniversity.com/rules/axe/4.3/landmark-unique?application=RuleDescription) | Landmarks should have a unique role or role/label/title (i.e. accessible name) combination | Moderate | cat.semantics, best-practice | failure | | +| [meta-viewport-large](https://dequeuniversity.com/rules/axe/4.3/meta-viewport-large?application=RuleDescription) | Ensures <meta name="viewport"> can scale a significant amount | Minor | cat.sensory-and-visual-cues, best-practice | failure | | +| [meta-viewport](https://dequeuniversity.com/rules/axe/4.3/meta-viewport?application=RuleDescription) | Ensures <meta name="viewport"> does not disable text scaling and zooming | Critical | cat.sensory-and-visual-cues, best-practice, ACT | failure | [b4f0c3](https://act-rules.github.io/rules/b4f0c3) | +| [page-has-heading-one](https://dequeuniversity.com/rules/axe/4.3/page-has-heading-one?application=RuleDescription) | Ensure that the page, or at least one of its frames contains a level-one heading | Moderate | cat.semantics, best-practice | failure | | +| [presentation-role-conflict](https://dequeuniversity.com/rules/axe/4.3/presentation-role-conflict?application=RuleDescription) | Flags elements whose role is none or presentation and which cause the role conflict resolution to trigger. | Minor | cat.aria, best-practice | failure | | +| [region](https://dequeuniversity.com/rules/axe/4.3/region?application=RuleDescription) | Ensures all page content is contained by landmarks | Moderate | cat.keyboard, best-practice | failure | | +| [scope-attr-valid](https://dequeuniversity.com/rules/axe/4.3/scope-attr-valid?application=RuleDescription) | Ensures the scope attribute is used correctly on tables | Moderate, Critical | cat.tables, best-practice | failure | | +| [skip-link](https://dequeuniversity.com/rules/axe/4.3/skip-link?application=RuleDescription) | Ensure all skip links have a focusable target | Moderate | cat.keyboard, best-practice | failure, needs review | | +| [tabindex](https://dequeuniversity.com/rules/axe/4.3/tabindex?application=RuleDescription) | Ensures tabindex attribute values are not greater than 0 | Serious | cat.keyboard, best-practice | failure | | +| [table-duplicate-name](https://dequeuniversity.com/rules/axe/4.3/table-duplicate-name?application=RuleDescription) | Ensure that tables do not have the same summary and caption | Minor | cat.tables, best-practice | failure | | + +## WCAG 2.0 and 2.1 level AAA rules + +Rules that check for conformance to WCAG AAA success criteria that can be fully automated. + +| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules | +| :--------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- | :----- | :------------------------------- | :---------------- | :----------------------------------------------------------------------------------------------------- | +| [identical-links-same-purpose](https://dequeuniversity.com/rules/axe/4.3/identical-links-same-purpose?application=RuleDescription) | Ensure that links with the same accessible name serve a similar purpose | Minor | cat.semantics, wcag2aaa, wcag249 | needs review | [b20e66](https://act-rules.github.io/rules/b20e66), [fd3a94](https://act-rules.github.io/rules/fd3a94) | ## Experimental Rules diff --git a/lib/rules/identical-links-same-purpose.json b/lib/rules/identical-links-same-purpose.json index ea6e4fdb48..4786ffebe0 100644 --- a/lib/rules/identical-links-same-purpose.json +++ b/lib/rules/identical-links-same-purpose.json @@ -3,7 +3,7 @@ "selector": "a[href], area[href], [role=\"link\"]", "excludeHidden": false, "matches": "identical-links-same-purpose-matches", - "tags": ["cat.semantics", "wcag2aaa", "wcag249", "best-practice"], + "tags": ["cat.semantics", "wcag2aaa", "wcag249"], "actIds": ["b20e66", "fd3a94"], "metadata": { "description": "Ensure that links with the same accessible name serve a similar purpose", diff --git a/lib/rules/meta-refresh.json b/lib/rules/meta-refresh.json index 10317c86d8..de24867624 100644 --- a/lib/rules/meta-refresh.json +++ b/lib/rules/meta-refresh.json @@ -5,7 +5,6 @@ "tags": [ "cat.time-and-media", "wcag2a", - "wcag2aaa", "wcag221", "wcag224", "wcag325" From c39110d08eea8d6ed2d6f8ac131c69103d6c74c7 Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Thu, 7 Oct 2021 11:23:44 +0200 Subject: [PATCH 2/3] Don't log use of wcag21aaa as a tag --- lib/core/base/audit.js | 5 ++--- test/core/base/audit.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lib/core/base/audit.js b/lib/core/base/audit.js index bf47c49701..1bb598947d 100644 --- a/lib/core/base/audit.js +++ b/lib/core/base/audit.js @@ -11,7 +11,6 @@ import { performanceTimer } from '../utils'; import doT from '@deque/dot'; -import log from '../log'; import constants from '../constants'; const dotRegex = /\{\{.+?\}\}/g; @@ -593,8 +592,8 @@ class Audit { } else if (['tag', 'tags', undefined].includes(only.type)) { only.type = 'tag'; const unmatchedTags = only.values.filter(tag => !tags.includes(tag)); - if (unmatchedTags.length !== 0) { - log('Could not find tags `' + unmatchedTags.join('`, `') + '`'); + if (unmatchedTags.length !== 0 && !/wcag2[1-3]a{1,3}/.test(unmatchedTags)) { + axe.log('Could not find tags `' + unmatchedTags.join('`, `') + '`'); } } else { throw new Error(`Unknown runOnly type '${only.type}'`); diff --git a/test/core/base/audit.js b/test/core/base/audit.js index c8fad7340d..957fa55fab 100644 --- a/test/core/base/audit.js +++ b/test/core/base/audit.js @@ -1286,6 +1286,14 @@ describe('Audit', function() { }); describe('Audit#normalizeOptions', function() { + var axeLog; + beforeEach(function () { + axeLog = axe.log; + }); + afterEach(function () { + axe.log = axeLog; + }); + it('returns the options object when it is valid', function() { var opt = { runOnly: { @@ -1440,5 +1448,33 @@ describe('Audit', function() { }); }); }); + + it('logs an issue when a tag is unknown', function () { + var message = ''; + axe.log = function (m) { + message = m; + }; + a.normalizeOptions({ + runOnly: { + type: 'tags', + values: ['unknwon-tag'] + } + }); + assert.include(message, 'Could not find tags'); + }); + + it('logs no issues for unknown WCAG level tags', function () { + var message = ''; + axe.log = function (m) { + message = m; + }; + a.normalizeOptions({ + runOnly: { + type: 'tags', + values: ['wcag23aaa'] + } + }); + assert.isEmpty(message); + }); }); }); From d5a0491688070360fbe610e124e5d11d28d5dd51 Mon Sep 17 00:00:00 2001 From: Wilco Fiers Date: Fri, 8 Oct 2021 13:36:43 +0200 Subject: [PATCH 3/3] address comments --- lib/core/base/audit.js | 8 ++++++-- test/core/base/audit.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/core/base/audit.js b/lib/core/base/audit.js index 1bb598947d..14d01cbaa2 100644 --- a/lib/core/base/audit.js +++ b/lib/core/base/audit.js @@ -591,8 +591,12 @@ class Audit { // Validate 'tags' (e.g. anything not 'rule') } else if (['tag', 'tags', undefined].includes(only.type)) { only.type = 'tag'; - const unmatchedTags = only.values.filter(tag => !tags.includes(tag)); - if (unmatchedTags.length !== 0 && !/wcag2[1-3]a{1,3}/.test(unmatchedTags)) { + + const unmatchedTags = only.values.filter(tag => ( + !tags.includes(tag) && + !/wcag2[1-3]a{1,3}/.test(tag) + )); + if (unmatchedTags.length !== 0) { axe.log('Could not find tags `' + unmatchedTags.join('`, `') + '`'); } } else { diff --git a/test/core/base/audit.js b/test/core/base/audit.js index 957fa55fab..170de0cf08 100644 --- a/test/core/base/audit.js +++ b/test/core/base/audit.js @@ -1476,5 +1476,19 @@ describe('Audit', function() { }); assert.isEmpty(message); }); + + it('logs an issue when a tag is unknown, together with a wcag level tag', function () { + var message = ''; + axe.log = function (m) { + message = m; + }; + a.normalizeOptions({ + runOnly: { + type: 'tags', + values: ['wcag23aaa', 'unknwon-tag'] + } + }); + assert.include(message, 'Could not find tags'); + }); }); });