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`] = `
+
+`;
+
+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 () {