-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(TreeView): updated treeview test to use rtl (#13025)
* test(TreeView): updated test to use rtl * test(TreeView): updated test * Update packages/react/src/components/TreeView/TreeView-test.js Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com> * test(treeview): updated test --------- Co-authored-by: TJ Egan <tw15egan@gmail.com> Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
- Loading branch information
1 parent
b1a6be2
commit d8b5d6d
Showing
2 changed files
with
179 additions
and
1,058 deletions.
There are no files selected for viewing
247 changes: 179 additions & 68 deletions
247
packages/react/src/components/TreeView/TreeView-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,95 +1,206 @@ | ||
/** | ||
* Copyright IBM Corp. 2020 | ||
* Copyright IBM Corp. 2022 | ||
* | ||
* This source code is licensed under the Apache-2.0 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import { CaretDown } from '@carbon/icons-react'; | ||
import React from 'react'; | ||
import { mount } from 'enzyme'; | ||
import { Document, Folder } from '@carbon/icons-react'; | ||
import TreeView, { TreeNode } from './'; | ||
import TreeView from './TreeView'; | ||
import TreeNode from './TreeNode'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { fireEvent, render, screen, within } from '@testing-library/react'; | ||
|
||
const prefix = 'cds'; | ||
|
||
describe('TreeView', () => { | ||
let wrapper; | ||
let onTreeSelect; | ||
let onNodeSelect; | ||
|
||
beforeEach(() => { | ||
onTreeSelect = jest.fn(); | ||
onNodeSelect = jest.fn(); | ||
wrapper = mount( | ||
<TreeView label="Tree view" selected={['1']} onSelect={onTreeSelect}> | ||
<TreeNode id="1" value="1" label="1" /> | ||
<TreeNode id="2" value="2" label="2" onSelect={onNodeSelect} /> | ||
<TreeNode id="5" value="5" label="5" isExpanded> | ||
<TreeNode id="5-1" value="5-1" label="5-1" /> | ||
<TreeNode id="5-2" value="5-2" label="5-2" /> | ||
<TreeNode id="5-3" value="5-3" label="5-3" isExpanded> | ||
<TreeNode id="5-4" value="5-4" label="5-4" /> | ||
describe('renders as expected - Component API', () => { | ||
it('should spread extra props onto outermost element', () => { | ||
render(<TreeView data-testid="test-id" label="Tree" />); | ||
|
||
expect(screen.getByRole('tree')).toHaveAttribute( | ||
'data-testid', | ||
'test-id' | ||
); | ||
}); | ||
|
||
it('should respect active prop', () => { | ||
render( | ||
<TreeView active="Node 1" label="Tree"> | ||
<TreeNode data-testid="Node 1" id="Node 1" label="Node 1" /> | ||
<TreeNode id="Node 2" label="Node 2" /> | ||
</TreeView> | ||
); | ||
|
||
const node = screen.getByTestId('Node 1'); | ||
|
||
expect(node).toHaveClass(`${prefix}--tree-node--active`); | ||
}); | ||
|
||
it('should render children as expected', () => { | ||
render( | ||
<TreeView label="Tree View"> | ||
<TreeNode isExpanded={true} data-testid="Node 1" label="Node 1"> | ||
<TreeNode data-testid="Node 2" label="Node 2" /> | ||
</TreeNode> | ||
</TreeNode> | ||
</TreeView> | ||
); | ||
}); | ||
</TreeView> | ||
); | ||
|
||
it('should render', () => { | ||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
const nodeParent = screen.getByTestId('Node 1'); | ||
const nodeChild = screen.getByTestId('Node 2'); | ||
|
||
expect(nodeParent).toHaveClass(`${prefix}--tree-parent-node`); | ||
expect(nodeChild).toHaveClass(`${prefix}--tree-leaf-node`); | ||
|
||
expect(within(nodeParent).getByText('Node 1')).toBeInTheDocument(); | ||
expect(within(nodeChild).getByText('Node 2')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should support a custom `className` prop on the outermost element', () => { | ||
const { container } = render( | ||
<TreeView className="custom-class" label="Tree" /> | ||
); | ||
|
||
const ul = container?.getElementsByTagName('ul')[0]; | ||
|
||
expect(ul).toHaveClass('custom-class'); | ||
}); | ||
|
||
it('should respect hideLabel prop', () => { | ||
render( | ||
<TreeView id="Tree" label="Tree View" hideLabel> | ||
<TreeNode id="Node 1" data-testid="Node 1" label="Node 1" /> | ||
</TreeView> | ||
); | ||
|
||
expect( | ||
screen.queryByText('Tree View', { selector: 'label' }) | ||
).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('should respect label prop', () => { | ||
render( | ||
<TreeView label="Tree View" selected={['Node 1']}> | ||
<TreeNode id="Node 1" data-testid="Node 1" label="Node 1" /> | ||
</TreeView> | ||
); | ||
|
||
expect(screen.getByLabelText('Tree View')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should respect multiselect prop', () => { | ||
render( | ||
<TreeView multiselect label="Tree"> | ||
<TreeNode data-testid="Node 1" label="Node 1" /> | ||
<TreeNode data-testid="Node 2" label="Node 2" /> | ||
</TreeView> | ||
); | ||
|
||
const tree = screen.getByRole('tree'); | ||
const lists = tree?.getElementsByTagName('li'); | ||
|
||
it('should render with icons', () => { | ||
wrapper = mount( | ||
<TreeView label="Tree view" selected={['1']}> | ||
<TreeNode renderIcon={Document} id="1" value="1" label="1" /> | ||
<TreeNode renderIcon={Document} id="2" value="2" label="2" /> | ||
<TreeNode renderIcon={Folder} id="5" value="5" label="5" isExpanded> | ||
<TreeNode renderIcon={Document} id="5-1" value="5-1" label="5-1" /> | ||
<TreeNode renderIcon={Document} id="5-2" value="5-2" label="5-2" /> | ||
userEvent.click(lists[0], { ctrlKey: true }); | ||
userEvent.click(lists[1], { ctrlKey: true }); | ||
|
||
expect(lists[0]).toHaveAttribute('aria-selected', 'true'); | ||
expect(lists[1]).toHaveAttribute('aria-selected', 'true'); | ||
}); | ||
|
||
it('should respect onSelect prop', () => { | ||
const onSelectSpy = jest.fn(); | ||
|
||
render( | ||
<TreeView label="Tree View"> | ||
<TreeNode | ||
renderIcon={Folder} | ||
id="5-3" | ||
value="5-3" | ||
label="5-3" | ||
isExpanded> | ||
<TreeNode renderIcon={Document} id="5-4" value="5-4" label="5-4" /> | ||
</TreeNode> | ||
</TreeNode> | ||
</TreeView> | ||
); | ||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
onSelect={onSelectSpy} | ||
id="Node 1" | ||
data-testid="Node 1" | ||
label="Node 1" | ||
/> | ||
</TreeView> | ||
); | ||
|
||
it('should be able to hide the label', () => { | ||
expect(wrapper.find('TreeLabel').text()).toBe('Tree view'); | ||
wrapper.setProps({ hideLabel: true }); | ||
expect(wrapper.find('TreeLabel').text()).toBeFalsy(); | ||
}); | ||
fireEvent.click(screen.getByTestId('Node 1')); | ||
|
||
describe('Single node selection', () => { | ||
it('should be able to preselect a node', () => { | ||
expect(wrapper.find(`.${prefix}--tree-node--selected`).text()).toBe('1'); | ||
expect(onSelectSpy).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle selection at the tree level', () => { | ||
const onTreeSelect = jest.fn(); | ||
wrapper.setProps({ onSelect: onTreeSelect }); | ||
wrapper.find('TreeNode[value="2"]').simulate('click'); | ||
expect(onTreeSelect).toHaveBeenCalledTimes(1); | ||
it('should respect selected prop', () => { | ||
render( | ||
<TreeView label="Tree View" selected={['Node 1']}> | ||
<TreeNode id="Node 1" data-testid="Node 1" label="Node 1" /> | ||
</TreeView> | ||
); | ||
|
||
expect(screen.getByRole('treeitem', { name: 'Node 1' })).toHaveClass( | ||
`${prefix}--tree-node--selected` | ||
); | ||
}); | ||
|
||
it('should handle selection at the node level', () => { | ||
wrapper.find('TreeNode[value="2"]').simulate('click'); | ||
expect(onTreeSelect).toHaveBeenCalledTimes(1); | ||
expect(onNodeSelect).toHaveBeenCalledTimes(1); | ||
it('should respect size prop', () => { | ||
render(<TreeView size="xs" label="Tree" />); | ||
|
||
const tree = screen.getByRole('tree'); | ||
|
||
expect(tree).toHaveClass(`${prefix}--tree--xs`); | ||
}); | ||
}); | ||
|
||
describe('Tree node expansion', () => { | ||
it('Caret icon should not render in leaf nodes', () => { | ||
expect(wrapper.find(CaretDown).length).toBe(2); | ||
describe('behaves as expected', () => { | ||
it('should render tree with expanded node', () => { | ||
render( | ||
<TreeView label="Tree View"> | ||
<TreeNode data-testid="Node 1" label="Node 1" isExpanded={true}> | ||
<TreeNode data-testid="Node 2" label="Node 2" /> | ||
</TreeNode> | ||
</TreeView> | ||
); | ||
|
||
const nodeParent = screen.getByTestId('Node 1'); | ||
const nodeChild = nodeParent?.querySelector('div > span'); | ||
|
||
expect(nodeChild).toHaveClass(`${prefix}--tree-parent-node__toggle`); | ||
expect(within(nodeParent).getByText('Node 1')).toBeInTheDocument(); | ||
expect(within(nodeParent).getByText('Node 2')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should render tree with disabled nodes', () => { | ||
render( | ||
<TreeView label="Tree View"> | ||
<TreeNode label="Node 1" data-testid="Node 1" /> | ||
<TreeNode | ||
data-testid="Node 2" | ||
label="Node 2" | ||
disabled={true} | ||
isExpanded={true}> | ||
<TreeNode isExpanded={true} data-testid="Node 3" label="Node 3" /> | ||
</TreeNode> | ||
</TreeView> | ||
); | ||
|
||
const nodeChild = screen.getByTestId('Node 2'); | ||
|
||
expect(nodeChild.getAttribute('aria-disabled')).toEqual('true'); | ||
}); | ||
|
||
it('should render tree with icons', () => { | ||
const CustomIcon = jest.fn(() => { | ||
return <svg data-testid="test-icon" />; | ||
}); | ||
|
||
render( | ||
<TreeView label="Tree View"> | ||
<TreeNode | ||
renderIcon={CustomIcon} | ||
data-testid="Node 1" | ||
label="Node 1" | ||
/> | ||
</TreeView> | ||
); | ||
|
||
expect(screen.getByTestId('Node 1')).toHaveClass( | ||
`${prefix}--tree-node--with-icon` | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.