@sproutsocial/seeds-react-menu 0.1.0 → 0.2.1
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/.eslintignore +6 -0
- package/.eslintrc.js +6 -2
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +23 -1
- package/dist/esm/index.js +243 -217
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +104 -38
- package/dist/index.d.ts +104 -38
- package/dist/index.js +272 -243
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
- package/src/ActionMenu/ActionMenu.feature +9 -3
- package/src/ActionMenu/ActionMenu.tsx +76 -42
- package/src/ActionMenu/__tests__/ActionMenu.test.tsx +36 -42
- package/src/ActionMenu/__tests__/ActionMenu.typetest.tsx +13 -13
- package/src/MenuContent/MenuContent.tsx +31 -1
- package/src/MenuContent/MenuContentTypes.ts +3 -4
- package/src/MenuContent/styles.tsx +10 -6
- package/src/MenuContext.tsx +1 -6
- package/src/MenuFooter/MenuFooter.feature +1 -1
- package/src/MenuFooter/MenuFooter.tsx +8 -0
- package/src/MenuFooter/__tests__/MenuFooter.test.tsx +53 -26
- package/src/MenuFooter/styles.tsx +1 -1
- package/src/MenuGroup/MenuGroup.feature +14 -26
- package/src/MenuGroup/MenuGroup.tsx +21 -1
- package/src/MenuGroup/MenuGroupTypes.ts +1 -0
- package/src/MenuGroup/__tests__/MenuGroup.test.tsx +41 -6
- package/src/MenuGroup/styles.tsx +4 -3
- package/src/MenuHeader/MenuHeader.tsx +16 -5
- package/src/MenuHeader/__tests__/MenuHeader.test.tsx +50 -6
- package/src/MenuHeader/__tests__/MenuHeader.typetest.tsx +1 -0
- package/src/MenuHeader/styles.tsx +21 -22
- package/src/MenuItem/MenuItem.feature +66 -26
- package/src/MenuItem/MenuItem.tsx +39 -20
- package/src/MenuItem/MenuItemTypes.ts +13 -1
- package/src/MenuItem/__tests__/MenuItem.test.tsx +431 -154
- package/src/MenuItem/__tests__/MenuItem.typetest.tsx +57 -38
- package/src/MenuItem/styles.tsx +44 -3
- package/src/{MenuItemSelectable/MenuItemSelectable.tsx → MenuItem/useOptionProps.tsx} +32 -54
- package/src/MenuRoot/MenuRoot.feature +20 -10
- package/src/MenuRoot/MenuRoot.tsx +14 -18
- package/src/MenuRoot/__tests__/MenuRoot.test.tsx +168 -34
- package/src/MenuRoot/__tests__/MenuRoot.typetest.tsx +10 -10
- package/src/MultiSelectMenu/MultiSelectMenu.feature +2 -13
- package/src/MultiSelectMenu/MultiSelectMenu.tsx +9 -1
- package/src/MultiSelectMenu/__tests__/MultiSelectMenu.test.tsx +154 -153
- package/src/MultiSelectMenu/__tests__/MultiSelectMenu.typetest.tsx +10 -10
- package/src/SingleSelectMenu/SingleSelectMenu.feature +11 -0
- package/src/SingleSelectMenu/SingleSelectMenu.tsx +10 -0
- package/src/SingleSelectMenu/__tests__/SingleSelectMenu.test.tsx +11 -14
- package/src/SingleSelectMenu/__tests__/SingleSelectMenu.typetest.tsx +14 -14
- package/src/__tests__/Menu.test.tsx +20 -16
- package/src/hooks/useItemsFromChildren.tsx +2 -4
- package/src/index.ts +0 -1
- package/src/menuTestingUtils.tsx +7 -4
- package/tsconfig.json +1 -1
- package/src/MenuItemSelectable/MenuItemSelectable.feature +0 -99
- package/src/MenuItemSelectable/MenuItemSelectableTypes.ts +0 -15
- package/src/MenuItemSelectable/__tests__/MenuItemSelectable.test.tsx +0 -303
- package/src/MenuItemSelectable/__tests__/MenuItemSelectable.typetest.tsx +0 -56
- package/src/MenuItemSelectable/index.ts +0 -5
- package/src/MenuItemSelectable/styles.tsx +0 -21
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
/* eslint-disable testing-library/no-unnecessary-act */
|
|
2
|
+
import React from "react";
|
|
2
3
|
import {
|
|
3
4
|
screen,
|
|
4
5
|
render,
|
|
5
6
|
waitFor,
|
|
6
7
|
} from "@sproutsocial/seeds-react-testing-library";
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
PointerEventsCheckLevel,
|
|
10
|
+
type UserEvent,
|
|
11
|
+
} from "@testing-library/user-event";
|
|
12
|
+
import type { ByRoleMatcher, ByRoleOptions } from "@testing-library/react";
|
|
8
13
|
import { theme } from "@sproutsocial/seeds-react-theme";
|
|
9
14
|
import {
|
|
15
|
+
ActionMenu,
|
|
10
16
|
MenuItem,
|
|
11
17
|
MenuToggleButton,
|
|
12
18
|
MenuContent,
|
|
13
|
-
|
|
19
|
+
MultiSelectMenu,
|
|
20
|
+
INPUT_TYPES,
|
|
14
21
|
} from "../../index";
|
|
15
|
-
import { TestWithMenuRoot } from "../../menuTestingUtils";
|
|
22
|
+
import { TestWithMenuRoot, TestWithMockedMenu } from "../../menuTestingUtils";
|
|
23
|
+
|
|
24
|
+
const books = [
|
|
25
|
+
{
|
|
26
|
+
index: 0,
|
|
27
|
+
id: "book-1",
|
|
28
|
+
author: "Harper Lee",
|
|
29
|
+
title: "To Kill a Mockingbird",
|
|
30
|
+
},
|
|
31
|
+
{ index: 1, id: "book-2", author: "Lev Tolstoy", title: "War and Peace" },
|
|
32
|
+
];
|
|
16
33
|
|
|
17
34
|
const menuItemProps = {
|
|
18
35
|
key: "book123",
|
|
@@ -31,198 +48,458 @@ const testMenuContext = {
|
|
|
31
48
|
getItemProps: jest.fn((props) => ({ ...props })),
|
|
32
49
|
isListbox: false,
|
|
33
50
|
};
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
describe("MenuItem User Behavior", () => {
|
|
37
|
-
describe("MenuItem is clickable", () => {
|
|
38
|
-
it("fires onClick event when clicked and not disabled", async () => {
|
|
39
|
-
const handleClick = jest.fn();
|
|
40
|
-
const { user } = render(
|
|
41
|
-
<TestWithMenuRoot
|
|
42
|
-
triggerElement={testTriggerElement}
|
|
43
|
-
{...testMenuContext}
|
|
44
|
-
>
|
|
45
|
-
<MenuContent>
|
|
46
|
-
<MenuItem {...menuItemProps} onClick={handleClick} />
|
|
47
|
-
</MenuContent>
|
|
48
|
-
</TestWithMenuRoot>
|
|
49
|
-
);
|
|
51
|
+
const testMenuToggleElement = <MenuToggleButton>Open</MenuToggleButton>;
|
|
50
52
|
|
|
53
|
+
const INTERACTION_TYPES = {
|
|
54
|
+
click: {
|
|
55
|
+
action: "clicking with mouse",
|
|
56
|
+
activate: async (
|
|
57
|
+
user: UserEvent,
|
|
58
|
+
role: ByRoleMatcher = "option",
|
|
59
|
+
options: ByRoleOptions = {}
|
|
60
|
+
) => {
|
|
61
|
+
const firstItem = screen.getByRole(role, {
|
|
62
|
+
name: books[0].title,
|
|
63
|
+
...options,
|
|
64
|
+
});
|
|
65
|
+
await user
|
|
66
|
+
.setup({
|
|
67
|
+
pointerEventsCheck: PointerEventsCheckLevel.Never,
|
|
68
|
+
})
|
|
69
|
+
.click(firstItem);
|
|
70
|
+
},
|
|
71
|
+
deactivate: async (
|
|
72
|
+
user: UserEvent,
|
|
73
|
+
role: ByRoleMatcher = "option",
|
|
74
|
+
options: ByRoleOptions = {}
|
|
75
|
+
) => {
|
|
76
|
+
const firstItem = screen.getByRole(role, {
|
|
77
|
+
name: books[0].title,
|
|
78
|
+
...options,
|
|
79
|
+
});
|
|
51
80
|
await user
|
|
52
81
|
.setup({
|
|
53
82
|
pointerEventsCheck: PointerEventsCheckLevel.Never,
|
|
54
83
|
})
|
|
55
|
-
.click(
|
|
84
|
+
.click(firstItem);
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
enter: {
|
|
88
|
+
action: "pressing the Enter key",
|
|
89
|
+
activate: async (user: UserEvent) => {
|
|
90
|
+
await user.keyboard("{arrowdown}{enter}");
|
|
91
|
+
},
|
|
92
|
+
deactivate: async (user: UserEvent) => {
|
|
93
|
+
await user.keyboard("{enter}");
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
space: {
|
|
97
|
+
action: "pressing the Space key",
|
|
98
|
+
activate: async (user: UserEvent) => {
|
|
99
|
+
await user.keyboard("{arrowdown} ");
|
|
100
|
+
},
|
|
101
|
+
deactivate: async (user: UserEvent) => {
|
|
102
|
+
await user.keyboard(" ");
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
};
|
|
56
106
|
|
|
57
|
-
|
|
107
|
+
describe("MenuItem when not isListbox", () => {
|
|
108
|
+
describe("User Behavior", () => {
|
|
109
|
+
describe("is clickable", () => {
|
|
110
|
+
it("fires onClick event when clicked and not disabled", async () => {
|
|
111
|
+
const handleClick = jest.fn();
|
|
112
|
+
const { user } = render(
|
|
113
|
+
<TestWithMenuRoot
|
|
114
|
+
menuToggleElement={testMenuToggleElement}
|
|
115
|
+
{...testMenuContext}
|
|
116
|
+
>
|
|
117
|
+
<MenuContent>
|
|
118
|
+
<MenuItem {...menuItemProps} onClick={handleClick} />
|
|
119
|
+
</MenuContent>
|
|
120
|
+
</TestWithMenuRoot>
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
await user
|
|
124
|
+
.setup({
|
|
125
|
+
pointerEventsCheck: PointerEventsCheckLevel.Never,
|
|
126
|
+
})
|
|
127
|
+
.click(screen.getByRole("menuitem"));
|
|
128
|
+
|
|
129
|
+
await waitFor(() => expect(handleClick).toHaveBeenCalledTimes(1));
|
|
130
|
+
});
|
|
58
131
|
});
|
|
59
|
-
});
|
|
60
132
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
133
|
+
describe("MenuItem can be triggered via keyboard", () => {
|
|
134
|
+
it(`fires onClick event when enter and not disabled`, async () => {
|
|
135
|
+
const handleClick = jest.fn();
|
|
136
|
+
const handleStateChange = jest.fn();
|
|
137
|
+
|
|
138
|
+
const { user } = render(
|
|
139
|
+
<ActionMenu
|
|
140
|
+
menuToggleElement={testMenuToggleElement}
|
|
141
|
+
isOpen
|
|
142
|
+
onStateChange={handleStateChange}
|
|
143
|
+
>
|
|
144
|
+
<MenuContent>
|
|
145
|
+
<MenuItem
|
|
146
|
+
{...menuItemProps}
|
|
147
|
+
data-testid="menu-test"
|
|
148
|
+
key={0}
|
|
149
|
+
onKeyDown={handleClick}
|
|
150
|
+
tabIndex={0}
|
|
151
|
+
/>
|
|
152
|
+
</MenuContent>
|
|
153
|
+
</ActionMenu>
|
|
154
|
+
);
|
|
155
|
+
const targetElem = screen.getByTestId("menu-test");
|
|
156
|
+
|
|
157
|
+
await user.tab();
|
|
158
|
+
expect(targetElem).toHaveFocus();
|
|
159
|
+
|
|
160
|
+
await user.keyboard("{enter}");
|
|
161
|
+
|
|
162
|
+
await waitFor(() =>
|
|
163
|
+
expect(handleStateChange).toHaveBeenCalledWith({
|
|
164
|
+
isOpen: false,
|
|
165
|
+
type: "__togglebutton_keydown_enter__",
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
expect(handleClick).toHaveBeenCalled();
|
|
169
|
+
});
|
|
170
|
+
it(`fires onClick event when space and not disabled`, async () => {
|
|
171
|
+
const handleClick = jest.fn();
|
|
172
|
+
const handleStateChange = jest.fn();
|
|
173
|
+
|
|
174
|
+
const { user } = render(
|
|
175
|
+
<ActionMenu
|
|
176
|
+
menuToggleElement={testMenuToggleElement}
|
|
177
|
+
isOpen
|
|
178
|
+
onStateChange={handleStateChange}
|
|
179
|
+
>
|
|
180
|
+
<MenuContent>
|
|
181
|
+
<MenuItem
|
|
182
|
+
{...menuItemProps}
|
|
183
|
+
data-testid="menu-test"
|
|
184
|
+
key={0}
|
|
185
|
+
onKeyDown={handleClick}
|
|
186
|
+
tabIndex={0}
|
|
187
|
+
/>
|
|
188
|
+
</MenuContent>
|
|
189
|
+
</ActionMenu>
|
|
190
|
+
);
|
|
191
|
+
const targetElem = screen.getByTestId("menu-test");
|
|
192
|
+
|
|
193
|
+
await user.tab();
|
|
194
|
+
expect(targetElem).toHaveFocus();
|
|
195
|
+
|
|
196
|
+
await user.keyboard(" ");
|
|
197
|
+
|
|
198
|
+
await waitFor(() =>
|
|
199
|
+
expect(handleStateChange).toHaveBeenCalledWith({
|
|
200
|
+
isOpen: false,
|
|
201
|
+
type: "__togglebutton_keydown_space_button__",
|
|
202
|
+
})
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
expect(handleClick).toHaveBeenCalled();
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test.each(Object.values(INTERACTION_TYPES))(
|
|
210
|
+
`does not fire onClick event when disabled and $action`,
|
|
211
|
+
async ({ activate }) => {
|
|
212
|
+
const handleClick = jest.fn();
|
|
213
|
+
|
|
214
|
+
const testItem = books[0];
|
|
215
|
+
|
|
216
|
+
const { user } = render(
|
|
217
|
+
<ActionMenu
|
|
218
|
+
menuToggleElement={<MenuToggleButton>Open</MenuToggleButton>}
|
|
219
|
+
isOpen
|
|
220
|
+
>
|
|
221
|
+
<MenuContent>
|
|
222
|
+
<MenuItem id={testItem.id} disabled={true} onClick={handleClick}>
|
|
223
|
+
{testItem.title}
|
|
224
|
+
</MenuItem>
|
|
225
|
+
</MenuContent>
|
|
226
|
+
</ActionMenu>
|
|
227
|
+
);
|
|
65
228
|
|
|
66
|
-
|
|
229
|
+
await activate(user, "menuitem");
|
|
230
|
+
|
|
231
|
+
expect(handleClick).not.toHaveBeenCalled();
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
describe("API", () => {
|
|
237
|
+
it("accepts children", () => {
|
|
238
|
+
render(
|
|
67
239
|
<ActionMenu
|
|
68
|
-
|
|
240
|
+
id="test-menu-item-selectable"
|
|
241
|
+
menuToggleElement={testMenuToggleElement}
|
|
69
242
|
isOpen
|
|
70
|
-
onStateChange={handleStateChange}
|
|
71
243
|
>
|
|
72
244
|
<MenuContent>
|
|
73
|
-
<MenuItem
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
onKeyDown={handleClick}
|
|
78
|
-
tabIndex={0}
|
|
79
|
-
/>
|
|
245
|
+
<MenuItem onClick={() => {}} id="test">
|
|
246
|
+
Hello world!
|
|
247
|
+
<span>testing</span>
|
|
248
|
+
</MenuItem>
|
|
80
249
|
</MenuContent>
|
|
81
250
|
</ActionMenu>
|
|
82
251
|
);
|
|
83
|
-
const targetElem = screen.getByTestId("menu-test");
|
|
84
|
-
|
|
85
|
-
await user.tab();
|
|
86
|
-
expect(targetElem).toHaveFocus();
|
|
87
252
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
expect(handleStateChange).toHaveBeenCalledWith({
|
|
92
|
-
isOpen: false,
|
|
93
|
-
type: "__togglebutton_keydown_enter__",
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
expect(handleClick).toHaveBeenCalled();
|
|
253
|
+
const menuItem = screen.getByText("Hello world!");
|
|
254
|
+
const span = screen.getByText("testing");
|
|
255
|
+
expect(menuItem).toContainElement(span);
|
|
97
256
|
});
|
|
98
|
-
it(`fires onClick event when space and not disabled`, async () => {
|
|
99
|
-
const handleClick = jest.fn();
|
|
100
|
-
const handleStateChange = jest.fn();
|
|
101
257
|
|
|
102
|
-
|
|
258
|
+
it("accepts box & system Props", () => {
|
|
259
|
+
render(
|
|
103
260
|
<ActionMenu
|
|
104
|
-
|
|
261
|
+
id="test-menu-item-selectable"
|
|
262
|
+
menuToggleElement={testMenuToggleElement}
|
|
105
263
|
isOpen
|
|
106
|
-
onStateChange={handleStateChange}
|
|
107
264
|
>
|
|
108
265
|
<MenuContent>
|
|
109
|
-
<MenuItem
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
onKeyDown={handleClick}
|
|
114
|
-
tabIndex={0}
|
|
115
|
-
/>
|
|
266
|
+
<MenuItem display="flex" p={300} onClick={() => {}} id="test">
|
|
267
|
+
Hello world!
|
|
268
|
+
<span>testing</span>
|
|
269
|
+
</MenuItem>
|
|
116
270
|
</MenuContent>
|
|
117
271
|
</ActionMenu>
|
|
118
272
|
);
|
|
119
|
-
const targetElem = screen.getByTestId("menu-test");
|
|
120
273
|
|
|
121
|
-
|
|
122
|
-
expect(
|
|
274
|
+
const menuItem = screen.getByRole("menuitem");
|
|
275
|
+
expect(menuItem).toHaveStyle(`padding: ${theme.space[300]}`);
|
|
276
|
+
expect(menuItem).toHaveStyle(`display: flex`);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|
|
123
280
|
|
|
124
|
-
|
|
281
|
+
const testByType = {
|
|
282
|
+
[INPUT_TYPES.CHECKBOX]: {
|
|
283
|
+
isSelected: () => {
|
|
284
|
+
expect(
|
|
285
|
+
screen.getByRole("checkbox", { checked: true })
|
|
286
|
+
).toBeInTheDocument();
|
|
287
|
+
},
|
|
288
|
+
isNotSelected: () => {
|
|
289
|
+
expect(
|
|
290
|
+
screen.queryByRole("checkbox", { checked: true })
|
|
291
|
+
).not.toBeInTheDocument();
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
[INPUT_TYPES.RADIO]: {
|
|
295
|
+
isSelected: () => {
|
|
296
|
+
expect(screen.getByRole("radio", { checked: true })).toBeInTheDocument();
|
|
297
|
+
},
|
|
298
|
+
isNotSelected: () => {
|
|
299
|
+
expect(
|
|
300
|
+
screen.queryByRole("radio", { checked: true })
|
|
301
|
+
).not.toBeInTheDocument();
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
[INPUT_TYPES.SWITCH]: {
|
|
305
|
+
isSelected: () => {
|
|
306
|
+
expect(screen.getByRole("switch", { checked: true })).toBeInTheDocument();
|
|
307
|
+
},
|
|
308
|
+
isNotSelected: () => {
|
|
309
|
+
expect(
|
|
310
|
+
screen.queryByRole("switch", { checked: true })
|
|
311
|
+
).not.toBeInTheDocument();
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
[INPUT_TYPES.ICON]: {
|
|
315
|
+
isSelected: () => {
|
|
316
|
+
expect(
|
|
317
|
+
screen.getByDataQaLabel({ icon: "check-solid" })
|
|
318
|
+
).toBeInTheDocument();
|
|
319
|
+
},
|
|
320
|
+
isNotSelected: () => {
|
|
321
|
+
expect(
|
|
322
|
+
screen.queryByDataQaLabel({ icon: "check-solid" })
|
|
323
|
+
).not.toBeInTheDocument();
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
};
|
|
125
327
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
328
|
+
describe("MenuItem when isListbox", () => {
|
|
329
|
+
describe("User Behavior", () => {
|
|
330
|
+
describe.each([
|
|
331
|
+
INPUT_TYPES.CHECKBOX,
|
|
332
|
+
INPUT_TYPES.RADIO,
|
|
333
|
+
INPUT_TYPES.SWITCH,
|
|
334
|
+
INPUT_TYPES.ICON,
|
|
335
|
+
])("when the input type is %s", (inputType) => {
|
|
336
|
+
test.each(Object.values(INTERACTION_TYPES))(
|
|
337
|
+
"can be checked and unchecked when $action",
|
|
338
|
+
async ({ activate, deactivate }) => {
|
|
339
|
+
const { user } = render(
|
|
340
|
+
<MultiSelectMenu
|
|
341
|
+
menuToggleElement={<MenuToggleButton>Open</MenuToggleButton>}
|
|
342
|
+
defaultIsOpen
|
|
343
|
+
>
|
|
344
|
+
<MenuContent>
|
|
345
|
+
{books.map((book) => {
|
|
346
|
+
return (
|
|
347
|
+
<MenuItem key={book.id} id={book.id} inputType={inputType}>
|
|
348
|
+
{book.title}
|
|
349
|
+
</MenuItem>
|
|
350
|
+
);
|
|
351
|
+
})}
|
|
352
|
+
</MenuContent>
|
|
353
|
+
</MultiSelectMenu>
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// check that menu is visible
|
|
357
|
+
expect(
|
|
358
|
+
screen.getByRole("option", {
|
|
359
|
+
name: books[0].title,
|
|
360
|
+
selected: false,
|
|
361
|
+
})
|
|
362
|
+
).toBeInTheDocument();
|
|
363
|
+
|
|
364
|
+
// Check that checkboxes are rendered
|
|
365
|
+
if (inputType !== INPUT_TYPES.ICON)
|
|
366
|
+
expect(screen.getAllByRole(inputType)).toHaveLength(books.length);
|
|
367
|
+
|
|
368
|
+
// Perform the action to select the item
|
|
369
|
+
await activate(user);
|
|
370
|
+
|
|
371
|
+
expect(
|
|
372
|
+
await screen.findByRole("option", {
|
|
373
|
+
name: books[0].title,
|
|
374
|
+
selected: true,
|
|
375
|
+
})
|
|
376
|
+
).toBeInTheDocument();
|
|
132
377
|
|
|
133
|
-
|
|
378
|
+
testByType[inputType].isSelected();
|
|
379
|
+
|
|
380
|
+
// Perform the action to deselect the item
|
|
381
|
+
deactivate(user);
|
|
382
|
+
|
|
383
|
+
expect(
|
|
384
|
+
await screen.findByRole("option", {
|
|
385
|
+
name: books[0].title,
|
|
386
|
+
selected: false,
|
|
387
|
+
})
|
|
388
|
+
).toBeInTheDocument();
|
|
389
|
+
|
|
390
|
+
testByType[inputType].isNotSelected();
|
|
391
|
+
}
|
|
392
|
+
);
|
|
134
393
|
});
|
|
394
|
+
});
|
|
135
395
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
index: 1,
|
|
149
|
-
id: "book-2",
|
|
150
|
-
author: "Lev Tolstoy",
|
|
151
|
-
title: "War and Peace",
|
|
152
|
-
},
|
|
153
|
-
];
|
|
396
|
+
describe("API", () => {
|
|
397
|
+
test.each([INPUT_TYPES.CHECKBOX, INPUT_TYPES.RADIO, INPUT_TYPES.SWITCH])(
|
|
398
|
+
"supports %s input types",
|
|
399
|
+
(inputType) => {
|
|
400
|
+
const testItem = books[0];
|
|
401
|
+
render(
|
|
402
|
+
<TestWithMockedMenu context={{ items: books, isListbox: true }}>
|
|
403
|
+
<MenuItem id={testItem.id} inputType={inputType}>
|
|
404
|
+
{testItem.title}
|
|
405
|
+
</MenuItem>
|
|
406
|
+
</TestWithMockedMenu>
|
|
407
|
+
);
|
|
154
408
|
|
|
155
|
-
|
|
409
|
+
expect(screen.getByRole(inputType)).toBeInTheDocument();
|
|
410
|
+
}
|
|
411
|
+
);
|
|
156
412
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
items: books,
|
|
163
|
-
selectedItem: testItem,
|
|
164
|
-
}}
|
|
413
|
+
it("uses the check icon by default when no inputType provided", () => {
|
|
414
|
+
const testItem = books[0];
|
|
415
|
+
render(
|
|
416
|
+
<TestWithMockedMenu
|
|
417
|
+
context={{ items: books, selectedItem: testItem, isListbox: true }}
|
|
165
418
|
>
|
|
166
|
-
<MenuItem
|
|
167
|
-
|
|
168
|
-
disabled={true}
|
|
169
|
-
onClick={handleStateChange}
|
|
170
|
-
>
|
|
171
|
-
{testItem.title}
|
|
172
|
-
</MenuItem>
|
|
173
|
-
</TestWithMenuRoot>
|
|
419
|
+
<MenuItem id={testItem.id}>{testItem.title}</MenuItem>
|
|
420
|
+
</TestWithMockedMenu>
|
|
174
421
|
);
|
|
175
|
-
await user
|
|
176
|
-
.setup({
|
|
177
|
-
pointerEventsCheck: PointerEventsCheckLevel.Never,
|
|
178
|
-
})
|
|
179
|
-
.click(screen.getByRole("menuitem"));
|
|
180
422
|
|
|
181
|
-
expect(
|
|
423
|
+
expect(
|
|
424
|
+
screen.getByDataQaLabel({ icon: "check-solid" })
|
|
425
|
+
).toBeInTheDocument();
|
|
182
426
|
});
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
427
|
|
|
186
|
-
describe(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
428
|
+
describe.each([
|
|
429
|
+
INPUT_TYPES.CHECKBOX,
|
|
430
|
+
INPUT_TYPES.RADIO,
|
|
431
|
+
INPUT_TYPES.SWITCH,
|
|
432
|
+
INPUT_TYPES.ICON,
|
|
433
|
+
])("when the input type is %s", (inputType) => {
|
|
434
|
+
it("enables it's checked state when selected in the context", () => {
|
|
435
|
+
const testItem = books[0];
|
|
436
|
+
render(
|
|
437
|
+
<TestWithMockedMenu
|
|
438
|
+
context={{ items: books, selectedItem: testItem, isListbox: true }}
|
|
439
|
+
>
|
|
440
|
+
<MenuItem id={testItem.id} inputType={inputType}>
|
|
441
|
+
{testItem.title}
|
|
442
|
+
</MenuItem>
|
|
443
|
+
</TestWithMockedMenu>
|
|
444
|
+
);
|
|
202
445
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
});
|
|
446
|
+
screen.getByRole("option", { selected: true });
|
|
447
|
+
testByType[inputType].isSelected();
|
|
448
|
+
});
|
|
207
449
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
450
|
+
it("enables it's checked state when selected by default", () => {
|
|
451
|
+
const testItem = books[0];
|
|
452
|
+
render(
|
|
453
|
+
<TestWithMenuRoot
|
|
454
|
+
menuToggleElement={<MenuToggleButton>Open</MenuToggleButton>}
|
|
455
|
+
{...{
|
|
456
|
+
isOpen: true,
|
|
457
|
+
items: books,
|
|
458
|
+
selectedItem: testItem,
|
|
459
|
+
}}
|
|
460
|
+
>
|
|
461
|
+
<MenuItem id={testItem.id} inputType={inputType}>
|
|
462
|
+
{testItem.title}
|
|
463
|
+
</MenuItem>
|
|
464
|
+
</TestWithMenuRoot>
|
|
465
|
+
);
|
|
223
466
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
467
|
+
screen.getByRole("option", { selected: true });
|
|
468
|
+
testByType[inputType].isSelected();
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it("allows its checked state to be deselected when using the context", async () => {
|
|
472
|
+
const testItem = books[0];
|
|
473
|
+
const TestItemWithState = () => {
|
|
474
|
+
const [selectedItem, setSelectedItem] = React.useState<
|
|
475
|
+
typeof testItem | undefined
|
|
476
|
+
>(testItem);
|
|
477
|
+
return (
|
|
478
|
+
<TestWithMockedMenu context={{ items: books, selectedItem }}>
|
|
479
|
+
<MenuItem
|
|
480
|
+
id={testItem.id}
|
|
481
|
+
inputType={inputType}
|
|
482
|
+
onClick={() => setSelectedItem(undefined)}
|
|
483
|
+
>
|
|
484
|
+
{testItem.title}
|
|
485
|
+
</MenuItem>
|
|
486
|
+
</TestWithMockedMenu>
|
|
487
|
+
);
|
|
488
|
+
};
|
|
489
|
+
const { user } = render(<TestItemWithState />);
|
|
490
|
+
|
|
491
|
+
const menuItem = screen.getByRole("option", { selected: true });
|
|
492
|
+
testByType[inputType].isSelected();
|
|
493
|
+
|
|
494
|
+
await user.click(menuItem);
|
|
495
|
+
|
|
496
|
+
expect(
|
|
497
|
+
await screen.findByRole("option", {
|
|
498
|
+
selected: false,
|
|
499
|
+
})
|
|
500
|
+
).toBeInTheDocument();
|
|
501
|
+
testByType[inputType].isNotSelected();
|
|
502
|
+
});
|
|
503
|
+
});
|
|
227
504
|
});
|
|
228
505
|
});
|