Skip to content

Commit

Permalink
test: add test cases for keyboard operations
Browse files Browse the repository at this point in the history
  • Loading branch information
aojunhao123 committed Nov 11, 2024
1 parent 751e850 commit cc3b839
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 103 deletions.
15 changes: 13 additions & 2 deletions examples/mutiple-with-maxCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,31 @@ export default () => {
multiple
maxCount={3}
treeData={treeData}
onChange={onChange}
value={value}
// onChange={onChange}
// value={value}
/>

<h2>checkable with maxCount</h2>
<TreeSelect
style={{ width: 300 }}
multiple
treeCheckable
treeCheckStrictly
maxCount={3}
treeData={treeData}
onChange={onChange}
value={value}
/>
<TreeSelect
style={{ width: 300 }}
treeData={[
{ key: '0', value: '0', title: '0 label' },
{ key: '1', value: '1', title: '1 label' },
{ key: '2', value: '2', title: '2 label' },
]}
multiple
maxCount={2}
/>
</>
);
};
157 changes: 157 additions & 0 deletions tests/Select.maxCount.spec.tsx
Original file line number Diff line number Diff line change
@@ -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(<TreeSelect multiple maxCount={2} treeData={treeData} open {...props} />);
};

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(
<TreeSelect treeData={treeData} multiple open maxCount={2} onSelect={onSelect} />,
);

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(
<TreeSelect
treeData={treeData}
multiple
open
treeDefaultExpandAll
maxCount={2}
value={['0', '1']}
/>,
);

// verify that the third option is disabled
expect(container.querySelector('.rc-tree-select-tree-treenode-disabled')?.textContent).toBe(
'2 label',
);
});
});
100 changes: 0 additions & 100 deletions tests/Select.multiple.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<TreeSelect multiple maxCount={2} treeData={treeData} open {...props} />);
};

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);
});
});
});
12 changes: 11 additions & 1 deletion tests/util.tsx
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit cc3b839

Please sign in to comment.