diff --git a/components/table/__tests__/Table.filter.test.js b/components/table/__tests__/Table.filter.test.js new file mode 100644 index 000000000..85623688a --- /dev/null +++ b/components/table/__tests__/Table.filter.test.js @@ -0,0 +1,336 @@ +import Vue from 'vue' +import { mount, render } from '@vue/test-utils' +import Table from '..' + +describe('Table.filter', () => { + const filterFn = (value, record) => record.name.indexOf(value) !== -1 + const column = { + title: 'Name', + dataIndex: 'name', + filters: [ + { text: 'Boy', value: 'boy' }, + { text: 'Girl', value: 'girl' }, + { + text: 'Title', + value: 'title', + children: [ + { text: 'Designer', value: 'designer' }, + { text: 'Coder', value: 'coder' }, + ], + }, + ], + onFilter: filterFn, + } + + const data = [ + { key: 0, name: 'Jack' }, + { key: 1, name: 'Lucy' }, + { key: 2, name: 'Tom' }, + { key: 3, name: 'Jerry' }, + ] + + function getTableOptions (props = {}, listeners = {}) { + return { + propsData: { + columns: [column], + dataSource: data, + pagination: false, + ...props, + }, + listeners: { + ...listeners, + }, + sync: false, + } + } + + function renderedNames (wrapper) { + return wrapper.findAll({ name: 'TableRow' }).wrappers.map(row => { + return row.props().record.name + }) + } + + it('renders filter correctly', (done) => { + const wrapper = mount(Table, getTableOptions()) + Vue.nextTick(() => { + expect(wrapper.html()).toMatchSnapshot() + done() + }) + }) + + it('renders menu correctly', (done) => { + const wrapper = mount(Table, getTableOptions()) + Vue.nextTick(() => { + const dropdownWrapper = wrapper.find({ name: 'Trigger' }).vm.renderComponent() + expect(dropdownWrapper.$el.outerHTML).toMatchSnapshot() + done() + }) + }) + + it('renders radio filter correctly', (done) => { + const wrapper = mount(Table, getTableOptions({ + columns: [{ + ...column, + filterMultiple: false, + }], + })) + Vue.nextTick(() => { + const dropdownWrapper = wrapper.find({ name: 'Trigger' }).vm.renderComponent() + expect(dropdownWrapper.$el.outerHTML).toMatchSnapshot() + done() + }) + }) + + it('renders custom content correctly', (done) => { + const wrapper = mount(Table, { + ...getTableOptions({ + columns: [{ + ...column, + slots: { + filterDropdown: 'filterDropdown', + }, + }], + }), + slots: { + filterDropdown: `
custom filter
`, + }, + }) + + Vue.nextTick(() => { + const dropdownWrapper = wrapper.find({ name: 'Trigger' }).vm.renderComponent() + expect(dropdownWrapper.$el.outerHTML).toMatchSnapshot() + done() + }) + }) + // TODO + // it('can be controlled by filterDropdownVisible', () => { + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // filterDropdownVisible: true, + // }], + // })) + + // let dropdown = wrapper.find('Dropdown').at(0) + // expect(dropdown.props().visible).toBe(true) + + // wrapper.setProps({ + // columns: [{ + // ...column, + // filterDropdownVisible: false, + // }], + // }) + + // dropdown = wrapper.find('Dropdown').at(0) + // expect(dropdown.props().visible).toBe(false) + // }) + + // it('fires change event when visible change', () => { + // const handleChange = jest.fn() + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // onFilterDropdownVisibleChange: handleChange, + // }], + // })) + + // wrapper.find('.ant-dropdown-trigger').at(0).trigger('click') + + // expect(handleChange).toBeCalledWith(true) + // }) + + // it('can be controlled by filteredValue', () => { + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // filteredValue: ['Lucy'], + // }], + // })) + + // expect(wrapper.find('tbody tr').length).toBe(1) + // wrapper.setProps({ + // columns: [{ + // ...column, + // filteredValue: [], + // }], + // }) + // expect(wrapper.find('tbody tr').length).toBe(4) + // }) + + // it('can be controlled by filteredValue null', () => { + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // filteredValue: ['Lucy'], + // }], + // })) + + // expect(wrapper.find('tbody tr').length).toBe(1) + // wrapper.setProps({ + // columns: [{ + // ...column, + // filteredValue: null, + // }], + // }) + // expect(wrapper.find('tbody tr').length).toBe(4) + // }) + + // it('fires change event', () => { + // const handleChange = jest.fn() + // const wrapper = mount(Table, getTableOptions({ onChange: handleChange })) + // const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent()) + + // dropdownWrapper.find('MenuItem').at(0).trigger('click') + // dropdownWrapper.find('.confirm').trigger('click') + + // expect(handleChange).toBeCalledWith({}, { name: ['boy'] }, {}) + // }) + + // it('three levels menu', () => { + // const filters = [ + // { text: 'Upper', value: 'Upper' }, + // { text: 'Lower', value: 'Lower' }, + // { + // text: 'Level2', + // value: 'Level2', + // children: [ + // { text: 'Large', value: 'Large' }, + // { text: 'Small', value: 'Small' }, + // { + // text: 'Level3', + // value: 'Level3', + // children: [ + // { text: 'Black', value: 'Black' }, + // { text: 'White', value: 'White' }, + // { text: 'Jack', value: 'Jack' }, + // ], + // }, + // ], + // }, + // ] + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // filters, + // }], + // })) + // jest.useFakeTimers() + // const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent()) + // dropdownWrapper.find('.ant-dropdown-menu-submenu-title').at(0).trigger('mouseEnter') + // jest.runAllTimers() + // dropdownWrapper.update() + // dropdownWrapper.find('.ant-dropdown-menu-submenu-title').at(1).trigger('mouseEnter') + // jest.runAllTimers() + // dropdownWrapper.update() + // dropdownWrapper.find('MenuItem').last().trigger('click') + // dropdownWrapper.find('.confirm').trigger('click') + // wrapper.update() + // expect(renderedNames(wrapper)).toEqual(['Jack']) + // jest.useRealTimers() + // }) + + // it('works with JSX in controlled mode', () => { + // const { Column } = Table + + // const App = { + // data () { + // return { + // filters: {}, + // } + // }, + // methods: { + // handleChange (pagination, filters) { + // this.setState({ filters }) + // }, + // }, + // render () { + // return ( + // + // + //
+ // ) + // }, + // } + + // const wrapper = mount(App) + // const dropdownWrapper = mount(wrapper.find('Trigger').instance().getComponent()) + + // dropdownWrapper.find('MenuItem').at(0).trigger('click') + // dropdownWrapper.find('.confirm').trigger('click') + // wrapper.update() + // expect(renderedNames(wrapper)).toEqual(['Jack']) + + // dropdownWrapper.find('.clear').trigger('click') + // wrapper.update() + // expect(renderedNames(wrapper)).toEqual(['Jack', 'Lucy', 'Tom', 'Jerry']) + // }) + + // it('works with grouping columns in controlled mode', () => { + // const columns = [ + // { + // title: 'group', + // key: 'group', + // children: [ + // { + // title: 'Name', + // dataIndex: 'name', + // key: 'name', + // filters: [ + // { text: 'Jack', value: 'Jack' }, + // { text: 'Lucy', value: 'Lucy' }, + // ], + // onFilter: filterFn, + // filteredValue: ['Jack'], + // }, + // { + // title: 'Age', + // dataIndex: 'age', + // key: 'age', + // }, + // ], + // }, + // ] + // const testData = [ + // { key: 0, name: 'Jack', age: 11 }, + // { key: 1, name: 'Lucy', age: 20 }, + // { key: 2, name: 'Tom', age: 21 }, + // { key: 3, name: 'Jerry', age: 22 }, + // ] + // const wrapper = mount(Table, { + // columns, + // dataSource: testData, + // }) + + // expect(renderedNames(wrapper)).toEqual(['Jack']) + // }) + + // it('confirm filter when dropdown hidden', () => { + // const handleChange = jest.fn() + // const wrapper = mount(Table, getTableOptions({ + // columns: [{ + // ...column, + // filters: [ + // { text: 'Jack', value: 'Jack' }, + // { text: 'Lucy', value: 'Lucy' }, + // ], + // }], + + // }, { change: handleChange })) + + // wrapper.findAll('.ant-dropdown-trigger').at(0).trigger('click') + // wrapper.findAll('.ant-dropdown-menu-item').at(0).trigger('click') + // wrapper.findAll('.ant-dropdown-trigger').at(0).trigger('click') + + // expect(handleChange).toBeCalled() + // }) +}) diff --git a/components/table/__tests__/Table.pagination.test.js b/components/table/__tests__/Table.pagination.test.js index 3cba75858..961e0d37d 100644 --- a/components/table/__tests__/Table.pagination.test.js +++ b/components/table/__tests__/Table.pagination.test.js @@ -31,15 +31,6 @@ describe('Table.pagination', () => { }, sync: false, } - // return { - // render () { - // return ( - // - // ) - // }, - // } } function renderedNames (wrapper) { diff --git a/components/table/__tests__/Table.sorter.test.js b/components/table/__tests__/Table.sorter.test.js new file mode 100644 index 000000000..e018e0aa4 --- /dev/null +++ b/components/table/__tests__/Table.sorter.test.js @@ -0,0 +1,153 @@ +import Vue from 'vue' +import { mount } from '@vue/test-utils' +import Table from '..' + +describe('Table.sorter', () => { + const sorterFn = (a, b) => a.name[0].charCodeAt() - b.name[0].charCodeAt() + + const column = { + title: 'Name', + dataIndex: 'name', + sorter: sorterFn, + } + + const data = [ + { key: 0, name: 'Jack' }, + { key: 1, name: 'Lucy' }, + { key: 2, name: 'Tom' }, + { key: 3, name: 'Jerry' }, + ] + + function getTableOptions (props = {}, columnProps = {}, listeners = {}) { + return { + propsData: { + columns: [{ + ...column, + ...columnProps, + }], + dataSource: data, + pagination: false, + ...props, + }, + listeners: { + ...listeners, + }, + sync: false, + attachedToDocument: true, + } + } + + function renderedNames (wrapper) { + return wrapper.findAll({ name: 'TableRow' }).wrappers.map(row => { + return row.props().record.name + }) + } + + it('renders sorter icon correctly', (done) => { + const wrapper = mount(Table, getTableOptions()) + Vue.nextTick(() => { + expect(wrapper.find('thead').html()).toMatchSnapshot() + done() + }) + }) + + it('default sort order ascend', (done) => { + const wrapper = mount(Table, getTableOptions({}, { + defaultSortOrder: 'ascend', + })) + Vue.nextTick(() => { + expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']) + done() + }) + }) + + it('default sort order descend', (done) => { + const wrapper = mount(Table, getTableOptions({}, { + defaultSortOrder: 'descend', + })) + Vue.nextTick(() => { + expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']) + done() + }) + }) + + it('sort records', (done) => { + const wrapper = mount(Table, getTableOptions()) + Vue.nextTick(() => { + wrapper.find('.ant-table-column-sorter-up').trigger('click') + Vue.nextTick(() => { + // expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']) + expect(wrapper.find('.ant-table-tbody').text()).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom'].join('')) + wrapper.find('.ant-table-column-sorter-down').trigger('click') + Vue.nextTick(() => { + expect(wrapper.find('.ant-table-tbody').text()).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry'].join('')) + done() + }) + }) + }) + }) + + it('can be controlled by sortOrder', (done) => { + const wrapper = mount(Table, getTableOptions({ + columns: [{ ...column, sortOrder: 'ascend' }], + })) + Vue.nextTick(() => { + expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']) + done() + }) + }) + + it('fires change event', (done) => { + const handleChange = jest.fn() + const wrapper = mount(Table, getTableOptions({}, {}, { change: handleChange })) + + wrapper.find('.ant-table-column-sorter-up').trigger('click') + Vue.nextTick(() => { + const sorter = handleChange.mock.calls[0][2] + expect(sorter.column.dataIndex).toBe('name') + expect(sorter.order).toBe('ascend') + expect(sorter.field).toBe('name') + expect(sorter.columnKey).toBe('name') + done() + }) + }) + + it('works with grouping columns in controlled mode', (done) => { + const columns = [ + { + title: 'group', + key: 'group', + children: [ + { + title: 'Name', + dataIndex: 'name', + key: 'name', + sorter: sorterFn, + sortOrder: 'descend', + }, + { + title: 'Age', + dataIndex: 'age', + key: 'age', + }, + ], + }, + ] + const testData = [ + { key: 0, name: 'Jack', age: 11 }, + { key: 1, name: 'Lucy', age: 20 }, + { key: 2, name: 'Tom', age: 21 }, + { key: 3, name: 'Jerry', age: 22 }, + ] + const wrapper = mount(Table, { + propsData: { + columns, dataSource: testData, + }, + sync: false, + }) + Vue.nextTick(() => { + expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']) + done() + }) + }) +}) diff --git a/components/table/__tests__/__snapshots__/Table.filter.test.js.snap b/components/table/__tests__/__snapshots__/Table.filter.test.js.snap new file mode 100644 index 000000000..c5a051b35 --- /dev/null +++ b/components/table/__tests__/__snapshots__/Table.filter.test.js.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Table.filter renders custom content correctly 1`] = ` +
+ +
+`; + +exports[`Table.filter renders filter correctly 1`] = ` +
+ + + + + + + + + + + + + + + + +
Name
+ Jack
+ Lucy
+ Tom
+ Jerry
+ + + + + + +`; + +exports[`Table.filter renders menu correctly 1`] = ` +
+ +
+`; + +exports[`Table.filter renders radio filter correctly 1`] = ` +
+ +
+`; diff --git a/components/table/__tests__/__snapshots__/Table.sorter.test.js.snap b/components/table/__tests__/__snapshots__/Table.sorter.test.js.snap new file mode 100644 index 000000000..9ed59c735 --- /dev/null +++ b/components/table/__tests__/__snapshots__/Table.sorter.test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Table.sorter renders sorter icon correctly 1`] = ` + + + Name
+
+ + + +`; diff --git a/components/trigger/Trigger.jsx b/components/trigger/Trigger.jsx index 547411e7f..e21db9236 100644 --- a/components/trigger/Trigger.jsx +++ b/components/trigger/Trigger.jsx @@ -360,6 +360,7 @@ export default { } else { this._component.popupProps = popupProps } + return this._component }, getContainer () {