11
11
import { RuleTester } from 'eslint' ;
12
12
import parserOptionsMapper from '../../__util__/parserOptionsMapper' ;
13
13
import rule from '../../../src/rules/label-has-associated-control' ;
14
+ import ruleOptionsMapperFactory from '../../__util__/ruleOptionsMapperFactory' ;
14
15
15
16
// -----------------------------------------------------------------------------
16
17
// Tests
@@ -25,12 +26,17 @@ const expectedError = {
25
26
type : 'JSXOpeningElement' ,
26
27
} ;
27
28
28
- const alwaysValid = [
29
- { code : '<div />' } ,
30
- { code : '<CustomElement />' } ,
29
+ const htmlForValid = [
31
30
{ code : '<label htmlFor="js_id"><span><span><span>A label</span></span></span></label>' , options : [ { depth : 4 } ] } ,
32
31
{ code : '<label htmlFor="js_id" aria-label="A label" />' } ,
33
32
{ code : '<label htmlFor="js_id" aria-labelledby="A label" />' } ,
33
+ // Custom label component.
34
+ { code : '<CustomLabel htmlFor="js_id" aria-label="A label" />' , options : [ { labelComponents : [ 'CustomLabel' ] } ] } ,
35
+ { code : '<CustomLabel htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] , labelComponents : [ 'CustomLabel' ] } ] } ,
36
+ // Custom label attributes.
37
+ { code : '<label htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] } ] } ,
38
+ ] ;
39
+ const nestingValid = [
34
40
{ code : '<label>A label<input /></label>' } ,
35
41
{ code : '<label><img alt="A label" /><input /></label>' } ,
36
42
{ code : '<label><img aria-label="A label" /><input /></label>' } ,
@@ -40,16 +46,54 @@ const alwaysValid = [
40
46
{ code : '<label><span><span><span><span>A label</span><input /></span></span></span></label>' , options : [ { depth : 5 } ] } ,
41
47
{ code : '<label><span><span><span><span aria-label="A label" /><input /></span></span></span></label>' , options : [ { depth : 5 } ] } ,
42
48
{ code : '<label><span><span><span><input aria-label="A label" /></span></span></span></label>' , options : [ { depth : 5 } ] } ,
43
- // Custom label component.
44
- { code : '<CustomLabel htmlFor="js_id" aria-label="A label" />' , options : [ { labelComponents : [ 'CustomLabel' ] } ] } ,
45
- { code : '<CustomLabel htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] , labelComponents : [ 'CustomLabel' ] } ] } ,
46
- // Custom label attributes.
47
- { code : '<label htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] } ] } ,
48
49
// Custom controlComponents.
49
50
{ code : '<label><span>A label<CustomInput /></span></label>' , options : [ { controlComponents : [ 'CustomInput' ] } ] } ,
50
51
{ code : '<CustomLabel><span>A label<CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] } ] } ,
51
52
{ code : '<CustomLabel><span label="A label"><CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] , labelAttributes : [ 'label' ] } ] } ,
52
53
] ;
54
+
55
+ const bothValid = [
56
+ { code : '<label htmlFor="js_id"><span><span><span>A label<input /></span></span></span></label>' , options : [ { depth : 4 } ] } ,
57
+ { code : '<label htmlFor="js_id" aria-label="A label"><input /></label>' } ,
58
+ { code : '<label htmlFor="js_id" aria-labelledby="A label"><input /></label>' } ,
59
+ // Custom label component.
60
+ { code : '<CustomLabel htmlFor="js_id" aria-label="A label"><input /></CustomLabel>' , options : [ { labelComponents : [ 'CustomLabel' ] } ] } ,
61
+ { code : '<CustomLabel htmlFor="js_id" label="A label"><input /></CustomLabel>' , options : [ { labelAttributes : [ 'label' ] , labelComponents : [ 'CustomLabel' ] } ] } ,
62
+ // Custom label attributes.
63
+ { code : '<label htmlFor="js_id" label="A label"><input /></label>' , options : [ { labelAttributes : [ 'label' ] } ] } ,
64
+ ] ;
65
+
66
+ const alwaysValid = [
67
+ { code : '<div />' } ,
68
+ { code : '<CustomElement />' } ,
69
+ ] ;
70
+
71
+ const htmlForInvalid = [
72
+ { code : '<label htmlFor="js_id"><span><span><span>A label</span></span></span></label>' , options : [ { depth : 4 } ] , errors : [ expectedError ] } ,
73
+ { code : '<label htmlFor="js_id" aria-label="A label" />' , errors : [ expectedError ] } ,
74
+ { code : '<label htmlFor="js_id" aria-labelledby="A label" />' , errors : [ expectedError ] } ,
75
+ // Custom label component.
76
+ { code : '<CustomLabel htmlFor="js_id" aria-label="A label" />' , options : [ { labelComponents : [ 'CustomLabel' ] } ] , errors : [ expectedError ] } ,
77
+ { code : '<CustomLabel htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] , labelComponents : [ 'CustomLabel' ] } ] , errors : [ expectedError ] } ,
78
+ // Custom label attributes.
79
+ { code : '<label htmlFor="js_id" label="A label" />' , options : [ { labelAttributes : [ 'label' ] } ] , errors : [ expectedError ] } ,
80
+ ] ;
81
+ const nestingInvalid = [
82
+ { code : '<label>A label<input /></label>' , errors : [ expectedError ] } ,
83
+ { code : '<label><img alt="A label" /><input /></label>' , errors : [ expectedError ] } ,
84
+ { code : '<label><img aria-label="A label" /><input /></label>' , errors : [ expectedError ] } ,
85
+ { code : '<label><span>A label<input /></span></label>' , errors : [ expectedError ] } ,
86
+ { code : '<label><span><span>A label<input /></span></span></label>' , options : [ { depth : 3 } ] , errors : [ expectedError ] } ,
87
+ { code : '<label><span><span><span>A label<input /></span></span></span></label>' , options : [ { depth : 4 } ] , errors : [ expectedError ] } ,
88
+ { code : '<label><span><span><span><span>A label</span><input /></span></span></span></label>' , options : [ { depth : 5 } ] , errors : [ expectedError ] } ,
89
+ { code : '<label><span><span><span><span aria-label="A label" /><input /></span></span></span></label>' , options : [ { depth : 5 } ] , errors : [ expectedError ] } ,
90
+ { code : '<label><span><span><span><input aria-label="A label" /></span></span></span></label>' , options : [ { depth : 5 } ] , errors : [ expectedError ] } ,
91
+ // Custom controlComponents.
92
+ { code : '<label><span>A label<CustomInput /></span></label>' , options : [ { controlComponents : [ 'CustomInput' ] } ] , errors : [ expectedError ] } ,
93
+ { code : '<CustomLabel><span>A label<CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] } ] , errors : [ expectedError ] } ,
94
+ { code : '<CustomLabel><span label="A label"><CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] , labelAttributes : [ 'label' ] } ] , errors : [ expectedError ] } ,
95
+ ] ;
96
+
53
97
const neverValid = [
54
98
{ code : '<label htmlFor="js_id" />' , errors : [ expectedError ] } ,
55
99
{ code : '<label htmlFor="js_id"><input /></label>' , errors : [ expectedError ] } ,
@@ -67,11 +111,72 @@ const neverValid = [
67
111
{ code : '<CustomLabel><span><CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] } ] , errors : [ expectedError ] } ,
68
112
{ code : '<CustomLabel><span><CustomInput /></span></CustomLabel>' , options : [ { controlComponents : [ 'CustomInput' ] , labelComponents : [ 'CustomLabel' ] , labelAttributes : [ 'label' ] } ] , errors : [ expectedError ] } ,
69
113
] ;
114
+ // htmlFor valid
115
+ ruleTester . run ( ruleName , rule , {
116
+ valid : [
117
+ ...alwaysValid ,
118
+ ...htmlForValid ,
119
+ ]
120
+ . map ( ruleOptionsMapperFactory ( {
121
+ assert : 'htmlFor' ,
122
+ } ) )
123
+ . map ( parserOptionsMapper ) ,
124
+ invalid : [
125
+ ...neverValid ,
126
+ ...nestingInvalid ,
127
+ ]
128
+ . map ( ruleOptionsMapperFactory ( {
129
+ assert : 'htmlFor' ,
130
+ } ) )
131
+ . map ( parserOptionsMapper ) ,
132
+ } ) ;
70
133
134
+ // nesting valid
71
135
ruleTester . run ( ruleName , rule , {
72
136
valid : [
73
137
...alwaysValid ,
138
+ ...nestingValid ,
139
+ ]
140
+ . map ( ruleOptionsMapperFactory ( {
141
+ assert : 'nesting' ,
142
+ } ) )
143
+ . map ( parserOptionsMapper ) ,
144
+ invalid : [
145
+ ...neverValid ,
146
+ ...htmlForInvalid ,
147
+ ]
148
+ . map ( ruleOptionsMapperFactory ( {
149
+ assert : 'nesting' ,
150
+ } ) )
151
+ . map ( parserOptionsMapper ) ,
152
+ } ) ;
153
+
154
+ // either valid
155
+ ruleTester . run ( ruleName , rule , {
156
+ valid : [
157
+ ...alwaysValid ,
158
+ ...htmlForValid ,
159
+ ...nestingValid ,
160
+ ]
161
+ . map ( ruleOptionsMapperFactory ( {
162
+ assert : 'either' ,
163
+ } ) )
164
+ . map ( parserOptionsMapper ) ,
165
+ invalid : [
166
+ ...neverValid ,
74
167
] . map ( parserOptionsMapper ) ,
168
+ } ) ;
169
+
170
+ // both valid
171
+ ruleTester . run ( ruleName , rule , {
172
+ valid : [
173
+ ...alwaysValid ,
174
+ ...bothValid ,
175
+ ]
176
+ . map ( ruleOptionsMapperFactory ( {
177
+ assert : 'both' ,
178
+ } ) )
179
+ . map ( parserOptionsMapper ) ,
75
180
invalid : [
76
181
...neverValid ,
77
182
] . map ( parserOptionsMapper ) ,
0 commit comments