@khanacademy/wonder-blocks-card 0.0.0-PR2859-20251119004500 → 0.0.0-PR2876-20251209213809
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 +27 -2
- package/package.json +5 -5
- package/dist/__tests__/components/card.test.d.ts +0 -1
- package/dist/__tests__/components/card.typestest.d.ts +0 -1
- package/dist/__tests__/components/dismiss-button.test.d.ts +0 -1
- package/src/__tests__/components/card.test.tsx +0 -274
- package/src/__tests__/components/card.typestest.tsx +0 -207
- package/src/__tests__/components/dismiss-button.test.tsx +0 -145
- package/src/components/card.tsx +0 -302
- package/src/components/dismiss-button.tsx +0 -50
- package/src/index.ts +0 -3
- package/tsconfig-build.json +0 -16
- package/tsconfig-build.tsbuildinfo +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-card
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-PR2876-20251209213809
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [ad430d7]
|
|
8
|
+
- @khanacademy/wonder-blocks-core@0.0.0-PR2876-20251209213809
|
|
9
|
+
- @khanacademy/wonder-blocks-icon-button@0.0.0-PR2876-20251209213809
|
|
10
|
+
- @khanacademy/wonder-blocks-tokens@14.1.3
|
|
11
|
+
|
|
12
|
+
## 1.3.2
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [70d6c08]
|
|
17
|
+
- @khanacademy/wonder-blocks-tokens@14.1.3
|
|
18
|
+
- @khanacademy/wonder-blocks-icon-button@11.0.1
|
|
19
|
+
|
|
20
|
+
## 1.3.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [0fd41cc]
|
|
25
|
+
- Updated dependencies [d36860e]
|
|
26
|
+
- @khanacademy/wonder-blocks-icon-button@11.0.0
|
|
27
|
+
|
|
28
|
+
## 1.3.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
|
6
31
|
|
|
7
|
-
-
|
|
32
|
+
- d36c492: Updates labeling requirements and adds testId to dismiss button
|
|
8
33
|
|
|
9
34
|
## 1.2.5
|
|
10
35
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Card component for Wonder Blocks.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.0.0-
|
|
6
|
+
"version": "0.0.0-PR2876-20251209213809",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
22
22
|
"source": "src/index.js",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@khanacademy/wonder-blocks-core": "
|
|
25
|
-
"@khanacademy/wonder-blocks-icon-button": "
|
|
26
|
-
"@khanacademy/wonder-blocks-tokens": "14.1.
|
|
24
|
+
"@khanacademy/wonder-blocks-core": "0.0.0-PR2876-20251209213809",
|
|
25
|
+
"@khanacademy/wonder-blocks-icon-button": "0.0.0-PR2876-20251209213809",
|
|
26
|
+
"@khanacademy/wonder-blocks-tokens": "14.1.3"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"aphrodite": "^1.2.5",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@phosphor-icons/core": "^2.0.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@khanacademy/wb-dev-build-settings": "
|
|
34
|
+
"@khanacademy/wb-dev-build-settings": "0.0.0-PR2876-20251209213809"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,274 +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 Card from "../../components/card";
|
|
6
|
-
|
|
7
|
-
describe("Card", () => {
|
|
8
|
-
describe("Basic rendering", () => {
|
|
9
|
-
it("should render children correctly", () => {
|
|
10
|
-
// Arrange
|
|
11
|
-
render(
|
|
12
|
-
<Card>
|
|
13
|
-
<div data-testid="child-content">Card Content</div>
|
|
14
|
-
</Card>,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
// Act
|
|
18
|
-
const childContent = screen.getByTestId("child-content");
|
|
19
|
-
|
|
20
|
-
// Assert
|
|
21
|
-
expect(childContent).toBeInTheDocument();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("should not render dismiss button by default", () => {
|
|
25
|
-
// Arrange
|
|
26
|
-
render(
|
|
27
|
-
<Card>
|
|
28
|
-
<div>Content</div>
|
|
29
|
-
</Card>,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
// Act
|
|
33
|
-
const dismissButton = screen.queryByRole("button");
|
|
34
|
-
|
|
35
|
-
// Assert
|
|
36
|
-
expect(dismissButton).not.toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe("Dismiss button functionality", () => {
|
|
41
|
-
it("should render dismiss button when onDismiss is present", () => {
|
|
42
|
-
// Arrange
|
|
43
|
-
render(
|
|
44
|
-
<Card
|
|
45
|
-
onDismiss={() => {}}
|
|
46
|
-
labels={{dismissButtonAriaLabel: "Close"}}
|
|
47
|
-
>
|
|
48
|
-
<div>Content</div>
|
|
49
|
-
</Card>,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
// Act
|
|
53
|
-
const dismissButton = screen.getByRole("button");
|
|
54
|
-
|
|
55
|
-
// Assert
|
|
56
|
-
expect(dismissButton).toBeInTheDocument();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should not render dismiss button there is no onDismiss prop", () => {
|
|
60
|
-
// Arrange
|
|
61
|
-
render(
|
|
62
|
-
<Card>
|
|
63
|
-
<div>Content</div>
|
|
64
|
-
</Card>,
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Act
|
|
68
|
-
const dismissButton = screen.queryByRole("button");
|
|
69
|
-
|
|
70
|
-
// Assert
|
|
71
|
-
expect(dismissButton).not.toBeInTheDocument();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("should call onDismiss when dismiss button is clicked", async () => {
|
|
75
|
-
// Arrange
|
|
76
|
-
const mockOnDismiss = jest.fn();
|
|
77
|
-
render(
|
|
78
|
-
<Card
|
|
79
|
-
labels={{dismissButtonAriaLabel: "Close it!"}}
|
|
80
|
-
onDismiss={mockOnDismiss}
|
|
81
|
-
>
|
|
82
|
-
<div>Content</div>
|
|
83
|
-
</Card>,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
// Act
|
|
87
|
-
const dismissButton = screen.getByRole("button", {
|
|
88
|
-
name: "Close it!",
|
|
89
|
-
});
|
|
90
|
-
await userEvent.click(dismissButton);
|
|
91
|
-
|
|
92
|
-
// Assert
|
|
93
|
-
expect(mockOnDismiss).toHaveBeenCalledTimes(1);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe("Test IDs", () => {
|
|
98
|
-
it("should apply a custom testId for card", () => {
|
|
99
|
-
// Arrange
|
|
100
|
-
render(
|
|
101
|
-
<Card testId="my-card">
|
|
102
|
-
<div>Content</div>
|
|
103
|
-
</Card>,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
// Act
|
|
107
|
-
const card = screen.getByTestId("my-card");
|
|
108
|
-
|
|
109
|
-
// Assert
|
|
110
|
-
expect(card).toBeInTheDocument();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("should append -dismiss-button to testId for dismiss button", () => {
|
|
114
|
-
// Arrange
|
|
115
|
-
render(
|
|
116
|
-
<Card
|
|
117
|
-
testId="my-card"
|
|
118
|
-
onDismiss={() => {}}
|
|
119
|
-
labels={{dismissButtonAriaLabel: "Close"}}
|
|
120
|
-
>
|
|
121
|
-
<div>Content</div>
|
|
122
|
-
</Card>,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
// Act
|
|
126
|
-
const dismissButton = screen.getByTestId("my-card-dismiss-button");
|
|
127
|
-
|
|
128
|
-
// Assert
|
|
129
|
-
expect(dismissButton).toBeInTheDocument();
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe("Accessibility", () => {
|
|
134
|
-
it("should pass custom aria-label to dismiss button", () => {
|
|
135
|
-
// Arrange
|
|
136
|
-
render(
|
|
137
|
-
<Card
|
|
138
|
-
onDismiss={() => {}}
|
|
139
|
-
labels={{dismissButtonAriaLabel: "Custom Close"}}
|
|
140
|
-
>
|
|
141
|
-
<div>Content</div>
|
|
142
|
-
</Card>,
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
// Act
|
|
146
|
-
const dismissButton = screen.getByRole("button", {
|
|
147
|
-
name: "Custom Close",
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// Assert
|
|
151
|
-
expect(dismissButton).toBeInTheDocument();
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it("should render with a custom tag", () => {
|
|
155
|
-
// Arrange
|
|
156
|
-
render(
|
|
157
|
-
<Card tag="section" labels={{cardAriaLabel: "Card Section"}}>
|
|
158
|
-
<h2>Heading</h2>
|
|
159
|
-
<p>Description</p>
|
|
160
|
-
</Card>,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
// Act
|
|
164
|
-
const section = screen.getByRole("region");
|
|
165
|
-
|
|
166
|
-
// Assert
|
|
167
|
-
expect(section).toBeInTheDocument();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("should apply labels.cardAriaLabel for a custom tag (preferred)", () => {
|
|
171
|
-
// Arrange
|
|
172
|
-
render(
|
|
173
|
-
<Card
|
|
174
|
-
tag="section"
|
|
175
|
-
labels={{cardAriaLabel: "Custom section label"}}
|
|
176
|
-
>
|
|
177
|
-
<h2>Heading</h2>
|
|
178
|
-
<p>Description</p>
|
|
179
|
-
</Card>,
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
// Act
|
|
183
|
-
const section = screen.getByRole("region", {
|
|
184
|
-
name: "Custom section label",
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// Assert
|
|
188
|
-
expect(section).toBeInTheDocument();
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it("should apply aria-labelledby for a custom tag", () => {
|
|
192
|
-
// Arrange
|
|
193
|
-
render(
|
|
194
|
-
<div>
|
|
195
|
-
<h2 id="card-heading">My Card Title</h2>
|
|
196
|
-
<Card tag="section" aria-labelledby="card-heading">
|
|
197
|
-
<p>Description</p>
|
|
198
|
-
</Card>
|
|
199
|
-
</div>,
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
// Act
|
|
203
|
-
const section = screen.getByRole("region", {
|
|
204
|
-
name: "My Card Title",
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// Assert
|
|
208
|
-
expect(section).toBeInTheDocument();
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it("should only apply aria-labelledby", () => {
|
|
212
|
-
// Arrange
|
|
213
|
-
render(
|
|
214
|
-
<div>
|
|
215
|
-
<h2 id="card-heading">My Card Title</h2>
|
|
216
|
-
<Card
|
|
217
|
-
tag="section"
|
|
218
|
-
aria-labelledby="card-heading"
|
|
219
|
-
aria-label="Fallback label"
|
|
220
|
-
>
|
|
221
|
-
<p>Description</p>
|
|
222
|
-
</Card>
|
|
223
|
-
</div>,
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// Act
|
|
227
|
-
const section = screen.getByRole("region", {
|
|
228
|
-
name: "My Card Title",
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
// Assert
|
|
232
|
-
expect(section).toBeInTheDocument();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("should apply the inert attribute", () => {
|
|
236
|
-
// Arrange
|
|
237
|
-
render(
|
|
238
|
-
<Card inert testId="card">
|
|
239
|
-
<h2>Heading</h2>
|
|
240
|
-
<p>Description</p>
|
|
241
|
-
<button>Button</button>
|
|
242
|
-
</Card>,
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
// Act
|
|
246
|
-
const section = screen.getByTestId("card");
|
|
247
|
-
|
|
248
|
-
// Assert
|
|
249
|
-
expect(section).toHaveAttribute("inert");
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe("Complex content scenarios", () => {
|
|
254
|
-
it("should work with fragment children", () => {
|
|
255
|
-
// Arrange
|
|
256
|
-
render(
|
|
257
|
-
<Card>
|
|
258
|
-
<>
|
|
259
|
-
<span data-testid="fragment-child-1">First</span>
|
|
260
|
-
<span data-testid="fragment-child-2">Second</span>
|
|
261
|
-
</>
|
|
262
|
-
</Card>,
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// Act
|
|
266
|
-
const firstChild = screen.getByTestId("fragment-child-1");
|
|
267
|
-
const secondChild = screen.getByTestId("fragment-child-2");
|
|
268
|
-
|
|
269
|
-
// Assert
|
|
270
|
-
expect(firstChild).toBeInTheDocument();
|
|
271
|
-
expect(secondChild).toBeInTheDocument();
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
});
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
// Import Button and Link for proper usage examples
|
|
4
|
-
import Button from "@khanacademy/wonder-blocks-button";
|
|
5
|
-
import Link from "@khanacademy/wonder-blocks-link";
|
|
6
|
-
import Card from "../../components/card";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Basic Card usage
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
<Card>Hello, world!</Card>;
|
|
13
|
-
|
|
14
|
-
<Card>
|
|
15
|
-
<div>Some content</div>
|
|
16
|
-
</Card>;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Card with Button and Link components (correct usage)
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
<Card>
|
|
23
|
-
<Button onClick={() => {}}>Click me</Button>
|
|
24
|
-
</Card>;
|
|
25
|
-
|
|
26
|
-
<Card>
|
|
27
|
-
<Link href="/foo">Click me</Link>
|
|
28
|
-
</Card>;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Card with all style props
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
<Card
|
|
35
|
-
background="base-default"
|
|
36
|
-
borderRadius="small"
|
|
37
|
-
paddingSize="small"
|
|
38
|
-
elevation="none"
|
|
39
|
-
>
|
|
40
|
-
Content
|
|
41
|
-
</Card>;
|
|
42
|
-
|
|
43
|
-
<Card
|
|
44
|
-
background="base-subtle"
|
|
45
|
-
borderRadius="medium"
|
|
46
|
-
paddingSize="medium"
|
|
47
|
-
elevation="low"
|
|
48
|
-
>
|
|
49
|
-
Content
|
|
50
|
-
</Card>;
|
|
51
|
-
|
|
52
|
-
<Card paddingSize="none">Content</Card>;
|
|
53
|
-
|
|
54
|
-
// @ts-expect-error - invalid background value
|
|
55
|
-
<Card background="invalid-background">Content</Card>;
|
|
56
|
-
|
|
57
|
-
// @ts-expect-error - invalid borderRadius value
|
|
58
|
-
<Card borderRadius="invalid-radius">Content</Card>;
|
|
59
|
-
|
|
60
|
-
// @ts-expect-error - invalid paddingSize value
|
|
61
|
-
<Card paddingSize="invalid-padding">Content</Card>;
|
|
62
|
-
|
|
63
|
-
// @ts-expect-error - invalid elevation value
|
|
64
|
-
<Card elevation="invalid-elevation">Content</Card>;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Card with dismiss functionality
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
<Card onDismiss={() => {}} labels={{dismissButtonAriaLabel: "Close card"}}>
|
|
71
|
-
Content
|
|
72
|
-
</Card>;
|
|
73
|
-
|
|
74
|
-
// @ts-expect-error - onDismiss requires dismissButtonAriaLabel
|
|
75
|
-
<Card onDismiss={() => {}}>Content</Card>;
|
|
76
|
-
|
|
77
|
-
// @ts-expect-error - onDismiss requires dismissButtonAriaLabel
|
|
78
|
-
<Card onDismiss={() => {}} labels={{}}>
|
|
79
|
-
Content
|
|
80
|
-
</Card>;
|
|
81
|
-
|
|
82
|
-
// @ts-expect-error - onClick is not allowed on Card wrapper
|
|
83
|
-
<Card onClick={() => {}}>Content</Card>;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Card with different HTML tags
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
|
-
<Card tag="div">Content</Card>;
|
|
90
|
-
|
|
91
|
-
// @ts-expect-error - button tag not allowed, use Wonder Blocks Button component instead
|
|
92
|
-
<Card tag="button">Content</Card>;
|
|
93
|
-
|
|
94
|
-
// @ts-expect-error - anchor tag not allowed, use Wonder Blocks Link component instead
|
|
95
|
-
<Card tag="a">Content</Card>;
|
|
96
|
-
|
|
97
|
-
<Card tag="section" labels={{cardAriaLabel: "Card section"}}>
|
|
98
|
-
Content
|
|
99
|
-
</Card>;
|
|
100
|
-
|
|
101
|
-
<Card tag="figure" labels={{cardAriaLabel: "Card figure"}}>
|
|
102
|
-
Content
|
|
103
|
-
</Card>;
|
|
104
|
-
|
|
105
|
-
<Card tag="section" aria-label="Card section">
|
|
106
|
-
Content
|
|
107
|
-
</Card>;
|
|
108
|
-
|
|
109
|
-
<Card tag="figure" aria-label="Card figure">
|
|
110
|
-
Content
|
|
111
|
-
</Card>;
|
|
112
|
-
|
|
113
|
-
<Card tag="section" aria-labelledby="someId">
|
|
114
|
-
<h2 id="someId">Card title</h2>
|
|
115
|
-
</Card>;
|
|
116
|
-
|
|
117
|
-
<Card tag="figure" aria-labelledby="someId2">
|
|
118
|
-
<h2 id="someId2">Card title</h2>
|
|
119
|
-
</Card>;
|
|
120
|
-
|
|
121
|
-
// @ts-expect-error - aria-labelledby cannot be used with labels.cardAriaLabel
|
|
122
|
-
<Card
|
|
123
|
-
tag="figure"
|
|
124
|
-
aria-labelledby="someId2"
|
|
125
|
-
labels={{cardAriaLabel: "preferred label"}}
|
|
126
|
-
>
|
|
127
|
-
<h2 id="someId2">Card title</h2>
|
|
128
|
-
</Card>;
|
|
129
|
-
|
|
130
|
-
// @ts-expect-error - aria-labelledby cannot be used with labels.cardAriaLabel
|
|
131
|
-
<Card
|
|
132
|
-
tag="section"
|
|
133
|
-
aria-labelledby="someId2"
|
|
134
|
-
labels={{cardAriaLabel: "preferred label"}}
|
|
135
|
-
>
|
|
136
|
-
<h2 id="someId2">Card title</h2>
|
|
137
|
-
</Card>;
|
|
138
|
-
|
|
139
|
-
<Card tag="figure" aria-labelledby="someId2" aria-label="fallback label">
|
|
140
|
-
<h2 id="someId2">Card title</h2>
|
|
141
|
-
</Card>;
|
|
142
|
-
|
|
143
|
-
<Card tag="section">Content</Card>;
|
|
144
|
-
|
|
145
|
-
<Card tag="figure">Content</Card>;
|
|
146
|
-
|
|
147
|
-
<Card tag="section" labels={{}}>
|
|
148
|
-
Content
|
|
149
|
-
</Card>;
|
|
150
|
-
|
|
151
|
-
<Card tag="figure" labels={{}}>
|
|
152
|
-
Content
|
|
153
|
-
</Card>;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Card with additional props
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
<Card testId="my-card">Content</Card>;
|
|
160
|
-
|
|
161
|
-
<Card inert>Content</Card>;
|
|
162
|
-
|
|
163
|
-
<Card ref={React.createRef<HTMLDivElement>()}>Content</Card>;
|
|
164
|
-
|
|
165
|
-
<Card styles={{root: {width: 200}, dismissButton: {position: "absolute"}}}>
|
|
166
|
-
Content
|
|
167
|
-
</Card>;
|
|
168
|
-
|
|
169
|
-
<Card
|
|
170
|
-
tag="section"
|
|
171
|
-
onDismiss={() => {}}
|
|
172
|
-
labels={{
|
|
173
|
-
cardAriaLabel: "Card section",
|
|
174
|
-
dismissButtonAriaLabel: "Close card",
|
|
175
|
-
}}
|
|
176
|
-
>
|
|
177
|
-
Content
|
|
178
|
-
</Card>;
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Card with all props
|
|
182
|
-
*/
|
|
183
|
-
|
|
184
|
-
<Card
|
|
185
|
-
aria-busy={true}
|
|
186
|
-
aria-roledescription="A custom card"
|
|
187
|
-
background="base-subtle"
|
|
188
|
-
borderRadius="medium"
|
|
189
|
-
paddingSize="medium"
|
|
190
|
-
elevation="low"
|
|
191
|
-
tag="figure"
|
|
192
|
-
onDismiss={() => {}}
|
|
193
|
-
labels={{
|
|
194
|
-
cardAriaLabel: "Card figure",
|
|
195
|
-
dismissButtonAriaLabel: "Close card",
|
|
196
|
-
}}
|
|
197
|
-
testId="complex-card"
|
|
198
|
-
inert
|
|
199
|
-
styles={{
|
|
200
|
-
root: {width: 300},
|
|
201
|
-
dismissButton: {top: 10, right: 10},
|
|
202
|
-
}}
|
|
203
|
-
ref={React.createRef<HTMLElement>()}
|
|
204
|
-
role="status"
|
|
205
|
-
>
|
|
206
|
-
<div>Complex content</div>
|
|
207
|
-
</Card>;
|
|
@@ -1,145 +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 {DismissButton} from "../../components/dismiss-button";
|
|
6
|
-
|
|
7
|
-
describe("DismissButton", () => {
|
|
8
|
-
describe("Basic rendering", () => {
|
|
9
|
-
it("should render as a button", () => {
|
|
10
|
-
// Arrange & Act
|
|
11
|
-
render(<DismissButton />);
|
|
12
|
-
|
|
13
|
-
// Assert
|
|
14
|
-
expect(screen.getByRole("button")).toBeInTheDocument();
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe("Accessibility", () => {
|
|
19
|
-
it("should use default aria-label when not provided", () => {
|
|
20
|
-
// Arrange & Act
|
|
21
|
-
render(<DismissButton />);
|
|
22
|
-
|
|
23
|
-
// Assert
|
|
24
|
-
expect(
|
|
25
|
-
screen.getByRole("button", {name: "Close"}),
|
|
26
|
-
).toBeInTheDocument();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("should use custom aria-label when provided", () => {
|
|
30
|
-
// Arrange & Act
|
|
31
|
-
render(<DismissButton aria-label="Dismiss notification" />);
|
|
32
|
-
|
|
33
|
-
// Assert
|
|
34
|
-
expect(
|
|
35
|
-
screen.getByRole("button", {name: "Dismiss notification"}),
|
|
36
|
-
).toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("should be keyboard accessible", () => {
|
|
40
|
-
// Arrange
|
|
41
|
-
render(<DismissButton aria-label="Close" />);
|
|
42
|
-
|
|
43
|
-
// Act
|
|
44
|
-
const button = screen.getByRole("button");
|
|
45
|
-
button.focus();
|
|
46
|
-
|
|
47
|
-
// Assert
|
|
48
|
-
expect(button).toHaveFocus();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("Event handling", () => {
|
|
53
|
-
it("should call onClick when button is clicked", async () => {
|
|
54
|
-
// Arrange
|
|
55
|
-
const mockOnClick = jest.fn();
|
|
56
|
-
render(<DismissButton onClick={mockOnClick} aria-label="Close" />);
|
|
57
|
-
|
|
58
|
-
// Act
|
|
59
|
-
const button = screen.getByRole("button", {name: "Close"});
|
|
60
|
-
await userEvent.click(button);
|
|
61
|
-
|
|
62
|
-
// Assert
|
|
63
|
-
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("should call onClick with event parameter", async () => {
|
|
67
|
-
// Arrange
|
|
68
|
-
const mockOnClick = jest.fn();
|
|
69
|
-
render(<DismissButton onClick={mockOnClick} aria-label="Close" />);
|
|
70
|
-
|
|
71
|
-
// Act
|
|
72
|
-
const button = screen.getByRole("button", {name: "Close"});
|
|
73
|
-
await userEvent.click(button);
|
|
74
|
-
|
|
75
|
-
// Assert
|
|
76
|
-
expect(mockOnClick).toHaveBeenCalledWith(
|
|
77
|
-
expect.objectContaining({
|
|
78
|
-
type: "click",
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("should handle missing onClick prop gracefully", async () => {
|
|
84
|
-
// Arrange
|
|
85
|
-
render(<DismissButton aria-label="Close" />);
|
|
86
|
-
|
|
87
|
-
// Act & Assert
|
|
88
|
-
const button = screen.getByRole("button", {name: "Close"});
|
|
89
|
-
await expect(userEvent.click(button)).resolves.not.toThrow();
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("should support keyboard activation with Enter", async () => {
|
|
93
|
-
// Arrange
|
|
94
|
-
const mockOnClick = jest.fn();
|
|
95
|
-
render(<DismissButton onClick={mockOnClick} aria-label="Close" />);
|
|
96
|
-
|
|
97
|
-
// Act
|
|
98
|
-
const button = screen.getByRole("button", {name: "Close"});
|
|
99
|
-
button.focus();
|
|
100
|
-
await userEvent.keyboard("{Enter}");
|
|
101
|
-
|
|
102
|
-
// Assert
|
|
103
|
-
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("should support keyboard activation with Space", async () => {
|
|
107
|
-
// Arrange
|
|
108
|
-
const mockOnClick = jest.fn();
|
|
109
|
-
render(<DismissButton onClick={mockOnClick} aria-label="Close" />);
|
|
110
|
-
|
|
111
|
-
// Act
|
|
112
|
-
const button = screen.getByRole("button", {name: "Close"});
|
|
113
|
-
button.focus();
|
|
114
|
-
await userEvent.keyboard(" ");
|
|
115
|
-
|
|
116
|
-
// Assert
|
|
117
|
-
expect(mockOnClick).toHaveBeenCalledTimes(1);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe("Test ID support", () => {
|
|
122
|
-
it("should set data-testid attribute when testId is provided", () => {
|
|
123
|
-
// Arrange
|
|
124
|
-
const testId = "dismiss-button-test";
|
|
125
|
-
render(<DismissButton testId={testId} aria-label="Close" />);
|
|
126
|
-
|
|
127
|
-
// Act
|
|
128
|
-
const button = screen.getByTestId(testId);
|
|
129
|
-
|
|
130
|
-
// Assert
|
|
131
|
-
expect(button).toHaveAttribute("data-testid", testId);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("should not have data-testid attribute when testId is not provided", () => {
|
|
135
|
-
// Arrange
|
|
136
|
-
render(<DismissButton aria-label="Close" />);
|
|
137
|
-
|
|
138
|
-
// Act
|
|
139
|
-
const button = screen.getByRole("button");
|
|
140
|
-
|
|
141
|
-
// Assert
|
|
142
|
-
expect(button).not.toHaveAttribute("data-testid");
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
});
|