From 0608b039712c064d4af14a9fb916644a61497787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michae=CC=88l=20De=20Boey?= Date: Fri, 25 Oct 2024 14:50:47 +0200 Subject: [PATCH 1/2] [Refactor] use `messageId` instead of `message` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michaël De Boey Co-authored-by: Jordan Harband --- __tests__/src/rules/alt-text-test.js | 23 +++++------ .../src/rules/anchor-has-content-test.js | 2 +- ...aria-activedescendant-has-tabindex-test.js | 2 +- __tests__/src/rules/aria-props-test.js | 10 +++-- __tests__/src/rules/aria-proptypes-test.js | 25 ++---------- __tests__/src/rules/aria-role-test.js | 2 +- .../rules/aria-unsupported-elements-test.js | 4 +- .../src/rules/autocomplete-valid-test.js | 6 ++- .../click-events-have-key-events-test.js | 4 +- .../src/rules/heading-has-content-test.js | 2 +- __tests__/src/rules/html-has-lang-test.js | 2 +- __tests__/src/rules/iframe-has-title-test.js | 2 +- __tests__/src/rules/img-redundant-alt-test.js | 2 +- __tests__/src/rules/lang-test.js | 2 +- __tests__/src/rules/no-access-key-test.js | 2 +- .../rules/no-aria-hidden-on-focusable-test.js | 2 +- __tests__/src/rules/no-autofocus-test.js | 2 +- .../src/rules/no-distracting-elements-test.js | 3 +- .../src/rules/prefer-tag-over-role-test.js | 3 +- .../role-has-required-aria-props-test.js | 3 +- .../rules/role-supports-aria-props-test.js | 11 +----- __tests__/src/rules/scope-test.js | 2 +- .../src/rules/tabindex-no-positive-test.js | 2 +- src/rules/alt-text.js | 36 ++++++++++++----- src/rules/anchor-has-content.js | 7 ++-- .../aria-activedescendant-has-tabindex.js | 7 ++-- src/rules/aria-props.js | 25 ++++++------ src/rules/aria-proptypes.js | 39 ++++++++----------- src/rules/aria-role.js | 7 ++-- src/rules/aria-unsupported-elements.js | 13 ++++--- src/rules/autocomplete-valid.js | 8 +++- src/rules/click-events-have-key-events.js | 7 ++-- src/rules/heading-has-content.js | 7 ++-- src/rules/html-has-lang.js | 7 ++-- src/rules/iframe-has-title.js | 7 ++-- src/rules/img-redundant-alt.js | 7 ++-- src/rules/lang.js | 9 +++-- src/rules/no-access-key.js | 7 ++-- src/rules/no-aria-hidden-on-focusable.js | 5 ++- src/rules/no-autofocus.js | 7 ++-- src/rules/no-distracting-elements.js | 12 +++--- src/rules/prefer-tag-over-role.js | 7 ++-- src/rules/role-has-required-aria-props.js | 13 ++++--- src/rules/role-supports-aria-props.js | 19 ++++----- src/rules/scope.js | 7 ++-- src/rules/tabindex-no-positive.js | 7 ++-- 46 files changed, 205 insertions(+), 183 deletions(-) diff --git a/__tests__/src/rules/alt-text-test.js b/__tests__/src/rules/alt-text-test.js index 24e36e23d..31b15b71c 100644 --- a/__tests__/src/rules/alt-text-test.js +++ b/__tests__/src/rules/alt-text-test.js @@ -18,39 +18,40 @@ import rule from '../../../src/rules/alt-text'; const ruleTester = new RuleTester(); -const missingPropError = (type) => ({ - message: `${type} elements must have an alt prop, either with meaningful text, or an empty string for decorative images.`, +const missingPropError = (nodeType) => ({ + messageId: 'img-no-alt', + data: { nodeType }, type: 'JSXOpeningElement', }); -const altValueError = (type) => ({ - message: `Invalid alt value for ${type}. \ -Use alt="" for presentational images.`, +const altValueError = (nodeType) => ({ + messageId: 'img-invalid-alt', + data: { nodeType }, type: 'JSXOpeningElement', }); const ariaLabelValueError = { - message: 'The aria-label attribute must have a value. The alt attribute is preferred over aria-label for images.', + messageId: 'img-no-aria-label-value', }; const ariaLabelledbyValueError = { - message: 'The aria-labelledby attribute must have a value. The alt attribute is preferred over aria-labelledby for images.', + messageId: 'img-no-aria-labelledby-value', }; const preferAltError = () => ({ - message: 'Prefer alt="" over a presentational role. First rule of aria is to not use aria if it can be achieved via native HTML.', + messageId: 'img-presentation-role', type: 'JSXOpeningElement', }); const objectError = { - message: 'Embedded elements must have alternative text by providing inner text, aria-label or aria-labelledby props.', + messageId: 'object', }; const areaError = { - message: 'Each area of an image map must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.', + messageId: 'area', }; const inputImageError = { - message: ' elements with type="image" must have a text alternative through the `alt`, `aria-label`, or `aria-labelledby` prop.', + messageId: 'input-image', }; const componentsSettings = { diff --git a/__tests__/src/rules/anchor-has-content-test.js b/__tests__/src/rules/anchor-has-content-test.js index c55dbb9fb..b5680b76b 100644 --- a/__tests__/src/rules/anchor-has-content-test.js +++ b/__tests__/src/rules/anchor-has-content-test.js @@ -19,7 +19,7 @@ import rule from '../../../src/rules/anchor-has-content'; const ruleTester = new RuleTester(); const expectedError = { - message: 'Anchors must have content and the content must be accessible by a screen reader.', + messageId: 'error', type: 'JSXOpeningElement', }; diff --git a/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js b/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js index 5310ac9ac..2368b6d63 100644 --- a/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js +++ b/__tests__/src/rules/aria-activedescendant-has-tabindex-test.js @@ -19,7 +19,7 @@ import rule from '../../../src/rules/aria-activedescendant-has-tabindex'; const ruleTester = new RuleTester(); const expectedError = { - message: 'An element that manages focus with `aria-activedescendant` must have a tabindex', + messageId: 'error', type: 'JSXOpeningElement', }; diff --git a/__tests__/src/rules/aria-props-test.js b/__tests__/src/rules/aria-props-test.js index 1236fa7c7..71c26d363 100644 --- a/__tests__/src/rules/aria-props-test.js +++ b/__tests__/src/rules/aria-props-test.js @@ -23,18 +23,22 @@ const ariaAttributes = [...aria.keys()]; const errorMessage = (name) => { const suggestions = getSuggestion(name, ariaAttributes); - const message = `${name}: This attribute is an invalid ARIA attribute.`; if (suggestions.length > 0) { return { type: 'JSXAttribute', - message: `${message} Did you mean to use ${suggestions}?`, + messageId: 'error-with-suggestions', + data: { + name, + suggestions, + }, }; } return { type: 'JSXAttribute', - message, + messageId: 'error', + data: { name }, }; }; diff --git a/__tests__/src/rules/aria-proptypes-test.js b/__tests__/src/rules/aria-proptypes-test.js index 851cd7b30..b6dfc7d75 100644 --- a/__tests__/src/rules/aria-proptypes-test.js +++ b/__tests__/src/rules/aria-proptypes-test.js @@ -29,27 +29,10 @@ const errorMessage = (name) => { values: permittedValues, } = aria.get(name.toLowerCase()); - switch (type) { - case 'tristate': - return { message: `The value for ${name} must be a boolean or the string "mixed".` }; - case 'token': - return { message: `The value for ${name} must be a single token from the following: ${permittedValues}.` }; - case 'tokenlist': - return { - message: `The value for ${name} must be a list of one or more \ -tokens from the following: ${permittedValues}.`, - }; - case 'idlist': - return { message: `The value for ${name} must be a list of strings that represent DOM element IDs (idlist)` }; - case 'id': - return { message: `The value for ${name} must be a string that represents a DOM element ID` }; - case 'boolean': - case 'string': - case 'integer': - case 'number': - default: - return { message: `The value for ${name} must be a ${type}.` }; - } + return { + messageId: type, + data: { name, permittedValues, type }, + }; }; test('validityCheck', (t) => { diff --git a/__tests__/src/rules/aria-role-test.js b/__tests__/src/rules/aria-role-test.js index 9a8ec3a89..21a51fe07 100644 --- a/__tests__/src/rules/aria-role-test.js +++ b/__tests__/src/rules/aria-role-test.js @@ -20,7 +20,7 @@ import rule from '../../../src/rules/aria-role'; const ruleTester = new RuleTester(); const errorMessage = { - message: 'Elements with ARIA roles must use a valid, non-abstract ARIA role.', + messageId: 'error', type: 'JSXAttribute', }; diff --git a/__tests__/src/rules/aria-unsupported-elements-test.js b/__tests__/src/rules/aria-unsupported-elements-test.js index 0b7533325..4ec6e4caf 100644 --- a/__tests__/src/rules/aria-unsupported-elements-test.js +++ b/__tests__/src/rules/aria-unsupported-elements-test.js @@ -21,8 +21,8 @@ import rule from '../../../src/rules/aria-unsupported-elements'; const ruleTester = new RuleTester(); const errorMessage = (invalidProp) => ({ - message: `This element does not support ARIA roles, states and properties. \ -Try removing the prop '${invalidProp}'.`, + messageId: 'error', + data: { invalidProp }, type: 'JSXOpeningElement', }); diff --git a/__tests__/src/rules/autocomplete-valid-test.js b/__tests__/src/rules/autocomplete-valid-test.js index 57b1257c0..c0fda8652 100644 --- a/__tests__/src/rules/autocomplete-valid-test.js +++ b/__tests__/src/rules/autocomplete-valid-test.js @@ -20,12 +20,14 @@ import rule from '../../../src/rules/autocomplete-valid'; const ruleTester = new RuleTester(); const invalidAutocomplete = [{ - message: axeFailMessage('autocomplete-valid'), + messageId: 'error', + data: { message: axeFailMessage('autocomplete-valid') }, type: 'JSXOpeningElement', }]; const inappropriateAutocomplete = [{ - message: axeFailMessage('autocomplete-appropriate'), + messageId: 'error', + data: { message: axeFailMessage('autocomplete-appropriate') }, type: 'JSXOpeningElement', }]; diff --git a/__tests__/src/rules/click-events-have-key-events-test.js b/__tests__/src/rules/click-events-have-key-events-test.js index 683a71b7b..a5870c383 100644 --- a/__tests__/src/rules/click-events-have-key-events-test.js +++ b/__tests__/src/rules/click-events-have-key-events-test.js @@ -18,10 +18,8 @@ import rule from '../../../src/rules/click-events-have-key-events'; const ruleTester = new RuleTester(); -const errorMessage = 'Visible, non-interactive elements with click handlers must have at least one keyboard listener.'; - const expectedError = { - message: errorMessage, + messageId: 'error', type: 'JSXOpeningElement', }; diff --git a/__tests__/src/rules/heading-has-content-test.js b/__tests__/src/rules/heading-has-content-test.js index f9955440e..d59a82ed6 100644 --- a/__tests__/src/rules/heading-has-content-test.js +++ b/__tests__/src/rules/heading-has-content-test.js @@ -19,7 +19,7 @@ import rule from '../../../src/rules/heading-has-content'; const ruleTester = new RuleTester(); const expectedError = { - message: 'Headings must have content and the content must be accessible by a screen reader.', + messageId: 'error', type: 'JSXOpeningElement', }; diff --git a/__tests__/src/rules/html-has-lang-test.js b/__tests__/src/rules/html-has-lang-test.js index 4af612b9c..5d0d6911d 100644 --- a/__tests__/src/rules/html-has-lang-test.js +++ b/__tests__/src/rules/html-has-lang-test.js @@ -19,7 +19,7 @@ import rule from '../../../src/rules/html-has-lang'; const ruleTester = new RuleTester(); const expectedError = { - message: ' elements must have the lang prop.', + messageId: 'error', type: 'JSXOpeningElement', }; diff --git a/__tests__/src/rules/iframe-has-title-test.js b/__tests__/src/rules/iframe-has-title-test.js index 0bf60311f..5ced742f5 100644 --- a/__tests__/src/rules/iframe-has-title-test.js +++ b/__tests__/src/rules/iframe-has-title-test.js @@ -19,7 +19,7 @@ import rule from '../../../src/rules/iframe-has-title'; const ruleTester = new RuleTester(); const expectedError = { - message: '