From 60ddc6577b70e27e9e7fe340d163b01360035e13 Mon Sep 17 00:00:00 2001 From: Steven Lambert <2433219+straker@users.noreply.github.com> Date: Fri, 5 Jun 2020 08:35:09 -0600 Subject: [PATCH] feat(has-text-content): add generic check has-text-content (#2234) * feat(has-text-content): add generic check has-text-content * make empty-heading minor --- .../generic/has-text-content-evaluate.js | 7 +++++++ .../shared/button-has-visible-text-evaluate.js | 18 ------------------ lib/checks/shared/button-has-visible-text.json | 2 +- ...uate.js => has-accessible-text-evaluate.js} | 4 ++-- lib/checks/shared/has-accessible-text.json | 11 +++++++++++ lib/checks/shared/has-visible-text.json | 2 +- lib/core/base/metadata-function-map.js | 8 ++++---- lib/rules/empty-heading.json | 2 +- test/checks/shared/button-has-visible-text.js | 2 -- 9 files changed, 27 insertions(+), 29 deletions(-) create mode 100644 lib/checks/generic/has-text-content-evaluate.js delete mode 100644 lib/checks/shared/button-has-visible-text-evaluate.js rename lib/checks/shared/{has-visible-text-evaluate.js => has-accessible-text-evaluate.js} (52%) create mode 100644 lib/checks/shared/has-accessible-text.json diff --git a/lib/checks/generic/has-text-content-evaluate.js b/lib/checks/generic/has-text-content-evaluate.js new file mode 100644 index 0000000000..17b8976c9a --- /dev/null +++ b/lib/checks/generic/has-text-content-evaluate.js @@ -0,0 +1,7 @@ +import { sanitize, subtreeText } from '../../commons/text'; + +function hasTextContentEvaluate(node, options, virtualNode) { + return sanitize(subtreeText(virtualNode)) !== ''; +} + +export default hasTextContentEvaluate; diff --git a/lib/checks/shared/button-has-visible-text-evaluate.js b/lib/checks/shared/button-has-visible-text-evaluate.js deleted file mode 100644 index fb714ef43d..0000000000 --- a/lib/checks/shared/button-has-visible-text-evaluate.js +++ /dev/null @@ -1,18 +0,0 @@ -import { accessibleTextVirtual } from '../../commons/text'; - -function buttonHasVisibleTextEvaluate(node, options, virtualNode) { - let nodeName = node.nodeName.toUpperCase(); - let role = node.getAttribute('role'); - let label; - - if (nodeName === 'BUTTON' || (role === 'button' && nodeName !== 'INPUT')) { - label = accessibleTextVirtual(virtualNode); - this.data(label); - - return !!label; - } else { - return false; - } -} - -export default buttonHasVisibleTextEvaluate; diff --git a/lib/checks/shared/button-has-visible-text.json b/lib/checks/shared/button-has-visible-text.json index 3769f84234..e28465f5f3 100644 --- a/lib/checks/shared/button-has-visible-text.json +++ b/lib/checks/shared/button-has-visible-text.json @@ -1,6 +1,6 @@ { "id": "button-has-visible-text", - "evaluate": "button-has-visible-text-evaluate", + "evaluate": "has-text-content-evaluate", "metadata": { "impact": "critical", "messages": { diff --git a/lib/checks/shared/has-visible-text-evaluate.js b/lib/checks/shared/has-accessible-text-evaluate.js similarity index 52% rename from lib/checks/shared/has-visible-text-evaluate.js rename to lib/checks/shared/has-accessible-text-evaluate.js index e3e0c07023..19222e8c49 100644 --- a/lib/checks/shared/has-visible-text-evaluate.js +++ b/lib/checks/shared/has-accessible-text-evaluate.js @@ -1,7 +1,7 @@ import { accessibleTextVirtual } from '../../commons/text'; -function hasVisibleTextEvaluate(node, options, virtualNode) { +function hasAccessibleTextEvaluate(node, options, virtualNode) { return accessibleTextVirtual(virtualNode).length > 0; } -export default hasVisibleTextEvaluate; +export default hasAccessibleTextEvaluate; diff --git a/lib/checks/shared/has-accessible-text.json b/lib/checks/shared/has-accessible-text.json new file mode 100644 index 0000000000..8aa07402e5 --- /dev/null +++ b/lib/checks/shared/has-accessible-text.json @@ -0,0 +1,11 @@ +{ + "id": "has-accessible-text", + "evaluate": "has-accessible-text-evaluate", + "metadata": { + "impact": "minor", + "messages": { + "pass": "Element has text that is visible to screen readers", + "fail": "Element does not have text that is visible to screen readers" + } + } +} diff --git a/lib/checks/shared/has-visible-text.json b/lib/checks/shared/has-visible-text.json index e72634c22a..81c2f57a24 100644 --- a/lib/checks/shared/has-visible-text.json +++ b/lib/checks/shared/has-visible-text.json @@ -1,6 +1,6 @@ { "id": "has-visible-text", - "evaluate": "has-visible-text-evaluate", + "evaluate": "has-text-content-evaluate", "metadata": { "impact": "minor", "messages": { diff --git a/lib/core/base/metadata-function-map.js b/lib/core/base/metadata-function-map.js index a0c477d6b2..db99a49263 100644 --- a/lib/core/base/metadata-function-map.js +++ b/lib/core/base/metadata-function-map.js @@ -42,6 +42,7 @@ import autocompleteValidEvaluate from '../../checks/forms/autocomplete-valid-eva import attrNonSpaceContentEvaluate from '../../checks/generic/attr-non-space-content-evaluate'; import hasDescendantAfter from '../../checks/generic/has-descendant-after'; import hasDescendantEvaluate from '../../checks/generic/has-descendant-evaluate'; +import hasTextContentEvaluate from '../../checks/generic/has-text-content-evaluate'; import matchesDefinitionEvaluate from '../../checks/generic/matches-definition-evaluate'; import pageNoDuplicateAfter from '../../checks/generic/page-no-duplicate-after'; import pageNoDuplicateEvaluate from '../../checks/generic/page-no-duplicate-evaluate'; @@ -63,11 +64,10 @@ import uniqueFrameTitleEvaluate from '../../checks/navigation/unique-frame-title import ariaLabelEvaluate from '../../checks/shared/aria-label-evaluate'; import ariaLabelledbyEvaluate from '../../checks/shared/aria-labelledby-evaluate'; import avoidInlineSpacingEvaluate from '../../checks/shared/avoid-inline-spacing-evaluate'; -import buttonHasVisibleTextEvaluate from '../../checks/shared/button-has-visible-text-evaluate'; import docHasTitleEvaluate from '../../checks/shared/doc-has-title-evaluate'; import existsEvaluate from '../../checks/shared/exists-evaluate'; +import hasAccessibleTextEvaluate from '../../checks/shared/has-accessible-text-evaluate'; import hasAltEvaluate from '../../checks/shared/has-alt-evaluate'; -import hasVisibleTextEvaluate from '../../checks/shared/has-visible-text-evaluate'; import isOnScreenEvaluate from '../../checks/shared/is-on-screen-evaluate'; import nonEmptyIfPresentEvaluate from '../../checks/shared/non-empty-if-present-evaluate'; import svgNonEmptyTitleEvaluate from '../../checks/shared/svg-non-empty-title-evaluate'; @@ -204,6 +204,7 @@ const metadataFunctionMap = { 'attr-non-space-content-evaluate': attrNonSpaceContentEvaluate, 'has-descendant-after': hasDescendantAfter, 'has-descendant-evaluate': hasDescendantEvaluate, + 'has-text-content-evaluate': hasTextContentEvaluate, 'matches-definition-evaluate': matchesDefinitionEvaluate, 'page-no-duplicate-after': pageNoDuplicateAfter, 'page-no-duplicate-evaluate': pageNoDuplicateEvaluate, @@ -225,11 +226,10 @@ const metadataFunctionMap = { 'aria-label-evaluate': ariaLabelEvaluate, 'aria-labelledby-evaluate': ariaLabelledbyEvaluate, 'avoid-inline-spacing-evaluate': avoidInlineSpacingEvaluate, - 'button-has-visible-text-evaluate': buttonHasVisibleTextEvaluate, 'doc-has-title-evaluate': docHasTitleEvaluate, 'exists-evaluate': existsEvaluate, + 'has-accessible-text-evaluate': hasAccessibleTextEvaluate, 'has-alt-evaluate': hasAltEvaluate, - 'has-visible-text-evaluate': hasVisibleTextEvaluate, 'is-on-screen-evaluate': isOnScreenEvaluate, 'non-empty-if-present-evaluate': nonEmptyIfPresentEvaluate, 'svg-non-empty-title-evaluate': svgNonEmptyTitleEvaluate, diff --git a/lib/rules/empty-heading.json b/lib/rules/empty-heading.json index 3c32db6900..391e041c8a 100644 --- a/lib/rules/empty-heading.json +++ b/lib/rules/empty-heading.json @@ -8,6 +8,6 @@ "help": "Headings must not be empty" }, "all": [], - "any": ["has-visible-text"], + "any": ["has-accessible-text"], "none": [] } diff --git a/test/checks/shared/button-has-visible-text.js b/test/checks/shared/button-has-visible-text.js index 17a33e98ef..042832d40a 100644 --- a/test/checks/shared/button-has-visible-text.js +++ b/test/checks/shared/button-has-visible-text.js @@ -28,7 +28,6 @@ describe('button-has-visible-text', function() { .getCheckEvaluate('button-has-visible-text') .apply(checkContext, checkArgs) ); - assert.deepEqual(checkContext._data, 'Name'); }); it('should return true if ARIA button has text', function() { @@ -42,7 +41,6 @@ describe('button-has-visible-text', function() { .getCheckEvaluate('button-has-visible-text') .apply(checkContext, checkArgs) ); - assert.deepEqual(checkContext._data, 'Text'); }); it('should return false if ARIA button has no text', function() {