@@ -27,8 +27,8 @@ const ruleTester = new RuleTester();
27
27
28
28
const expectedError = {
29
29
message : 'Elements with onClick handlers must be focusable. ' +
30
- 'Either set the tabIndex property (usually 0), or use an element type which ' +
31
- 'is inherently focusable such as `button`.' ,
30
+ 'Either set the tabIndex property to a valid value (usually 0), ' +
31
+ 'or use an element type which is inherently focusable such as `button`.' ,
32
32
type : 'JSXOpeningElement'
33
33
} ;
34
34
@@ -46,20 +46,23 @@ ruleTester.run('onclick-has-focus', rule, {
46
46
{ code : '<div aria-hidden={2 >= 1} onClick={() => void 0} />' , parserOptions } ,
47
47
{ code : '<input type="text" onClick={() => void 0} />' , parserOptions } ,
48
48
{ code : '<input type="hidden" onClick={() => void 0} tabIndex="-1" />' , parserOptions } ,
49
+ { code : '<input type="hidden" onClick={() => void 0} tabIndex={-1} />' , parserOptions } ,
49
50
{ code : '<input onClick={() => void 0} />' , parserOptions } ,
50
51
{ code : '<button onClick={() => void 0} className="foo" />' , parserOptions } ,
51
52
{ code : '<option onClick={() => void 0} className="foo" />' , parserOptions } ,
52
53
{ code : '<select onClick={() => void 0} className="foo" />' , parserOptions } ,
53
54
{ code : '<area href="#" onClick={() => void 0} className="foo" />' , parserOptions } ,
54
55
{ code : '<textarea onClick={() => void 0} className="foo" />' , parserOptions } ,
55
56
{ code : '<a tabIndex="0" onClick={() => void 0} />' , parserOptions } ,
57
+ { code : '<a tabIndex={0} onClick={() => void 0} />' , parserOptions } ,
56
58
{ code : '<a role="button" href="#" onClick={() => void 0} />' , parserOptions } ,
57
59
{ code : '<a onClick={() => void 0} href="http://x.y.z" />' , parserOptions } ,
58
60
{ code : '<a onClick={() => void 0} href="http://x.y.z" tabIndex="0" />' , parserOptions } ,
61
+ { code : '<a onClick={() => void 0} href="http://x.y.z" tabIndex={0} />' , parserOptions } ,
59
62
{ code : '<TestComponent onClick={doFoo} />' , parserOptions } ,
60
63
{ code : '<input onClick={() => void 0} type="hidden" />;' , parserOptions } ,
61
64
{ code : '<span onClick="doSomething();" tabIndex="0">Click me!</span>' , parserOptions } ,
62
- { code : '<span onClick="doSomething();" tabIndex="0" >Click me!</span>' , parserOptions } ,
65
+ { code : '<span onClick="doSomething();" tabIndex={0} >Click me!</span>' , parserOptions } ,
63
66
{ code : '<span onClick="doSomething();" tabIndex="-1">Click me too!</span>' , parserOptions } ,
64
67
{ code : '<a href="javascript:void(0);" onClick="doSomething();">Click ALL the things!</a>' , parserOptions } ,
65
68
{ code : '<Foo.Bar onClick={() => void 0} aria-hidden={false} />;' , parserOptions } ,
@@ -69,17 +72,22 @@ ruleTester.run('onclick-has-focus', rule, {
69
72
invalid : [
70
73
{ code : '<span onClick="submitForm();">Submit</span>' , errors : [ expectedError ] , parserOptions } ,
71
74
{ code : '<span onClick="submitForm();" tabIndex={undefined}>Submit</span>' , errors : [ expectedError ] , parserOptions } ,
75
+ { code : '<span onClick="submitForm();" tabIndex="bad">Submit</span>' , errors : [ expectedError ] , parserOptions } ,
72
76
{ code : '<a onClick="showNextPage();">Next page</a>' , errors : [ expectedError ] , parserOptions } ,
77
+ { code : '<a onClick="showNextPage();" tabIndex={undefined}>Next page</a>' , errors : [ expectedError ] , parserOptions } ,
78
+ { code : '<a onClick="showNextPage();" tabIndex="bad">Next page</a>' , errors : [ expectedError ] , parserOptions } ,
79
+ { code : '<a onClick={() => void 0} />' , errors : [ expectedError ] , parserOptions } ,
73
80
{ code : '<area onClick={() => void 0} className="foo" />' , errors : [ expectedError ] , parserOptions } ,
74
81
{ code : '<div onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
82
+ { code : '<div onClick={() => void 0} tabIndex={undefined} />;' , errors : [ expectedError ] , parserOptions } ,
83
+ { code : '<div onClick={() => void 0} tabIndex="bad" />;' , errors : [ expectedError ] , parserOptions } ,
75
84
{ code : '<div onClick={() => void 0} role={undefined} />;' , errors : [ expectedError ] , parserOptions } ,
85
+ { code : '<div onClick={() => void 0} aria-hidden={false} />;' , errors : [ expectedError ] , parserOptions } ,
76
86
{ code : '<div onClick={() => void 0} {...props} />;' , errors : [ expectedError ] , parserOptions } ,
77
87
{ code : '<section onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
78
88
{ code : '<main onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
79
89
{ code : '<article onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
80
90
{ code : '<header onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
81
- { code : '<footer onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions } ,
82
- { code : '<div onClick={() => void 0} aria-hidden={false} />;' , errors : [ expectedError ] , parserOptions } ,
83
- { code : '<a onClick={() => void 0} />' , errors : [ expectedError ] , parserOptions }
91
+ { code : '<footer onClick={() => void 0} />;' , errors : [ expectedError ] , parserOptions }
84
92
]
85
93
} ) ;
0 commit comments