Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Commit 94bd0ad

Browse files
authored
Merge pull request #10 from rpearce/redo-all-the-things
Rewrite all the things for latest react
2 parents 093963f + 9c1489c commit 94bd0ad

File tree

12 files changed

+6298
-5974
lines changed

12 files changed

+6298
-5974
lines changed

.eslintrc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"sourceType": "module"
1515
},
1616
"plugins": [
17-
"react"
17+
"react",
18+
"react-hooks"
1819
],
1920
"rules": {
2021
"array-bracket-spacing": [ "error", "always" ],
@@ -24,32 +25,33 @@
2425
"comma-dangle": [ "error", "never" ],
2526
"computed-property-spacing": [ "error", "never" ],
2627
"curly": [ "error", "all" ],
27-
"eqeqeq": [ "error", "always" ],
2828
"eol-last": [ "error", "always" ],
29+
"eqeqeq": [ "error", "always" ],
2930
"func-call-spacing": [ "error", "never" ],
3031
"indent": [ "error", 2 ],
3132
"linebreak-style": [ "error", "unix" ],
3233
"no-console": "off",
3334
"no-else-return": [ "error" ],
3435
"no-empty-function": [ "error" ],
35-
"no-multiple-empty-lines": [2, { "max": 1, "maxEOF": 1 }],
3636
"no-extra-parens": [ "error" ],
3737
"no-lone-blocks": [ "error" ],
3838
"no-multi-assign": [ "error" ],
39+
"no-multiple-empty-lines": [2, { "max": 1, "maxEOF": 1 }],
3940
"no-new": [ "error" ],
4041
"no-new-func": [ "error" ],
4142
"no-param-reassign": [ "error" ],
4243
"no-return-assign": [ "error" ],
4344
"no-sequences": [ "error" ],
4445
"no-trailing-spaces": [ "error" ],
46+
"no-useless-return": [ "error" ],
4547
"no-void": [ "error" ],
4648
"no-with": [ "error" ],
47-
"no-useless-return": [ "error" ],
4849
"object-curly-spacing": [ "error", "always" ],
4950
"quotes": [ "error", "single" ],
51+
"react-hooks/rules-of-hooks": "error",
52+
"react/jsx-no-undef": "error",
5053
"react/jsx-uses-react": "error",
5154
"react/jsx-uses-vars": "error",
52-
"react/jsx-no-undef": "error",
5355
"react/prop-types": 0,
5456
"semi": [ "error", "never" ],
5557
"yoda": [ "error" ]

__tests__/index.js

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
import React, { createRef } from 'react'
2+
import { fireEvent, render } from 'react-testing-library'
3+
import 'jest-dom/extend-expect'
4+
5+
import ButtonA11y from '../source'
6+
7+
test('renders with aria-label, handles click', () => {
8+
const onClick = jest.fn()
9+
const { getByLabelText } = render(
10+
<ButtonA11y
11+
aria-label="Mock Label"
12+
className="mock-className"
13+
onClick={onClick}
14+
/>
15+
)
16+
const el = getByLabelText('Mock Label')
17+
18+
expect(el).toBeInTheDocument()
19+
20+
fireEvent.click(el)
21+
22+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
23+
})
24+
25+
test('renders with children, handles click', () => {
26+
const onClick = jest.fn()
27+
const { getByText } = render(
28+
<ButtonA11y
29+
className="mock-className"
30+
onClick={onClick}
31+
>
32+
Click Me
33+
</ButtonA11y>
34+
)
35+
const el = getByText('Click Me')
36+
37+
expect(el).toBeInTheDocument()
38+
39+
fireEvent.click(el)
40+
41+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
42+
})
43+
44+
test('renders with button role and tabIndex 0', () => {
45+
const onClick = jest.fn()
46+
const { getByText } = render(
47+
<ButtonA11y
48+
className="mock-className"
49+
onClick={onClick}
50+
>
51+
Click Me
52+
</ButtonA11y>
53+
)
54+
const el = getByText('Click Me')
55+
56+
expect(el).toBeInTheDocument()
57+
expect(el.getAttribute('role')).toEqual('button')
58+
expect(el.getAttribute('tabindex')).toEqual('0')
59+
})
60+
61+
test('calls onKeyDown and onClick when key is Enter', () => {
62+
const onClick = jest.fn()
63+
const onKeyDown = jest.fn()
64+
const { getByText } = render(
65+
<ButtonA11y
66+
className="mock-className"
67+
onKeyDown={onKeyDown}
68+
onClick={onClick}
69+
type=""
70+
>
71+
Click Me
72+
</ButtonA11y>
73+
)
74+
const el = getByText('Click Me')
75+
76+
expect(el).toBeInTheDocument()
77+
78+
fireEvent.keyDown(el, { key: 'Enter' })
79+
80+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
81+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
82+
})
83+
84+
test('calls onKeyDown and onClick when key is empty space', () => {
85+
const onClick = jest.fn()
86+
const onKeyDown = jest.fn()
87+
const { getByText } = render(
88+
<ButtonA11y
89+
className="mock-className"
90+
onKeyDown={onKeyDown}
91+
onClick={onClick}
92+
type=""
93+
>
94+
Click Me
95+
</ButtonA11y>
96+
)
97+
const el = getByText('Click Me')
98+
99+
expect(el).toBeInTheDocument()
100+
101+
fireEvent.keyDown(el, { key: ' ' })
102+
103+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
104+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
105+
})
106+
107+
test('calls onKeyDown and onClick when key is Spacebar', () => {
108+
const onClick = jest.fn()
109+
const onKeyDown = jest.fn()
110+
const onScroll = jest.fn()
111+
const { getByText } = render(
112+
<ButtonA11y
113+
className="mock-className"
114+
onKeyDown={onKeyDown}
115+
onClick={onClick}
116+
type=""
117+
>
118+
Click Me
119+
</ButtonA11y>
120+
)
121+
const el = getByText('Click Me')
122+
123+
global.document.addEventListener('scroll', onScroll)
124+
125+
expect(el).toBeInTheDocument()
126+
127+
fireEvent.keyDown(el, { key: 'Spacebar' })
128+
129+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
130+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
131+
expect(onScroll).not.toHaveBeenCalled()
132+
})
133+
134+
test('calls onKeyDown and onClick when keyCode is 13', () => {
135+
const onClick = jest.fn()
136+
const onKeyDown = jest.fn()
137+
const { getByText } = render(
138+
<ButtonA11y
139+
className="mock-className"
140+
onKeyDown={onKeyDown}
141+
onClick={onClick}
142+
type=""
143+
>
144+
Click Me
145+
</ButtonA11y>
146+
)
147+
const el = getByText('Click Me')
148+
149+
expect(el).toBeInTheDocument()
150+
151+
fireEvent.keyDown(el, { keyCode: 13 })
152+
153+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
154+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
155+
})
156+
157+
test('calls onKeyDown and onClick when keyCode is 32', () => {
158+
const onClick = jest.fn()
159+
const onKeyDown = jest.fn()
160+
const { getByText } = render(
161+
<ButtonA11y
162+
className="mock-className"
163+
onKeyDown={onKeyDown}
164+
onClick={onClick}
165+
type=""
166+
>
167+
Click Me
168+
</ButtonA11y>
169+
)
170+
const el = getByText('Click Me')
171+
172+
expect(el).toBeInTheDocument()
173+
174+
fireEvent.keyDown(el, { keyCode: 32 })
175+
176+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
177+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
178+
})
179+
180+
test('only calls onKeyDown when random key', () => {
181+
const onClick = jest.fn()
182+
const onKeyDown = jest.fn()
183+
const { getByText } = render(
184+
<ButtonA11y
185+
className="mock-className"
186+
onKeyDown={onKeyDown}
187+
onClick={onClick}
188+
type=""
189+
>
190+
Click Me
191+
</ButtonA11y>
192+
)
193+
const el = getByText('Click Me')
194+
195+
expect(el).toBeInTheDocument()
196+
197+
fireEvent.keyDown(el, { key: 'Delete' })
198+
199+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
200+
expect(onClick).not.toHaveBeenCalled()
201+
})
202+
203+
test('only calls onKeyDown when random keyCode', () => {
204+
const onClick = jest.fn()
205+
const onKeyDown = jest.fn()
206+
const { getByText } = render(
207+
<ButtonA11y
208+
className="mock-className"
209+
onKeyDown={onKeyDown}
210+
onClick={onClick}
211+
type=""
212+
>
213+
Click Me
214+
</ButtonA11y>
215+
)
216+
const el = getByText('Click Me')
217+
218+
expect(el).toBeInTheDocument()
219+
220+
fireEvent.keyDown(el, { keyCode: 17 })
221+
222+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
223+
expect(onClick).not.toHaveBeenCalled()
224+
})
225+
226+
test('does not break when onKeyDown not passed', () => {
227+
const onClick = jest.fn()
228+
const { getByText } = render(
229+
<ButtonA11y
230+
className="mock-className"
231+
onClick={onClick}
232+
type=""
233+
>
234+
Click Me
235+
</ButtonA11y>
236+
)
237+
const el = getByText('Click Me')
238+
239+
expect(el).toBeInTheDocument()
240+
241+
fireEvent.keyDown(el, { key: 'Enter' })
242+
243+
expect(onClick).toHaveBeenCalledWith(expect.any(Object))
244+
})
245+
246+
test('does not break when onClick not passed', () => {
247+
const onKeyDown = jest.fn()
248+
const { getByText } = render(
249+
<ButtonA11y
250+
className="mock-className"
251+
onKeyDown={onKeyDown}
252+
type=""
253+
>
254+
Click Me
255+
</ButtonA11y>
256+
)
257+
const el = getByText('Click Me')
258+
259+
expect(el).toBeInTheDocument()
260+
261+
fireEvent.keyDown(el, { key: 'Enter' })
262+
263+
expect(onKeyDown).toHaveBeenCalledWith(expect.any(Object))
264+
})
265+
266+
test('renders as div element', () => {
267+
const { container, getByText } = render(
268+
<ButtonA11y
269+
className="mock-className"
270+
element="div"
271+
onClick={jest.fn()}
272+
>
273+
Click Me
274+
</ButtonA11y>
275+
)
276+
277+
expect(getByText('Click Me')).toBeInTheDocument()
278+
expect(container.firstChild.tagName).toEqual('DIV')
279+
})
280+
281+
test('forwards a ref', () => {
282+
const ref = createRef()
283+
render(
284+
<ButtonA11y
285+
className="mock-className"
286+
onClick={jest.fn()}
287+
ref={ref}
288+
>
289+
Click Me
290+
</ButtonA11y>
291+
)
292+
293+
expect(ref.current).toBeInTheDocument()
294+
})
295+
296+
test('errors when no children & no aria-label', () => {
297+
expect(() => {
298+
render(
299+
<ButtonA11y
300+
className="mock-className"
301+
element="span"
302+
onClick={jest.fn()}
303+
/>
304+
)
305+
}).toThrow(
306+
'react-button-a11y: `aria-label` required for accessibility'
307+
)
308+
})
309+
310+
// This is allowed but is unwise for accessibility
311+
test('renders when not strictMode, no children & no aria-label', () => {
312+
const { getByRole } = render(
313+
<ButtonA11y
314+
className="mock-className"
315+
element="span"
316+
onClick={jest.fn()}
317+
strictMode={false}
318+
/>
319+
)
320+
const el = getByRole('button')
321+
322+
expect(el).toBeInTheDocument()
323+
})

0 commit comments

Comments
 (0)