@khanacademy/wonder-blocks-clickable 4.1.2 → 4.2.0
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.
- package/CHANGELOG.md +20 -0
- package/dist/es/index.js +2 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/src/components/__tests__/clickable-behavior.test.tsx +111 -105
- package/src/components/__tests__/clickable.test.tsx +56 -52
- package/src/components/clickable.tsx +2 -2
- package/tsconfig-build.tsbuildinfo +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import {MemoryRouter, Route, Switch} from "react-router-dom";
|
|
3
3
|
import {render, screen, fireEvent, waitFor} from "@testing-library/react";
|
|
4
|
-
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import {userEvent} from "@testing-library/user-event";
|
|
5
5
|
|
|
6
6
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
7
7
|
import Clickable from "../clickable";
|
|
@@ -14,7 +14,7 @@ describe("Clickable", () => {
|
|
|
14
14
|
window.location = {assign: jest.fn()};
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test("client-side navigation", () => {
|
|
17
|
+
test("client-side navigation", async () => {
|
|
18
18
|
// Arrange
|
|
19
19
|
render(
|
|
20
20
|
<MemoryRouter>
|
|
@@ -32,13 +32,13 @@ describe("Clickable", () => {
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
// Act
|
|
35
|
-
userEvent.click(screen.
|
|
35
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
36
36
|
|
|
37
37
|
// Assert
|
|
38
|
-
expect(screen.
|
|
38
|
+
expect(await screen.findByText("Hello, world!")).toBeInTheDocument();
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test("client-side navigation with unknown URL fails", () => {
|
|
41
|
+
test("client-side navigation with unknown URL fails", async () => {
|
|
42
42
|
// Arrange
|
|
43
43
|
render(
|
|
44
44
|
<MemoryRouter>
|
|
@@ -56,13 +56,13 @@ describe("Clickable", () => {
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
// Act
|
|
59
|
-
userEvent.click(screen.
|
|
59
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
60
60
|
|
|
61
61
|
// Assert
|
|
62
62
|
expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
test("client-side navigation with `skipClientNav` set to `true` fails", () => {
|
|
65
|
+
test("client-side navigation with `skipClientNav` set to `true` fails", async () => {
|
|
66
66
|
// Arrange
|
|
67
67
|
render(
|
|
68
68
|
<MemoryRouter>
|
|
@@ -80,13 +80,13 @@ describe("Clickable", () => {
|
|
|
80
80
|
);
|
|
81
81
|
|
|
82
82
|
// Act
|
|
83
|
-
userEvent.click(screen.
|
|
83
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
84
84
|
|
|
85
85
|
// Assert
|
|
86
86
|
expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
test("disallow navigation when href and disabled are both set", () => {
|
|
89
|
+
test("disallow navigation when href and disabled are both set", async () => {
|
|
90
90
|
// Arrange
|
|
91
91
|
render(
|
|
92
92
|
<MemoryRouter>
|
|
@@ -104,13 +104,13 @@ describe("Clickable", () => {
|
|
|
104
104
|
);
|
|
105
105
|
|
|
106
106
|
// Act
|
|
107
|
-
userEvent.click(screen.
|
|
107
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
108
108
|
|
|
109
109
|
// Assert
|
|
110
110
|
expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
test("a link is rendered with the given href", () => {
|
|
113
|
+
test("a link is rendered with the given href", async () => {
|
|
114
114
|
// Arrange, Act
|
|
115
115
|
render(
|
|
116
116
|
<Clickable testId="button" href="/foo" skipClientNav={true}>
|
|
@@ -119,12 +119,12 @@ describe("Clickable", () => {
|
|
|
119
119
|
);
|
|
120
120
|
|
|
121
121
|
// Assert
|
|
122
|
-
const link = screen.
|
|
122
|
+
const link = await screen.findByRole("link");
|
|
123
123
|
expect(link).toBeInTheDocument();
|
|
124
124
|
expect(link).toHaveAttribute("href", "/foo");
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
test("should navigate to a specific link using the keyboard", () => {
|
|
127
|
+
test("should navigate to a specific link using the keyboard", async () => {
|
|
128
128
|
// Arrange
|
|
129
129
|
render(
|
|
130
130
|
<Clickable testId="button" href="/foo" skipClientNav={true}>
|
|
@@ -133,7 +133,7 @@ describe("Clickable", () => {
|
|
|
133
133
|
);
|
|
134
134
|
|
|
135
135
|
// Act
|
|
136
|
-
const button = screen.
|
|
136
|
+
const button = await screen.findByTestId("button");
|
|
137
137
|
// simulate Enter
|
|
138
138
|
// eslint-disable-next-line testing-library/prefer-user-event
|
|
139
139
|
fireEvent.keyUp(button, {keyCode: 13});
|
|
@@ -164,7 +164,7 @@ describe("Clickable", () => {
|
|
|
164
164
|
);
|
|
165
165
|
|
|
166
166
|
// Act
|
|
167
|
-
userEvent.click(screen.
|
|
167
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
168
168
|
|
|
169
169
|
// Assert
|
|
170
170
|
expect(screen.queryByText("Hello, world!")).not.toBeInTheDocument();
|
|
@@ -194,7 +194,7 @@ describe("Clickable", () => {
|
|
|
194
194
|
);
|
|
195
195
|
|
|
196
196
|
// Act
|
|
197
|
-
userEvent.click(screen.
|
|
197
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
198
198
|
|
|
199
199
|
// Assert
|
|
200
200
|
expect(safeWithNavMock).not.toHaveBeenCalled();
|
|
@@ -222,11 +222,13 @@ describe("Clickable", () => {
|
|
|
222
222
|
);
|
|
223
223
|
|
|
224
224
|
// Act
|
|
225
|
-
userEvent.click(screen.
|
|
225
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
226
226
|
|
|
227
227
|
// Assert
|
|
228
|
-
await waitFor(() => {
|
|
229
|
-
expect(
|
|
228
|
+
await waitFor(async () => {
|
|
229
|
+
expect(
|
|
230
|
+
await screen.findByText("Hello, world!"),
|
|
231
|
+
).toBeInTheDocument();
|
|
230
232
|
});
|
|
231
233
|
});
|
|
232
234
|
|
|
@@ -254,7 +256,7 @@ describe("Clickable", () => {
|
|
|
254
256
|
);
|
|
255
257
|
|
|
256
258
|
// Act
|
|
257
|
-
userEvent.click(screen.
|
|
259
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
258
260
|
|
|
259
261
|
// Assert
|
|
260
262
|
await waitFor(() => {
|
|
@@ -285,7 +287,7 @@ describe("Clickable", () => {
|
|
|
285
287
|
);
|
|
286
288
|
|
|
287
289
|
// Act
|
|
288
|
-
userEvent.click(screen.
|
|
290
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
289
291
|
|
|
290
292
|
// Assert
|
|
291
293
|
await waitFor(() => {
|
|
@@ -317,7 +319,7 @@ describe("Clickable", () => {
|
|
|
317
319
|
);
|
|
318
320
|
|
|
319
321
|
// Act
|
|
320
|
-
userEvent.click(screen.
|
|
322
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
321
323
|
|
|
322
324
|
// Assert
|
|
323
325
|
await waitFor(() => {
|
|
@@ -348,7 +350,7 @@ describe("Clickable", () => {
|
|
|
348
350
|
);
|
|
349
351
|
|
|
350
352
|
// Act
|
|
351
|
-
userEvent.click(screen.
|
|
353
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
352
354
|
|
|
353
355
|
// Assert
|
|
354
356
|
await waitFor(() => {
|
|
@@ -356,7 +358,7 @@ describe("Clickable", () => {
|
|
|
356
358
|
});
|
|
357
359
|
});
|
|
358
360
|
|
|
359
|
-
test("safeWithNav with skipClientNav=false calls safeWithNav but doesn't wait to navigate", () => {
|
|
361
|
+
test("safeWithNav with skipClientNav=false calls safeWithNav but doesn't wait to navigate", async () => {
|
|
360
362
|
// Arrange
|
|
361
363
|
const safeWithNavMock = jest.fn();
|
|
362
364
|
render(
|
|
@@ -380,12 +382,12 @@ describe("Clickable", () => {
|
|
|
380
382
|
);
|
|
381
383
|
|
|
382
384
|
// Act
|
|
383
|
-
userEvent.click(screen.
|
|
385
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
384
386
|
|
|
385
387
|
// Assert
|
|
386
388
|
expect(safeWithNavMock).toHaveBeenCalled();
|
|
387
389
|
// client side nav to /foo
|
|
388
|
-
expect(screen.
|
|
390
|
+
expect(await screen.findByText("Hello, world!")).toBeInTheDocument();
|
|
389
391
|
// not a full page nav
|
|
390
392
|
expect(window.location.assign).not.toHaveBeenCalledWith("/foo");
|
|
391
393
|
});
|
|
@@ -415,19 +417,19 @@ describe("Clickable", () => {
|
|
|
415
417
|
);
|
|
416
418
|
|
|
417
419
|
// Act
|
|
418
|
-
userEvent.click(screen.
|
|
420
|
+
await userEvent.click(await screen.findByTestId("button"));
|
|
419
421
|
|
|
420
422
|
// Assert
|
|
421
423
|
await waitFor(() => {
|
|
422
424
|
expect(safeWithNavMock).toHaveBeenCalled();
|
|
423
425
|
});
|
|
424
426
|
// client side nav to /foo
|
|
425
|
-
expect(screen.
|
|
427
|
+
expect(await screen.findByText("Hello, world!")).toBeInTheDocument();
|
|
426
428
|
// not a full page nav
|
|
427
429
|
expect(window.location.assign).not.toHaveBeenCalledWith("/foo");
|
|
428
430
|
});
|
|
429
431
|
|
|
430
|
-
test("should add aria-disabled if disabled is set", () => {
|
|
432
|
+
test("should add aria-disabled if disabled is set", async () => {
|
|
431
433
|
// Arrange
|
|
432
434
|
|
|
433
435
|
// Act
|
|
@@ -437,13 +439,13 @@ describe("Clickable", () => {
|
|
|
437
439
|
</Clickable>,
|
|
438
440
|
);
|
|
439
441
|
|
|
440
|
-
const button = screen.
|
|
442
|
+
const button = await screen.findByTestId("clickable-button");
|
|
441
443
|
|
|
442
444
|
// Assert
|
|
443
445
|
expect(button).toHaveAttribute("aria-disabled", "true");
|
|
444
446
|
});
|
|
445
447
|
|
|
446
|
-
test("should add aria-label if one is passed in", () => {
|
|
448
|
+
test("should add aria-label if one is passed in", async () => {
|
|
447
449
|
// Arrange
|
|
448
450
|
|
|
449
451
|
// Act
|
|
@@ -456,7 +458,7 @@ describe("Clickable", () => {
|
|
|
456
458
|
</Clickable>,
|
|
457
459
|
);
|
|
458
460
|
|
|
459
|
-
const button = screen.
|
|
461
|
+
const button = await screen.findByTestId("clickable-button");
|
|
460
462
|
|
|
461
463
|
// Assert
|
|
462
464
|
expect(button).toHaveAttribute(
|
|
@@ -465,7 +467,7 @@ describe("Clickable", () => {
|
|
|
465
467
|
);
|
|
466
468
|
});
|
|
467
469
|
|
|
468
|
-
test("should not have an aria-label if one is not passed in", () => {
|
|
470
|
+
test("should not have an aria-label if one is not passed in", async () => {
|
|
469
471
|
// Arrange
|
|
470
472
|
|
|
471
473
|
// Act
|
|
@@ -475,13 +477,13 @@ describe("Clickable", () => {
|
|
|
475
477
|
</Clickable>,
|
|
476
478
|
);
|
|
477
479
|
|
|
478
|
-
const button = screen.
|
|
480
|
+
const button = await screen.findByTestId("clickable-button");
|
|
479
481
|
|
|
480
482
|
// Assert
|
|
481
483
|
expect(button).not.toHaveAttribute("aria-label");
|
|
482
484
|
});
|
|
483
485
|
|
|
484
|
-
test("allow keyboard navigation when disabled is set", () => {
|
|
486
|
+
test("allow keyboard navigation when disabled is set", async () => {
|
|
485
487
|
// Arrange
|
|
486
488
|
render(
|
|
487
489
|
<div>
|
|
@@ -495,18 +497,18 @@ describe("Clickable", () => {
|
|
|
495
497
|
// Act
|
|
496
498
|
// RTL's focuses on `document.body` by default, so we need to focus on
|
|
497
499
|
// the first button
|
|
498
|
-
userEvent.tab();
|
|
500
|
+
await userEvent.tab();
|
|
499
501
|
|
|
500
502
|
// Then we focus on our Clickable button.
|
|
501
|
-
userEvent.tab();
|
|
503
|
+
await userEvent.tab();
|
|
502
504
|
|
|
503
|
-
const button = screen.
|
|
505
|
+
const button = await screen.findByTestId("clickable-button");
|
|
504
506
|
|
|
505
507
|
// Assert
|
|
506
508
|
expect(button).toHaveFocus();
|
|
507
509
|
});
|
|
508
510
|
|
|
509
|
-
test("should not have a tabIndex if one is not set", () => {
|
|
511
|
+
test("should not have a tabIndex if one is not set", async () => {
|
|
510
512
|
// Arrange
|
|
511
513
|
|
|
512
514
|
// Act
|
|
@@ -516,13 +518,13 @@ describe("Clickable", () => {
|
|
|
516
518
|
</Clickable>,
|
|
517
519
|
);
|
|
518
520
|
|
|
519
|
-
const button = screen.
|
|
521
|
+
const button = await screen.findByTestId("clickable-button");
|
|
520
522
|
|
|
521
523
|
// Assert
|
|
522
524
|
expect(button).not.toHaveAttribute("tabIndex");
|
|
523
525
|
});
|
|
524
526
|
|
|
525
|
-
test("should have the tabIndex that is passed in", () => {
|
|
527
|
+
test("should have the tabIndex that is passed in", async () => {
|
|
526
528
|
// Arrange
|
|
527
529
|
|
|
528
530
|
// Act
|
|
@@ -532,13 +534,13 @@ describe("Clickable", () => {
|
|
|
532
534
|
</Clickable>,
|
|
533
535
|
);
|
|
534
536
|
|
|
535
|
-
const button = screen.
|
|
537
|
+
const button = await screen.findByTestId("clickable-button");
|
|
536
538
|
|
|
537
539
|
// Assert
|
|
538
540
|
expect(button).toHaveAttribute("tabIndex", "1");
|
|
539
541
|
});
|
|
540
542
|
|
|
541
|
-
test("forwards the ref to the clickable button element", () => {
|
|
543
|
+
test("forwards the ref to the clickable button element", async () => {
|
|
542
544
|
// Arrange
|
|
543
545
|
const ref: React.RefObject<HTMLButtonElement> = React.createRef();
|
|
544
546
|
|
|
@@ -553,7 +555,7 @@ describe("Clickable", () => {
|
|
|
553
555
|
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
|
|
554
556
|
});
|
|
555
557
|
|
|
556
|
-
test("forwards the ref to the clickable anchor element ", () => {
|
|
558
|
+
test("forwards the ref to the clickable anchor element ", async () => {
|
|
557
559
|
// Arrange
|
|
558
560
|
const ref: React.RefObject<HTMLAnchorElement> = React.createRef();
|
|
559
561
|
|
|
@@ -586,7 +588,7 @@ describe("Clickable", () => {
|
|
|
586
588
|
return <Clickable {...restProps}>{() => children}</Clickable>;
|
|
587
589
|
};
|
|
588
590
|
|
|
589
|
-
test("onKeyDown", () => {
|
|
591
|
+
test("onKeyDown", async () => {
|
|
590
592
|
// Arrange
|
|
591
593
|
let keyCode: any;
|
|
592
594
|
render(
|
|
@@ -597,13 +599,13 @@ describe("Clickable", () => {
|
|
|
597
599
|
|
|
598
600
|
// Act
|
|
599
601
|
// eslint-disable-next-line testing-library/prefer-user-event
|
|
600
|
-
fireEvent.keyDown(screen.
|
|
602
|
+
fireEvent.keyDown(await screen.findByRole("button"), {keyCode: 32});
|
|
601
603
|
|
|
602
604
|
// Assert
|
|
603
605
|
expect(keyCode).toEqual(32);
|
|
604
606
|
});
|
|
605
607
|
|
|
606
|
-
test("onKeyUp", () => {
|
|
608
|
+
test("onKeyUp", async () => {
|
|
607
609
|
// Arrange
|
|
608
610
|
let keyCode: any;
|
|
609
611
|
render(
|
|
@@ -614,13 +616,13 @@ describe("Clickable", () => {
|
|
|
614
616
|
|
|
615
617
|
// Act
|
|
616
618
|
// eslint-disable-next-line testing-library/prefer-user-event
|
|
617
|
-
fireEvent.keyUp(screen.
|
|
619
|
+
fireEvent.keyUp(await screen.findByRole("button"), {keyCode: 32});
|
|
618
620
|
|
|
619
621
|
// Assert
|
|
620
622
|
expect(keyCode).toEqual(32);
|
|
621
623
|
});
|
|
622
624
|
|
|
623
|
-
test("onMouseDown", () => {
|
|
625
|
+
test("onMouseDown", async () => {
|
|
624
626
|
// Arrange
|
|
625
627
|
let clientX: any;
|
|
626
628
|
render(
|
|
@@ -631,13 +633,15 @@ describe("Clickable", () => {
|
|
|
631
633
|
|
|
632
634
|
// Act
|
|
633
635
|
// eslint-disable-next-line testing-library/prefer-user-event
|
|
634
|
-
fireEvent.mouseDown(screen.
|
|
636
|
+
fireEvent.mouseDown(await screen.findByRole("button"), {
|
|
637
|
+
clientX: 10,
|
|
638
|
+
});
|
|
635
639
|
|
|
636
640
|
// Assert
|
|
637
641
|
expect(clientX).toEqual(10);
|
|
638
642
|
});
|
|
639
643
|
|
|
640
|
-
test("onMouseUp", () => {
|
|
644
|
+
test("onMouseUp", async () => {
|
|
641
645
|
// Arrange
|
|
642
646
|
let clientX: any;
|
|
643
647
|
render(
|
|
@@ -648,7 +652,7 @@ describe("Clickable", () => {
|
|
|
648
652
|
|
|
649
653
|
// Act
|
|
650
654
|
// eslint-disable-next-line testing-library/prefer-user-event
|
|
651
|
-
fireEvent.mouseUp(screen.
|
|
655
|
+
fireEvent.mouseUp(await screen.findByRole("button"), {clientX: 10});
|
|
652
656
|
|
|
653
657
|
// Assert
|
|
654
658
|
expect(clientX).toEqual(10);
|
|
@@ -323,7 +323,7 @@ const Clickable = React.forwardRef(function Clickable(
|
|
|
323
323
|
{(state, childrenProps) =>
|
|
324
324
|
getCorrectTag(state, router, {
|
|
325
325
|
...restProps,
|
|
326
|
-
"data-
|
|
326
|
+
"data-testid": testId,
|
|
327
327
|
style: getStyle(state),
|
|
328
328
|
...childrenProps,
|
|
329
329
|
})
|
|
@@ -348,7 +348,7 @@ const Clickable = React.forwardRef(function Clickable(
|
|
|
348
348
|
{(state, childrenProps) =>
|
|
349
349
|
getCorrectTag(state, router, {
|
|
350
350
|
...restProps,
|
|
351
|
-
"data-
|
|
351
|
+
"data-testid": testId,
|
|
352
352
|
style: getStyle(state),
|
|
353
353
|
...childrenProps,
|
|
354
354
|
})
|