@khanacademy/wonder-blocks-modal 5.1.11 → 5.1.13
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 +22 -0
- package/package.json +10 -10
- package/src/components/__tests__/close-button.test.tsx +0 -37
- package/src/components/__tests__/focus-trap.test.tsx +0 -100
- package/src/components/__tests__/modal-backdrop.test.tsx +0 -241
- package/src/components/__tests__/modal-dialog.test.tsx +0 -87
- package/src/components/__tests__/modal-header.test.tsx +0 -97
- package/src/components/__tests__/modal-launcher.test.tsx +0 -436
- package/src/components/__tests__/modal-panel.test.tsx +0 -42
- package/src/components/__tests__/one-pane-dialog.test.tsx +0 -87
- package/src/components/close-button.tsx +0 -64
- package/src/components/focus-trap.tsx +0 -148
- package/src/components/modal-backdrop.tsx +0 -172
- package/src/components/modal-content.tsx +0 -81
- package/src/components/modal-context.ts +0 -16
- package/src/components/modal-dialog.tsx +0 -164
- package/src/components/modal-footer.tsx +0 -54
- package/src/components/modal-header.tsx +0 -194
- package/src/components/modal-launcher.tsx +0 -297
- package/src/components/modal-panel.tsx +0 -188
- package/src/components/one-pane-dialog.tsx +0 -244
- package/src/components/scroll-disabler.ts +0 -95
- package/src/index.ts +0 -17
- package/src/themes/default.ts +0 -36
- package/src/themes/khanmigo.ts +0 -16
- package/src/themes/themed-modal-dialog.tsx +0 -44
- package/src/util/constants.ts +0 -6
- package/src/util/find-focusable-nodes.ts +0 -12
- package/src/util/maybe-get-portal-mounted-modal-host-element.test.tsx +0 -133
- package/src/util/maybe-get-portal-mounted-modal-host-element.ts +0 -35
- package/src/util/types.ts +0 -13
- package/tsconfig-build.json +0 -20
- package/tsconfig-build.tsbuildinfo +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-modal
|
|
2
2
|
|
|
3
|
+
## 5.1.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [3463bde3]
|
|
8
|
+
- @khanacademy/wonder-blocks-icon-button@5.5.0
|
|
9
|
+
|
|
10
|
+
## 5.1.12
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 02a1b298: Make sure we don't package tsconfig and tsbuildinfo files
|
|
15
|
+
- Updated dependencies [02a1b298]
|
|
16
|
+
- @khanacademy/wonder-blocks-breadcrumbs@2.2.7
|
|
17
|
+
- @khanacademy/wonder-blocks-core@7.0.1
|
|
18
|
+
- @khanacademy/wonder-blocks-icon-button@5.4.1
|
|
19
|
+
- @khanacademy/wonder-blocks-layout@2.2.1
|
|
20
|
+
- @khanacademy/wonder-blocks-theming@2.0.4
|
|
21
|
+
- @khanacademy/wonder-blocks-timing@5.0.2
|
|
22
|
+
- @khanacademy/wonder-blocks-tokens@2.0.1
|
|
23
|
+
- @khanacademy/wonder-blocks-typography@2.1.16
|
|
24
|
+
|
|
3
25
|
## 5.1.11
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-modal",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.13",
|
|
4
4
|
"design": "v2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime": "^7.18.6",
|
|
19
|
-
"@khanacademy/wonder-blocks-breadcrumbs": "^2.2.
|
|
20
|
-
"@khanacademy/wonder-blocks-core": "^7.0.
|
|
21
|
-
"@khanacademy/wonder-blocks-icon-button": "^5.
|
|
22
|
-
"@khanacademy/wonder-blocks-layout": "^2.2.
|
|
23
|
-
"@khanacademy/wonder-blocks-theming": "^2.0.
|
|
24
|
-
"@khanacademy/wonder-blocks-timing": "^5.0.
|
|
25
|
-
"@khanacademy/wonder-blocks-tokens": "^2.0.
|
|
26
|
-
"@khanacademy/wonder-blocks-typography": "^2.1.
|
|
19
|
+
"@khanacademy/wonder-blocks-breadcrumbs": "^2.2.7",
|
|
20
|
+
"@khanacademy/wonder-blocks-core": "^7.0.1",
|
|
21
|
+
"@khanacademy/wonder-blocks-icon-button": "^5.5.0",
|
|
22
|
+
"@khanacademy/wonder-blocks-layout": "^2.2.1",
|
|
23
|
+
"@khanacademy/wonder-blocks-theming": "^2.0.4",
|
|
24
|
+
"@khanacademy/wonder-blocks-timing": "^5.0.2",
|
|
25
|
+
"@khanacademy/wonder-blocks-tokens": "^2.0.1",
|
|
26
|
+
"@khanacademy/wonder-blocks-typography": "^2.1.16"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@phosphor-icons/core": "^2.0.2",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"react-dom": "16.14.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@khanacademy/wonder-blocks-breadcrumbs": "^2.2.
|
|
35
|
+
"@khanacademy/wonder-blocks-breadcrumbs": "^2.2.7",
|
|
36
36
|
"@khanacademy/wb-dev-build-settings": "^1.0.1"
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {render, screen} from "@testing-library/react";
|
|
3
|
-
|
|
4
|
-
import expectRenderError from "../../../../../utils/testing/expect-render-error";
|
|
5
|
-
import CloseButton from "../close-button";
|
|
6
|
-
import ModalContext from "../modal-context";
|
|
7
|
-
|
|
8
|
-
describe("CloseButton", () => {
|
|
9
|
-
test("ModalContext.Provider and onClose should warn", () => {
|
|
10
|
-
expectRenderError(
|
|
11
|
-
<ModalContext.Provider value={{closeModal: () => {}}}>
|
|
12
|
-
<CloseButton light={false} onClick={() => {}} />,
|
|
13
|
-
</ModalContext.Provider>,
|
|
14
|
-
"You've specified 'onClose' on a modal when using ModalLauncher. Please specify 'onClose' on the ModalLauncher instead",
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("testId should be set in the Icon element", () => {
|
|
19
|
-
// Arrange
|
|
20
|
-
render(
|
|
21
|
-
<div>
|
|
22
|
-
<ModalContext.Provider value={{closeModal: () => {}}}>
|
|
23
|
-
<CloseButton testId="modal-example-close" />,
|
|
24
|
-
</ModalContext.Provider>
|
|
25
|
-
</div>,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
// Act
|
|
29
|
-
const closeButton = screen.getByRole("button");
|
|
30
|
-
|
|
31
|
-
// Assert
|
|
32
|
-
expect(closeButton).toHaveAttribute(
|
|
33
|
-
"data-testid",
|
|
34
|
-
"modal-example-close",
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {render, screen} from "@testing-library/react";
|
|
3
|
-
import {userEvent} from "@testing-library/user-event";
|
|
4
|
-
|
|
5
|
-
import Button from "@khanacademy/wonder-blocks-button";
|
|
6
|
-
import {Choice, RadioGroup} from "@khanacademy/wonder-blocks-form";
|
|
7
|
-
|
|
8
|
-
import FocusTrap from "../focus-trap";
|
|
9
|
-
|
|
10
|
-
describe("FocusTrap", () => {
|
|
11
|
-
it("Focus should move to the first focusable element", async () => {
|
|
12
|
-
// Arrange
|
|
13
|
-
render(
|
|
14
|
-
<>
|
|
15
|
-
<FocusTrap>
|
|
16
|
-
<RadioGroup
|
|
17
|
-
label="some-label"
|
|
18
|
-
description="some-description"
|
|
19
|
-
groupName="some-group-name"
|
|
20
|
-
onChange={() => {}}
|
|
21
|
-
selectedValue={""}
|
|
22
|
-
>
|
|
23
|
-
<Choice
|
|
24
|
-
label="first option"
|
|
25
|
-
value="some-choice-value"
|
|
26
|
-
/>
|
|
27
|
-
<Choice
|
|
28
|
-
label="second option"
|
|
29
|
-
value="some-choice-value-2"
|
|
30
|
-
description="Some choice description."
|
|
31
|
-
/>
|
|
32
|
-
</RadioGroup>
|
|
33
|
-
<Button>A button</Button>
|
|
34
|
-
</FocusTrap>
|
|
35
|
-
<Button>An external button</Button>
|
|
36
|
-
</>,
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// Initial focused element
|
|
40
|
-
const firstRadioButton = await screen.findByRole("radio", {
|
|
41
|
-
name: /first option/i,
|
|
42
|
-
});
|
|
43
|
-
firstRadioButton.focus();
|
|
44
|
-
|
|
45
|
-
// Act
|
|
46
|
-
// focus on the button
|
|
47
|
-
await userEvent.tab();
|
|
48
|
-
// focus on the last sentinel
|
|
49
|
-
await userEvent.tab();
|
|
50
|
-
|
|
51
|
-
// Assert
|
|
52
|
-
// Redirect focus to the first radiobutton.
|
|
53
|
-
expect(firstRadioButton).toHaveFocus();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("Focus should move to the last focusable element", async () => {
|
|
57
|
-
// Arrange
|
|
58
|
-
render(
|
|
59
|
-
<>
|
|
60
|
-
<FocusTrap>
|
|
61
|
-
<RadioGroup
|
|
62
|
-
label="some-label"
|
|
63
|
-
description="some-description"
|
|
64
|
-
groupName="some-group-name"
|
|
65
|
-
onChange={() => {}}
|
|
66
|
-
selectedValue={""}
|
|
67
|
-
>
|
|
68
|
-
<Choice
|
|
69
|
-
label="first option"
|
|
70
|
-
value="some-choice-value"
|
|
71
|
-
/>
|
|
72
|
-
<Choice
|
|
73
|
-
label="second option"
|
|
74
|
-
value="some-choice-value-2"
|
|
75
|
-
description="Some choice description."
|
|
76
|
-
/>
|
|
77
|
-
</RadioGroup>
|
|
78
|
-
<Button>A focusable button</Button>
|
|
79
|
-
</FocusTrap>
|
|
80
|
-
<Button>An external button</Button>
|
|
81
|
-
</>,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// Initial focused element
|
|
85
|
-
const firstRadioButton = await screen.findByRole("radio", {
|
|
86
|
-
name: /first option/i,
|
|
87
|
-
});
|
|
88
|
-
firstRadioButton.focus();
|
|
89
|
-
|
|
90
|
-
// Act
|
|
91
|
-
// focus on the first sentinel
|
|
92
|
-
await userEvent.tab({shift: true});
|
|
93
|
-
|
|
94
|
-
// Assert
|
|
95
|
-
// Redirect focus to the button.
|
|
96
|
-
expect(
|
|
97
|
-
await screen.findByRole("button", {name: "A focusable button"}),
|
|
98
|
-
).toHaveFocus();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {render, screen, fireEvent, waitFor} from "@testing-library/react";
|
|
3
|
-
import {userEvent} from "@testing-library/user-event";
|
|
4
|
-
|
|
5
|
-
import ModalBackdrop from "../modal-backdrop";
|
|
6
|
-
import OnePaneDialog from "../one-pane-dialog";
|
|
7
|
-
|
|
8
|
-
const exampleModal = (
|
|
9
|
-
<OnePaneDialog
|
|
10
|
-
content={<div data-testid="example-modal-content" />}
|
|
11
|
-
title="Title"
|
|
12
|
-
footer={<div data-testid="example-modal-footer" />}
|
|
13
|
-
testId="example-modal-test-id"
|
|
14
|
-
/>
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
const exampleModalWithButtons = (
|
|
18
|
-
<OnePaneDialog
|
|
19
|
-
content={
|
|
20
|
-
<div>
|
|
21
|
-
<button>first focusable button</button>
|
|
22
|
-
<button />
|
|
23
|
-
<button />
|
|
24
|
-
</div>
|
|
25
|
-
}
|
|
26
|
-
title="Title"
|
|
27
|
-
footer={<div data-modal-footer />}
|
|
28
|
-
/>
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
describe("ModalBackdrop", () => {
|
|
32
|
-
test("Clicking the backdrop triggers `onCloseModal`", async () => {
|
|
33
|
-
// Arrange
|
|
34
|
-
const onCloseModal = jest.fn();
|
|
35
|
-
|
|
36
|
-
render(
|
|
37
|
-
<ModalBackdrop
|
|
38
|
-
onCloseModal={onCloseModal}
|
|
39
|
-
testId="modal-backdrop-test-id"
|
|
40
|
-
>
|
|
41
|
-
{exampleModal}
|
|
42
|
-
</ModalBackdrop>,
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const backdrop = await screen.findByTestId("modal-backdrop-test-id");
|
|
46
|
-
|
|
47
|
-
//Act
|
|
48
|
-
await userEvent.click(backdrop);
|
|
49
|
-
|
|
50
|
-
// Assert
|
|
51
|
-
expect(onCloseModal).toHaveBeenCalled();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("Clicking the modal content does not trigger `onCloseModal`", async () => {
|
|
55
|
-
// Arrange
|
|
56
|
-
const onCloseModal = jest.fn();
|
|
57
|
-
|
|
58
|
-
render(
|
|
59
|
-
<ModalBackdrop onCloseModal={onCloseModal}>
|
|
60
|
-
{exampleModal}
|
|
61
|
-
</ModalBackdrop>,
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
// Act
|
|
65
|
-
await userEvent.click(
|
|
66
|
-
await screen.findByTestId("example-modal-content"),
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
// Assert
|
|
70
|
-
expect(onCloseModal).not.toHaveBeenCalled();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("Clicking and dragging into the backdrop does not close modal", async () => {
|
|
74
|
-
// Arrange
|
|
75
|
-
const onCloseModal = jest.fn();
|
|
76
|
-
|
|
77
|
-
render(
|
|
78
|
-
<ModalBackdrop
|
|
79
|
-
onCloseModal={onCloseModal}
|
|
80
|
-
testId="modal-backdrop-test-id"
|
|
81
|
-
>
|
|
82
|
-
{exampleModal}
|
|
83
|
-
</ModalBackdrop>,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const panel = await screen.findByTestId("example-modal-test-id");
|
|
87
|
-
const backdrop = await screen.findByTestId("modal-backdrop-test-id");
|
|
88
|
-
|
|
89
|
-
// Act
|
|
90
|
-
|
|
91
|
-
// Dragging the mouse
|
|
92
|
-
// eslint-disable-next-line testing-library/prefer-user-event
|
|
93
|
-
fireEvent.mouseDown(panel);
|
|
94
|
-
// eslint-disable-next-line testing-library/prefer-user-event
|
|
95
|
-
fireEvent.mouseUp(backdrop);
|
|
96
|
-
|
|
97
|
-
// Assert
|
|
98
|
-
expect(onCloseModal).not.toHaveBeenCalled();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("Clicking and dragging in from the backdrop does not close modal", async () => {
|
|
102
|
-
// Arrange
|
|
103
|
-
const onCloseModal = jest.fn();
|
|
104
|
-
|
|
105
|
-
render(
|
|
106
|
-
<ModalBackdrop
|
|
107
|
-
onCloseModal={onCloseModal}
|
|
108
|
-
testId="modal-backdrop-test-id"
|
|
109
|
-
>
|
|
110
|
-
{exampleModal}
|
|
111
|
-
</ModalBackdrop>,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const panel = await screen.findByTestId("example-modal-test-id");
|
|
115
|
-
const backdrop = await screen.findByTestId("modal-backdrop-test-id");
|
|
116
|
-
|
|
117
|
-
// Act
|
|
118
|
-
|
|
119
|
-
// Dragging the mouse
|
|
120
|
-
// eslint-disable-next-line testing-library/prefer-user-event
|
|
121
|
-
fireEvent.mouseDown(backdrop);
|
|
122
|
-
// eslint-disable-next-line testing-library/prefer-user-event
|
|
123
|
-
fireEvent.mouseUp(panel);
|
|
124
|
-
|
|
125
|
-
// Assert
|
|
126
|
-
expect(onCloseModal).not.toHaveBeenCalled();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("Clicking the modal footer does not trigger `onCloseModal`", async () => {
|
|
130
|
-
// Arrange
|
|
131
|
-
const onCloseModal = jest.fn();
|
|
132
|
-
|
|
133
|
-
render(
|
|
134
|
-
<ModalBackdrop onCloseModal={onCloseModal}>
|
|
135
|
-
{exampleModal}
|
|
136
|
-
</ModalBackdrop>,
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
// Act
|
|
140
|
-
await userEvent.click(
|
|
141
|
-
await screen.findByTestId("example-modal-footer"),
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
// Assert
|
|
145
|
-
expect(onCloseModal).not.toHaveBeenCalled();
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test("If initialFocusId is set and element is found, we focus that element inside the modal", async () => {
|
|
149
|
-
// Arrange
|
|
150
|
-
const initialFocusId = "initial-focus";
|
|
151
|
-
|
|
152
|
-
render(
|
|
153
|
-
<ModalBackdrop
|
|
154
|
-
initialFocusId={initialFocusId}
|
|
155
|
-
onCloseModal={() => {}}
|
|
156
|
-
>
|
|
157
|
-
<OnePaneDialog
|
|
158
|
-
content={
|
|
159
|
-
<div data-modal-content>
|
|
160
|
-
<input type="text" />
|
|
161
|
-
<button id="initial-focus">Initial focus</button>
|
|
162
|
-
</div>
|
|
163
|
-
}
|
|
164
|
-
title="Title"
|
|
165
|
-
footer={<div data-modal-footer />}
|
|
166
|
-
/>
|
|
167
|
-
</ModalBackdrop>,
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
// Act
|
|
171
|
-
const initialFocusElement = await screen.findByRole("button", {
|
|
172
|
-
name: "Initial focus",
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// Assert
|
|
176
|
-
await waitFor(() => expect(initialFocusElement).toHaveFocus());
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
test("If initialFocusId is set but element is NOT found, we focus on the first focusable element instead", async () => {
|
|
180
|
-
// Arrange
|
|
181
|
-
// This element does not exist in the DOM
|
|
182
|
-
const initialFocusId = "unknown-node";
|
|
183
|
-
|
|
184
|
-
const {container} = render(
|
|
185
|
-
<ModalBackdrop
|
|
186
|
-
initialFocusId={initialFocusId}
|
|
187
|
-
onCloseModal={() => {}}
|
|
188
|
-
>
|
|
189
|
-
{exampleModalWithButtons}
|
|
190
|
-
</ModalBackdrop>,
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
// Act
|
|
194
|
-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
|
|
195
|
-
const initialFocusElement = container.querySelector(
|
|
196
|
-
`#${initialFocusId}`,
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
const firstFocusableElement = await screen.findByRole("button", {
|
|
200
|
-
name: "first focusable button",
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// Assert
|
|
204
|
-
// first we verify the element doesn't exist in the DOM
|
|
205
|
-
expect(initialFocusElement).not.toBeInTheDocument();
|
|
206
|
-
// verify the focus is set on the first focusable element instead
|
|
207
|
-
await waitFor(() => expect(firstFocusableElement).toHaveFocus());
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test("If no initialFocusId is set, we focus the first button in the modal", async () => {
|
|
211
|
-
// Arrange
|
|
212
|
-
render(
|
|
213
|
-
<ModalBackdrop onCloseModal={() => {}}>
|
|
214
|
-
{exampleModalWithButtons}
|
|
215
|
-
</ModalBackdrop>,
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
// Act
|
|
219
|
-
const firstFocusableElement = await screen.findByRole("button", {
|
|
220
|
-
name: "first focusable button",
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Assert
|
|
224
|
-
await waitFor(() => expect(firstFocusableElement).toHaveFocus());
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
test("If there are no focusable elements, we focus the Dialog instead", async () => {
|
|
228
|
-
// Arrange
|
|
229
|
-
render(
|
|
230
|
-
<ModalBackdrop onCloseModal={() => {}}>
|
|
231
|
-
{exampleModal}
|
|
232
|
-
</ModalBackdrop>,
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
// Act
|
|
236
|
-
const firstFocusableElement = await screen.findByRole("dialog");
|
|
237
|
-
|
|
238
|
-
// Assert
|
|
239
|
-
await waitFor(() => expect(firstFocusableElement).toHaveFocus());
|
|
240
|
-
});
|
|
241
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {render, screen} from "@testing-library/react";
|
|
3
|
-
|
|
4
|
-
import ModalDialog from "../modal-dialog";
|
|
5
|
-
|
|
6
|
-
describe("ModalDialog", () => {
|
|
7
|
-
it("should render its contents", () => {
|
|
8
|
-
// Arrange
|
|
9
|
-
|
|
10
|
-
// Act
|
|
11
|
-
render(
|
|
12
|
-
<ModalDialog aria-labelledby="123">
|
|
13
|
-
<h1 id="123">A modal</h1>
|
|
14
|
-
<p>The contents</p>
|
|
15
|
-
</ModalDialog>,
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
// Assert
|
|
19
|
-
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("should announce the dialog if aria-labelledby is set", () => {
|
|
23
|
-
// Arrange
|
|
24
|
-
|
|
25
|
-
// Act
|
|
26
|
-
render(
|
|
27
|
-
<ModalDialog aria-labelledby="dialog-title">
|
|
28
|
-
<h1 id="dialog-title">A modal</h1>
|
|
29
|
-
<p>The contents</p>
|
|
30
|
-
</ModalDialog>,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
// Assert
|
|
34
|
-
expect(
|
|
35
|
-
screen.getByRole("dialog", {name: "A modal"}),
|
|
36
|
-
).toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("should announce the dialog's contents if aria-describedby is set", () => {
|
|
40
|
-
// Arrange
|
|
41
|
-
|
|
42
|
-
// Act
|
|
43
|
-
render(
|
|
44
|
-
<ModalDialog
|
|
45
|
-
aria-labelledby="dialog-title"
|
|
46
|
-
aria-describedby="dialog-body"
|
|
47
|
-
>
|
|
48
|
-
<h1 id="dialog-title">A modal</h1>
|
|
49
|
-
<p id="dialog-body">The contents</p>
|
|
50
|
-
</ModalDialog>,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// Assert
|
|
54
|
-
expect(
|
|
55
|
-
screen.getByRole("dialog", {description: "The contents"}),
|
|
56
|
-
).toBeInTheDocument();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("adds testId to the dialog element", () => {
|
|
60
|
-
// Arrange
|
|
61
|
-
|
|
62
|
-
// Act
|
|
63
|
-
render(
|
|
64
|
-
<ModalDialog aria-labelledby="dialog-title" testId="test-id">
|
|
65
|
-
<h1 id="dialog-title">A modal</h1>
|
|
66
|
-
</ModalDialog>,
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
// Assert
|
|
70
|
-
expect(screen.getByTestId("test-id")).toBeInTheDocument();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("forwards the ref to the dialog element", () => {
|
|
74
|
-
// Arrange
|
|
75
|
-
const ref: React.RefObject<HTMLDivElement> = React.createRef();
|
|
76
|
-
|
|
77
|
-
// Act
|
|
78
|
-
render(
|
|
79
|
-
<ModalDialog ref={ref} aria-labelledby="dialog-title">
|
|
80
|
-
<h1 id="dialog-title">A modal</h1>
|
|
81
|
-
</ModalDialog>,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// Assert
|
|
85
|
-
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {render, screen} from "@testing-library/react";
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Breadcrumbs,
|
|
6
|
-
BreadcrumbsItem,
|
|
7
|
-
} from "@khanacademy/wonder-blocks-breadcrumbs";
|
|
8
|
-
|
|
9
|
-
import ModalHeader from "../modal-header";
|
|
10
|
-
|
|
11
|
-
const exampleBreadcrumbs: React.ReactElement<
|
|
12
|
-
React.ComponentProps<typeof Breadcrumbs>
|
|
13
|
-
> = (
|
|
14
|
-
<Breadcrumbs>
|
|
15
|
-
<BreadcrumbsItem>breadcrumb item</BreadcrumbsItem>
|
|
16
|
-
</Breadcrumbs>
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
describe("ModalHeader", () => {
|
|
20
|
-
test("renders the title by default", () => {
|
|
21
|
-
// Arrange, Act
|
|
22
|
-
render(<ModalHeader title="Title" titleId="modal-title" />);
|
|
23
|
-
|
|
24
|
-
// Assert
|
|
25
|
-
expect(screen.getByText("Title")).toBeInTheDocument();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("using only `breadcrumbs` should render the header", () => {
|
|
29
|
-
// Arrange, Act
|
|
30
|
-
render(
|
|
31
|
-
<ModalHeader
|
|
32
|
-
title="Title"
|
|
33
|
-
breadcrumbs={exampleBreadcrumbs}
|
|
34
|
-
titleId="modal-title"
|
|
35
|
-
/>,
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// Assert
|
|
39
|
-
expect(screen.getByText("breadcrumb item")).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("using only `subtitle` should render the header", () => {
|
|
43
|
-
// Arrange, Act
|
|
44
|
-
render(
|
|
45
|
-
<ModalHeader
|
|
46
|
-
title="Title"
|
|
47
|
-
subtitle="Subtitle"
|
|
48
|
-
titleId="modal-title"
|
|
49
|
-
/>,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
// Assert
|
|
53
|
-
expect(screen.getByText("Subtitle")).toBeInTheDocument();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test("testId should be added to the title", () => {
|
|
57
|
-
// Arrange
|
|
58
|
-
render(
|
|
59
|
-
<ModalHeader
|
|
60
|
-
title="Title"
|
|
61
|
-
subtitle="Subtitle"
|
|
62
|
-
testId="test-example-header"
|
|
63
|
-
titleId="modal-title"
|
|
64
|
-
/>,
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Act
|
|
68
|
-
const title = screen.getByText("Title");
|
|
69
|
-
|
|
70
|
-
// Assert
|
|
71
|
-
expect(title).toHaveAttribute(
|
|
72
|
-
"data-testid",
|
|
73
|
-
"test-example-header-title",
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("testId should be added to the subtitle", () => {
|
|
78
|
-
// Arrange
|
|
79
|
-
render(
|
|
80
|
-
<ModalHeader
|
|
81
|
-
title="Title"
|
|
82
|
-
subtitle="Subtitle"
|
|
83
|
-
testId="test-example-header"
|
|
84
|
-
titleId="modal-title"
|
|
85
|
-
/>,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
// Act
|
|
89
|
-
const subtitle = screen.getByText("Subtitle");
|
|
90
|
-
|
|
91
|
-
// Assert
|
|
92
|
-
expect(subtitle).toHaveAttribute(
|
|
93
|
-
"data-testid",
|
|
94
|
-
"test-example-header-subtitle",
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
});
|