You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
651 lines
18 KiB
651 lines
18 KiB
import { mount } from '@vue/test-utils';
|
|
import { asyncExpect, sleep } from '../../../tests/utils';
|
|
import Table from '..';
|
|
jest.mock('../../_util/Portal');
|
|
describe('Table.rowSelection', () => {
|
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
|
|
afterEach(() => {
|
|
errorSpy.mockReset();
|
|
document.body.innerHTML = '';
|
|
});
|
|
|
|
afterAll(() => {
|
|
errorSpy.mockRestore();
|
|
});
|
|
const columns = [
|
|
{
|
|
title: 'Name',
|
|
dataIndex: 'name',
|
|
},
|
|
];
|
|
|
|
const data = [
|
|
{ key: 0, name: 'Jack' },
|
|
{ key: 1, name: 'Lucy' },
|
|
{ key: 2, name: 'Tom' },
|
|
{ key: 3, name: 'Jerry' },
|
|
];
|
|
function getTableOptions(props = {}) {
|
|
return {
|
|
props: {
|
|
columns,
|
|
dataSource: data,
|
|
rowSelection: {},
|
|
...props,
|
|
},
|
|
sync: false,
|
|
attachedToDocument: true,
|
|
};
|
|
}
|
|
function renderedNames(wrapper) {
|
|
return wrapper.findAllComponents({ name: 'BodyRow' }).map(row => {
|
|
return row.props().record.name;
|
|
});
|
|
}
|
|
|
|
function getSelections(wrapper) {
|
|
return [...wrapper.vm.table.selectedKeySet].sort();
|
|
}
|
|
|
|
xit('select by checkbox', async () => {
|
|
const wrapper = mount(Table, getTableOptions());
|
|
const checkboxes = wrapper.findAll('input');
|
|
const checkboxAll = checkboxes[0];
|
|
checkboxAll.element.checked = true;
|
|
checkboxAll.trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([0, 1, 2, 3]);
|
|
});
|
|
checkboxes[1].element.checked = false;
|
|
checkboxes[1].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([1, 2, 3]);
|
|
});
|
|
checkboxes[1].element.checked = true;
|
|
checkboxes[1].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([0, 1, 2, 3]);
|
|
});
|
|
});
|
|
|
|
xit('select by radio', async () => {
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection: { type: 'radio' } }));
|
|
const radios = wrapper.findAll('input');
|
|
|
|
expect(radios.length).toBe(4);
|
|
radios[0].element.checked = true;
|
|
radios[0].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([0]);
|
|
});
|
|
radios[radios.length - 1].element.checked = true;
|
|
radios[radios.length - 1].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([3]);
|
|
});
|
|
});
|
|
|
|
it('pass getCheckboxProps to checkbox', async () => {
|
|
const rowSelection = {
|
|
getCheckboxProps: record => ({
|
|
disabled: record.name === 'Lucy',
|
|
name: record.name,
|
|
}),
|
|
};
|
|
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const checkboxes = wrapper.findAll('input');
|
|
await sleep();
|
|
expect(checkboxes[1].wrapperElement.disabled).toBe(false);
|
|
expect(checkboxes[1].wrapperElement.name).toEqual(data[0].name);
|
|
expect(checkboxes[2].wrapperElement.disabled).toBe(true);
|
|
expect(checkboxes[2].wrapperElement.name).toEqual(data[1].name);
|
|
});
|
|
|
|
it('works with pagination', async () => {
|
|
const wrapper = mount(Table, getTableOptions({ pagination: { pageSize: 2 } }));
|
|
|
|
await sleep();
|
|
const checkboxAll = wrapper.find('input');
|
|
checkboxAll.wrapperElement.checked = true;
|
|
checkboxAll.trigger('change');
|
|
const pagers = wrapper.findAllComponents({ name: 'Pager' });
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findComponent({ name: 'ACheckbox' }).props()).toEqual(
|
|
expect.objectContaining({ checked: true, indeterminate: false }),
|
|
);
|
|
});
|
|
pagers[1].trigger('click');
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findComponent({ name: 'ACheckbox' }).props()).toEqual(
|
|
expect.objectContaining({ checked: false, indeterminate: false }),
|
|
);
|
|
});
|
|
pagers[0].trigger('click');
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findComponent({ name: 'ACheckbox' }).props()).toEqual(
|
|
expect.objectContaining({ checked: true, indeterminate: false }),
|
|
);
|
|
});
|
|
});
|
|
|
|
// https://github.com/ant-design/ant-design/issues/4020
|
|
it('handles defaultChecked', async () => {
|
|
const rowSelection = {
|
|
getCheckboxProps: record => {
|
|
return {
|
|
defaultChecked: record.key === 0,
|
|
};
|
|
},
|
|
};
|
|
|
|
mount(Table, getTableOptions({ rowSelection }));
|
|
|
|
expect(errorSpy).toHaveBeenCalledWith(
|
|
'Warning: [ant-design-vue: Table] Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.',
|
|
);
|
|
});
|
|
|
|
xit('can be controlled', async () => {
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection: { selectedRowKeys: [0] } }));
|
|
|
|
expect(getSelections(wrapper)).toEqual([0]);
|
|
|
|
wrapper.setProps({ rowSelection: { selectedRowKeys: [1] } });
|
|
await asyncExpect(() => {
|
|
expect(getSelections(wrapper)).toEqual([1]);
|
|
});
|
|
});
|
|
|
|
it('fires change & select events', async () => {
|
|
const handleChange = jest.fn();
|
|
const handleSelect = jest.fn();
|
|
const rowSelection = {
|
|
onChange: handleChange,
|
|
onSelect: handleSelect,
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const checkboxs = wrapper.findAll('input');
|
|
checkboxs[checkboxs.length - 1].element.checked = true;
|
|
checkboxs[checkboxs.length - 1].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(handleChange).toBeCalledWith([3], [{ key: 3, name: 'Jerry' }]);
|
|
expect(handleSelect.mock.calls.length).toBe(1);
|
|
expect(handleSelect.mock.calls[0][0]).toEqual({ key: 3, name: 'Jerry' });
|
|
expect(handleSelect.mock.calls[0][1]).toEqual(true);
|
|
expect(handleSelect.mock.calls[0][2]).toEqual([{ key: 3, name: 'Jerry' }]);
|
|
});
|
|
});
|
|
|
|
it('fires selectAll event', async () => {
|
|
const handleSelectAll = jest.fn();
|
|
const rowSelection = {
|
|
onSelectAll: handleSelectAll,
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const checkboxs = wrapper.findAll('input');
|
|
checkboxs[0].element.checked = true;
|
|
checkboxs[0].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(handleSelectAll).toBeCalledWith(true, data, data);
|
|
});
|
|
checkboxs[0].element.checked = false;
|
|
checkboxs[0].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(handleSelectAll).toBeCalledWith(false, [], data);
|
|
});
|
|
});
|
|
|
|
it('render with default selection correctly', async () => {
|
|
const rowSelection = {
|
|
selections: true,
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
await asyncExpect(() => {
|
|
expect(dropdownWrapper.html()).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
it('click select all selection', () => {
|
|
const handleChange = jest.fn();
|
|
const rowSelection = {
|
|
onChange: handleChange,
|
|
selections: true,
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
dropdownWrapper.findAll('.ant-dropdown-menu-item')[0].trigger('click');
|
|
|
|
expect(handleChange.mock.calls[0][0]).toEqual([0, 1, 2, 3]);
|
|
});
|
|
|
|
it('fires selectInvert event', async () => {
|
|
const handleSelectInvert = jest.fn();
|
|
const rowSelection = {
|
|
onSelectInvert: handleSelectInvert,
|
|
selections: true,
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const checkboxes = wrapper.findAll('input');
|
|
checkboxes[1].element.checked = true;
|
|
checkboxes[1].trigger('change');
|
|
await sleep();
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
const div = dropdownWrapper.findAll('li.ant-dropdown-menu-item');
|
|
div[1].trigger('click');
|
|
|
|
expect(handleSelectInvert).toBeCalledWith([1, 2, 3]);
|
|
});
|
|
|
|
it('fires selection event', async () => {
|
|
const handleSelectOdd = jest.fn();
|
|
const handleSelectEven = jest.fn();
|
|
const rowSelection = {
|
|
selections: [
|
|
Table.SELECTION_ALL,
|
|
Table.SELECTION_INVERT,
|
|
{
|
|
key: 'odd',
|
|
text: '奇数项',
|
|
onSelect: handleSelectOdd,
|
|
},
|
|
{
|
|
key: 'even',
|
|
text: '偶数项',
|
|
onSelect: handleSelectEven,
|
|
},
|
|
],
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
await sleep();
|
|
expect(dropdownWrapper.findAll('.ant-dropdown-menu-item').length).toBe(4);
|
|
|
|
dropdownWrapper.findAll('.ant-dropdown-menu-item')[2].trigger('click');
|
|
expect(handleSelectOdd).toBeCalledWith([0, 1, 2, 3]);
|
|
|
|
dropdownWrapper.findAll('.ant-dropdown-menu-item')[3].trigger('click');
|
|
expect(handleSelectEven).toBeCalledWith([0, 1, 2, 3]);
|
|
});
|
|
|
|
it('could hide default selection options', () => {
|
|
const rowSelection = {
|
|
hideDefaultSelections: true,
|
|
selections: [
|
|
{
|
|
key: 'odd',
|
|
text: '奇数项',
|
|
},
|
|
{
|
|
key: 'even',
|
|
text: '偶数项',
|
|
},
|
|
],
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
expect(dropdownWrapper.findAll('.ant-dropdown-menu-item').length).toBe(2);
|
|
});
|
|
|
|
it('handle custom selection onSelect correctly when hide default selection options', () => {
|
|
const handleSelectOdd = jest.fn();
|
|
const handleSelectEven = jest.fn();
|
|
const rowSelection = {
|
|
hideDefaultSelections: true,
|
|
selections: [
|
|
{
|
|
key: 'odd',
|
|
text: '奇数项',
|
|
onSelect: handleSelectOdd,
|
|
},
|
|
{
|
|
key: 'even',
|
|
text: '偶数项',
|
|
onSelect: handleSelectEven,
|
|
},
|
|
],
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
expect(dropdownWrapper.findAll('.ant-dropdown-menu-item').length).toBe(2);
|
|
|
|
dropdownWrapper.findAll('.ant-dropdown-menu-item')[0].trigger('click');
|
|
expect(handleSelectOdd).toBeCalledWith([0, 1, 2, 3]);
|
|
|
|
dropdownWrapper.findAll('.ant-dropdown-menu-item')[1].trigger('click');
|
|
expect(handleSelectEven).toBeCalledWith([0, 1, 2, 3]);
|
|
});
|
|
|
|
// https:// github.com/ant-design/ant-design/issues/4245
|
|
it('handles disabled checkbox correctly when dataSource changes', async () => {
|
|
const rowSelection = {
|
|
getCheckboxProps: record => {
|
|
return { disabled: record.disabled };
|
|
},
|
|
};
|
|
const wrapper = mount(Table, getTableOptions({ rowSelection }));
|
|
const newData = [
|
|
{ key: 7, name: 'Jack', disabled: true },
|
|
{ key: 8, name: 'Lucy', disabled: true },
|
|
];
|
|
await asyncExpect(() => {
|
|
wrapper.setProps({ dataSource: newData });
|
|
});
|
|
await asyncExpect(() => {
|
|
wrapper.findAll('input').forEach(checkbox => {
|
|
expect(checkbox.wrapperElement.disabled).toBe(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
// https://github.com/ant-design/ant-design/issues/4779
|
|
it('should not switch pagination when select record', async () => {
|
|
const newData = [];
|
|
for (let i = 0; i < 20; i += 1) {
|
|
newData.push({
|
|
key: i.toString(),
|
|
name: i.toString(),
|
|
});
|
|
}
|
|
const wrapper = mount(
|
|
Table,
|
|
getTableOptions({
|
|
rowSelection: {},
|
|
dataSource: newData,
|
|
}),
|
|
);
|
|
await sleep();
|
|
const pager = wrapper.findAllComponents({ name: 'Pager' });
|
|
pager[pager.length - 1].trigger('click'); // switch to second page
|
|
wrapper.findAll('input')[0].element.checked = true;
|
|
wrapper.findAll('input')[0].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(renderedNames(wrapper)).toEqual([
|
|
'10',
|
|
'11',
|
|
'12',
|
|
'13',
|
|
'14',
|
|
'15',
|
|
'16',
|
|
'17',
|
|
'18',
|
|
'19',
|
|
]);
|
|
});
|
|
});
|
|
|
|
it('highlight selected row', async () => {
|
|
const wrapper = mount(Table, getTableOptions());
|
|
wrapper.findAll('input')[1].element.checked = true;
|
|
wrapper.findAll('input')[1].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAll('tbody tr')[0].classes()).toContain('ant-table-row-selected');
|
|
});
|
|
});
|
|
|
|
it('fix selection column on the left', async () => {
|
|
const wrapper = mount(
|
|
Table,
|
|
getTableOptions({
|
|
rowSelection: { fixed: true },
|
|
}),
|
|
);
|
|
await asyncExpect(() => {
|
|
expect(wrapper.html()).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
// https://github.com/ant-design/ant-design/issues/10629
|
|
it('should keep all checked state when remove item from dataSource', async () => {
|
|
const wrapper = mount(Table, {
|
|
props: {
|
|
columns,
|
|
dataSource: data,
|
|
rowSelection: {
|
|
selectedRowKeys: [0, 1, 2, 3],
|
|
},
|
|
},
|
|
sync: false,
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAllComponents({ name: 'ACheckbox' }).length).toBe(5);
|
|
const allCheckbox = wrapper.findAllComponents({ name: 'ACheckbox' });
|
|
Array(allCheckbox.length).forEach((_, index) => {
|
|
const checkbox = allCheckbox[index];
|
|
expect(checkbox.vm.checked).toBe(true);
|
|
expect(checkbox.vm.indeterminate).toBe(false);
|
|
});
|
|
wrapper.setProps({
|
|
dataSource: data.slice(1),
|
|
rowSelection: {
|
|
selectedRowKeys: [1, 2, 3],
|
|
},
|
|
});
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAllComponents({ name: 'ACheckbox' }).length).toBe(4);
|
|
const allCheckbox = wrapper.findAllComponents({ name: 'ACheckbox' });
|
|
Array(allCheckbox.length).forEach((_, index) => {
|
|
const checkbox = allCheckbox[index];
|
|
expect(checkbox.vm.checked).toBe(true);
|
|
expect(checkbox.vm.indeterminate).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
// https://github.com/ant-design/ant-design/issues/11042
|
|
it('add columnTitle for rowSelection', async () => {
|
|
const wrapper = mount(Table, {
|
|
props: {
|
|
columns,
|
|
dataSource: data,
|
|
rowSelection: {
|
|
columnTitle: '多选',
|
|
},
|
|
},
|
|
sync: false,
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAll('thead tr th')[0].text()).toBe('多选');
|
|
});
|
|
await asyncExpect(() => {
|
|
wrapper.setProps({
|
|
rowSelection: {
|
|
type: 'radio',
|
|
columnTitle: '单选',
|
|
},
|
|
});
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAll('thead tr th')[0].text()).toBe('单选');
|
|
});
|
|
});
|
|
|
|
// https://github.com/ant-design/ant-design/issues/11384
|
|
it('should keep item even if in filter', async () => {
|
|
const filterColumns = [
|
|
{
|
|
title: 'Name',
|
|
dataIndex: 'name',
|
|
filters: [
|
|
{
|
|
text: 'Jack',
|
|
value: 'Jack',
|
|
},
|
|
{
|
|
text: 'Lucy',
|
|
value: 'Lucy',
|
|
},
|
|
],
|
|
filterDropdownOpen: true,
|
|
onFilter: (value, record) => record.name.indexOf(value) === 0,
|
|
},
|
|
];
|
|
|
|
const onChange = jest.fn();
|
|
const rowSelection = {
|
|
onChange,
|
|
};
|
|
|
|
const wrapper = mount(Table, {
|
|
props: {
|
|
columns: filterColumns,
|
|
dataSource: data,
|
|
rowSelection,
|
|
},
|
|
sync: false,
|
|
});
|
|
|
|
const dropdownWrapper = mount(
|
|
{
|
|
render() {
|
|
return wrapper.findComponent({ name: 'Trigger' }).vm.getComponent();
|
|
},
|
|
},
|
|
{ sync: false },
|
|
);
|
|
await sleep();
|
|
function clickFilter(indexList) {
|
|
indexList.forEach(index => {
|
|
dropdownWrapper
|
|
.findAll('.ant-dropdown-menu-item .ant-checkbox-wrapper')
|
|
[index].trigger('click');
|
|
});
|
|
dropdownWrapper.find('.ant-table-filter-dropdown-btns .ant-btn-primary').trigger('click');
|
|
}
|
|
|
|
function clickItem() {
|
|
wrapper.findAll(
|
|
'tbody .ant-table-selection-column .ant-checkbox-input',
|
|
)[0].element.checked = true;
|
|
wrapper.findAll('tbody .ant-table-selection-column .ant-checkbox-input')[0].trigger('change');
|
|
}
|
|
|
|
// Check Jack
|
|
clickFilter([0]);
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAll('tbody tr').length).toBe(1);
|
|
});
|
|
await asyncExpect(() => {
|
|
clickItem();
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(onChange.mock.calls[0][0].length).toBe(1);
|
|
expect(onChange.mock.calls[0][1].length).toBe(1);
|
|
});
|
|
|
|
// Check Lucy
|
|
clickFilter([0]);
|
|
await sleep();
|
|
clickFilter([1]);
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findAll('tbody tr').length).toBe(1);
|
|
});
|
|
await asyncExpect(() => {
|
|
clickItem();
|
|
});
|
|
await asyncExpect(() => {
|
|
expect(onChange.mock.calls[1][0].length).toBe(2);
|
|
expect(onChange.mock.calls[1][1].length).toBe(2);
|
|
});
|
|
});
|
|
|
|
it('render correctly when set childrenColumnName', async () => {
|
|
const newDatas = [
|
|
{
|
|
key: 1,
|
|
name: 'Jack',
|
|
children: [
|
|
{
|
|
key: 11,
|
|
name: 'John Brown',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 2,
|
|
name: 'Lucy',
|
|
children: [
|
|
{
|
|
key: 21,
|
|
name: 'Lucy Brown',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const wrapper = mount(Table, {
|
|
props: {
|
|
columns,
|
|
dataSource: newDatas,
|
|
rowSelection: {},
|
|
childrenColumnName: 'test',
|
|
},
|
|
sync: false,
|
|
});
|
|
|
|
const checkboxes = wrapper.findAll('input');
|
|
checkboxes[1].element.checked = true;
|
|
checkboxes[1].trigger('change');
|
|
await sleep();
|
|
expect(wrapper.findComponent({ name: 'ACheckbox' }).props()).toEqual(
|
|
expect.objectContaining({ checked: false, indeterminate: true }),
|
|
);
|
|
checkboxes[2].element.checked = true;
|
|
checkboxes[2].trigger('change');
|
|
await asyncExpect(() => {
|
|
expect(wrapper.findComponent({ name: 'ACheckbox' }).props()).toEqual(
|
|
expect.objectContaining({ checked: true, indeterminate: false }),
|
|
);
|
|
});
|
|
});
|
|
});
|