@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,9 +1,7 @@
1
1
  // @flow
2
2
  import * as React from "react";
3
3
  import {MemoryRouter, Route, Switch} from "react-router-dom";
4
- import {mount} from "enzyme";
5
- import "jest-enzyme";
6
- import {render, screen} from "@testing-library/react";
4
+ import {render, screen, fireEvent} from "@testing-library/react";
7
5
  import userEvent from "@testing-library/user-event";
8
6
 
9
7
  import {View} from "@khanacademy/wonder-blocks-core";
@@ -23,7 +21,7 @@ describe("Clickable", () => {
23
21
 
24
22
  test("client-side navigation", () => {
25
23
  // Arrange
26
- const wrapper = mount(
24
+ render(
27
25
  <MemoryRouter>
28
26
  <View>
29
27
  <Clickable testId="button" href="/foo">
@@ -31,7 +29,7 @@ describe("Clickable", () => {
31
29
  </Clickable>
32
30
  <Switch>
33
31
  <Route path="/foo">
34
- <View id="foo">Hello, world!</View>
32
+ <View>Hello, world!</View>
35
33
  </Route>
36
34
  </Switch>
37
35
  </View>
@@ -39,18 +37,15 @@ describe("Clickable", () => {
39
37
  );
40
38
 
41
39
  // Act
42
- const clickableWrapper = wrapper
43
- .find(`[data-test-id="button"]`)
44
- .first();
45
- clickableWrapper.simulate("click", {button: 0});
40
+ userEvent.click(screen.getByTestId("button"));
46
41
 
47
42
  // Assert
48
- expect(wrapper.find("#foo").exists()).toBe(true);
43
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
49
44
  });
50
45
 
51
46
  test("client-side navigation with unknown URL fails", () => {
52
47
  // Arrange
53
- const wrapper = mount(
48
+ render(
54
49
  <MemoryRouter>
55
50
  <View>
56
51
  <Clickable testId="button" href="/unknown">
@@ -58,7 +53,7 @@ describe("Clickable", () => {
58
53
  </Clickable>
59
54
  <Switch>
60
55
  <Route path="/foo">
61
- <View id="foo">Hello, world!</View>
56
+ <View>Hello, world!</View>
62
57
  </Route>
63
58
  </Switch>
64
59
  </View>
@@ -66,16 +61,15 @@ describe("Clickable", () => {
66
61
  );
67
62
 
68
63
  // Act
69
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
70
- buttonWrapper.simulate("click", {button: 0});
64
+ userEvent.click(screen.getByTestId("button"));
71
65
 
72
66
  // Assert
73
- expect(wrapper.find("#foo").exists()).toBe(false);
67
+ expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
74
68
  });
75
69
 
76
70
  test("client-side navigation with `skipClientNav` set to `true` fails", () => {
77
71
  // Arrange
78
- const wrapper = mount(
72
+ render(
79
73
  <MemoryRouter>
80
74
  <View>
81
75
  <Clickable testId="button" href="/foo" skipClientNav>
@@ -83,7 +77,7 @@ describe("Clickable", () => {
83
77
  </Clickable>
84
78
  <Switch>
85
79
  <Route path="/foo">
86
- <View id="foo">Hello, world!</View>
80
+ <View>Hello, world!</View>
87
81
  </Route>
88
82
  </Switch>
89
83
  </View>
@@ -91,16 +85,15 @@ describe("Clickable", () => {
91
85
  );
92
86
 
93
87
  // Act
94
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
95
- buttonWrapper.simulate("click", {button: 0});
88
+ userEvent.click(screen.getByTestId("button"));
96
89
 
97
90
  // Assert
98
- expect(wrapper.find("#foo").exists()).toBe(false);
91
+ expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
99
92
  });
100
93
 
101
94
  test("disallow navigation when href and disabled are both set", () => {
102
95
  // Arrange
103
- const wrapper = mount(
96
+ render(
104
97
  <MemoryRouter>
105
98
  <View>
106
99
  <Clickable testId="button" href="/foo" disabled={true}>
@@ -108,7 +101,7 @@ describe("Clickable", () => {
108
101
  </Clickable>
109
102
  <Switch>
110
103
  <Route path="/foo">
111
- <View id="foo">Hello, world!</View>
104
+ <View>Hello, world!</View>
112
105
  </Route>
113
106
  </Switch>
114
107
  </View>
@@ -116,37 +109,39 @@ describe("Clickable", () => {
116
109
  );
117
110
 
118
111
  // Act
119
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
120
- buttonWrapper.simulate("click", {button: 0});
112
+ userEvent.click(screen.getByTestId("button"));
121
113
 
122
114
  // Assert
123
- expect(wrapper.find("#foo").exists()).toBe(false);
115
+ expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
124
116
  });
125
117
 
126
- test("should verify if href is passed to Clickablebehavior", () => {
118
+ test("a link is rendered with the given href", () => {
127
119
  // Arrange, Act
128
- const wrapper = mount(
120
+ render(
129
121
  <Clickable testId="button" href="/foo" skipClientNav={true}>
130
122
  {(eventState) => <h1>Click Me!</h1>}
131
123
  </Clickable>,
132
124
  );
133
125
 
134
126
  // Assert
135
- expect(wrapper.find("ClickableBehavior")).toHaveProp({href: "/foo"});
127
+ const link = screen.getByRole("link");
128
+ expect(link).toBeInTheDocument();
129
+ expect(link).toHaveAttribute("href", "/foo");
136
130
  });
137
131
 
138
132
  test("should navigate to a specific link using the keyboard", () => {
139
133
  // Arrange
140
- const wrapper = mount(
134
+ render(
141
135
  <Clickable testId="button" href="/foo" skipClientNav={true}>
142
136
  {(eventState) => <h1>Click Me!</h1>}
143
137
  </Clickable>,
144
138
  );
145
139
 
146
140
  // Act
147
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
141
+ const button = screen.getByTestId("button");
148
142
  // simulate Enter
149
- buttonWrapper.simulate("keyup", {keyCode: 13});
143
+ // eslint-disable-next-line testing-library/prefer-user-event
144
+ fireEvent.keyUp(button, {keyCode: 13});
150
145
 
151
146
  // Assert
152
147
  expect(window.location.assign).toHaveBeenCalledWith("/foo");
@@ -154,7 +149,7 @@ describe("Clickable", () => {
154
149
 
155
150
  test("beforeNav rejection blocks client-side navigation", async () => {
156
151
  // Arrange
157
- const wrapper = mount(
152
+ render(
158
153
  <MemoryRouter>
159
154
  <div>
160
155
  <Clickable
@@ -166,7 +161,7 @@ describe("Clickable", () => {
166
161
  </Clickable>
167
162
  <Switch>
168
163
  <Route path="/foo">
169
- <div id="foo">Hello, world!</div>
164
+ <div>Hello, world!</div>
170
165
  </Route>
171
166
  </Switch>
172
167
  </div>
@@ -174,19 +169,17 @@ describe("Clickable", () => {
174
169
  );
175
170
 
176
171
  // Act
177
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
178
- buttonWrapper.simulate("click", {button: 0});
172
+ userEvent.click(screen.getByTestId("button"));
179
173
  await wait(0);
180
- buttonWrapper.update();
181
174
 
182
175
  // Assert
183
- expect(wrapper.find("#foo")).not.toExist();
176
+ expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
184
177
  });
185
178
 
186
179
  test("beforeNav rejection blocks calling safeWithNav", async () => {
187
180
  // Arrange
188
181
  const safeWithNavMock = jest.fn();
189
- const wrapper = mount(
182
+ render(
190
183
  <MemoryRouter>
191
184
  <div>
192
185
  <Clickable
@@ -199,7 +192,7 @@ describe("Clickable", () => {
199
192
  </Clickable>
200
193
  <Switch>
201
194
  <Route path="/foo">
202
- <div id="foo">Hello, world!</div>
195
+ <div>Hello, world!</div>
203
196
  </Route>
204
197
  </Switch>
205
198
  </div>
@@ -207,10 +200,8 @@ describe("Clickable", () => {
207
200
  );
208
201
 
209
202
  // Act
210
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
211
- buttonWrapper.simulate("click", {button: 0});
203
+ userEvent.click(screen.getByTestId("button"));
212
204
  await wait(0);
213
- buttonWrapper.update();
214
205
 
215
206
  // Assert
216
207
  expect(safeWithNavMock).not.toHaveBeenCalled();
@@ -218,7 +209,7 @@ describe("Clickable", () => {
218
209
 
219
210
  test("beforeNav resolution results in client-side navigation", async () => {
220
211
  // Arrange
221
- const wrapper = mount(
212
+ render(
222
213
  <MemoryRouter>
223
214
  <div>
224
215
  <Clickable
@@ -230,7 +221,7 @@ describe("Clickable", () => {
230
221
  </Clickable>
231
222
  <Switch>
232
223
  <Route path="/foo">
233
- <div id="foo">Hello, world!</div>
224
+ <div>Hello, world!</div>
234
225
  </Route>
235
226
  </Switch>
236
227
  </div>
@@ -238,19 +229,17 @@ describe("Clickable", () => {
238
229
  );
239
230
 
240
231
  // Act
241
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
242
- buttonWrapper.simulate("click", {button: 0});
232
+ userEvent.click(screen.getByTestId("button"));
243
233
  await wait(0);
244
- buttonWrapper.update();
245
234
 
246
235
  // Assert
247
- expect(wrapper.find("#foo")).toExist();
236
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
248
237
  });
249
238
 
250
239
  test("beforeNav resolution results in safeWithNav being called", async () => {
251
240
  // Arrange
252
241
  const safeWithNavMock = jest.fn();
253
- const wrapper = mount(
242
+ render(
254
243
  <MemoryRouter>
255
244
  <div>
256
245
  <Clickable
@@ -263,7 +252,7 @@ describe("Clickable", () => {
263
252
  </Clickable>
264
253
  <Switch>
265
254
  <Route path="/foo">
266
- <div id="foo">Hello, world!</div>
255
+ <div>Hello, world!</div>
267
256
  </Route>
268
257
  </Switch>
269
258
  </div>
@@ -271,10 +260,8 @@ describe("Clickable", () => {
271
260
  );
272
261
 
273
262
  // Act
274
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
275
- buttonWrapper.simulate("click", {button: 0});
263
+ userEvent.click(screen.getByTestId("button"));
276
264
  await wait(0);
277
- buttonWrapper.update();
278
265
 
279
266
  // Assert
280
267
  expect(safeWithNavMock).toHaveBeenCalled();
@@ -282,7 +269,7 @@ describe("Clickable", () => {
282
269
 
283
270
  test("safeWithNav with skipClientNav=true waits for promise resolution", async () => {
284
271
  // Arrange
285
- const wrapper = mount(
272
+ render(
286
273
  <MemoryRouter>
287
274
  <div>
288
275
  <Clickable
@@ -295,7 +282,7 @@ describe("Clickable", () => {
295
282
  </Clickable>
296
283
  <Switch>
297
284
  <Route path="/foo">
298
- <div id="foo">Hello, world!</div>
285
+ <div>Hello, world!</div>
299
286
  </Route>
300
287
  </Switch>
301
288
  </div>
@@ -303,10 +290,8 @@ describe("Clickable", () => {
303
290
  );
304
291
 
305
292
  // Act
306
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
307
- buttonWrapper.simulate("click", {button: 0});
293
+ userEvent.click(screen.getByTestId("button"));
308
294
  await wait(0);
309
- buttonWrapper.update();
310
295
 
311
296
  // Assert
312
297
  expect(window.location.assign).toHaveBeenCalledWith("/foo");
@@ -314,7 +299,7 @@ describe("Clickable", () => {
314
299
 
315
300
  test("beforeNav resolution and safeWithNav with skipClientNav=true waits for promise resolution", async () => {
316
301
  // Arrange
317
- const wrapper = mount(
302
+ render(
318
303
  <MemoryRouter>
319
304
  <div>
320
305
  <Clickable
@@ -328,7 +313,7 @@ describe("Clickable", () => {
328
313
  </Clickable>
329
314
  <Switch>
330
315
  <Route path="/foo">
331
- <div id="foo">Hello, world!</div>
316
+ <div>Hello, world!</div>
332
317
  </Route>
333
318
  </Switch>
334
319
  </div>
@@ -336,10 +321,8 @@ describe("Clickable", () => {
336
321
  );
337
322
 
338
323
  // Act
339
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
340
- buttonWrapper.simulate("click", {button: 0});
324
+ userEvent.click(screen.getByTestId("button"));
341
325
  await wait(0);
342
- buttonWrapper.update();
343
326
 
344
327
  // Assert
345
328
  expect(window.location.assign).toHaveBeenCalledWith("/foo");
@@ -347,7 +330,7 @@ describe("Clickable", () => {
347
330
 
348
331
  test("safeWithNav with skipClientNav=true waits for promise rejection", async () => {
349
332
  // Arrange
350
- const wrapper = mount(
333
+ render(
351
334
  <MemoryRouter>
352
335
  <div>
353
336
  <Clickable
@@ -360,7 +343,7 @@ describe("Clickable", () => {
360
343
  </Clickable>
361
344
  <Switch>
362
345
  <Route path="/foo">
363
- <div id="foo">Hello, world!</div>
346
+ <div>Hello, world!</div>
364
347
  </Route>
365
348
  </Switch>
366
349
  </div>
@@ -368,10 +351,8 @@ describe("Clickable", () => {
368
351
  );
369
352
 
370
353
  // Act
371
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
372
- buttonWrapper.simulate("click", {button: 0});
354
+ userEvent.click(screen.getByTestId("button"));
373
355
  await wait(0);
374
- buttonWrapper.update();
375
356
 
376
357
  // Assert
377
358
  expect(window.location.assign).toHaveBeenCalledWith("/foo");
@@ -380,7 +361,7 @@ describe("Clickable", () => {
380
361
  test("safeWithNav with skipClientNav=false calls safeWithNav but doesn't wait to navigate", () => {
381
362
  // Arrange
382
363
  const safeWithNavMock = jest.fn();
383
- const wrapper = mount(
364
+ render(
384
365
  <MemoryRouter>
385
366
  <div>
386
367
  <Clickable
@@ -393,7 +374,7 @@ describe("Clickable", () => {
393
374
  </Clickable>
394
375
  <Switch>
395
376
  <Route path="/foo">
396
- <div id="foo">Hello, world!</div>
377
+ <div>Hello, world!</div>
397
378
  </Route>
398
379
  </Switch>
399
380
  </div>
@@ -401,23 +382,20 @@ describe("Clickable", () => {
401
382
  );
402
383
 
403
384
  // Act
404
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
405
- buttonWrapper.simulate("click", {button: 0});
385
+ userEvent.click(screen.getByTestId("button"));
406
386
 
407
387
  // Assert
408
388
  expect(safeWithNavMock).toHaveBeenCalled();
409
- expect(wrapper).toIncludeText(
410
- "Hello, world!" /*client side nav to /foo*/,
411
- );
412
- expect(window.location.assign).not.toHaveBeenCalledWith(
413
- "/foo" /*not a full page nav*/,
414
- );
389
+ // client side nav to /foo
390
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
391
+ // not a full page nav
392
+ expect(window.location.assign).not.toHaveBeenCalledWith("/foo");
415
393
  });
416
394
 
417
395
  test("safeWithNav with beforeNav resolution and skipClientNav=false calls safeWithNav but doesn't wait to navigate", async () => {
418
396
  // Arrange
419
397
  const safeWithNavMock = jest.fn();
420
- const wrapper = mount(
398
+ render(
421
399
  <MemoryRouter>
422
400
  <div>
423
401
  <Clickable
@@ -431,7 +409,7 @@ describe("Clickable", () => {
431
409
  </Clickable>
432
410
  <Switch>
433
411
  <Route path="/foo">
434
- <div id="foo">Hello, world!</div>
412
+ <div>Hello, world!</div>
435
413
  </Route>
436
414
  </Switch>
437
415
  </div>
@@ -439,19 +417,15 @@ describe("Clickable", () => {
439
417
  );
440
418
 
441
419
  // Act
442
- const buttonWrapper = wrapper.find(`[data-test-id="button"]`).first();
443
- buttonWrapper.simulate("click", {button: 0});
420
+ userEvent.click(screen.getByTestId("button"));
444
421
  await wait(0);
445
- buttonWrapper.update();
446
422
 
447
423
  // Assert
448
424
  expect(safeWithNavMock).toHaveBeenCalled();
449
- expect(wrapper).toIncludeText(
450
- "Hello, world!" /*client side nav to /foo*/,
451
- );
452
- expect(window.location.assign).not.toHaveBeenCalledWith(
453
- "/foo" /*not a full page nav*/,
454
- );
425
+ // client side nav to /foo
426
+ expect(screen.getByText("Hello, world!")).toBeInTheDocument();
427
+ // not a full page nav
428
+ expect(window.location.assign).not.toHaveBeenCalledWith("/foo");
455
429
  });
456
430
 
457
431
  test("should add aria-disabled if disabled is set", () => {
@@ -470,6 +444,44 @@ describe("Clickable", () => {
470
444
  expect(button).toHaveAttribute("aria-disabled", "true");
471
445
  });
472
446
 
447
+ test("should add aria-label if one is passed in", () => {
448
+ // Arrange
449
+
450
+ // Act
451
+ render(
452
+ <Clickable
453
+ testId="clickable-button"
454
+ aria-label="clickable-button-aria-label"
455
+ >
456
+ {(eventState) => <h1>Click Me!</h1>}
457
+ </Clickable>,
458
+ );
459
+
460
+ const button = screen.getByTestId("clickable-button");
461
+
462
+ // Assert
463
+ expect(button).toHaveAttribute(
464
+ "aria-label",
465
+ "clickable-button-aria-label",
466
+ );
467
+ });
468
+
469
+ test("should not have an aria-label if one is not passed in", () => {
470
+ // Arrange
471
+
472
+ // Act
473
+ render(
474
+ <Clickable testId="clickable-button">
475
+ {(eventState) => <h1>Click Me!</h1>}
476
+ </Clickable>,
477
+ );
478
+
479
+ const button = screen.getByTestId("clickable-button");
480
+
481
+ // Assert
482
+ expect(button).not.toHaveAttribute("aria-label");
483
+ });
484
+
473
485
  test("allow keyboard navigation when disabled is set", () => {
474
486
  // Arrange
475
487
  render(
@@ -513,38 +525,36 @@ describe("Clickable", () => {
513
525
 
514
526
  test("onKeyDown", () => {
515
527
  // Arrange
516
- const keyMock = jest.fn();
517
- const wrapper = mount(
518
- <ClickableWrapper onKeyDown={keyMock}>
528
+ let keyCode;
529
+ render(
530
+ <ClickableWrapper onKeyDown={(e) => (keyCode = e.keyCode)}>
519
531
  Click me!
520
532
  </ClickableWrapper>,
521
533
  );
522
534
 
523
535
  // Act
524
- wrapper.find("Clickable").simulate("keydown", {keyCode: 32});
536
+ // eslint-disable-next-line testing-library/prefer-user-event
537
+ fireEvent.keyDown(screen.getByRole("button"), {keyCode: 32});
525
538
 
526
539
  // Assert
527
- expect(keyMock).toHaveBeenCalledWith(
528
- expect.objectContaining({keyCode: 32}),
529
- );
540
+ expect(keyCode).toEqual(32);
530
541
  });
531
542
 
532
543
  test("onKeyUp", () => {
533
544
  // Arrange
534
- const keyMock = jest.fn();
535
- const wrapper = mount(
536
- <ClickableWrapper onKeyDown={keyMock}>
545
+ let keyCode;
546
+ render(
547
+ <ClickableWrapper onKeyUp={(e) => (keyCode = e.keyCode)}>
537
548
  Click me!
538
549
  </ClickableWrapper>,
539
550
  );
540
551
 
541
552
  // Act
542
- wrapper.find("Clickable").simulate("keydown", {keyCode: 32});
553
+ // eslint-disable-next-line testing-library/prefer-user-event
554
+ fireEvent.keyUp(screen.getByRole("button"), {keyCode: 32});
543
555
 
544
556
  // Assert
545
- expect(keyMock).toHaveBeenCalledWith(
546
- expect.objectContaining({keyCode: 32}),
547
- );
557
+ expect(keyCode).toEqual(32);
548
558
  });
549
559
  });
550
560
  });
@@ -176,7 +176,6 @@ type Props =
176
176
  type DefaultProps = {|
177
177
  light: $PropertyType<Props, "light">,
178
178
  disabled: $PropertyType<Props, "disabled">,
179
- "aria-label": $PropertyType<Props, "aria-label">,
180
179
  |};
181
180
 
182
181
  const StyledAnchor = addStyle<"a">("a");
@@ -220,7 +219,6 @@ export default class Clickable extends React.Component<Props> {
220
219
  static defaultProps: DefaultProps = {
221
220
  light: false,
222
221
  disabled: false,
223
- "aria-label": "",
224
222
  };
225
223
 
226
224
  getCorrectTag: (