test: add table sorter & filter test

pull/165/head
tjz 2018-05-27 14:01:18 +08:00
parent 31155384a4
commit 4e60734212
6 changed files with 595 additions and 9 deletions

View File

@ -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: `<div class='custom-filter-dropdown'>custom filter</div>`,
},
})
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 (
// <Table dataSource={data} onChange={this.handleChange}>
// <Column
// title='name'
// dataIndex='name'
// key='name'
// filters={[
// { text: 'Jack', value: 'Jack' },
// { text: 'Lucy', value: 'Lucy' },
// ]}
// filteredValue={this.state.filters.name}
// onFilter={filterFn}
// />
// </Table>
// )
// },
// }
// 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()
// })
})

View File

@ -31,15 +31,6 @@ describe('Table.pagination', () => {
},
sync: false,
}
// return {
// render () {
// return (
// <Table
// {...tableProps}
// />
// )
// },
// }
}
function renderedNames (wrapper) {

View File

@ -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()
})
})
})

View File

@ -0,0 +1,94 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Table.filter renders custom content correctly 1`] = `
<div>
<div class="ant-dropdown ant-dropdown-placement-bottomLeft" style="display: none;">
<div class="ant-dropdown-content">
<div class="custom-filter-dropdown">custom filter</div>
</div>
</div>
</div>
`;
exports[`Table.filter renders filter correctly 1`] = `
<div class="ant-table-wrapper"><span tag="div" class="ant-spin-nested-loading"><div class="ant-spin-container"><div class="ant-table ant-table-scroll-position-left ant-table-large"><div class="ant-table-content"><!----><div class="ant-table-body"><table class=""><colgroup><col></colgroup><thead class="ant-table-thead"><tr><th key="name" class="ant-table-column-has-filters"><span>Name<i title="Filter menu" class="anticon anticon-filter ant-dropdown-trigger"></i></span></th>
</tr>
</thead>
<tbody class="ant-table-tbody">
<tr class="ant-table-row ant-table-row-level-0">
<td class="ant-table-column-has-filters"><span class="ant-table-row-indent indent-level-0" style="padding-left: 0px;"></span>
<!---->Jack</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0">
<td class="ant-table-column-has-filters"><span class="ant-table-row-indent indent-level-0" style="padding-left: 0px;"></span>
<!---->Lucy</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0">
<td class="ant-table-column-has-filters"><span class="ant-table-row-indent indent-level-0" style="padding-left: 0px;"></span>
<!---->Tom</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0">
<td class="ant-table-column-has-filters"><span class="ant-table-row-indent indent-level-0" style="padding-left: 0px;"></span>
<!---->Jerry</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</span>
</div>
`;
exports[`Table.filter renders menu correctly 1`] = `
<div>
<div class="ant-dropdown ant-dropdown-placement-bottomLeft" style="display: none;">
<div class="ant-table-filter-dropdown ant-dropdown-content">
<ul class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical" role="menu" aria-activedescendant="" tabindex="0">
<li role="menuitem" class="ant-dropdown-menu-item">
<label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
</label><span>Boy</span></li>
<li role="menuitem" class="ant-dropdown-menu-item">
<label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
</label><span>Girl</span></li>
<li class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical">
<div aria-owns="title$Menu" aria-haspopup="true" title="Title" class="ant-dropdown-menu-submenu-title">Title
<i class="ant-dropdown-menu-submenu-arrow"></i>
</div>
</li>
</ul>
<div class="ant-table-filter-dropdown-btns">
<a class="ant-table-filter-dropdown-link confirm">OK</a>
<a class="ant-table-filter-dropdown-link clear">Reset</a>
</div>
</div>
</div>
</div>
`;
exports[`Table.filter renders radio filter correctly 1`] = `
<div>
<div class="ant-dropdown ant-dropdown-placement-bottomLeft" style="display: none;">
<div class="ant-table-filter-dropdown ant-dropdown-content">
<ul class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical" role="menu" aria-activedescendant="" tabindex="0">
<li role="menuitem" class="ant-dropdown-menu-item">
<label class="ant-radio-wrapper"><span class="ant-radio"><input type="radio" class="ant-radio-input"><span class="ant-radio-inner"></span></span>
</label><span>Boy</span></li>
<li role="menuitem" class="ant-dropdown-menu-item">
<label class="ant-radio-wrapper"><span class="ant-radio"><input type="radio" class="ant-radio-input"><span class="ant-radio-inner"></span></span>
</label><span>Girl</span></li>
<li class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical">
<div aria-owns="title$Menu" aria-haspopup="true" title="Title" class="ant-dropdown-menu-submenu-title">Title
<i class="ant-dropdown-menu-submenu-arrow"></i>
</div>
</li>
</ul>
<div class="ant-table-filter-dropdown-btns">
<a class="ant-table-filter-dropdown-link confirm">OK</a>
<a class="ant-table-filter-dropdown-link clear">Reset</a>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Table.sorter renders sorter icon correctly 1`] = `
<thead class="ant-table-thead">
<tr>
<th key="name" class="ant-table-column-has-filters"><span>Name<div class="ant-table-column-sorter"><span title="↑" class="ant-table-column-sorter-up off"><i class="anticon anticon-caret-up"></i></span><span title="↓" class="ant-table-column-sorter-down off"><i class="anticon anticon-caret-down"></i></span></div>
</span>
</th>
</tr>
</thead>
`;

View File

@ -360,6 +360,7 @@ export default {
} else {
this._component.popupProps = popupProps
}
return this._component
},
getContainer () {