Skip to content

Commit e3aa7d9

Browse files
authored
Merge pull request #149 from Ke1sy/fix-previous-half-selection-on-update-selectedIds
fix half-selection after manual manipulations with nodes and updating…
2 parents dddeef6 + 1c0a981 commit e3aa7d9

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

src/TreeView/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ export const propagateSelectChange = (
215215
const some = enabledChildren.some(
216216
(x) =>
217217
selectedIds.has(x) ||
218-
changes.some.has(x) ||
218+
(changes.some.has(x) && !changes.none.has(x)) ||
219219
(halfSelectedIds.has(x) && !changes.none.has(x))
220220
);
221221
if (!some) {

src/__tests__/ControlledTree.test.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ const folder = {
4444
{ name: "Onions" },
4545
],
4646
},
47+
{
48+
name: "Deserts",
49+
children: [
50+
{ name: "Cookies" },
51+
{
52+
name: "Cakes",
53+
children: [
54+
{
55+
name: "Cheesecake",
56+
children: [{ name: "Classic" }, { name: "Chocolate" }],
57+
},
58+
{ name: "Vanilla" },
59+
],
60+
},
61+
],
62+
},
4763
],
4864
};
4965

@@ -171,6 +187,7 @@ function MultiSelectCheckboxControlledWithStateInside() {
171187
<MultiSelectCheckboxControlled
172188
selectedIds={selectedIds}
173189
data={dataWithoutIds}
190+
defaultExpandedIds={[1, 7, 11, 16, 22, 24, 25]}
174191
/>
175192
</div>
176193
);
@@ -372,6 +389,70 @@ describe("Data without ids", () => {
372389
expect(nodes[6]).toHaveAttribute("aria-checked", "false");
373390
});
374391

392+
test("SelectedIds should clear selection and half-selection after manual selection of top level parent and deselection of low level child", () => {
393+
const { queryAllByRole, queryAllByTestId } = render(
394+
<MultiSelectCheckboxControlledWithStateInside />
395+
);
396+
397+
const nodes = queryAllByRole("treeitem");
398+
399+
expect(nodes[11]).toHaveAttribute("aria-checked", "true");
400+
401+
fireEvent.click(queryAllByTestId("clear-selected-nodes")[0]);
402+
403+
expect(nodes[11]).toHaveAttribute("aria-checked", "false");
404+
405+
fireEvent.click(queryAllByTestId("select-only-vegetables")[0]);
406+
407+
expect(nodes[15]).toHaveAttribute("aria-checked", "true");
408+
expect(nodes[16]).toHaveAttribute("aria-checked", "true");
409+
expect(nodes[17]).toHaveAttribute("aria-checked", "true");
410+
expect(nodes[18]).toHaveAttribute("aria-checked", "true");
411+
expect(nodes[19]).toHaveAttribute("aria-checked", "true");
412+
expect(nodes[20]).toHaveAttribute("aria-checked", "true");
413+
414+
nodes[21].focus();
415+
if (document.activeElement == null)
416+
throw new Error(
417+
`Expected to find an active element on the document (after focusing the second element with role["treeitem"]), but did not.`
418+
);
419+
fireEvent.click(nodes[21].getElementsByClassName("checkbox-icon")[0]); // select Deserts
420+
421+
expect(nodes[21]).toHaveAttribute("aria-checked", "true"); // Deserts
422+
expect(nodes[22]).toHaveAttribute("aria-checked", "true"); // Cookies
423+
expect(nodes[23]).toHaveAttribute("aria-checked", "true"); // Cakes
424+
expect(nodes[24]).toHaveAttribute("aria-checked", "true"); // Cheesecake
425+
expect(nodes[25]).toHaveAttribute("aria-checked", "true"); // Classic cheesecake
426+
expect(nodes[26]).toHaveAttribute("aria-checked", "true"); // Chocolate cheesecake
427+
expect(nodes[27]).toHaveAttribute("aria-checked", "true"); // Vanilla
428+
429+
nodes[26].focus();
430+
if (document.activeElement == null)
431+
throw new Error(
432+
`Expected to find an active element on the document (after focusing the second element with role["treeitem"]), but did not.`
433+
);
434+
fireEvent.click(nodes[26].getElementsByClassName("checkbox-icon")[0]); // deselect Chocolate cheesecake
435+
436+
expect(nodes[21]).toHaveAttribute("aria-checked", "mixed"); // Deserts
437+
expect(nodes[22]).toHaveAttribute("aria-checked", "true"); // Cookies
438+
expect(nodes[23]).toHaveAttribute("aria-checked", "mixed"); // Cakes
439+
expect(nodes[24]).toHaveAttribute("aria-checked", "mixed"); // Cheesecake
440+
expect(nodes[25]).toHaveAttribute("aria-checked", "true"); // Classic cheesecake
441+
expect(nodes[26]).toHaveAttribute("aria-checked", "false"); // Chocolate cheesecake
442+
expect(nodes[27]).toHaveAttribute("aria-checked", "true"); // Vanilla
443+
444+
fireEvent.click(queryAllByTestId("select-only-vegetables")[0]);
445+
446+
expect(nodes[21]).toHaveAttribute("aria-checked", "false"); // Deserts
447+
expect(nodes[22]).toHaveAttribute("aria-checked", "false"); // Cookies
448+
expect(nodes[23]).toHaveAttribute("aria-checked", "false"); // Cakes
449+
expect(nodes[24]).toHaveAttribute("aria-checked", "false"); // Cheesecake
450+
expect(nodes[25]).toHaveAttribute("aria-checked", "false"); // Classic cheesecake
451+
expect(nodes[26]).toHaveAttribute("aria-checked", "false"); // Chocolate cheesecake
452+
expect(nodes[27]).toHaveAttribute("aria-checked", "false"); // Vanilla
453+
expect(nodes[15]).toHaveAttribute("aria-checked", "true");
454+
});
455+
375456
test("SelectedIds should select all children if parent node selected", () => {
376457
const { queryAllByRole } = render(
377458
<MultiSelectCheckboxControlled selectedIds={[16]} data={dataWithoutIds} />

0 commit comments

Comments
 (0)