diff --git a/__tests__/src/rules/label-has-associated-control-test.js b/__tests__/src/rules/label-has-associated-control-test.js
index 0bd14107..c765d971 100644
--- a/__tests__/src/rules/label-has-associated-control-test.js
+++ b/__tests__/src/rules/label-has-associated-control-test.js
@@ -26,6 +26,11 @@ const expectedError = {
type: 'JSXOpeningElement',
};
+const expectedErrorNoLabel = {
+ message: 'A form label must have accessible text.',
+ type: 'JSXOpeningElement',
+};
+
const componentsSettings = {
'jsx-a11y': {
components: {
@@ -132,12 +137,12 @@ const nestingInvalid = [
];
const neverValid = [
- { code: '', errors: [expectedError] },
- { code: '', errors: [expectedError] },
- { code: '', errors: [expectedError] },
- { code: '', errors: [expectedError] },
+ { code: '', errors: [expectedErrorNoLabel] },
+ { code: '', errors: [expectedErrorNoLabel] },
+ { code: '', errors: [expectedErrorNoLabel] },
+ { code: '', errors: [expectedErrorNoLabel] },
{ code: '', errors: [expectedError] },
- { code: '
', errors: [expectedError] },
+ { code: '', errors: [expectedErrorNoLabel] },
{ code: '', errors: [expectedError] },
// Custom label component.
{ code: '', options: [{ labelComponents: ['CustomLabel'] }], errors: [expectedError] },
@@ -146,11 +151,11 @@ const neverValid = [
// Custom label attributes.
{ code: '', options: [{ labelAttributes: ['label'] }], errors: [expectedError] },
// Custom controlComponents.
- { code: '', options: [{ controlComponents: ['CustomInput'] }], errors: [expectedError] },
- { code: '', options: [{ controlComponents: ['CustomInput'], labelComponents: ['CustomLabel'] }], errors: [expectedError] },
- { code: '', options: [{ controlComponents: ['CustomInput'], labelComponents: ['CustomLabel'], labelAttributes: ['label'] }], errors: [expectedError] },
- { code: '', settings: componentsSettings, errors: [expectedError] },
- { code: '', settings: componentsSettings, errors: [expectedError] },
+ { code: '', options: [{ controlComponents: ['CustomInput'] }], errors: [expectedErrorNoLabel] },
+ { code: '', options: [{ controlComponents: ['CustomInput'], labelComponents: ['CustomLabel'] }], errors: [expectedErrorNoLabel] },
+ { code: '', options: [{ controlComponents: ['CustomInput'], labelComponents: ['CustomLabel'], labelAttributes: ['label'] }], errors: [expectedErrorNoLabel] },
+ { code: '', settings: componentsSettings, errors: [expectedErrorNoLabel] },
+ { code: '', settings: componentsSettings, errors: [expectedErrorNoLabel] },
];
// htmlFor valid
ruleTester.run(ruleName, rule, {
diff --git a/src/rules/label-has-associated-control.js b/src/rules/label-has-associated-control.js
index fd66f2cf..5646859c 100644
--- a/src/rules/label-has-associated-control.js
+++ b/src/rules/label-has-associated-control.js
@@ -18,6 +18,7 @@ import mayContainChildComponent from '../util/mayContainChildComponent';
import mayHaveAccessibleLabel from '../util/mayHaveAccessibleLabel';
const errorMessage = 'A form label must be associated with a control.';
+const errorMessageNoLabel = 'A form label must have accessible text.';
const schema = generateObjSchema({
labelComponents: arraySchema,
@@ -91,31 +92,37 @@ export default ({
controlComponents,
);
- if (hasAccessibleLabel) {
- switch (assertType) {
- case 'htmlFor':
- if (hasLabelId) {
- return;
- }
- break;
- case 'nesting':
- if (hasNestedControl) {
- return;
- }
- break;
- case 'both':
- if (hasLabelId && hasNestedControl) {
- return;
- }
- break;
- case 'either':
- if (hasLabelId || hasNestedControl) {
- return;
- }
- break;
- default:
- break;
- }
+ if (!hasAccessibleLabel) {
+ context.report({
+ node: node.openingElement,
+ message: errorMessageNoLabel,
+ });
+ return;
+ }
+
+ switch (assertType) {
+ case 'htmlFor':
+ if (hasLabelId) {
+ return;
+ }
+ break;
+ case 'nesting':
+ if (hasNestedControl) {
+ return;
+ }
+ break;
+ case 'both':
+ if (hasLabelId && hasNestedControl) {
+ return;
+ }
+ break;
+ case 'either':
+ if (hasLabelId || hasNestedControl) {
+ return;
+ }
+ break;
+ default:
+ break;
}
// htmlFor case