@sproutsocial/seeds-react-menu 0.2.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.
@@ -1,3 +1,5 @@
1
+ /* eslint-disable testing-library/prefer-find-by */
2
+ /* eslint-disable testing-library/no-wait-for-multiple-assertions */
1
3
  /* eslint-disable testing-library/no-unnecessary-act */
2
4
  import {
3
5
  MultiSelectMenu,
@@ -9,9 +11,6 @@ import {
9
11
  import {
10
12
  render,
11
13
  screen,
12
- fireEvent,
13
- act,
14
- cleanup,
15
14
  waitFor,
16
15
  } from "@sproutsocial/seeds-react-testing-library";
17
16
 
@@ -23,11 +22,7 @@ const menuItems = [
23
22
  ];
24
23
 
25
24
  describe("MultiSelectMenu", () => {
26
- afterEach(() => {
27
- cleanup();
28
- });
29
-
30
- it("should render the menuItemSelectables when provided as children", async () => {
25
+ it("should render the MenuItems when provided as children", async () => {
31
26
  const { user } = render(
32
27
  <MultiSelectMenu
33
28
  menuToggleElement={
@@ -70,7 +65,7 @@ describe("MultiSelectMenu", () => {
70
65
  });
71
66
  });
72
67
 
73
- xit("should allow for multiple items to be selected", async () => {
68
+ it("should allow for multiple items to be selected", async () => {
74
69
  const { user } = render(
75
70
  <MultiSelectMenu
76
71
  menuToggleElement={
@@ -113,20 +108,22 @@ describe("MultiSelectMenu", () => {
113
108
 
114
109
  await waitFor(() => {
115
110
  // Check that the first item is selected
116
- expect(item1).toHaveAttribute("aria-checked", "true");
111
+ expect(item1).toHaveAttribute("aria-selected", "true");
117
112
  });
118
113
 
119
114
  // Select second item
120
- // TODO: can this be done in the same act as the first item?
121
115
  await user.click(item2);
122
116
 
123
117
  await waitFor(() => {
124
118
  // Check that the second item is selected
125
- expect(item2).toHaveAttribute("aria-checked", "true");
119
+ expect(item2).toHaveAttribute("aria-selected", "true");
126
120
  });
121
+
122
+ // check that first item is still selected
123
+ expect(item1).toHaveAttribute("aria-selected", "true");
127
124
  });
128
125
 
129
- xit("Should maintain selected state when closed and reopened", async () => {
126
+ it("Should maintain selected state when closed and reopened", async () => {
130
127
  const { user } = render(
131
128
  <MultiSelectMenu
132
129
  menuToggleElement={
@@ -167,27 +164,29 @@ describe("MultiSelectMenu", () => {
167
164
  await user.click(item1);
168
165
 
169
166
  await waitFor(() => {
170
- expect(item1).toHaveAttribute("aria-checked", "true");
167
+ expect(item1).toHaveAttribute("aria-selected", "true");
171
168
  });
172
169
 
173
170
  // Close Menu (MultiSelect does not close automatically)
174
171
  await user.click(toggleButton);
175
172
 
176
173
  // Make sure the menu is closed
177
- expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
174
+ await waitFor(() =>
175
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument()
176
+ );
178
177
 
179
178
  // Open menu again
180
179
  await user.click(toggleButton);
181
180
 
182
- await waitFor(() => {
183
- // Make sure the menu is open
184
- expect(screen.getByRole("listbox")).toBeInTheDocument();
185
- // Make sure the item is still selected
186
- expect(item1).toHaveAttribute("aria-checked", "true");
187
- });
181
+ // Make sure the menu is open
182
+ await waitFor(() =>
183
+ expect(screen.getByRole("listbox")).toBeInTheDocument()
184
+ );
185
+ // Make sure the item is still selected
186
+ expect(item1).toHaveAttribute("aria-selected", "true");
188
187
  });
189
188
 
190
- xit("should be able to navigate using the keyboard", async () => {
189
+ it("should be able to navigate using the keyboard", async () => {
191
190
  const { user } = render(
192
191
  <MultiSelectMenu
193
192
  menuToggleElement={
@@ -213,137 +212,139 @@ describe("MultiSelectMenu", () => {
213
212
  </MultiSelectMenu>
214
213
  );
215
214
 
216
- const toggleButton = screen.getByRole("button", { name: "testable menu" });
215
+ // Open Menu
216
+ await user.keyboard("{Tab}{Enter}");
217
+ expect(await screen.findByRole("listbox")).toBeInTheDocument();
217
218
 
218
- // Open Menu;
219
- fireEvent.focus(toggleButton);
220
- await user.keyboard("{Enter}");
219
+ // Check that the first item is highlighted
221
220
  await user.keyboard("{ArrowDown}");
222
-
223
- await waitFor(() => {
224
- // Check that the first item is highlighted
225
- const item1 = screen.getByRole("option", { name: "Item 1" });
226
- expect(item1).toHaveFocus();
227
- });
221
+ expect(screen.getByRole("listbox")).toHaveAttribute(
222
+ "aria-activedescendant",
223
+ screen.getByRole("option", { name: "Item 1" }).getAttribute("id")
224
+ );
228
225
 
229
226
  // Select the first item
230
227
  await user.keyboard("{Enter}");
231
- await user.keyboard("{ArrowDown}");
228
+
232
229
  // select the second item
230
+ await user.keyboard("{ArrowDown}");
233
231
  await user.keyboard(" ");
234
232
 
233
+ // Check that the second item is highlighted and selected
234
+ const item2 = screen.getByRole("option", { name: "Item 2" });
235
+ await waitFor(() => expect(item2).toHaveAttribute("aria-selected", "true"));
236
+ expect(screen.getByRole("listbox")).toHaveAttribute(
237
+ "aria-activedescendant",
238
+ item2.getAttribute("id")
239
+ );
240
+
241
+ // Check that the first item is still selected
242
+ const item1 = screen.getByRole("option", { name: "Item 1" });
243
+ expect(item1).toHaveAttribute("aria-selected", "true");
244
+ });
245
+
246
+ it("Should work with a initially selected items", async () => {
247
+ const { user } = render(
248
+ <MultiSelectMenu
249
+ menuToggleElement={
250
+ <MenuToggleButton aria-label="testable menu" role="button">
251
+ Testable Menu
252
+ </MenuToggleButton>
253
+ }
254
+ selectedItems={[menuItems[1], menuItems[2]]}
255
+ >
256
+ <MenuContent>
257
+ <MenuGroup>
258
+ {menuItems.map((item) => (
259
+ <MenuItem
260
+ key={item.id}
261
+ id={item.id}
262
+ data-testid={item.id}
263
+ label={item.label}
264
+ >
265
+ {item.label}
266
+ </MenuItem>
267
+ ))}
268
+ </MenuGroup>
269
+ </MenuContent>
270
+ </MultiSelectMenu>
271
+ );
272
+
273
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
274
+
275
+ const toggleButton = screen.getByRole("button", {
276
+ name: "testable menu",
277
+ });
278
+
279
+ // Open Menu
280
+ await user.click(toggleButton);
281
+
282
+ const item1 = screen.getByRole("option", { name: "Item 1" });
283
+ const item2 = screen.getByRole("option", { name: "Item 2" });
284
+ const item3 = screen.getByRole("option", { name: "Item 3" });
285
+
235
286
  await waitFor(() => {
236
- // Check that the second item is focused and selected
237
- const item2 = screen.getByRole("option", { name: "Item 2" });
238
- expect(item2).toHaveFocus();
239
- expect(item2).toBeChecked();
240
-
241
- // Check that the first item is still selected
242
- const item1 = screen.getByRole("menuitem", { name: "Item 1" });
243
- expect(item1).toBeChecked();
287
+ expect(item1).not.toHaveStyle("pointer-events: none");
244
288
  });
245
289
 
246
- xit("should stay open after menu item selection", async () => {
247
- const { user } = render(
248
- <MultiSelectMenu
249
- menuToggleElement={
250
- <MenuToggleButton aria-label="testable menu" role="button">
251
- Testable Menu
252
- </MenuToggleButton>
253
- }
254
- >
255
- <MenuContent>
256
- <MenuGroup>
257
- {menuItems.map((item) => (
258
- <MenuItem
259
- key={item.id}
260
- id={item.id}
261
- data-testid={item.id}
262
- label={item.label}
263
- >
264
- {item.label}
265
- </MenuItem>
266
- ))}
267
- </MenuGroup>
268
- </MenuContent>
269
- </MultiSelectMenu>
270
- );
271
-
272
- const menuContentContainer = screen.queryByRole("listbox");
273
-
274
- expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
275
-
276
- const toggleButton = screen.getByRole("button", {
277
- name: "testable menu",
278
- });
279
-
280
- // Open Menu
281
- await user.click(toggleButton);
282
-
283
- const item1 = screen.getByRole("option", { name: "Item 1" });
284
-
285
- await waitFor(() => {
286
- expect(item1).not.toHaveStyle("pointer-events: none");
287
- });
288
-
289
- // Select Item 1
290
- await user.click(item1);
291
-
292
- await waitFor(() => {
293
- expect(menuContentContainer).toBeInTheDocument();
294
- });
290
+ // Check that the first item is not selected
291
+ expect(item1).not.toHaveAttribute("aria-selected", "true");
292
+ // Check that the second item is selected
293
+ expect(item2).toHaveAttribute("aria-selected", "true");
294
+ // Check that the third item is selected
295
+ expect(item3).toHaveAttribute("aria-selected", "true");
296
+ });
297
+
298
+ it("should stay open after menu item selection", async () => {
299
+ const mockSelectedItemsChange = jest.fn();
300
+ const { user } = render(
301
+ <MultiSelectMenu
302
+ menuToggleElement={
303
+ <MenuToggleButton aria-label="testable menu" role="button">
304
+ Testable Menu
305
+ </MenuToggleButton>
306
+ }
307
+ onSelectedItemsChange={mockSelectedItemsChange}
308
+ >
309
+ <MenuContent>
310
+ <MenuGroup>
311
+ {menuItems.map((item) => (
312
+ <MenuItem
313
+ key={item.id}
314
+ id={item.id}
315
+ data-testid={item.id}
316
+ label={item.label}
317
+ >
318
+ {item.label}
319
+ </MenuItem>
320
+ ))}
321
+ </MenuGroup>
322
+ </MenuContent>
323
+ </MultiSelectMenu>
324
+ );
325
+
326
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
327
+
328
+ const toggleButton = screen.getByRole("button", {
329
+ name: "testable menu",
295
330
  });
296
331
 
297
- xit("Should work with a initially selected items", async () => {
298
- const { user } = render(
299
- <MultiSelectMenu
300
- menuToggleElement={
301
- <MenuToggleButton aria-label="testable menu" role="button">
302
- Testable Menu
303
- </MenuToggleButton>
304
- }
305
- defaultSelectedItems={[menuItems[1], menuItems[2]]}
306
- >
307
- <MenuContent>
308
- <MenuGroup>
309
- {menuItems.map((item) => (
310
- <MenuItem
311
- key={item.id}
312
- id={item.id}
313
- data-testid={item.id}
314
- label={item.label}
315
- >
316
- {item.label}
317
- </MenuItem>
318
- ))}
319
- </MenuGroup>
320
- </MenuContent>
321
- </MultiSelectMenu>
322
- );
323
-
324
- expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
325
-
326
- const toggleButton = screen.getByRole("button", {
327
- name: "testable menu",
328
- });
329
-
330
- // Open Menu
331
- await user.click(toggleButton);
332
-
333
- const item1 = screen.getByRole("option", { name: "Item 1" });
334
- const item2 = screen.getByRole("option", { name: "Item 2" });
335
- const item3 = screen.getByRole("option", { name: "Item 3" });
336
-
337
- await waitFor(() => {
338
- expect(item1).not.toHaveStyle("pointer-events: none");
339
- });
340
-
341
- act(() => {
342
- // Check that the second item is selected
343
- expect(item2).toHaveAttribute("aria-checked", "true");
344
- // Check that the third item is selected
345
- expect(item3).toHaveAttribute("aria-checked", "true");
346
- });
332
+ // Open Menu
333
+ await user.click(toggleButton);
334
+
335
+ const item1 = screen.getByRole("option", { name: "Item 1" });
336
+
337
+ await waitFor(() => {
338
+ expect(item1).not.toHaveStyle("pointer-events: none");
347
339
  });
340
+
341
+ // Select Item 1
342
+ await user.click(item1);
343
+
344
+ // Check that the menu is still open
345
+ expect(await screen.findByRole("listbox")).toBeInTheDocument();
346
+
347
+ // Check that callback called
348
+ expect(mockSelectedItemsChange).toHaveBeenCalledTimes(1);
348
349
  });
349
350
  });
@@ -36,6 +36,7 @@ export const SingleSelectMenu = ({
36
36
  itemToString,
37
37
  stateReducer: (state, actionAndChanges) => {
38
38
  let newState: Partial<UseSelectState<TypeDefaultItemProps>>;
39
+ // eslint-disable-next-line react-hooks/rules-of-hooks, prefer-const
39
40
  newState = useSelectStateReducer(state, actionAndChanges);
40
41
  return externalStateReducer
41
42
  ? externalStateReducer(state, {
@@ -16,6 +16,7 @@ const walkAllChildren = (
16
16
  // console.log("element", element);
17
17
  callback(element, parents);
18
18
  const newParents = [...parents, element];
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
20
  const children = (element as any).props?.children;
20
21
  React.Children.toArray(children).forEach((child) => {
21
22
  walk(child, newParents);
package/tsconfig.json CHANGED
@@ -8,5 +8,5 @@
8
8
  "verbatimModuleSyntax": true
9
9
  },
10
10
  "include": ["src/**/*"],
11
- "exclude": ["node_modules", "dist"]
11
+ "exclude": ["node_modules", "dist", "coverage"]
12
12
  }