From 18213bbfec8dd4a649e7830e00c97131193116a3 Mon Sep 17 00:00:00 2001 From: delangle Date: Fri, 17 May 2024 13:56:53 +0200 Subject: [PATCH] [core] Use describe TreeView for keyboard selection tests --- .../SimpleTreeView/SimpleTreeView.test.tsx | 19 - .../src/TreeItem/TreeItem.test.tsx | 460 ------------------ .../useTreeViewKeyboardNavigation.test.tsx | 395 ++++++++++++++- .../useTreeViewSelection.test.tsx | 195 ++------ .../describeTreeView/describeTreeView.tsx | 7 + .../describeTreeView.types.ts | 5 + 6 files changed, 444 insertions(+), 637 deletions(-) diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.test.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.test.tsx index f1a74fc5a8f3..bed460497471 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.test.tsx +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.test.tsx @@ -110,25 +110,6 @@ describe('', () => { expect(handleTreeItemKeyDown.callCount).to.equal(3); }); - it('should select item when Enter key is pressed ', () => { - const handleKeyDown = spy(); - - const { getByTestId } = render( - - - , - ); - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).not.to.have.attribute('aria-selected'); - - fireEvent.keyDown(getByTestId('one'), { key: 'Enter' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected'); - }); - it('should not error when component state changes', () => { function MyComponent() { const [, setState] = React.useState(1); diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx index 5ea5973c0010..fca12d47ca78 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx @@ -200,466 +200,6 @@ describe('', () => { expect(getByRole('group')).to.contain(getByText('test2')); }); - - describe('Single Selection', () => { - describe('keyboard', () => { - it('should select an item when space is pressed', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).not.to.have.attribute('aria-selected'); - - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - }); - - it('should not deselect an item when space is pressed on a selected item', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).toHaveFocus(); - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - }); - - it('should not select an node when space is pressed and disableSelection', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - - expect(getByTestId('one')).not.to.have.attribute('aria-selected'); - }); - - it('should select an item when Enter is pressed and the item is not selected', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - fireEvent.keyDown(getByTestId('one'), { key: 'Enter' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected'); - }); - - it('should not un-select an item when Enter is pressed and the item is selected', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - fireEvent.keyDown(getByTestId('one'), { key: 'Enter' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected'); - }); - }); - }); - - describe('Multi Selection', () => { - describe('deselection', () => { - it('should deselect the item when pressing space on a selected item', () => { - const { getByTestId } = render( - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).toHaveFocus(); - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - expect(getByTestId('one')).to.have.attribute('aria-selected', 'false'); - }); - }); - - describe('range selection', () => { - it('keyboard arrow', () => { - const { getByTestId, queryAllByRole, getByText } = render( - - - - - - - , - ); - - fireEvent.click(getByText('three')); - act(() => { - getByTestId('three').focus(); - }); - - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true }); - - expect(getByTestId('four')).toHaveFocus(); - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(2); - - fireEvent.keyDown(getByTestId('four'), { key: 'ArrowDown', shiftKey: true }); - - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('four')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(3); - - fireEvent.keyDown(getByTestId('five'), { key: 'ArrowUp', shiftKey: true }); - - expect(getByTestId('four')).toHaveFocus(); - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(2); - - fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(1); - - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(2); - - fireEvent.keyDown(getByTestId('two'), { key: 'ArrowUp', shiftKey: true }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('four')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('five')).to.have.attribute('aria-selected', 'false'); - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(3); - }); - - it('keyboard arrow does not select when selectionDisabled', () => { - const { getByTestId, queryAllByRole } = render( - - - - - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - fireEvent.keyDown(getByTestId('one'), { key: 'ArrowDown', shiftKey: true }); - - expect(getByTestId('two')).toHaveFocus(); - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(0); - - fireEvent.keyDown(getByTestId('two'), { key: 'ArrowUp', shiftKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(0); - }); - - it('keyboard arrow merge', () => { - const { getByTestId, getByText, queryAllByRole } = render( - - - - - - - - , - ); - - fireEvent.click(getByText('three')); - act(() => { - getByTestId('three').focus(); - }); - - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true }); - fireEvent.click(getByText('six'), { ctrlKey: true }); - fireEvent.keyDown(getByTestId('six'), { key: 'ArrowUp', shiftKey: true }); - fireEvent.keyDown(getByTestId('five'), { key: 'ArrowUp', shiftKey: true }); - fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true }); - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(5); - - fireEvent.keyDown(getByTestId('two'), { key: 'ArrowDown', shiftKey: true }); - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(3); - }); - - it('keyboard space', () => { - const { getByTestId, getByText } = render( - - - - - - - - - - - - - , - ); - - fireEvent.click(getByText('five')); - act(() => { - getByTestId('five').focus(); - }); - - fireEvent.keyDown(getByTestId('five'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('six'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('seven'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('eight'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('nine'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('nine'), { key: ' ', shiftKey: true }); - - expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('six')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('seven')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('eight')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('nine')).to.have.attribute('aria-selected', 'true'); - - fireEvent.keyDown(getByTestId('nine'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('eight'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('seven'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('six'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('five'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('two'), { key: 'ArrowUp' }); - fireEvent.keyDown(getByTestId('one'), { key: 'ArrowUp' }); - - fireEvent.keyDown(getByTestId('one'), { key: ' ', shiftKey: true }); - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('four')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('six')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('seven')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('eight')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('nine')).to.have.attribute('aria-selected', 'false'); - }); - - it('keyboard home and end', () => { - const { getByTestId } = render( - - - - - - - - - - - - - , - ); - - act(() => { - getByTestId('five').focus(); - }); - - fireEvent.keyDown(getByTestId('five'), { - key: 'End', - shiftKey: true, - ctrlKey: true, - }); - - expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('six')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('seven')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('eight')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('nine')).to.have.attribute('aria-selected', 'true'); - - fireEvent.keyDown(getByTestId('five'), { - key: 'Home', - shiftKey: true, - ctrlKey: true, - }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('four')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('six')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('seven')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('eight')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('nine')).to.have.attribute('aria-selected', 'false'); - }); - - it('keyboard home and end do not select when selectionDisabled', () => { - const { getByTestId, getByText, queryAllByRole } = render( - - - - - - - - - - - - - , - ); - - fireEvent.click(getByText('five')); - act(() => { - getByTestId('five').focus(); - }); - fireEvent.keyDown(getByTestId('five'), { - key: 'End', - shiftKey: true, - ctrlKey: true, - }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(0); - - fireEvent.keyDown(getByTestId('nine'), { - key: 'Home', - shiftKey: true, - ctrlKey: true, - }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(0); - }); - }); - - describe('multi selection', () => { - it('keyboard', () => { - const { getByTestId } = render( - - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'false'); - - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'false'); - - fireEvent.keyDown(getByTestId('one'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('two'), { key: ' ' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'true'); - }); - - it('keyboard holding ctrl', () => { - const { getByTestId } = render( - - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'false'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'false'); - - fireEvent.keyDown(getByTestId('one'), { key: ' ' }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'false'); - - fireEvent.keyDown(getByTestId('one'), { key: 'ArrowDown' }); - fireEvent.keyDown(getByTestId('two'), { key: ' ', ctrlKey: true }); - - expect(getByTestId('one')).to.have.attribute('aria-selected', 'true'); - expect(getByTestId('two')).to.have.attribute('aria-selected', 'true'); - }); - }); - - it('ctrl + a selects all', () => { - const { getByTestId, queryAllByRole } = render( - - - - - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(5); - }); - - it('ctrl + a does not select all when disableSelection', () => { - const { getByTestId, queryAllByRole } = render( - - - - - - - , - ); - - act(() => { - getByTestId('one').focus(); - }); - fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true }); - - expect(queryAllByRole('treeitem', { selected: true })).to.have.length(0); - }); - }); }); describe('prop: disabled', () => { diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.test.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.test.tsx index 6cf0805ab397..5eec9b602502 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.test.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.test.tsx @@ -6,10 +6,16 @@ import { UseTreeViewExpansionSignature, UseTreeViewItemsSignature, UseTreeViewKeyboardNavigationSignature, + UseTreeViewSelectionSignature, } from '@mui/x-tree-view/internals'; describeTreeView< - [UseTreeViewKeyboardNavigationSignature, UseTreeViewItemsSignature, UseTreeViewExpansionSignature] + [ + UseTreeViewKeyboardNavigationSignature, + UseTreeViewItemsSignature, + UseTreeViewExpansionSignature, + UseTreeViewSelectionSignature, + ] >('useTreeViewKeyboardNavigation', ({ render, treeViewComponent }) => { describe('Navigation (focus and expansion)', () => { describe('key: ArrowDown', () => { @@ -358,6 +364,391 @@ describeTreeView< }); }); + describe('Selection', () => { + describe('single selection', () => { + describe('key: Space', () => { + it('should select the focused item when Space is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ' }); + expect(response.isItemSelected('1')).to.equal(true); + }); + + it('should not un-select the focused item when Space is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['1'], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ' }); + expect(response.isItemSelected('1')).to.equal(true); + }); + + it('should not select the focused item when Space is pressed and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + disableSelection: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ' }); + expect(response.isItemSelected('1')).to.equal(false); + }); + }); + + describe('key: Enter', () => { + it('should select the focused item when Enter is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'Enter' }); + expect(response.isItemSelected('1')).to.equal(true); + }); + + it('should not un-select the focused item when Enter is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['1'], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'Enter' }); + expect(response.isItemSelected('1')).to.equal(true); + }); + + it('should not select the focused item when Enter is pressed and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + disableSelection: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'Enter' }); + expect(response.isItemSelected('1')).to.equal(false); + }); + }); + }); + + describe('multi selection', () => { + describe('key: Space', () => { + it('should select the focused item without un-selecting the other selected items when Space is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + defaultSelectedItems: ['1'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: ' ' }); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); + }); + + it('should un-select the focused item when Space is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + defaultSelectedItems: ['1', '2'], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ' }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); + }); + + it('should select the focused item without un-selecting the other selected items when Space is pressed while holding Ctrl', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + defaultSelectedItems: ['1'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: ' ', ctrlKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); + }); + + it('should un-select the focused item when Space is pressed while holding Ctrl', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + defaultSelectedItems: ['1', '2'], + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ', ctrlKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); + }); + + it('should not select the focused item when Space is pressed and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: ' ' }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + + describe('key: ArrowDown', () => { + it('should expand the selection range when ArrowDown is pressed while holding Shift from a selected item', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['2'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: 'ArrowDown', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + }); + + it('should not un-select the item below the focused item when ArrowDown is pressed while holding Shift from a selected item', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['2', '3'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: 'ArrowDown', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + }); + + it('should un-select the focused item when ArrowDown is pressed while holding Shift and the item below have been selected in the same range', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['3'], + }); + + act(() => { + response.getItemRoot('3').focus(); + }); + fireEvent.keyDown(response.getItemRoot('3'), { key: 'ArrowUp', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + + fireEvent.keyDown(response.getItemRoot('2'), { key: 'ArrowDown', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['3']); + }); + + it('should not select any item when ArrowDown is pressed while holding Shift and disabledSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'ArrowDown', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + + describe('key: ArrowUp', () => { + it('should expand the selection range when ArrowUp is pressed while holding Shift from a selected item', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['3'], + }); + + act(() => { + response.getItemRoot('3').focus(); + }); + fireEvent.keyDown(response.getItemRoot('3'), { key: 'ArrowUp', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + }); + + it('should not un-select the item above the focused item when ArrowUp is pressed while holding Shift from a selected item', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['2', '3'], + }); + + act(() => { + response.getItemRoot('3').focus(); + }); + fireEvent.keyDown(response.getItemRoot('3'), { key: 'ArrowUp', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + }); + + it('should un-select the focused item when ArrowUp is pressed while holding Shift and the item above have been selected in the same range', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultSelectedItems: ['2'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: 'ArrowDown', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '3']); + + fireEvent.keyDown(response.getItemRoot('3'), { key: 'ArrowUp', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); + }); + + it('should not select any item when ArrowUp is pressed while holding Shift and disabledSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { key: 'ArrowUp', shiftKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + + describe('key: Home', () => { + it('should select select the focused item and all the items above when Home is pressed while holding Shift + Ctrl', () => { + const response = render({ + items: [{ id: '1' }, { id: '2', children: [{ id: '2.1' }] }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultExpandedItems: ['2'], + }); + + act(() => { + response.getItemRoot('3').focus(); + }); + fireEvent.keyDown(response.getItemRoot('3'), { + key: 'Home', + shiftKey: true, + ctrlKey: true, + }); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2', '2.1', '3']); + }); + + it('should not select any item when Home is pressed while holding Shift + Ctrl and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('3').focus(); + }); + fireEvent.keyDown(response.getItemRoot('3'), { + key: 'Home', + shiftKey: true, + ctrlKey: true, + }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + + describe('key: End', () => { + it('should select select the focused item and all the items below when End is pressed while holding Shift + Ctrl', () => { + const response = render({ + items: [{ id: '1' }, { id: '2', children: [{ id: '2.1' }] }, { id: '3' }, { id: '4' }], + multiSelect: true, + defaultExpandedItems: ['2'], + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { + key: 'End', + shiftKey: true, + ctrlKey: true, + }); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '2.1', '3', '4']); + }); + + it('should not select any item when End is pressed while holding Shift + Ctrl and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('2').focus(); + }); + fireEvent.keyDown(response.getItemRoot('2'), { + key: 'End', + shiftKey: true, + ctrlKey: true, + }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + + describe('key: Ctrl + A', () => { + it('should select all items when Ctrl + A is pressed', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'a', ctrlKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2', '3', '4']); + }); + + it('should not select any item when Ctrl + A is pressed and disableSelection={true}', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }], + multiSelect: true, + disableSelection: true, + }); + + act(() => { + response.getItemRoot('1').focus(); + }); + fireEvent.keyDown(response.getItemRoot('1'), { key: 'a', ctrlKey: true }); + expect(response.getSelectedTreeItems()).to.deep.equal([]); + }); + }); + }); + }); + describe('Type-ahead', () => { it('should move the focus to the next item with a name that starts with the typed character', () => { const response = render({ @@ -487,7 +878,7 @@ describeTreeView< expect(response.getFocusedItemId()).to.equal('4'); }); - it('should not move focus when pressing a modifier key and a letter', () => { + it('should not move focus when a modifier key and a letter are pressed', () => { const response = render({ items: [ { id: '1', label: 'one' }, diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx index 63324c7ed7c3..f9a95090987b 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx @@ -155,8 +155,7 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', expect(() => { response.setProps({ defaultSelectedItems: ['2'] }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); }).toErrorDev( 'MUI X: A component is changing the default selectedItems state of an uncontrolled TreeView after being initialized. To suppress this warning opt to use a controlled TreeView.', ); @@ -219,12 +218,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', defaultSelectedItems: ['2'], }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemContent('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); }); it('should not un-select selected item when clicking on an item content', () => { @@ -247,11 +244,9 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', defaultSelectedItems: ['1', '2'], }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); fireEvent.click(response.getItemContent('1'), { ctrlKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); }); it('should un-select selected item when clicking on its content while holding Meta', () => { @@ -261,12 +256,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', defaultSelectedItems: ['1', '2'], }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); fireEvent.click(response.getItemContent('1'), { metaKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); }); it('should not select an item when click and disableSelection', () => { @@ -300,14 +293,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', defaultSelectedItems: ['1'], }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemContent('3'), { ctrlKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '3']); }); it('should expand the selection range when clicking on an item content below the last selected item while holding Shift', () => { @@ -317,18 +306,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemContent('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '2.1', '3']); }); it('should expand the selection range when clicking on an item content above the last selected item while holding Shift', () => { @@ -338,18 +319,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('3')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['3']); fireEvent.click(response.getItemContent('2'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '2.1', '3']); }); it('should expand the selection range when clicking on an item content while holding Shift after un-selecting another item', () => { @@ -359,32 +332,16 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemContent('2'), { ctrlKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); fireEvent.click(response.getItemContent('2'), { ctrlKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemContent('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2', '2.1', '3']); }); it('should not expand the selection range when clicking on a disabled item content then clicking on an item content while holding Shift', () => { @@ -400,18 +357,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal([]); fireEvent.click(response.getItemContent('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal([]); }); it('should not expand the selection range when clicking on an item content then clicking a disabled item content while holding Shift', () => { @@ -427,18 +376,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemContent('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); }); it('should not select disabled items that are part of the selected range', () => { @@ -448,14 +389,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemContent('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemContent('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '3']); }); }); }); @@ -574,12 +511,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', defaultSelectedItems: ['2'], }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemCheckboxInput('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); }); it('should un-select selected item when clicking on an item checkbox', () => { @@ -630,18 +565,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemCheckboxInput('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '2.1', '3']); }); it('should expand the selection range when clicking on an item checkbox above the last selected item while holding Shift', () => { @@ -652,18 +579,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('3')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['3']); fireEvent.click(response.getItemCheckboxInput('2'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2', '2.1', '3']); }); it('should expand the selection range when clicking on an item checkbox while holding Shift after un-selecting another item', () => { @@ -674,32 +593,16 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemCheckboxInput('2')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); fireEvent.click(response.getItemCheckboxInput('2')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemCheckboxInput('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(true); - expect(response.isItemSelected('3')).to.equal(true); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2', '2.1', '3']); }); it('should not expand the selection range when clicking on a disabled item checkbox then clicking on an item checkbox while holding Shift', () => { @@ -716,18 +619,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal([]); fireEvent.click(response.getItemCheckboxInput('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal([]); }); it('should not expand the selection range when clicking on an item checkbox then clicking a disabled item checkbox while holding Shift', () => { @@ -744,18 +639,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('2')); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); fireEvent.click(response.getItemCheckboxInput('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(false); - expect(response.isItemSelected('2')).to.equal(true); - expect(response.isItemSelected('2.1')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); - expect(response.isItemSelected('4')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['2']); }); it('should not select disabled items that are part of the selected range', () => { @@ -766,14 +653,10 @@ describeTreeView<[UseTreeViewSelectionSignature]>('useTreeViewSelection plugin', }); fireEvent.click(response.getItemCheckboxInput('1')); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(false); + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); fireEvent.click(response.getItemCheckboxInput('3'), { shiftKey: true }); - expect(response.isItemSelected('1')).to.equal(true); - expect(response.isItemSelected('2')).to.equal(false); - expect(response.isItemSelected('3')).to.equal(true); + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '3']); }); }); }); diff --git a/test/utils/tree-view/describeTreeView/describeTreeView.tsx b/test/utils/tree-view/describeTreeView/describeTreeView.tsx index 763cd8ee7d5d..0404df14fa18 100644 --- a/test/utils/tree-view/describeTreeView/describeTreeView.tsx +++ b/test/utils/tree-view/describeTreeView/describeTreeView.tsx @@ -59,6 +59,12 @@ const innerDescribeTreeView = ( const isItemSelected = (id: string) => getItemRoot(id).getAttribute('aria-selected') === 'true'; + const getSelectedTreeItems = () => + result + .queryAllByRole('treeitem') + .filter((item) => item.getAttribute('aria-selected') === 'true') + .map((item) => item.dataset.testid!); + return { getRoot, getAllTreeItemIds, @@ -71,6 +77,7 @@ const innerDescribeTreeView = ( getItemIconContainer, isItemExpanded, isItemSelected, + getSelectedTreeItems, }; }; diff --git a/test/utils/tree-view/describeTreeView/describeTreeView.types.ts b/test/utils/tree-view/describeTreeView/describeTreeView.types.ts index 6b21548e8c60..9a213f76b8bd 100644 --- a/test/utils/tree-view/describeTreeView/describeTreeView.types.ts +++ b/test/utils/tree-view/describeTreeView/describeTreeView.types.ts @@ -94,6 +94,11 @@ export interface DescribeTreeViewRendererReturnValue< * @returns {boolean} `true` if the item is selected, `false` otherwise. */ isItemSelected: (id: string) => boolean; + /** + * Returns the item id of all the items currently selected. + * @returns {HTMLElement[]} List of the item id of all the items currently selected. + */ + getSelectedTreeItems: () => string[]; } export type DescribeTreeViewRenderer = <