@khanacademy/wonder-blocks-clickable 2.3.1 → 2.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,14 @@
1
+ /* eslint-disable testing-library/prefer-user-event */
1
2
  /* eslint-disable max-lines */
2
3
  // @flow
3
4
  import * as React from "react";
4
- import {render, screen} from "@testing-library/react";
5
+ import {render, screen, fireEvent} from "@testing-library/react";
5
6
  import {MemoryRouter, Switch, Route} from "react-router-dom";
6
- import {mount, shallow} from "enzyme";
7
- import "jest-enzyme";
7
+ import userEvent from "@testing-library/user-event";
8
8
 
9
9
  import getClickableBehavior from "../../util/get-clickable-behavior.js";
10
10
  import ClickableBehavior from "../clickable-behavior.js";
11
+ import type {ClickableState} from "../clickable-behavior";
11
12
 
12
13
  const keyCodes = {
13
14
  tab: 9,
@@ -21,6 +22,20 @@ const wait = (delay: number = 0) =>
21
22
  return setTimeout(resolve, delay);
22
23
  });
23
24
 
25
+ const labelForState = (state: ClickableState): string => {
26
+ const labels = [];
27
+ if (state.hovered) {
28
+ labels.push("hovered");
29
+ }
30
+ if (state.focused) {
31
+ labels.push("focused");
32
+ }
33
+ if (state.pressed) {
34
+ labels.push("pressed");
35
+ }
36
+ return labels.join(" ");
37
+ };
38
+
24
39
  describe("ClickableBehavior", () => {
25
40
  beforeEach(() => {
26
41
  // Note: window.location.assign and window.open need mock functions in
@@ -37,7 +52,7 @@ describe("ClickableBehavior", () => {
37
52
 
38
53
  it("renders a label", () => {
39
54
  const onClick = jest.fn();
40
- const button = shallow(
55
+ render(
41
56
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
42
57
  {(state, childrenProps) => {
43
58
  return <button {...childrenProps}>Label</button>;
@@ -45,176 +60,165 @@ describe("ClickableBehavior", () => {
45
60
  </ClickableBehavior>,
46
61
  );
47
62
  expect(onClick).not.toHaveBeenCalled();
48
- button.simulate("click", {preventDefault: jest.fn()});
63
+ userEvent.click(screen.getByRole("button"));
49
64
  expect(onClick).toHaveBeenCalled();
50
65
  });
51
66
 
52
67
  it("changes only hovered state on mouse enter/leave", () => {
53
68
  const onClick = jest.fn();
54
- const button = shallow(
69
+ render(
55
70
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
56
71
  {(state, childrenProps) => {
57
- return <button {...childrenProps}>Label</button>;
72
+ const label = labelForState(state);
73
+ return <button {...childrenProps}>{label}</button>;
58
74
  }}
59
75
  </ClickableBehavior>,
60
76
  );
61
- expect(button.state("hovered")).toEqual(false);
62
- button.simulate("mouseenter", {
63
- buttons: 0,
64
- });
65
- expect(button.state("hovered")).toEqual(true);
66
- button.simulate("mouseleave");
67
- expect(button.state("hovered")).toEqual(false);
77
+ const button = screen.getByRole("button");
78
+ expect(button).not.toHaveTextContent("hovered");
79
+ userEvent.hover(button);
80
+ expect(button).toHaveTextContent("hovered");
81
+ userEvent.unhover(button);
82
+ expect(button).not.toHaveTextContent("hovered");
68
83
  });
69
84
 
70
85
  it("changes only pressed state on mouse enter/leave while dragging", () => {
71
86
  const onClick = jest.fn();
72
- const button = shallow(
87
+ render(
73
88
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
74
89
  {(state, childrenProps) => {
75
- return <button {...childrenProps}>Label</button>;
90
+ const label = labelForState(state);
91
+ return <button {...childrenProps}>{label}</button>;
76
92
  }}
77
93
  </ClickableBehavior>,
78
94
  );
79
- expect(button.state("pressed")).toEqual(false);
95
+ const button = screen.getByRole("button");
96
+ expect(button).not.toHaveTextContent("pressed");
80
97
 
81
- button.simulate("mousedown");
82
- button.simulate("dragstart", {preventDefault: jest.fn()});
83
- expect(button.state("pressed")).toEqual(true);
98
+ fireEvent.mouseDown(button);
99
+ fireEvent.dragStart(button);
100
+ fireEvent.mouseMove(button);
101
+ expect(button).toHaveTextContent("pressed");
84
102
 
85
- button.simulate("mouseleave");
86
- expect(button.state("pressed")).toEqual(false);
103
+ fireEvent.mouseLeave(button);
104
+ expect(button).not.toHaveTextContent("pressed");
87
105
 
88
- button.simulate("mouseenter", {
89
- buttons: 1,
90
- });
91
- expect(button.state("pressed")).toEqual(true);
106
+ fireEvent.mouseEnter(button, {buttons: 1});
107
+ expect(button).toHaveTextContent("pressed");
92
108
  });
93
109
 
94
110
  it("changes pressed state on mouse down/up", () => {
95
111
  const onClick = jest.fn();
96
- const button = shallow(
112
+ render(
97
113
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
98
114
  {(state, childrenProps) => {
99
- return <button {...childrenProps}>Label</button>;
115
+ const label = labelForState(state);
116
+ return <button {...childrenProps}>{label}</button>;
100
117
  }}
101
118
  </ClickableBehavior>,
102
119
  );
103
- expect(button.state("pressed")).toEqual(false);
104
- button.simulate("mousedown");
105
- expect(button.state("pressed")).toEqual(true);
106
- button.simulate("mouseup");
107
- expect(button.state("pressed")).toEqual(false);
120
+ const button = screen.getByRole("button");
121
+ expect(button).not.toHaveTextContent("pressed");
122
+ fireEvent.mouseDown(button);
123
+ expect(button).toHaveTextContent("pressed");
124
+ fireEvent.mouseUp(button);
125
+ expect(button).not.toHaveTextContent("pressed");
108
126
  });
109
127
 
110
128
  it("changes pressed state on touch start/end/cancel", () => {
111
129
  const onClick = jest.fn();
112
- const button = shallow(
130
+ render(
113
131
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
114
132
  {(state, childrenProps) => {
115
- return <button {...childrenProps}>Label</button>;
133
+ const label = labelForState(state);
134
+ return <button {...childrenProps}>{label}</button>;
116
135
  }}
117
136
  </ClickableBehavior>,
118
137
  );
119
- expect(button.state("pressed")).toEqual(false);
120
- button.simulate("touchstart");
121
- expect(button.state("pressed")).toEqual(true);
122
- button.simulate("touchend");
123
- expect(button.state("pressed")).toEqual(false);
124
-
125
- expect(button.state("pressed")).toEqual(false);
126
- button.simulate("touchstart");
127
- expect(button.state("pressed")).toEqual(true);
128
- button.simulate("touchcancel");
129
- expect(button.state("pressed")).toEqual(false);
138
+ const button = screen.getByRole("button");
139
+ expect(button).not.toHaveTextContent("pressed");
140
+ fireEvent.touchStart(button);
141
+ expect(button).toHaveTextContent("pressed");
142
+ fireEvent.touchEnd(button);
143
+ expect(button).not.toHaveTextContent("pressed");
144
+
145
+ expect(button).not.toHaveTextContent("pressed");
146
+ fireEvent.touchStart(button);
147
+ expect(button).toHaveTextContent("pressed");
148
+ fireEvent.touchCancel(button);
149
+ expect(button).not.toHaveTextContent("pressed");
130
150
  });
131
151
 
132
152
  it("enters focused state on key press after click", () => {
133
153
  const onClick = jest.fn();
134
- const button = shallow(
154
+ render(
135
155
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
136
156
  {(state, childrenProps) => {
137
- return <button {...childrenProps}>Label</button>;
157
+ const label = labelForState(state);
158
+ return <button {...childrenProps}>{label}</button>;
138
159
  }}
139
160
  </ClickableBehavior>,
140
161
  );
141
- expect(button.state("focused")).toEqual(false);
142
- button.simulate("keydown", {
143
- keyCode: keyCodes.space,
144
- preventDefault: jest.fn(),
145
- });
146
- button.simulate("keyup", {
147
- keyCode: keyCodes.space,
148
- preventDefault: jest.fn(),
149
- });
150
- button.simulate("click", {preventDefault: jest.fn()});
151
- expect(button.state("focused")).toEqual(true);
162
+ const button = screen.getByRole("button");
163
+ expect(button).not.toHaveTextContent("focused");
164
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
165
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
166
+ // NOTE(kevinb): userEvent.click() fires other events that we don't want
167
+ // affecting this test case.
168
+ fireEvent.click(button);
169
+ expect(button).toHaveTextContent("focused");
152
170
  });
153
171
 
154
172
  it("exits focused state on click after key press", () => {
155
173
  const onClick = jest.fn();
156
174
 
157
- const button = shallow(
175
+ render(
158
176
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
159
177
  {(state, childrenProps) => {
160
- return <button {...childrenProps}>Label</button>;
178
+ const label = labelForState(state);
179
+ return <button {...childrenProps}>{label}</button>;
161
180
  }}
162
181
  </ClickableBehavior>,
163
182
  );
164
- expect(button.state("focused")).toEqual(false);
165
- button.simulate("keydown", {
166
- keyCode: keyCodes.space,
167
- preventDefault: jest.fn(),
168
- });
169
- button.simulate("keyup", {
170
- keyCode: keyCodes.space,
171
- preventDefault: jest.fn(),
172
- });
173
- button.simulate("click", {preventDefault: jest.fn()});
174
- expect(button.state("focused")).toEqual(true);
175
- button.simulate("mousedown");
176
- button.simulate("mouseup");
177
- button.simulate("click", {preventDefault: jest.fn()});
178
- expect(button.state("focused")).toEqual(false);
183
+ const button = screen.getByRole("button");
184
+ expect(button).not.toHaveTextContent("focused");
185
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
186
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
187
+ // NOTE(kevinb): userEvent.click() fires other events that we don't want
188
+ // affecting this test case.
189
+ fireEvent.click(button);
190
+ expect(button).toHaveTextContent("focused");
191
+ userEvent.click(button);
192
+ expect(button).not.toHaveTextContent("focused");
179
193
  });
180
194
 
181
195
  it("changes pressed state on space/enter key down/up if <button>", () => {
182
196
  const onClick = jest.fn();
183
- const button = shallow(
197
+ render(
184
198
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
185
199
  {(state, childrenProps) => {
186
- return <button {...childrenProps}>Label</button>;
200
+ const label = labelForState(state);
201
+ return <button {...childrenProps}>{label}</button>;
187
202
  }}
188
203
  </ClickableBehavior>,
189
204
  );
190
- expect(button.state("pressed")).toEqual(false);
191
- button.simulate("keydown", {
192
- keyCode: keyCodes.space,
193
- preventDefault: jest.fn(),
194
- });
195
- expect(button.state("pressed")).toEqual(true);
196
- button.simulate("keyup", {
197
- keyCode: keyCodes.space,
198
- preventDefault: jest.fn(),
199
- });
200
- expect(button.state("pressed")).toEqual(false);
201
-
202
- button.simulate("keydown", {
203
- keyCode: keyCodes.enter,
204
- preventDefault: jest.fn(),
205
- });
206
- expect(button.state("pressed")).toEqual(true);
207
- button.simulate("keyup", {
208
- preventDefault: jest.fn(),
209
- keyCode: keyCodes.enter,
210
- });
211
- expect(button.state("pressed")).toEqual(false);
205
+ const button = screen.getByRole("button");
206
+ expect(button).not.toHaveTextContent("pressed");
207
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
208
+ expect(button).toHaveTextContent("pressed");
209
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
210
+ expect(button).not.toHaveTextContent("pressed");
211
+
212
+ fireEvent.keyDown(button, {keyCode: keyCodes.enter});
213
+ expect(button).toHaveTextContent("pressed");
214
+ fireEvent.keyUp(button, {keyCode: keyCodes.enter});
215
+ expect(button).not.toHaveTextContent("pressed");
212
216
  });
213
217
 
214
218
  it("changes pressed state on only enter key down/up for a link", () => {
215
219
  const onClick = jest.fn();
216
220
  // Use mount instead of a shallow render to trigger event defaults
217
- const link = mount(
221
+ render(
218
222
  <ClickableBehavior
219
223
  disabled={false}
220
224
  onClick={(e) => onClick(e)}
@@ -222,59 +226,60 @@ describe("ClickableBehavior", () => {
222
226
  role="link"
223
227
  >
224
228
  {(state, childrenProps) => {
229
+ const label = labelForState(state);
225
230
  return (
226
231
  <a
227
232
  href="https://www.khanacademy.org"
228
233
  {...childrenProps}
229
234
  >
230
- Label
235
+ {label}
231
236
  </a>
232
237
  );
233
238
  }}
234
239
  </ClickableBehavior>,
235
240
  );
236
- expect(link.state("pressed")).toEqual(false);
237
- link.simulate("keydown", {keyCode: keyCodes.enter});
238
- expect(link.state("pressed")).toEqual(true);
239
- link.simulate("keyup", {
240
- preventDefault: jest.fn(),
241
- keyCode: keyCodes.enter,
242
- });
243
- expect(link.state("pressed")).toEqual(false);
244
-
245
- link.simulate("keydown", {keyCode: keyCodes.space});
246
- expect(link.state("pressed")).toEqual(false);
247
- link.simulate("keyup", {
248
- preventDefault: jest.fn(),
249
- keyCode: keyCodes.space,
250
- });
251
- expect(link.state("pressed")).toEqual(false);
241
+ const link = screen.getByRole("link");
242
+ expect(link).not.toHaveTextContent("pressed");
243
+ fireEvent.keyDown(link, {keyCode: keyCodes.enter});
244
+ expect(link).toHaveTextContent("pressed");
245
+ fireEvent.keyUp(link, {keyCode: keyCodes.enter});
246
+ expect(link).not.toHaveTextContent("pressed");
247
+
248
+ fireEvent.keyDown(link, {keyCode: keyCodes.space});
249
+ expect(link).not.toHaveTextContent("pressed");
250
+ fireEvent.keyUp(link, {keyCode: keyCodes.space});
251
+ expect(link).not.toHaveTextContent("pressed");
252
252
  });
253
253
 
254
254
  it("gains focused state on focus event", () => {
255
255
  const onClick = jest.fn();
256
- const button = shallow(
256
+ render(
257
257
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
258
258
  {(state, childrenProps) => {
259
- return <button {...childrenProps}>Label</button>;
259
+ const label = labelForState(state);
260
+ return <button {...childrenProps}>{label}</button>;
260
261
  }}
261
262
  </ClickableBehavior>,
262
263
  );
263
- button.simulate("focus");
264
- expect(button.state("focused")).toEqual(true);
264
+ const button = screen.getByRole("button");
265
+ fireEvent.focus(button);
266
+ expect(button).toHaveTextContent("focused");
265
267
  });
266
268
 
267
269
  it("changes focused state on blur", () => {
268
270
  const onClick = jest.fn();
269
- const button = shallow(
271
+ render(
270
272
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
271
273
  {(state, childrenProps) => {
272
- return <button {...childrenProps}>Label</button>;
274
+ const label = labelForState(state);
275
+ return <button {...childrenProps}>{label}</button>;
273
276
  }}
274
277
  </ClickableBehavior>,
275
278
  );
276
- button.simulate("blur");
277
- expect(button.state("focused")).toEqual(false);
279
+ const button = screen.getByRole("button");
280
+ fireEvent.focus(button);
281
+ fireEvent.blur(button);
282
+ expect(button).not.toHaveTextContent("focused");
278
283
  });
279
284
 
280
285
  test("tabIndex should be 0", () => {
@@ -319,68 +324,64 @@ describe("ClickableBehavior", () => {
319
324
 
320
325
  it("does not change state if disabled", () => {
321
326
  const onClick = jest.fn();
322
- const button = shallow(
327
+ render(
323
328
  <ClickableBehavior disabled={true} onClick={(e) => onClick(e)}>
324
329
  {(state, childrenProps) => {
325
- return <button {...childrenProps}>Label</button>;
330
+ const label = labelForState(state);
331
+ return <button {...childrenProps}>{label}</button>;
326
332
  }}
327
333
  </ClickableBehavior>,
328
334
  );
329
335
 
336
+ const button = screen.getByRole("button");
330
337
  expect(onClick).not.toHaveBeenCalled();
331
- button.simulate("click", {preventDefault: jest.fn()});
338
+ fireEvent.click(button);
332
339
  expect(onClick).not.toHaveBeenCalled();
333
340
 
334
- expect(button.state("hovered")).toEqual(false);
335
- button.simulate("mouseenter", {
336
- buttons: 0,
337
- });
338
- expect(button.state("hovered")).toEqual(false);
339
- button.simulate("mouseleave");
340
- expect(button.state("hovered")).toEqual(false);
341
-
342
- expect(button.state("pressed")).toEqual(false);
343
- button.simulate("mousedown");
344
- expect(button.state("pressed")).toEqual(false);
345
- button.simulate("mouseup");
346
- expect(button.state("pressed")).toEqual(false);
347
-
348
- expect(button.state("pressed")).toEqual(false);
349
- button.simulate("touchstart");
350
- expect(button.state("pressed")).toEqual(false);
351
- button.simulate("touchend");
352
- expect(button.state("pressed")).toEqual(false);
353
-
354
- button.simulate("touchstart");
355
- button.simulate("touchcancel");
356
- expect(button.state("pressed")).toEqual(false);
357
-
358
- expect(button.state("focused")).toEqual(false);
359
- button.simulate("keyup", {
360
- preventDefault: jest.fn(),
341
+ expect(button).not.toHaveTextContent("hovered");
342
+ fireEvent.mouseEnter(button);
343
+ expect(button).not.toHaveTextContent("hovered");
344
+ fireEvent.mouseLeave(button);
345
+ expect(button).not.toHaveTextContent("hovered");
346
+
347
+ expect(button).not.toHaveTextContent("pressed");
348
+ fireEvent.mouseDown(button);
349
+ expect(button).not.toHaveTextContent("pressed");
350
+ fireEvent.mouseUp(button);
351
+ expect(button).not.toHaveTextContent("pressed");
352
+
353
+ expect(button).not.toHaveTextContent("pressed");
354
+ fireEvent.touchStart(button);
355
+ expect(button).not.toHaveTextContent("pressed");
356
+ fireEvent.touchEnd(button);
357
+ expect(button).not.toHaveTextContent("pressed");
358
+
359
+ fireEvent.touchStart(button);
360
+ fireEvent.touchCancel(button);
361
+ expect(button).not.toHaveTextContent("pressed");
362
+
363
+ expect(button).not.toHaveTextContent("focused");
364
+ fireEvent.keyUp(button, {
361
365
  keyCode: keyCodes.tab,
362
366
  });
363
- expect(button.state("focused")).toEqual(false);
364
- button.simulate("keydown", {keyCode: keyCodes.tab});
365
- expect(button.state("focused")).toEqual(false);
366
-
367
- expect(button.state("pressed")).toEqual(false);
368
- button.simulate("keydown", {keyCode: keyCodes.space});
369
- expect(button.state("pressed")).toEqual(false);
370
- button.simulate("keyup", {
371
- preventDefault: jest.fn(),
372
- keyCode: keyCodes.space,
373
- });
374
- expect(button.state("pressed")).toEqual(false);
367
+ expect(button).not.toHaveTextContent("focused");
368
+ fireEvent.keyDown(button, {keyCode: keyCodes.tab});
369
+ expect(button).not.toHaveTextContent("focused");
375
370
 
376
- button.simulate("keydown", {keyCode: keyCodes.space});
377
- button.simulate("blur");
378
- expect(button.state("pressed")).toEqual(false);
371
+ expect(button).not.toHaveTextContent("pressed");
372
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
373
+ expect(button).not.toHaveTextContent("pressed");
374
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
375
+ expect(button).not.toHaveTextContent("pressed");
379
376
 
380
- button.simulate("focus");
381
- expect(button.state("focused")).toEqual(true);
377
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
378
+ fireEvent.blur(button);
379
+ expect(button).not.toHaveTextContent("pressed");
382
380
 
383
- const anchor = shallow(
381
+ fireEvent.focus(button);
382
+ expect(button).toHaveTextContent("focused");
383
+
384
+ render(
384
385
  <ClickableBehavior
385
386
  disabled={true}
386
387
  href="https://www.khanacademy.org"
@@ -398,80 +399,78 @@ describe("ClickableBehavior", () => {
398
399
  </ClickableBehavior>,
399
400
  );
400
401
 
401
- expect(anchor.state("pressed")).toEqual(false);
402
- anchor.simulate("keydown", {keyCode: keyCodes.enter});
403
- expect(anchor.state("pressed")).toEqual(false);
404
- anchor.simulate("keyup", {
405
- preventDefault: jest.fn(),
406
- keyCode: keyCodes.enter,
407
- });
408
- expect(anchor.state("pressed")).toEqual(false);
402
+ const anchor = screen.getByRole("link");
403
+ expect(anchor).not.toHaveTextContent("pressed");
404
+ fireEvent.keyDown(anchor, {keyCode: keyCodes.enter});
405
+ expect(anchor).not.toHaveTextContent("pressed");
406
+ fireEvent.keyUp(anchor, {keyCode: keyCodes.enter});
407
+ expect(anchor).not.toHaveTextContent("pressed");
409
408
  });
410
409
 
411
410
  it("has onClick triggered just once per click by various means", () => {
412
411
  const onClick = jest.fn();
413
- const button = shallow(
412
+ render(
414
413
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
415
414
  {(state, childrenProps) => {
416
415
  return <button {...childrenProps}>Label</button>;
417
416
  }}
418
417
  </ClickableBehavior>,
419
418
  );
419
+ const button = screen.getByRole("button");
420
420
  expect(onClick).not.toHaveBeenCalled();
421
421
 
422
- button.simulate("mousedown");
423
- button.simulate("mouseup");
424
- button.simulate("click", {preventDefault: jest.fn()});
422
+ userEvent.click(button);
425
423
  expect(onClick).toHaveBeenCalledTimes(1);
426
424
 
427
- button.simulate("keydown", {
428
- keyCode: keyCodes.space,
429
- preventDefault: jest.fn(),
430
- });
431
- button.simulate("keyup", {
432
- keyCode: keyCodes.space,
433
- preventDefault: jest.fn(),
434
- });
425
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
426
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
435
427
  expect(onClick).toHaveBeenCalledTimes(2);
436
428
 
437
- button.simulate("keydown", {
438
- keyCode: keyCodes.enter,
439
- preventDefault: jest.fn(),
440
- });
441
- button.simulate("keyup", {
442
- preventDefault: jest.fn(),
443
- keyCode: keyCodes.enter,
444
- });
429
+ fireEvent.keyDown(button, {keyCode: keyCodes.enter});
430
+ fireEvent.keyUp(button, {keyCode: keyCodes.enter});
445
431
  expect(onClick).toHaveBeenCalledTimes(3);
446
432
 
447
- button.simulate("touchstart", {keyCode: keyCodes.space});
448
- button.simulate("touchend", {keyCode: keyCodes.space});
449
- button.simulate("click", {preventDefault: jest.fn()});
433
+ fireEvent.touchStart(button, {keyCode: keyCodes.space});
434
+ fireEvent.touchEnd(button, {keyCode: keyCodes.space});
435
+ fireEvent.click(button);
450
436
  expect(onClick).toHaveBeenCalledTimes(4);
451
437
  });
452
438
 
453
439
  it("resets state when set to disabled", () => {
454
440
  const onClick = jest.fn();
455
- const button = shallow(
441
+ const {rerender} = render(
456
442
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
457
443
  {(state, childrenProps) => {
458
- return <button {...childrenProps}>Label</button>;
444
+ const label = labelForState(state);
445
+ return <button {...childrenProps}>{label}</button>;
459
446
  }}
460
447
  </ClickableBehavior>,
461
448
  );
462
- button.setState({hovered: true, pressed: true, focused: true});
463
- button.setProps({disabled: true});
449
+ const button = screen.getByRole("button");
450
+ userEvent.tab(); // focus
451
+ userEvent.hover(button);
464
452
 
465
- expect(button.state("hovered")).toEqual(false);
466
- expect(button.state("pressed")).toEqual(false);
467
- expect(button.state("focused")).toEqual(true);
453
+ rerender(
454
+ <ClickableBehavior disabled={true} onClick={(e) => onClick(e)}>
455
+ {(state, childrenProps) => {
456
+ const label = labelForState(state);
457
+ return <button {...childrenProps}>{label}</button>;
458
+ }}
459
+ </ClickableBehavior>,
460
+ );
461
+
462
+ expect(button).not.toHaveTextContent("pressed");
463
+ expect(button).not.toHaveTextContent("hovered");
464
+
465
+ // The button remains focused even after it's been disabled
466
+ expect(button).toHaveTextContent("focused");
468
467
  });
469
468
 
470
469
  describe("full page load navigation", () => {
471
470
  it("both navigates and calls onClick for an anchor link", () => {
472
471
  const onClick = jest.fn();
473
472
  // Use mount instead of a shallow render to trigger event defaults
474
- const link = mount(
473
+ render(
475
474
  <ClickableBehavior
476
475
  href="https://khanacademy.org/"
477
476
  onClick={(e) => onClick(e)}
@@ -492,29 +491,24 @@ describe("ClickableBehavior", () => {
492
491
  }}
493
492
  </ClickableBehavior>,
494
493
  );
494
+ const link = screen.getByRole("link");
495
495
 
496
496
  // Space press should not trigger the onClick
497
- link.simulate("keydown", {keyCode: keyCodes.space});
498
- link.simulate("keyup", {
499
- preventDefault: jest.fn(),
500
- keyCode: keyCodes.space,
501
- });
497
+ fireEvent.keyDown(link, {keyCode: keyCodes.space});
498
+ fireEvent.keyUp(link, {keyCode: keyCodes.space});
502
499
  expect(onClick).toHaveBeenCalledTimes(0);
503
500
 
504
501
  // Navigation didn't happen with space
505
502
  expect(window.location.assign).toHaveBeenCalledTimes(0);
506
503
 
507
504
  // Enter press should trigger the onClick after keyup
508
- link.simulate("keydown", {keyCode: keyCodes.enter});
505
+ fireEvent.keyDown(link, {keyCode: keyCodes.enter});
509
506
  expect(onClick).toHaveBeenCalledTimes(0);
510
507
 
511
508
  // Navigation doesn't happen until after enter is released
512
509
  expect(window.location.assign).toHaveBeenCalledTimes(0);
513
510
 
514
- link.simulate("keyup", {
515
- preventDefault: jest.fn(),
516
- keyCode: keyCodes.enter,
517
- });
511
+ fireEvent.keyUp(link, {keyCode: keyCodes.enter});
518
512
  expect(onClick).toHaveBeenCalledTimes(1);
519
513
 
520
514
  // Navigation happened after enter click
@@ -523,7 +517,7 @@ describe("ClickableBehavior", () => {
523
517
 
524
518
  it("waits for safeWithNav to resolve before navigation", async () => {
525
519
  // Arrange
526
- const link = mount(
520
+ render(
527
521
  <ClickableBehavior
528
522
  href="https://khanacademy.org/"
529
523
  safeWithNav={() => Promise.resolve()}
@@ -546,7 +540,8 @@ describe("ClickableBehavior", () => {
546
540
  );
547
541
 
548
542
  // Act
549
- link.simulate("click", {preventDefault: jest.fn()});
543
+ const link = screen.getByRole("link");
544
+ userEvent.click(link);
550
545
  await wait(0);
551
546
 
552
547
  // Assert
@@ -555,7 +550,7 @@ describe("ClickableBehavior", () => {
555
550
 
556
551
  it("should show waiting UI before safeWithNav resolves", async () => {
557
552
  // Arrange
558
- const link = mount(
553
+ render(
559
554
  <ClickableBehavior
560
555
  href="https://khanacademy.org/"
561
556
  safeWithNav={() => Promise.resolve()}
@@ -578,15 +573,16 @@ describe("ClickableBehavior", () => {
578
573
  );
579
574
 
580
575
  // Act
581
- link.simulate("click", {preventDefault: jest.fn()});
576
+ const link = screen.getByRole("link");
577
+ userEvent.click(link);
582
578
 
583
579
  // Assert
584
- expect(link).toIncludeText("waiting");
580
+ expect(link).toHaveTextContent("waiting");
585
581
  });
586
582
 
587
583
  it("If onClick calls e.preventDefault() then we won't navigate", () => {
588
584
  // Arrange
589
- const wrapper = mount(
585
+ render(
590
586
  <ClickableBehavior
591
587
  href="/foo"
592
588
  onClick={(e) => e.preventDefault()}
@@ -596,23 +592,14 @@ describe("ClickableBehavior", () => {
596
592
  // The base element here doesn't matter in this testing
597
593
  // environment, but the simulated events in the test are in
598
594
  // line with what browsers do for this element.
599
- return (
600
- <button id="test-button" {...childrenProps}>
601
- label
602
- </button>
603
- );
595
+ return <button {...childrenProps}>label</button>;
604
596
  }}
605
597
  </ClickableBehavior>,
606
598
  );
607
599
 
608
600
  // Act
609
- const button = wrapper.find("#test-button").first();
610
- button.simulate("click", {
611
- preventDefault() {
612
- // $FlowIgnore[object-this-reference]
613
- this.defaultPrevented = true;
614
- },
615
- });
601
+ const button = screen.getByRole("button");
602
+ userEvent.click(button);
616
603
 
617
604
  // Assert
618
605
  expect(window.location.assign).not.toHaveBeenCalled();
@@ -622,7 +609,7 @@ describe("ClickableBehavior", () => {
622
609
  it("calls onClick correctly for a component that doesn't respond to enter", () => {
623
610
  const onClick = jest.fn();
624
611
  // Use mount instead of a shallow render to trigger event defaults
625
- const checkbox = mount(
612
+ render(
626
613
  // triggerOnEnter may be false for some elements e.g. checkboxes
627
614
  <ClickableBehavior onClick={(e) => onClick(e)} role="checkbox">
628
615
  {(state, childrenProps) => {
@@ -635,27 +622,22 @@ describe("ClickableBehavior", () => {
635
622
  );
636
623
 
637
624
  // Enter press should not do anything
638
- checkbox.simulate("keydown", {keyCode: keyCodes.enter});
625
+ const checkbox = screen.getByRole("checkbox");
626
+ fireEvent.keyDown(checkbox, {keyCode: keyCodes.enter});
639
627
  expect(onClick).toHaveBeenCalledTimes(0);
640
- checkbox.simulate("keyup", {
641
- preventDefault: jest.fn(),
642
- keyCode: keyCodes.enter,
643
- });
628
+ fireEvent.keyUp(checkbox, {keyCode: keyCodes.enter});
644
629
  expect(onClick).toHaveBeenCalledTimes(0);
645
630
 
646
631
  // Space press should trigger the onClick
647
- checkbox.simulate("keydown", {keyCode: keyCodes.space});
648
- checkbox.simulate("keyup", {
649
- preventDefault: jest.fn(),
650
- keyCode: keyCodes.space,
651
- });
632
+ fireEvent.keyDown(checkbox, {keyCode: keyCodes.space});
633
+ fireEvent.keyUp(checkbox, {keyCode: keyCodes.space});
652
634
  expect(onClick).toHaveBeenCalledTimes(1);
653
635
  });
654
636
 
655
637
  it("calls onClick for a button component on both enter/space", () => {
656
638
  const onClick = jest.fn();
657
639
  // Use mount instead of a shallow render to trigger event defaults
658
- const button = mount(
640
+ render(
659
641
  <ClickableBehavior onClick={(e) => onClick(e)}>
660
642
  {(state, childrenProps) => {
661
643
  // The base element here doesn't matter in this testing
@@ -667,21 +649,16 @@ describe("ClickableBehavior", () => {
667
649
  );
668
650
 
669
651
  // Enter press
670
- button.simulate("keydown", {keyCode: keyCodes.enter});
652
+ const button = screen.getByRole("button");
653
+ fireEvent.keyDown(button, {keyCode: keyCodes.enter});
671
654
  expect(onClick).toHaveBeenCalledTimes(0);
672
- button.simulate("keyup", {
673
- preventDefault: jest.fn(),
674
- keyCode: keyCodes.enter,
675
- });
655
+ fireEvent.keyUp(button, {keyCode: keyCodes.enter});
676
656
  expect(onClick).toHaveBeenCalledTimes(1);
677
657
 
678
658
  // Space press
679
- button.simulate("keydown", {keyCode: keyCodes.space});
659
+ fireEvent.keyDown(button, {keyCode: keyCodes.space});
680
660
  expect(onClick).toHaveBeenCalledTimes(1);
681
- button.simulate("keyup", {
682
- preventDefault: jest.fn(),
683
- keyCode: keyCodes.space,
684
- });
661
+ fireEvent.keyUp(button, {keyCode: keyCodes.space});
685
662
  expect(onClick).toHaveBeenCalledTimes(2);
686
663
  });
687
664
 
@@ -691,7 +668,7 @@ describe("ClickableBehavior", () => {
691
668
  it("calls onClick listener on space/enter with a non-usually clickable element", () => {
692
669
  const onClick = jest.fn();
693
670
  // Use mount instead of a shallow render to trigger event defaults
694
- const div = mount(
671
+ const {container} = render(
695
672
  <ClickableBehavior onClick={(e) => onClick(e)}>
696
673
  {(state, childrenProps) => {
697
674
  // The base element here doesn't matter in this testing
@@ -703,50 +680,42 @@ describe("ClickableBehavior", () => {
703
680
  );
704
681
 
705
682
  let expectedNumberTimesCalled = 0;
706
- const clickableDiv = div.find("div");
683
+ // eslint-disable-next-line testing-library/no-node-access, testing-library/no-container
684
+ const clickableDiv = container.querySelector("div");
685
+ if (!clickableDiv) {
686
+ throw new Error("couldn't find clickable div");
687
+ }
707
688
 
708
689
  // Enter press on a div
709
- clickableDiv.simulate("keydown", {keyCode: keyCodes.enter});
690
+ fireEvent.keyDown(clickableDiv, {keyCode: keyCodes.enter});
710
691
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
711
- clickableDiv.simulate("keyup", {
712
- preventDefault: jest.fn(),
692
+ fireEvent.keyUp(clickableDiv, {
713
693
  keyCode: keyCodes.enter,
714
694
  });
715
695
  expectedNumberTimesCalled += 1;
716
696
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
717
697
 
718
698
  // Simulate a mouse click.
719
- clickableDiv.simulate("mousedown");
720
- expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
721
- clickableDiv.simulate("mouseup");
722
- expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
723
- clickableDiv.simulate("click", {preventDefault: jest.fn()});
699
+ userEvent.click(clickableDiv);
724
700
  expectedNumberTimesCalled += 1;
725
701
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
726
702
 
727
703
  // Space press on a div
728
- clickableDiv.simulate("keydown", {keyCode: keyCodes.space});
704
+ fireEvent.keyDown(clickableDiv, {keyCode: keyCodes.space});
729
705
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
730
- clickableDiv.simulate("keyup", {
731
- preventDefault: jest.fn(),
732
- keyCode: keyCodes.space,
733
- });
706
+ fireEvent.keyUp(clickableDiv, {keyCode: keyCodes.space});
734
707
  expectedNumberTimesCalled += 1;
735
708
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
736
709
 
737
710
  // Simulate another mouse click.
738
- clickableDiv.simulate("mousedown");
739
- expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
740
- clickableDiv.simulate("mouseup");
741
- expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
742
- clickableDiv.simulate("click", {preventDefault: jest.fn()});
711
+ userEvent.click(clickableDiv);
743
712
  expectedNumberTimesCalled += 1;
744
713
  expect(onClick).toHaveBeenCalledTimes(expectedNumberTimesCalled);
745
714
  });
746
715
 
747
716
  it("calls onClick on mouseup when the mouse was dragging", () => {
748
717
  const onClick = jest.fn();
749
- const button = shallow(
718
+ render(
750
719
  <ClickableBehavior disabled={false} onClick={(e) => onClick(e)}>
751
720
  {(state, childrenProps) => {
752
721
  return <button {...childrenProps}>Label</button>;
@@ -754,28 +723,27 @@ describe("ClickableBehavior", () => {
754
723
  </ClickableBehavior>,
755
724
  );
756
725
 
757
- button.simulate("mousedown");
758
- button.simulate("dragstart", {preventDefault: jest.fn()});
759
- button.simulate("mouseleave");
760
- button.simulate("mouseup");
726
+ const button = screen.getByRole("button");
727
+ fireEvent.mouseDown(button);
728
+ fireEvent.dragStart(button);
729
+ fireEvent.mouseLeave(button);
730
+ fireEvent.mouseUp(button);
761
731
  expect(onClick).toHaveBeenCalledTimes(0);
762
732
 
763
- button.simulate("mousedown");
764
- button.simulate("dragstart", {preventDefault: jest.fn()});
765
- button.simulate("mouseup", {preventDefault: jest.fn()});
733
+ fireEvent.mouseDown(button);
734
+ fireEvent.dragStart(button);
735
+ fireEvent.mouseUp(button);
766
736
  expect(onClick).toHaveBeenCalledTimes(1);
767
737
 
768
- button.simulate("mouseenter", {
769
- buttons: 1,
770
- });
771
- button.simulate("mouseup", {preventDefault: jest.fn()});
738
+ fireEvent.mouseEnter(button, {buttons: 1});
739
+ fireEvent.mouseUp(button);
772
740
  expect(onClick).toHaveBeenCalledTimes(2);
773
741
  });
774
742
 
775
743
  it("doesn't trigger enter key when browser doesn't stop the click", () => {
776
744
  const onClick = jest.fn();
777
745
  // Use mount instead of a shallow render to trigger event defaults
778
- const checkbox = mount(
746
+ render(
779
747
  <ClickableBehavior onClick={(e) => onClick(e)} role="checkbox">
780
748
  {(state, childrenProps) => {
781
749
  // The base element here doesn't matter in this testing
@@ -786,14 +754,12 @@ describe("ClickableBehavior", () => {
786
754
  </ClickableBehavior>,
787
755
  );
788
756
 
757
+ const checkbox = screen.getByRole("checkbox");
789
758
  // Enter press should not do anything
790
- checkbox.simulate("keydown", {keyCode: keyCodes.enter});
759
+ fireEvent.keyDown(checkbox, {keyCode: keyCodes.enter});
791
760
  // This element still wants to have a click on enter press
792
- checkbox.simulate("click", {preventDefault: jest.fn()});
793
- checkbox.simulate("keyup", {
794
- preventDefault: jest.fn(),
795
- keyCode: keyCodes.enter,
796
- });
761
+ fireEvent.click(checkbox);
762
+ fireEvent.keyUp(checkbox, {keyCode: keyCodes.enter});
797
763
  expect(onClick).toHaveBeenCalledTimes(0);
798
764
  });
799
765
 
@@ -806,7 +772,7 @@ describe("ClickableBehavior", () => {
806
772
 
807
773
  it("handles client-side navigation when there's a router context", () => {
808
774
  // Arrange
809
- const wrapper = mount(
775
+ render(
810
776
  <MemoryRouter>
811
777
  <div>
812
778
  <ClickableBehaviorWithRouter
@@ -819,9 +785,7 @@ describe("ClickableBehavior", () => {
819
785
  // environment, but the simulated events in the test are in
820
786
  // line with what browsers do for this element.
821
787
  return (
822
- <button id="test-button" {...childrenProps}>
823
- label
824
- </button>
788
+ <button {...childrenProps}>label</button>
825
789
  );
826
790
  }}
827
791
  </ClickableBehaviorWithRouter>
@@ -835,17 +799,16 @@ describe("ClickableBehavior", () => {
835
799
  );
836
800
 
837
801
  // Act
838
- const button = wrapper.find("#test-button").first();
839
- button.simulate("click", {preventDefault: jest.fn()});
802
+ userEvent.click(screen.getByRole("button"));
840
803
 
841
804
  // Assert
842
- expect(wrapper).toIncludeText("Hello, world!");
805
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
843
806
  });
844
807
 
845
808
  describe("beforeNav", () => {
846
809
  it("waits for beforeNav to resolve before client-side navigating", async () => {
847
810
  // Arrange
848
- const wrapper = mount(
811
+ render(
849
812
  <MemoryRouter>
850
813
  <div>
851
814
  <ClickableBehaviorWithRouter
@@ -859,10 +822,7 @@ describe("ClickableBehavior", () => {
859
822
  // environment, but the simulated events in the test are in
860
823
  // line with what browsers do for this element.
861
824
  return (
862
- <button
863
- id="test-button"
864
- {...childrenProps}
865
- >
825
+ <button {...childrenProps}>
866
826
  {state.waiting
867
827
  ? "waiting"
868
828
  : "label"}
@@ -880,17 +840,16 @@ describe("ClickableBehavior", () => {
880
840
  );
881
841
 
882
842
  // Act
883
- const button = wrapper.find("#test-button").first();
884
- button.simulate("click", {preventDefault: jest.fn()});
843
+ userEvent.click(screen.getByRole("button"));
885
844
  await wait(0);
886
845
 
887
846
  // Assert
888
- expect(wrapper).toIncludeText("Hello, world!");
847
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
889
848
  });
890
849
 
891
850
  it("shows waiting state before navigating", async () => {
892
851
  // Arrange
893
- const wrapper = mount(
852
+ render(
894
853
  <MemoryRouter>
895
854
  <div>
896
855
  <ClickableBehaviorWithRouter
@@ -904,10 +863,7 @@ describe("ClickableBehavior", () => {
904
863
  // environment, but the simulated events in the test are in
905
864
  // line with what browsers do for this element.
906
865
  return (
907
- <button
908
- id="test-button"
909
- {...childrenProps}
910
- >
866
+ <button {...childrenProps}>
911
867
  {state.waiting
912
868
  ? "waiting"
913
869
  : "label"}
@@ -925,16 +881,15 @@ describe("ClickableBehavior", () => {
925
881
  );
926
882
 
927
883
  // Act
928
- const button = wrapper.find("#test-button").first();
929
- button.simulate("click", {preventDefault: jest.fn()});
884
+ userEvent.click(screen.getByRole("button"));
930
885
 
931
886
  // Assert
932
- expect(wrapper).toIncludeText("waiting");
887
+ expect(screen.getByText("waiting")).toBeInTheDocument();
933
888
  });
934
889
 
935
890
  it("does not navigate if beforeNav rejects", async () => {
936
891
  // Arrange
937
- const wrapper = mount(
892
+ render(
938
893
  <MemoryRouter>
939
894
  <div>
940
895
  <ClickableBehaviorWithRouter
@@ -948,10 +903,7 @@ describe("ClickableBehavior", () => {
948
903
  // environment, but the simulated events in the test are in
949
904
  // line with what browsers do for this element.
950
905
  return (
951
- <button
952
- id="test-button"
953
- {...childrenProps}
954
- >
906
+ <button {...childrenProps}>
955
907
  label
956
908
  </button>
957
909
  );
@@ -967,18 +919,19 @@ describe("ClickableBehavior", () => {
967
919
  );
968
920
 
969
921
  // Act
970
- const button = wrapper.find("#test-button").first();
971
- button.simulate("click", {preventDefault: jest.fn()});
922
+ userEvent.click(screen.getByRole("button"));
972
923
  await wait(0);
973
924
 
974
925
  // Assert
975
- expect(wrapper).not.toIncludeText("Hello, world!");
926
+ expect(
927
+ screen.queryByText("Hello, world!"),
928
+ ).not.toBeInTheDocument();
976
929
  });
977
930
 
978
931
  it("calls safeWithNav if provided if beforeNav resolves", async () => {
979
932
  // Arrange
980
933
  const safeWithNavMock = jest.fn();
981
- const wrapper = mount(
934
+ render(
982
935
  <MemoryRouter>
983
936
  <div>
984
937
  <ClickableBehaviorWithRouter
@@ -993,10 +946,7 @@ describe("ClickableBehavior", () => {
993
946
  // environment, but the simulated events in the test are in
994
947
  // line with what browsers do for this element.
995
948
  return (
996
- <button
997
- id="test-button"
998
- {...childrenProps}
999
- >
949
+ <button {...childrenProps}>
1000
950
  {state.waiting
1001
951
  ? "waiting"
1002
952
  : "label"}
@@ -1014,8 +964,7 @@ describe("ClickableBehavior", () => {
1014
964
  );
1015
965
 
1016
966
  // Act
1017
- const button = wrapper.find("#test-button").first();
1018
- button.simulate("click", {preventDefault: jest.fn()});
967
+ userEvent.click(screen.getByRole("button"));
1019
968
  await wait(0);
1020
969
 
1021
970
  // Assert
@@ -1025,7 +974,7 @@ describe("ClickableBehavior", () => {
1025
974
 
1026
975
  it("doesn't wait for safeWithNav to resolve before client-side navigating", async () => {
1027
976
  // Arrange
1028
- const wrapper = mount(
977
+ render(
1029
978
  <MemoryRouter>
1030
979
  <div>
1031
980
  <ClickableBehaviorWithRouter
@@ -1039,9 +988,7 @@ describe("ClickableBehavior", () => {
1039
988
  // environment, but the simulated events in the test are in
1040
989
  // line with what browsers do for this element.
1041
990
  return (
1042
- <button id="test-button" {...childrenProps}>
1043
- label
1044
- </button>
991
+ <button {...childrenProps}>label</button>
1045
992
  );
1046
993
  }}
1047
994
  </ClickableBehaviorWithRouter>
@@ -1055,16 +1002,15 @@ describe("ClickableBehavior", () => {
1055
1002
  );
1056
1003
 
1057
1004
  // Act
1058
- const button = wrapper.find("#test-button").first();
1059
- button.simulate("click", {preventDefault: jest.fn()});
1005
+ userEvent.click(screen.getByRole("button"));
1060
1006
 
1061
1007
  // Assert
1062
- expect(wrapper).toIncludeText("Hello, world!");
1008
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
1063
1009
  });
1064
1010
 
1065
1011
  it("If onClick calls e.preventDefault() then we won't navigate", () => {
1066
1012
  // Arrange
1067
- const wrapper = mount(
1013
+ render(
1068
1014
  <MemoryRouter>
1069
1015
  <div>
1070
1016
  <ClickableBehaviorWithRouter
@@ -1077,9 +1023,7 @@ describe("ClickableBehavior", () => {
1077
1023
  // environment, but the simulated events in the test are in
1078
1024
  // line with what browsers do for this element.
1079
1025
  return (
1080
- <button id="test-button" {...childrenProps}>
1081
- label
1082
- </button>
1026
+ <button {...childrenProps}>label</button>
1083
1027
  );
1084
1028
  }}
1085
1029
  </ClickableBehaviorWithRouter>
@@ -1093,23 +1037,17 @@ describe("ClickableBehavior", () => {
1093
1037
  );
1094
1038
 
1095
1039
  // Act
1096
- const button = wrapper.find("#test-button").first();
1097
- button.simulate("click", {
1098
- preventDefault() {
1099
- // $FlowIgnore[object-this-reference]
1100
- this.defaultPrevented = true;
1101
- },
1102
- });
1040
+ userEvent.click(screen.getByRole("button"));
1103
1041
 
1104
1042
  // Assert
1105
- expect(wrapper).not.toIncludeText("Hello, world!");
1043
+ expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
1106
1044
  });
1107
1045
  });
1108
1046
 
1109
1047
  describe("target='_blank'", () => {
1110
1048
  it("opens a new tab", () => {
1111
1049
  // Arrange
1112
- const link = mount(
1050
+ render(
1113
1051
  <ClickableBehavior
1114
1052
  disabled={false}
1115
1053
  href="https://www.khanacademy.org"
@@ -1130,7 +1068,7 @@ describe("ClickableBehavior", () => {
1130
1068
  );
1131
1069
 
1132
1070
  // Act
1133
- link.simulate("click");
1071
+ userEvent.click(screen.getByRole("link"));
1134
1072
 
1135
1073
  // Assert
1136
1074
  expect(window.open).toHaveBeenCalledWith(
@@ -1142,7 +1080,7 @@ describe("ClickableBehavior", () => {
1142
1080
  it("opens a new tab when using 'safeWithNav'", () => {
1143
1081
  // Arrange
1144
1082
  const safeWithNavMock = jest.fn().mockResolvedValue();
1145
- const link = mount(
1083
+ render(
1146
1084
  <ClickableBehavior
1147
1085
  disabled={false}
1148
1086
  href="https://www.khanacademy.org"
@@ -1164,7 +1102,7 @@ describe("ClickableBehavior", () => {
1164
1102
  );
1165
1103
 
1166
1104
  // Act
1167
- link.simulate("click");
1105
+ userEvent.click(screen.getByRole("link"));
1168
1106
 
1169
1107
  // Assert
1170
1108
  expect(window.open).toHaveBeenCalledWith(
@@ -1176,7 +1114,7 @@ describe("ClickableBehavior", () => {
1176
1114
  it("calls 'safeWithNav'", () => {
1177
1115
  // Arrange
1178
1116
  const safeWithNavMock = jest.fn().mockResolvedValue();
1179
- const link = mount(
1117
+ render(
1180
1118
  <ClickableBehavior
1181
1119
  disabled={false}
1182
1120
  href="https://www.khanacademy.org"
@@ -1198,7 +1136,7 @@ describe("ClickableBehavior", () => {
1198
1136
  );
1199
1137
 
1200
1138
  // Act
1201
- link.simulate("click");
1139
+ userEvent.click(screen.getByRole("link"));
1202
1140
 
1203
1141
  // Assert
1204
1142
  expect(safeWithNavMock).toHaveBeenCalled();
@@ -1206,7 +1144,7 @@ describe("ClickableBehavior", () => {
1206
1144
 
1207
1145
  it("opens a new tab when inside a router", () => {
1208
1146
  // Arrange
1209
- const link = mount(
1147
+ render(
1210
1148
  <MemoryRouter initialEntries={["/"]}>
1211
1149
  <ClickableBehavior
1212
1150
  disabled={false}
@@ -1229,7 +1167,7 @@ describe("ClickableBehavior", () => {
1229
1167
  );
1230
1168
 
1231
1169
  // Act
1232
- link.simulate("click");
1170
+ userEvent.click(screen.getByRole("link"));
1233
1171
 
1234
1172
  // Assert
1235
1173
  expect(window.open).toHaveBeenCalledWith(
@@ -1241,7 +1179,7 @@ describe("ClickableBehavior", () => {
1241
1179
  it("opens a new tab when using 'safeWithNav' inside a router", () => {
1242
1180
  // Arrange
1243
1181
  const safeWithNavMock = jest.fn().mockResolvedValue();
1244
- const link = mount(
1182
+ render(
1245
1183
  <MemoryRouter initialEntries={["/"]}>
1246
1184
  <ClickableBehavior
1247
1185
  disabled={false}
@@ -1265,7 +1203,7 @@ describe("ClickableBehavior", () => {
1265
1203
  );
1266
1204
 
1267
1205
  // Act
1268
- link.simulate("click");
1206
+ userEvent.click(screen.getByRole("link"));
1269
1207
 
1270
1208
  // Assert
1271
1209
  expect(window.open).toHaveBeenCalledWith(
@@ -1277,7 +1215,7 @@ describe("ClickableBehavior", () => {
1277
1215
  it("calls 'safeWithNav' inside a router", () => {
1278
1216
  // Arrange
1279
1217
  const safeWithNavMock = jest.fn().mockResolvedValue();
1280
- const link = mount(
1218
+ render(
1281
1219
  <MemoryRouter initialEntries={["/"]}>
1282
1220
  <ClickableBehavior
1283
1221
  disabled={false}
@@ -1301,7 +1239,7 @@ describe("ClickableBehavior", () => {
1301
1239
  );
1302
1240
 
1303
1241
  // Act
1304
- link.simulate("click");
1242
+ userEvent.click(screen.getByRole("link"));
1305
1243
 
1306
1244
  // Assert
1307
1245
  expect(safeWithNavMock).toHaveBeenCalled();
@@ -1312,7 +1250,7 @@ describe("ClickableBehavior", () => {
1312
1250
  it("should use the 'rel' that was passed in", () => {
1313
1251
  // Arrange
1314
1252
  const childrenMock = jest.fn().mockImplementation(() => null);
1315
- mount(
1253
+ render(
1316
1254
  <ClickableBehavior
1317
1255
  href="https://www.khanacademy.org"
1318
1256
  rel="something_else"
@@ -1329,7 +1267,7 @@ describe("ClickableBehavior", () => {
1329
1267
  it("should use 'noopener noreferrer' as a default when target='_blank'", () => {
1330
1268
  // Arrange
1331
1269
  const childrenMock = jest.fn().mockImplementation(() => null);
1332
- mount(
1270
+ render(
1333
1271
  <ClickableBehavior
1334
1272
  href="https://www.khanacademy.org"
1335
1273
  target="_blank"
@@ -1345,7 +1283,7 @@ describe("ClickableBehavior", () => {
1345
1283
  it("should not use the default if target != '_blank'", () => {
1346
1284
  // Arrange
1347
1285
  const childrenMock = jest.fn().mockImplementation(() => null);
1348
- mount(
1286
+ render(
1349
1287
  <ClickableBehavior href="https://www.khanacademy.org">
1350
1288
  {childrenMock}
1351
1289
  </ClickableBehavior>,