diff --git a/packages/react/src/components/TreeView/TreeView-test.js b/packages/react/src/components/TreeView/TreeView-test.js index 1f246c1c4289..95e5574b5322 100644 --- a/packages/react/src/components/TreeView/TreeView-test.js +++ b/packages/react/src/components/TreeView/TreeView-test.js @@ -5,11 +5,12 @@ * LICENSE file in the root directory of this source tree. */ +import { fireEvent, render, screen, within } from '@testing-library/react'; + import React from 'react'; -import TreeView from './TreeView'; import TreeNode from './TreeNode'; +import TreeView from './TreeView'; import userEvent from '@testing-library/user-event'; -import { fireEvent, render, screen, within } from '@testing-library/react'; const prefix = 'cds'; @@ -296,4 +297,247 @@ describe('TreeView', () => { expect(parentNode).toHaveFocus(); }); }); + it('should respect multiselect prop (deselecting nodes)', async () => { + const user = userEvent.setup(); + render( + + + + + ); + const lists = screen.getAllByRole('treeitem'); + await user.keyboard('[ControlLeft>]'); + await user.click(lists[0]); + await user.click(lists[1]); + expect(lists[0]).toHaveAttribute('aria-selected', 'true'); + expect(lists[1]).toHaveAttribute('aria-selected', 'true'); + await user.keyboard('[ControlLeft>]'); + await user.click(lists[0]); + expect(lists[0]).toHaveAttribute('aria-selected', 'false'); + expect(lists[1]).toHaveAttribute('aria-selected', 'true'); + }); + it('should render tree with custom icons', () => { + const CustomIcon = () => ; + render( + + + + ); + expect(screen.getByTestId('test-icon')).toBeInTheDocument(); + }); + + it('should expand a collapsed parent node when right arrow is pressed', async () => { + const user = userEvent.setup(); + render( + + + + + + ); + const parentNode = screen.getByTestId('parent-node'); + expect(parentNode).not.toHaveAttribute('aria-expanded', 'true'); + parentNode.focus(); + expect(parentNode).toHaveFocus(); + await user.keyboard('[ArrowRight]'); + expect(parentNode).toHaveAttribute('aria-expanded', 'true'); + const childNode = screen.getByTestId('child-node'); + expect(childNode).toBeInTheDocument(); + }); + it('should navigate between nodes using ArrowUp and ArrowDown', async () => { + const user = userEvent.setup(); + render( + + + + + ); + const node1 = screen.getByTestId('Node 1'); + const node2 = screen.getByTestId('Node 2'); + node1.focus(); + expect(node1).toHaveFocus(); + await user.keyboard('[ArrowDown]'); + expect(node2).toHaveFocus(); + await user.keyboard('[ArrowUp]'); + expect(node1).toHaveFocus(); + }); + + it('should not render label when hideLabel is true', () => { + render( + + + + ); + expect(screen.queryByText('Tree View')).not.toBeInTheDocument(); + }); + + it('should render custom icons in TreeNode', () => { + const CustomIcon = () => ; + + render( + + + + + ); + + const node1Icon = screen.getByTestId('custom-icon'); + const node2 = screen.getByText('Node 2'); + + expect(node1Icon).toBeInTheDocument(); + expect(node2.querySelector('svg')).toBeNull(); + }); + it('should render the label correctly', () => { + render( + + + + + ); + + expect(screen.getByLabelText('My Tree View')).toBeInTheDocument(); + }); + + it('should collapse an expanded parent node when left arrow is pressed', async () => { + const user = userEvent.setup(); + + render( + + + + + + ); + + const parentNode = screen.getByTestId('parent-node'); + + // Initially, the parent node should be expanded + expect(parentNode).toHaveAttribute('aria-expanded', 'true'); + + // Focus on the parent node + parentNode.focus(); + await user.keyboard('[ArrowLeft]'); + + // The parent node should now be collapsed + expect(parentNode).toHaveAttribute('aria-expanded', 'false'); + }); + + it('should deselect a node when clicked again in multiselect mode', async () => { + const user = userEvent.setup(); + render( + + + + + ); + + const lists = screen.getAllByRole('treeitem'); + await user.keyboard('[ControlLeft>]'); + await user.click(lists[0]); + await user.click(lists[1]); + + expect(lists[0]).toHaveAttribute('aria-selected', 'true'); + expect(lists[1]).toHaveAttribute('aria-selected', 'true'); + + // Deselect Node 1 + await user.keyboard('[ControlLeft>]'); + await user.click(lists[0]); + + expect(lists[0]).toHaveAttribute('aria-selected', 'false'); + expect(lists[1]).toHaveAttribute('aria-selected', 'true'); + }); + it('should not allow interaction with disabled nodes', async () => { + const user = userEvent.setup(); + render( + + + + + ); + + const node1 = screen.getByTestId('Node 1'); + const node2 = screen.getByTestId('Node 2'); + + // The disabled node should not be focusable + await user.tab(); + expect(node1).toHaveFocus(); + + // The disabled node should also not be clickable + fireEvent.click(node2); + expect(node2).not.toHaveClass(`${prefix}--tree-node--selected`); + }); + it('should select nodes correctly when Home/End keys are used with multiselect and shiftKey+ctrlKey', async () => { + const user = userEvent.setup(); + + render( + + + + + + ); + + const node1 = screen.getByTestId('Node 1'); + const node2 = screen.getByTestId('Node 2'); + const node3 = screen.getByTestId('Node 3'); + + await user.click(node2); + expect(node2).toHaveFocus(); + await user.keyboard('[ControlLeft>][ShiftLeft>][Home]'); + expect(node1).toHaveClass(`${prefix}--tree-node--selected`); + expect(node2).toHaveClass(`${prefix}--tree-node--selected`); + }); + it('should select nodes correctly when Home key is used with multiselect and shiftKey+ctrlKey', async () => { + const user = userEvent.setup(); + + render( + + + + + + ); + + const node1 = screen.getByTestId('Node 1'); + const node2 = screen.getByTestId('Node 2'); + const node3 = screen.getByTestId('Node 3'); + + await user.click(node2); + expect(node2).toHaveFocus(); + + await user.keyboard('[ControlLeft>][ShiftLeft>][Home]'); + + expect(node1).toHaveClass(`${prefix}--tree-node--selected`); + expect(node2).toHaveClass(`${prefix}--tree-node--selected`); + expect(node3).not.toHaveClass(`${prefix}--tree-node--selected`); + }); + + it('should select multiple nodes when Home key is pressed with Shift and Ctrl keys', async () => { + const user = userEvent.setup(); + + render( + + + + + + ); + + const node1 = screen.getByTestId('Node 1'); + const node2 = screen.getByTestId('Node 2'); + const node3 = screen.getByTestId('Node 3'); + + await user.click(node2); + expect(node2).toHaveFocus(); + await user.keyboard('[ControlLeft>][ShiftLeft>][Home]'); + expect(node1).toHaveClass(`${prefix}--tree-node--selected`); + expect(node2).toHaveClass(`${prefix}--tree-node--selected`); + expect(node3).not.toHaveClass(`${prefix}--tree-node--selected`); + }); });