-
Notifications
You must be signed in to change notification settings - Fork 88
feat(combobox): add selectAll toggle property
#11721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e57a387
86806f9
6153643
e0bd2e1
8fd8f6e
63c5ebe
dcf1b0f
81d7f65
d750d43
6b870d3
705e1e7
c585981
c8ef92c
c04dc1f
e6f1c4b
b72225a
9c1f5bb
53dfbba
4fe311a
bfd365e
61defb1
8fe7e36
3404661
9ba6ca0
8685c9a
065fb33
913e4b2
617a049
e36076d
d67aea4
dfb11e7
9130ec5
06a3f6c
2628b23
8485111
1b9534a
70ed074
b6a9de5
a40ce67
a5c4c53
6a9b2cc
41dd343
7599e24
7abde7d
610603e
c265013
37b79e1
1c72a35
5ad6845
608cebe
8643e83
cc9a1eb
06e0759
dcb3c64
7377df6
d3cf34f
82a430e
b93440e
d772db7
d30f035
f89a3d3
679f133
baa0a9b
9bbf0fa
e23ccf2
f816680
53f7cef
5de43a8
b6ede7a
18a59b3
efa765b
418b88e
0586822
1b02ded
eab03c1
a6af93a
b3e4f95
4a742e9
c0301c1
2308e6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -752,7 +752,13 @@ describe("calcite-combobox", () => { | |
| </calcite-combobox>`, | ||
| ); | ||
|
|
||
| const item = await page.find("calcite-combobox-item"); | ||
| await page.waitForChanges(); | ||
|
Elijbet marked this conversation as resolved.
|
||
|
|
||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.callMethod("componentOnReady"); | ||
|
Elijbet marked this conversation as resolved.
|
||
| expect(combobox).not.toBeNull(); | ||
|
Elijbet marked this conversation as resolved.
|
||
|
|
||
| const item = await page.find("calcite-combobox-item#item-0"); | ||
| let a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li`); | ||
|
|
||
| expect(a11yItem).not.toBeNull(); | ||
|
|
@@ -794,7 +800,7 @@ describe("calcite-combobox", () => { | |
| item.setProperty("disabled", true); | ||
| await page.waitForChanges(); | ||
| await page.waitForTimeout(DEBOUNCE.nextTick); | ||
| a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li`); | ||
| a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li:nth-of-type(2)`); | ||
|
Elijbet marked this conversation as resolved.
|
||
|
|
||
| expect(a11yItem).toBeNull(); | ||
| }); | ||
|
|
@@ -2975,6 +2981,227 @@ describe("calcite-combobox", () => { | |
| expect((await combobox.getProperty("selectedItems")).length).toBe(1); | ||
| }); | ||
|
|
||
| describe("selectAllEnabled", async () => { | ||
| let page: E2EPage; | ||
|
|
||
| beforeEach(async () => { | ||
| page = await newE2EPage(); | ||
| await page.setContent( | ||
| html`<calcite-combobox selection-mode="multiple" select-all-enabled> | ||
| <calcite-combobox-item value="Trees" text-label="Trees"> | ||
| <calcite-combobox-item value="Pine" text-label="Pine"> | ||
| <calcite-combobox-item value="Pine Nested" text-label="Pine Nested"></calcite-combobox-item> | ||
| </calcite-combobox-item> | ||
| <calcite-combobox-item value="Sequoia" text-label="Sequoia"></calcite-combobox-item> | ||
| </calcite-combobox-item> | ||
| <calcite-combobox-item value="Flowers" text-label="Flowers"> | ||
| <calcite-combobox-item value="Daffodil" text-label="Daffodil"></calcite-combobox-item> | ||
| <calcite-combobox-item value="Nasturtium" text-label="Nasturtium"></calcite-combobox-item> | ||
| </calcite-combobox-item> | ||
| </calcite-combobox>`, | ||
| ); | ||
| await page.waitForChanges(); | ||
| }); | ||
|
|
||
| async function testToggleAllItems( | ||
| page: E2EPage, | ||
| toggleAction: ([selectAll, combobox]: [E2EElement, E2EElement]) => Promise<void>, | ||
| ): Promise<void> { | ||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.click(); | ||
| expect(await combobox.getProperty("open")).toBe(true); | ||
|
|
||
| const selectAll = await page.find(`calcite-combobox >>> .${CSS.selectAll}`); | ||
| await toggleAction([selectAll, combobox]); | ||
|
|
||
| let allComboboxItems = await findAll(page, "calcite-combobox-item"); | ||
| for (const item of allComboboxItems) { | ||
| expect(await item.getProperty("selected")).toBe(true); | ||
| } | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip.${CSS.allSelected}`)).toBeDefined(); | ||
|
|
||
| await toggleAction([selectAll, combobox]); | ||
|
|
||
| allComboboxItems = await findAll(page, "calcite-combobox-item"); | ||
| for (const item of allComboboxItems) { | ||
| expect(await item.getProperty("selected")).toBe(false); | ||
| } | ||
|
|
||
| const chip = await page.find(`calcite-combobox >>> calcite-chip.${CSS.allSelected}`); | ||
| expect(chip.classList.contains(`${CSS.chipInvisible}`)).toBe(true); | ||
| } | ||
|
|
||
| it("should toggle all items on and off with a click", async () => { | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| await testToggleAllItems(page, async ([selectAll, _combobox]) => { | ||
| await selectAll.click(); | ||
| }); | ||
| }); | ||
|
|
||
| it("should toggle all items on and off with KeyDown press `enter`", async () => { | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| await testToggleAllItems(page, async ([_selectAll, combobox]) => { | ||
| await combobox.press("Enter"); | ||
| }); | ||
| }); | ||
|
|
||
| it("indeterminate state", async () => { | ||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.click(); | ||
| expect(await combobox.getProperty("open")).toBe(true); | ||
|
|
||
| await (await combobox.find("calcite-combobox-item[value=Sequoia]")).click(); | ||
|
|
||
| const selectAll = await page.find(`calcite-combobox >>> calcite-combobox-item.${CSS.selectAll}`); | ||
| expect(await selectAll.getProperty("indeterminate")).toBe(true); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Sequoia]`)).toBeDefined(); | ||
|
|
||
| await (await combobox.find("calcite-combobox-item[value=Flowers]")).click(); | ||
|
|
||
| expect(await selectAll.getProperty("indeterminate")).toBe(true); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Flowers]`)).toBeDefined(); | ||
|
|
||
| const chip = await page.find(`calcite-combobox >>> calcite-chip.${CSS.allSelected}`); | ||
| expect(chip.classList.contains(`${CSS.chipInvisible}`)).toBe(true); | ||
|
|
||
| await selectAll.click(); | ||
| expect(await selectAll.getProperty("indeterminate")).toBe(false); | ||
| expect(await selectAll.getProperty("selected")).toBe(true); | ||
|
|
||
| expect(await page.find(`calcite-combobox >>> calcite-chip.${CSS.allSelected}`)).toBeDefined(); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Sequoia]`)).toBeNull(); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Flowers]`)).toBeNull(); | ||
|
|
||
| const allComboboxItems = await findAll(page, "calcite-combobox-item"); | ||
| for (const item of allComboboxItems) { | ||
| expect(await item.getProperty("selected")).toBe(true); | ||
| } | ||
| }); | ||
|
|
||
| async function testToggleListItems( | ||
| page: E2EPage, | ||
| toggleAction: ([listItem, combobox]: [E2EElement, E2EElement]) => Promise<void>, | ||
| ): Promise<void> { | ||
| const messages = await import("./assets/t9n/messages.json"); | ||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.click(); | ||
| expect(await combobox.getProperty("open")).toBe(true); | ||
|
|
||
| const allComboboxItems = await findAll(page, "calcite-combobox-item"); | ||
| for (const item of allComboboxItems) { | ||
| item.setProperty("selected", true); | ||
| } | ||
| await page.waitForChanges(); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value="${messages.allSelected}"]`)).toBeDefined(); | ||
|
Elijbet marked this conversation as resolved.
|
||
|
|
||
| const listItem = await combobox.find("calcite-combobox-item[value=Sequoia]"); | ||
| await toggleAction([listItem, combobox]); | ||
|
|
||
| const selectAll = await page.find(`calcite-combobox >>> calcite-combobox-item.${CSS.selectAll}`); | ||
| expect(await selectAll.getProperty("indeterminate")).toBe(true); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Sequoia]`)).toBeDefined(); | ||
|
|
||
| await toggleAction([listItem, combobox]); | ||
|
|
||
| expect(await selectAll.getProperty("indeterminate")).toBe(false); | ||
| expect(await selectAll.getProperty("selected")).toBe(true); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Sequoia]`)).toBeNull(); | ||
|
|
||
| await toggleAction([listItem, combobox]); | ||
|
|
||
| expect(await selectAll.getProperty("indeterminate")).toBe(true); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value=Sequoia]`)).toBeDefined(); | ||
| } | ||
|
|
||
| it("should toggle indeterminate state to `All Selected` when list items are toggled with a click", async () => { | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
| await testToggleListItems(page, async ([listItem, _combobox]) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not disable this rule. You don't need to specify await testToggleAllItems(page, async ([selectAll]) => { /* ... */ });Applies to similar unused var lines.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm passing both because I'm using either/or, right? I have 2 |
||
| await listItem.click(); | ||
| }); | ||
| }); | ||
|
|
||
| it("should toggle indeterminate state to `All Selected` when list items are toggled with a keydown `Enter`", async () => { | ||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not disable this rule. You don't need to specify await testToggleAllItems(page, async ([, combobox]) => { /* ... */ });Applies to similar unused var lines. |
||
| await testToggleAllItems(page, async ([_listItem, combobox]) => { | ||
| await combobox.press("Enter"); | ||
| }); | ||
| }); | ||
|
|
||
| it("should have indeterminate state when some items are initialized selected", async () => { | ||
| page = await newE2EPage(); | ||
| await page.setContent( | ||
| html`<calcite-combobox selection-mode="multiple" select-all-enabled> | ||
| <calcite-combobox-item value="Trees" text-label="Trees" selected> | ||
| <calcite-combobox-item value="Pine" text-label="Pine" /> | ||
| </calcite-combobox-item> | ||
| </calcite-combobox>`, | ||
| ); | ||
| await page.waitForChanges(); | ||
| const selectAll = await page.find(`calcite-combobox >>> calcite-combobox-item.${CSS.selectAll}`); | ||
| expect(await selectAll.getProperty("indeterminate")).toBe(true); | ||
| }); | ||
|
|
||
| it("should have selectAll state true when all items are initialized selected", async () => { | ||
| page = await newE2EPage(); | ||
| await page.setContent( | ||
| html`<calcite-combobox selection-mode="multiple" select-all-enabled> | ||
| <calcite-combobox-item value="Trees" text-label="Trees" selected> | ||
| <calcite-combobox-item value="Pine" text-label="Pine" selected /> | ||
| </calcite-combobox-item> | ||
| </calcite-combobox>`, | ||
| ); | ||
| await page.waitForChanges(); | ||
| const selectAll = await page.find(`calcite-combobox >>> calcite-combobox-item.${CSS.selectAll}`); | ||
| expect(await selectAll.getProperty("selected")).toBe(true); | ||
| }); | ||
|
|
||
| it("should bring back all the chips except `All Selected` when one item is deselected", async () => { | ||
| page = await newE2EPage(); | ||
| await page.setContent( | ||
| html`<calcite-combobox selection-mode="multiple" select-all-enabled> | ||
| <calcite-combobox-item value="Trees" text-label="Trees" selected> | ||
| <calcite-combobox-item value="Pine" text-label="Maple" selected /> | ||
| <calcite-combobox-item value="Pine" text-label="Pine" selected /> | ||
| </calcite-combobox-item> | ||
| </calcite-combobox>`, | ||
| ); | ||
| await page.waitForChanges(); | ||
| const messages = await import("./assets/t9n/messages.json"); | ||
|
|
||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.click(); | ||
| await page.waitForChanges(); | ||
|
|
||
| const listItem = await combobox.find("calcite-combobox-item[value=Pine]"); | ||
| await listItem.click(); | ||
|
|
||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value="Trees"]`)).toBeDefined(); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value="Maple"]`)).toBeDefined(); | ||
| expect(await page.find(`calcite-combobox >>> calcite-chip[value="${messages.allSelected}"]`)).toBeNull(); | ||
| }); | ||
|
|
||
| it("should update aria-selected on items when toggling 'Select All'", async () => { | ||
| const combobox = await page.find("calcite-combobox"); | ||
| await combobox.click(); | ||
|
|
||
| const selectAll = await page.find(`calcite-combobox >>> calcite-combobox-item.${CSS.selectAll}`); | ||
| await selectAll.click(); | ||
| await page.waitForChanges(); | ||
|
|
||
| let a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li:nth-of-type(2)`); | ||
| expect(await a11yItem.getProperty("ariaSelected")).toBe("true"); | ||
|
|
||
| a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li:nth-of-type(3)`); | ||
| expect(await a11yItem.getProperty("ariaSelected")).toBe("true"); | ||
|
|
||
| await selectAll.click(); | ||
| await page.waitForChanges(); | ||
|
|
||
| a11yItem = await page.find(`calcite-combobox >>> ul.${CSS.screenReadersOnly} li:nth-of-type(2)`); | ||
| expect(await a11yItem.getProperty("ariaSelected")).toBe("false"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("theme", () => { | ||
| describe("default", () => { | ||
| const comboboxHTML = html`<calcite-combobox label="test" max-items="6" open> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.