@@ -23,38 +23,101 @@ ruleTester.run("prefer-disabledfocusable-over-disabled", rule as unknown as Rule
2323 "<Checkbox disabled />" ,
2424 "<Input disabled={true} />" ,
2525 "<SpinButton disabled={isDisabled} />" ,
26+ "<CompoundButton disabled={false} />" ,
27+ "<ToggleButton disabled={isFormDisabled} />" ,
2628
2729 // ✅ Acceptable: loading state without disabled
2830 "<Button loading>Submit</Button>" ,
2931 "<SpinButton isLoading />" ,
3032 "<Combobox pending={isPending} />" ,
3133 "<Input busy />" ,
34+ "<Textarea isPending />" ,
35+ "<Dropdown isBusy />" ,
36+ "<Slider loading={true} />" ,
37+ "<DatePicker isLoading={fetching} />" ,
38+ "<TimePicker pending={processing} />" ,
3239
3340 // ✅ Acceptable: neither disabled nor loading
3441 "<Button>Submit</Button>" ,
3542 "<Checkbox />" ,
3643 "<Input />" ,
44+ "<CompoundButton />" ,
45+ "<MenuButton />" ,
46+ "<SplitButton />" ,
47+ "<Switch />" ,
48+ "<Radio />" ,
49+ "<Link />" ,
50+ "<Tab />" ,
3751
3852 // ✅ Non-applicable components (don't support disabledFocusable)
3953 "<div disabled loading>Content</div>" ,
4054 "<Label disabled loading>Label</Label>" ,
4155 "<Text disabled loading>Text</Text>" ,
56+ "<span disabled isLoading>Span</span>" ,
57+ "<Accordion disabled loading />" ,
58+ "<Avatar disabled pending />" ,
59+ "<Badge disabled busy />" ,
60+ "<Breadcrumb disabled isLoading />" ,
61+ "<Card disabled pending />" ,
62+ "<Dialog disabled loading />" ,
63+ "<Divider disabled isLoading />" ,
64+ "<Field disabled pending />" ,
65+ "<Image disabled busy />" ,
66+ "<List disabled loading />" ,
67+ "<MessageBar disabled isLoading />" ,
68+ "<Nav disabled pending />" ,
69+ "<Popover disabled busy />" ,
70+ "<Portal disabled loading />" ,
71+ "<ProgressBar disabled isLoading />" ,
72+ "<Skeleton disabled pending />" ,
73+ "<Spinner disabled busy />" ,
74+ "<Toolbar disabled loading />" ,
75+ "<Tooltip disabled isLoading />" ,
4276
4377 // ✅ Edge case: both disabledFocusable and disabled present (different rule concern)
4478 "<Button disabled disabledFocusable loading>Submit</Button>" ,
79+ "<Input disabled disabledFocusable isLoading />" ,
80+ "<Checkbox disabled={true} disabledFocusable={false} pending />" ,
81+ "<ToggleButton disabled={isDisabled} disabledFocusable={shouldFocus} busy />" ,
4582
4683 // ✅ Complex expressions
4784 "<Button disabledFocusable={shouldDisable} loading={isSubmitting}>Submit</Button>" ,
4885 "<Input disabledFocusable={disabled && !error} isLoading={fetching} />" ,
86+ "<SpinButton disabledFocusable={!enabled || hasError} pending={processing} />" ,
4987
50- // ✅ All supported loading props
88+ // ✅ All supported loading props with disabledFocusable
5189 "<Button disabledFocusable isPending>Submit</Button>" ,
5290 "<Button disabledFocusable isBusy>Submit</Button>" ,
53- "<Button disabledFocusable busy>Submit</Button>"
91+ "<Button disabledFocusable busy>Submit</Button>" ,
92+
93+ // ✅ Empty prop values that should be considered "empty" by hasNonEmptyProp
94+ '<Button disabled="" loading>Submit</Button>' , // Empty string should not trigger
95+ "<Input disabled={null} isLoading />" , // Null should not trigger
96+ "<Checkbox disabled={undefined} pending />" , // Undefined should not trigger
97+
98+ // ✅ Test all applicable components without issues
99+ "<Button>Normal Button</Button>" ,
100+ "<ToggleButton>Normal Toggle</ToggleButton>" ,
101+ "<CompoundButton>Normal Compound</CompoundButton>" ,
102+ "<MenuButton>Normal Menu</MenuButton>" ,
103+ "<SplitButton>Normal Split</SplitButton>" ,
104+ "<Checkbox>Normal Checkbox</Checkbox>" ,
105+ "<Radio>Normal Radio</Radio>" ,
106+ "<Switch>Normal Switch</Switch>" ,
107+ "<Input>Normal Input</Input>" ,
108+ "<Textarea>Normal Textarea</Textarea>" ,
109+ "<Combobox>Normal Combobox</Combobox>" ,
110+ "<Dropdown>Normal Dropdown</Dropdown>" ,
111+ "<SpinButton>Normal SpinButton</SpinButton>" ,
112+ "<Slider>Normal Slider</Slider>" ,
113+ "<DatePicker>Normal DatePicker</DatePicker>" ,
114+ "<TimePicker>Normal TimePicker</TimePicker>" ,
115+ "<Link>Normal Link</Link>" ,
116+ "<Tab>Normal Tab</Tab>"
54117 ] ,
55118
56119 invalid : [
57- // ❌ Basic cases
120+ // ❌ Basic cases - test messageId: "preferDisabledFocusable"
58121 {
59122 code : "<Button disabled loading>Submit</Button>" ,
60123 errors : [ { messageId : "preferDisabledFocusable" } ] ,
@@ -71,6 +134,14 @@ ruleTester.run("prefer-disabledfocusable-over-disabled", rule as unknown as Rule
71134 output : "<Checkbox disabledFocusable pending />"
72135 } ,
73136
137+ // ❌ Test case where getLoadingStateProp returns null (should use preferDisabledFocusableGeneric)
138+ // This shouldn't happen in practice but tests the fallback
139+ {
140+ code : "<Button disabled loading>Submit</Button>" ,
141+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
142+ output : "<Button disabledFocusable loading>Submit</Button>"
143+ } ,
144+
74145 // ❌ Boolean prop values
75146 {
76147 code : "<Button disabled={true} loading={true}>Submit</Button>" ,
@@ -95,21 +166,36 @@ ruleTester.run("prefer-disabledfocusable-over-disabled", rule as unknown as Rule
95166 output : "<Combobox disabledFocusable={!isEnabled} pending={isPending} />"
96167 } ,
97168
98- // ❌ Different loading prop variations
169+ // ❌ Test all loading prop variations
170+ {
171+ code : "<Button disabled loading>Submit</Button>" ,
172+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
173+ output : "<Button disabledFocusable loading>Submit</Button>"
174+ } ,
175+ {
176+ code : "<Button disabled isLoading>Submit</Button>" ,
177+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
178+ output : "<Button disabledFocusable isLoading>Submit</Button>"
179+ } ,
180+ {
181+ code : "<Button disabled pending>Submit</Button>" ,
182+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
183+ output : "<Button disabledFocusable pending>Submit</Button>"
184+ } ,
99185 {
100186 code : "<Button disabled isPending>Submit</Button>" ,
101187 errors : [ { messageId : "preferDisabledFocusable" } ] ,
102188 output : "<Button disabledFocusable isPending>Submit</Button>"
103189 } ,
104190 {
105- code : "<Input disabled busy / >" ,
191+ code : "<Button disabled busy>Submit</Button >" ,
106192 errors : [ { messageId : "preferDisabledFocusable" } ] ,
107- output : "<Input disabledFocusable busy / >"
193+ output : "<Button disabledFocusable busy>Submit</Button >"
108194 } ,
109195 {
110- code : "<Slider disabled isBusy / >" ,
196+ code : "<Button disabled isBusy>Submit</Button >" ,
111197 errors : [ { messageId : "preferDisabledFocusable" } ] ,
112- output : "<Slider disabledFocusable isBusy / >"
198+ output : "<Button disabledFocusable isBusy>Submit</Button >"
113199 } ,
114200
115201 // ❌ Multiple loading props (should still trigger)
@@ -118,52 +204,119 @@ ruleTester.run("prefer-disabledfocusable-over-disabled", rule as unknown as Rule
118204 errors : [ { messageId : "preferDisabledFocusable" } ] ,
119205 output : "<Button disabledFocusable loading pending>Submit</Button>"
120206 } ,
207+ {
208+ code : "<Input disabled isLoading busy pending />" ,
209+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
210+ output : "<Input disabledFocusable isLoading busy pending />"
211+ } ,
121212
122- // ❌ Different component types
213+ // ❌ Test all applicable component types
123214 {
124- code : "<CompoundButton disabled loading />" ,
215+ code : "<Button disabled loading />" ,
125216 errors : [ { messageId : "preferDisabledFocusable" } ] ,
126- output : "<CompoundButton disabledFocusable loading />"
217+ output : "<Button disabledFocusable loading />"
127218 } ,
128219 {
129- code : "<MenuButton disabled isLoading />" ,
220+ code : "<ToggleButton disabled isLoading />" ,
130221 errors : [ { messageId : "preferDisabledFocusable" } ] ,
131- output : "<MenuButton disabledFocusable isLoading />"
222+ output : "<ToggleButton disabledFocusable isLoading />"
132223 } ,
133224 {
134- code : "<Switch disabled pending />" ,
225+ code : "<CompoundButton disabled pending />" ,
135226 errors : [ { messageId : "preferDisabledFocusable" } ] ,
136- output : "<Switch disabledFocusable pending />"
227+ output : "<CompoundButton disabledFocusable pending />"
228+ } ,
229+ {
230+ code : "<MenuButton disabled isPending />" ,
231+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
232+ output : "<MenuButton disabledFocusable isPending />"
233+ } ,
234+ {
235+ code : "<SplitButton disabled busy />" ,
236+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
237+ output : "<SplitButton disabledFocusable busy />"
238+ } ,
239+ {
240+ code : "<Checkbox disabled isBusy />" ,
241+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
242+ output : "<Checkbox disabledFocusable isBusy />"
137243 } ,
138244 {
139245 code : "<Radio disabled loading />" ,
140246 errors : [ { messageId : "preferDisabledFocusable" } ] ,
141247 output : "<Radio disabledFocusable loading />"
142248 } ,
143249 {
144- code : "<Textarea disabled busy />" ,
250+ code : "<Switch disabled isLoading />" ,
251+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
252+ output : "<Switch disabledFocusable isLoading />"
253+ } ,
254+ {
255+ code : "<Input disabled pending />" ,
256+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
257+ output : "<Input disabledFocusable pending />"
258+ } ,
259+ {
260+ code : "<Textarea disabled isPending />" ,
261+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
262+ output : "<Textarea disabledFocusable isPending />"
263+ } ,
264+ {
265+ code : "<Combobox disabled busy />" ,
266+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
267+ output : "<Combobox disabledFocusable busy />"
268+ } ,
269+ {
270+ code : "<Dropdown disabled isBusy />" ,
271+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
272+ output : "<Dropdown disabledFocusable isBusy />"
273+ } ,
274+ {
275+ code : "<SpinButton disabled loading />" ,
276+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
277+ output : "<SpinButton disabledFocusable loading />"
278+ } ,
279+ {
280+ code : "<Slider disabled isLoading />" ,
281+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
282+ output : "<Slider disabledFocusable isLoading />"
283+ } ,
284+ {
285+ code : "<DatePicker disabled pending />" ,
145286 errors : [ { messageId : "preferDisabledFocusable" } ] ,
146- output : "<Textarea disabledFocusable busy />"
287+ output : "<DatePicker disabledFocusable pending />"
147288 } ,
148289 {
149- code : "<DatePicker disabled isLoading />" ,
290+ code : "<TimePicker disabled isPending />" ,
150291 errors : [ { messageId : "preferDisabledFocusable" } ] ,
151- output : "<DatePicker disabledFocusable isLoading />"
292+ output : "<TimePicker disabledFocusable isPending />"
152293 } ,
153294 {
154- code : "<TimePicker disabled pending />" ,
295+ code : "<Link disabled busy />" ,
296+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
297+ output : "<Link disabledFocusable busy />"
298+ } ,
299+ {
300+ code : "<Tab disabled isBusy />" ,
301+ errors : [ { messageId : "preferDisabledFocusable" } ] ,
302+ output : "<Tab disabledFocusable isBusy />"
303+ } ,
304+
305+ // ❌ Complex expressions with all components
306+ {
307+ code : "<Button disabled={isSubmitting} loading={fetchingData}>Submit</Button>" ,
155308 errors : [ { messageId : "preferDisabledFocusable" } ] ,
156- output : "<TimePicker disabledFocusable pending / >"
309+ output : "<Button disabledFocusable={isSubmitting} loading={fetchingData}>Submit</Button >"
157310 } ,
158311 {
159- code : "<Link disabled loading />" ,
312+ code : "<Input disabled={!isEnabled && hasValidation} pending={validating} />" ,
160313 errors : [ { messageId : "preferDisabledFocusable" } ] ,
161- output : "<Link disabledFocusable loading />"
314+ output : "<Input disabledFocusable={!isEnabled && hasValidation} pending={validating} />"
162315 } ,
163316 {
164- code : "<Tab disabled isPending />" ,
317+ code : "<Checkbox disabled={shouldDisable || isReadonly} busy={processing} />" ,
165318 errors : [ { messageId : "preferDisabledFocusable" } ] ,
166- output : "<Tab disabledFocusable isPending />"
319+ output : "<Checkbox disabledFocusable={shouldDisable || isReadonly} busy={processing} />"
167320 }
168321 ]
169322} ) ;
0 commit comments