diff --git a/examples/mutiple-with-maxCount.tsx b/examples/mutiple-with-maxCount.tsx index 7c2283f9..41171c04 100644 --- a/examples/mutiple-with-maxCount.tsx +++ b/examples/mutiple-with-maxCount.tsx @@ -46,8 +46,8 @@ export default () => { multiple maxCount={3} treeData={treeData} - onChange={onChange} - value={value} + // onChange={onChange} + // value={value} />

checkable with maxCount

@@ -55,11 +55,22 @@ export default () => { style={{ width: 300 }} multiple treeCheckable + treeCheckStrictly maxCount={3} treeData={treeData} onChange={onChange} value={value} /> + ); }; diff --git a/tests/Select.maxCount.spec.tsx b/tests/Select.maxCount.spec.tsx new file mode 100644 index 00000000..0e8f142e --- /dev/null +++ b/tests/Select.maxCount.spec.tsx @@ -0,0 +1,157 @@ +import { render, fireEvent, within } from '@testing-library/react'; +import KeyCode from 'rc-util/lib/KeyCode'; +import { keyDown, keyUp } from './util'; +import React from 'react'; +import TreeSelect from '../src'; + +describe('TreeSelect.maxCount', () => { + const treeData = [ + { key: '0', value: '0', title: '0 label' }, + { key: '1', value: '1', title: '1 label' }, + { key: '2', value: '2', title: '2 label' }, + { key: '3', value: '3', title: '3 label' }, + ]; + + const renderTreeSelect = (props?: any) => { + return render(); + }; + + const selectOptions = (container, optionTexts) => { + const dropdownList = container.querySelector('.rc-tree-select-dropdown'); + optionTexts.forEach(text => { + fireEvent.click(within(dropdownList).getByText(text)); + }); + }; + + it('should disable unselected options when selection reaches maxCount', () => { + const { container } = renderTreeSelect(); + + selectOptions(container, ['0 label', '1 label']); + + // Check if third and fourth options are disabled + const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement; + const option3 = within(dropdownList).getByText('2 label'); + const option4 = within(dropdownList).getByText('3 label'); + + expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); + expect(option4.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); + }); + + it('should allow deselecting options after reaching maxCount', () => { + const { container } = renderTreeSelect(); + const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement; + + selectOptions(container, ['0 label', '1 label']); + + // Try selecting third option, should be disabled + const option3 = within(dropdownList).getByText('2 label'); + fireEvent.click(option3); + expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); + + // Deselect first option + fireEvent.click(within(dropdownList).getByText('0 label')); + expect(within(dropdownList).queryByText('0 label')).toBeInTheDocument(); + + // Now should be able to select third option + fireEvent.click(option3); + expect(option3.closest('div')).not.toHaveClass('rc-tree-select-tree-treenode-disabled'); + }); + + it('should not trigger onChange when trying to select beyond maxCount', () => { + const handleChange = jest.fn(); + const { container } = renderTreeSelect({ onChange: handleChange }); + + selectOptions(container, ['0 label', '1 label']); + expect(handleChange).toHaveBeenCalledTimes(2); + + // Try selecting third option + const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement; + fireEvent.click(within(dropdownList).getByText('2 label')); + expect(handleChange).toHaveBeenCalledTimes(2); // Should not increase + }); + + it('should not affect deselection operations when maxCount is reached', () => { + const handleChange = jest.fn(); + const { container } = renderTreeSelect({ onChange: handleChange }); + + selectOptions(container, ['0 label', '1 label']); + expect(handleChange).toHaveBeenCalledTimes(2); + + // Deselect first option + const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement; + fireEvent.click(within(dropdownList).getByText('0 label')); + expect(handleChange).toHaveBeenCalledTimes(3); + + // Should be able to select third option + fireEvent.click(within(dropdownList).getByText('2 label')); + expect(handleChange).toHaveBeenCalledTimes(4); + }); + + it('should not allow any selection when maxCount is 0', () => { + const handleChange = jest.fn(); + const { container } = renderTreeSelect({ maxCount: 0, onChange: handleChange }); + + selectOptions(container, ['0 label', '1 label']); + expect(handleChange).not.toHaveBeenCalled(); + }); + + it('should not limit selection when maxCount is greater than number of options', () => { + const handleChange = jest.fn(); + const { container } = renderTreeSelect({ maxCount: 5, onChange: handleChange }); + + selectOptions(container, ['0 label', '1 label', '2 label', '3 label']); + expect(handleChange).toHaveBeenCalledTimes(4); + }); +}); + +describe('TreeSelect.maxCount keyboard operations', () => { + const treeData = [ + { key: '0', value: '0', title: '0 label' }, + { key: '1', value: '1', title: '1 label' }, + { key: '2', value: '2', title: '2 label' }, + ]; + + it('keyboard operations should not exceed maxCount limit', () => { + const onSelect = jest.fn(); + const { container } = render( + , + ); + + const input = container.querySelector('input'); + + keyDown(input, KeyCode.ENTER); + keyUp(input, KeyCode.ENTER); + + expect(onSelect).toHaveBeenCalledWith('0', expect.anything()); + + keyDown(input, KeyCode.DOWN); + keyDown(input, KeyCode.ENTER); + keyUp(input, KeyCode.ENTER); + + expect(onSelect).toHaveBeenCalledWith('1', expect.anything()); + + keyDown(input, KeyCode.DOWN); + keyDown(input, KeyCode.ENTER); + keyUp(input, KeyCode.ENTER); + + expect(onSelect).toHaveBeenCalledTimes(2); + }); + + it('when maxCount is reached, the option should be disabled', () => { + const { container } = render( + , + ); + + // verify that the third option is disabled + expect(container.querySelector('.rc-tree-select-tree-treenode-disabled')?.textContent).toBe( + '2 label', + ); + }); +}); diff --git a/tests/Select.multiple.spec.js b/tests/Select.multiple.spec.js index a91b95a3..5f2cebca 100644 --- a/tests/Select.multiple.spec.js +++ b/tests/Select.multiple.spec.js @@ -354,104 +354,4 @@ describe('TreeSelect.multiple', () => { expect(placeholder).toBeTruthy(); expect(placeholder.textContent).toBe('Fake placeholder'); }); - - describe('TreeSelect.maxCount', () => { - const treeData = [ - { key: '0', value: '0', title: '0 label' }, - { key: '1', value: '1', title: '1 label' }, - { key: '2', value: '2', title: '2 label' }, - { key: '3', value: '3', title: '3 label' }, - ]; - - const renderTreeSelect = props => { - return render(); - }; - - const selectOptions = (container, optionTexts) => { - const dropdownList = container.querySelector('.rc-tree-select-dropdown'); - optionTexts.forEach(text => { - fireEvent.click(within(dropdownList).getByText(text)); - }); - }; - - it('should disable unselected options when selection reaches maxCount', () => { - const { container } = renderTreeSelect(); - - selectOptions(container, ['0 label', '1 label']); - - // Check if third and fourth options are disabled - const dropdownList = container.querySelector('.rc-tree-select-dropdown'); - const option3 = within(dropdownList).getByText('2 label'); - const option4 = within(dropdownList).getByText('3 label'); - - expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); - expect(option4.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); - }); - - it('should allow deselecting options after reaching maxCount', () => { - const { container } = renderTreeSelect(); - const dropdownList = container.querySelector('.rc-tree-select-dropdown'); - - selectOptions(container, ['0 label', '1 label']); - - // Try selecting third option, should be disabled - const option3 = within(dropdownList).getByText('2 label'); - fireEvent.click(option3); - expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled'); - - // Deselect first option - fireEvent.click(within(dropdownList).getByText('0 label')); - expect(within(dropdownList).queryByText('0 label')).toBeInTheDocument(); - - // Now should be able to select third option - fireEvent.click(option3); - expect(option3.closest('div')).not.toHaveClass('rc-tree-select-tree-treenode-disabled'); - }); - - it('should not trigger onChange when trying to select beyond maxCount', () => { - const handleChange = jest.fn(); - const { container } = renderTreeSelect({ onChange: handleChange }); - - selectOptions(container, ['0 label', '1 label']); - expect(handleChange).toHaveBeenCalledTimes(2); - - // Try selecting third option - const dropdownList = container.querySelector('.rc-tree-select-dropdown'); - fireEvent.click(within(dropdownList).getByText('2 label')); - expect(handleChange).toHaveBeenCalledTimes(2); // Should not increase - }); - - it('should not affect deselection operations when maxCount is reached', () => { - const handleChange = jest.fn(); - const { container } = renderTreeSelect({ onChange: handleChange }); - - selectOptions(container, ['0 label', '1 label']); - expect(handleChange).toHaveBeenCalledTimes(2); - - // Deselect first option - const dropdownList = container.querySelector('.rc-tree-select-dropdown'); - fireEvent.click(within(dropdownList).getByText('0 label')); - expect(handleChange).toHaveBeenCalledTimes(3); - - // Should be able to select third option - fireEvent.click(within(dropdownList).getByText('2 label')); - expect(handleChange).toHaveBeenCalledTimes(4); - }); - - it('should not allow any selection when maxCount is 0', () => { - const handleChange = jest.fn(); - const { container } = renderTreeSelect({ maxCount: 0, onChange: handleChange }); - - selectOptions(container, ['0 label', '1 label']); - expect(handleChange).not.toHaveBeenCalled(); - }); - - it('should not limit selection when maxCount is greater than number of options', () => { - const handleChange = jest.fn(); - const { container } = renderTreeSelect({ maxCount: 5, onChange: handleChange }); - - selectOptions(container, ['0 label', '1 label', '2 label', '3 label']); - expect(handleChange).toHaveBeenCalledTimes(4); - }); - }); }); diff --git a/tests/util.tsx b/tests/util.tsx index d9f7123d..0f25ca97 100644 --- a/tests/util.tsx +++ b/tests/util.tsx @@ -1,6 +1,16 @@ -import { fireEvent } from '@testing-library/react'; +import { fireEvent, createEvent } from '@testing-library/react'; export function selectNode(index = 0) { const treeNode = document.querySelectorAll('.rc-tree-select-tree-node-content-wrapper')[index]; fireEvent.click(treeNode); } + +export function keyDown(element: HTMLElement, keyCode: number) { + const event = createEvent.keyDown(element, { keyCode }); + fireEvent(element, event); +} + +export function keyUp(element: HTMLElement, keyCode: number) { + const event = createEvent.keyUp(element, { keyCode }); + fireEvent(element, event); +}