diff --git a/packages/element3/src/components/Pagination/index.js b/packages/element3/src/components/Pagination/index.js new file mode 100644 index 000000000..10b050909 --- /dev/null +++ b/packages/element3/src/components/Pagination/index.js @@ -0,0 +1,7 @@ +import ElPagination from './src/Pagination.vue' + +ElPagination.install = function (app) { + app.component(ElPagination.name, ElPagination) +} + +export { ElPagination } diff --git a/packages/element3/src/components/Pagination/src/Layout.vue b/packages/element3/src/components/Pagination/src/Layout.vue new file mode 100644 index 000000000..a814ab1af --- /dev/null +++ b/packages/element3/src/components/Pagination/src/Layout.vue @@ -0,0 +1,49 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/Pagination.vue b/packages/element3/src/components/Pagination/src/Pagination.vue new file mode 100644 index 000000000..2042c6bd8 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/Pagination.vue @@ -0,0 +1,205 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/entity/Pager.ts b/packages/element3/src/components/Pagination/src/entity/Pager.ts new file mode 100644 index 000000000..3f46f0517 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/entity/Pager.ts @@ -0,0 +1,176 @@ +import mitt from 'mitt' +import { ElPaginationProps, Keep } from '../../types' +import { makerArray } from '../tools/makerArray' + +export enum PagerEventType { + CHANGE = 'change', + PREV = 'prev', + NEXT = 'next', + SIZE_CHANGE = 'size_change' +} + +export type PagerEventCb = (pageNumber: number) => void + +export interface PagerParam { + size: number + total: number + current: number + viewCount: number +} + +export type PagerStyle = Keep< + 'prevText' | 'nextText' | 'popperClass' | 'disabled' +> + +export class Pager { + private _current: number + private _total: number + private _size: number + private _viewCount: number + private _event = mitt() + private _sizes = [] + private _style: PagerStyle = { + popperClass: '', + prevText: '', + nextText: '', + disabled: false + } + + get style(): PagerStyle { + return this._style + } + + set style(v: PagerStyle) { + this._style = v + } + + get sizes(): number[] { + return this._sizes + } + + set sizes(v: number[]) { + this._sizes = v + } + + get size(): number { + return this._size + } + + set size(v: number) { + this.changeSize(v) + } + + get total(): number { + return this._total + } + + set total(v: number) { + this._total = v + } + + get pagerCountNotSelf(): number { + return this._viewCount - 1 + } + + get halfPager(): number { + return Math.floor(this.pagerCountNotSelf / 2) + } + + get leftCount(): number { + return Math.max(this._current - 1, 0) + } + + get rightCount(): number { + return Math.max(this.count - this._current, 0) + } + + get current(): number { + return this._current + } + + set current(v: number) { + this.jump(v) + } + + get count(): number { + return Math.ceil(this._total / this._size) + } + + get viewCount(): number { + return this._viewCount + } + + set viewCount(v: number) { + this._viewCount = v + } + + get pages(): number[] { + return makerArray(1, this.count) + } + + get viewPages(): number[] { + let leftViewCount = Math.min(this.leftCount, this.halfPager) + let rightViewCount = Math.min(this.rightCount, this.halfPager) + + if (leftViewCount > rightViewCount) { + leftViewCount = + this.pagerCountNotSelf - Math.min(rightViewCount, this.halfPager) + } else { + rightViewCount = + this.pagerCountNotSelf - Math.min(leftViewCount, this.halfPager) + } + + return this.catOut( + this._current - leftViewCount, + this._current + rightViewCount + ) + } + + get midViewPages(): number[] { + const result = this.viewPages + result.shift() + result.pop() + return result + } + + constructor(pagerParam: PagerParam) { + this._size = pagerParam.size + this._total = pagerParam.total + this._current = pagerParam.current + this._viewCount = pagerParam.viewCount + } + + catOut(start: number, end: number): number[] { + return this.pages.slice(Math.max(start - 1, 0), Math.min(end, this.count)) + } + + jump(v: number): void { + if (this._style.disabled) { + return + } + v = Math.min(this.count, v) + v = Math.max(1, v) + this._current = v + this._event.emit(PagerEventType.CHANGE, v) + } + + prev(step = 1): void { + this.jump(this._current - step) + this._event.emit(PagerEventType.PREV, this._current) + } + + next(step = 1): void { + this.jump(this._current + step) + this._event.emit(PagerEventType.NEXT, this._current) + } + + on(type: PagerEventType, cb: PagerEventCb): void { + this._event.on(type, cb) + } + + changeSize(v: number): void { + this._size = v + this._event.emit(PagerEventType.SIZE_CHANGE, v) + this.jump(this._current) + } +} diff --git a/packages/element3/src/components/Pagination/src/parts/Jumper.vue b/packages/element3/src/components/Pagination/src/parts/Jumper.vue new file mode 100644 index 000000000..aa615829c --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Jumper.vue @@ -0,0 +1,33 @@ + + diff --git a/packages/element3/src/components/Pagination/src/parts/Next.vue b/packages/element3/src/components/Pagination/src/parts/Next.vue new file mode 100644 index 000000000..a3c40b4a6 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Next.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/parts/Pager.vue b/packages/element3/src/components/Pagination/src/parts/Pager.vue new file mode 100644 index 000000000..d51f20582 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Pager.vue @@ -0,0 +1,66 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/parts/Prev.vue b/packages/element3/src/components/Pagination/src/parts/Prev.vue new file mode 100644 index 000000000..0b1b4a304 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Prev.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/parts/Sizes.vue b/packages/element3/src/components/Pagination/src/parts/Sizes.vue new file mode 100644 index 000000000..912c5ea06 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Sizes.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/packages/element3/src/components/Pagination/src/parts/Slot.vue b/packages/element3/src/components/Pagination/src/parts/Slot.vue new file mode 100644 index 000000000..85aec3ecc --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Slot.vue @@ -0,0 +1,15 @@ + diff --git a/packages/element3/src/components/Pagination/src/parts/Total.vue b/packages/element3/src/components/Pagination/src/parts/Total.vue new file mode 100644 index 000000000..e5034cccd --- /dev/null +++ b/packages/element3/src/components/Pagination/src/parts/Total.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/element3/src/components/Pagination/src/tools/element.ts b/packages/element3/src/components/Pagination/src/tools/element.ts new file mode 100644 index 000000000..c1b2c08d4 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/tools/element.ts @@ -0,0 +1,12 @@ +type SwitchFun = (el: Element | EventTarget) => void +export function switchClass([a, b]: [string, string]): SwitchFun { + return (el: Element) => { + if (!el.className.includes(a)) { + el.classList.add(a) + el.classList.remove(b) + } else { + el.classList.remove(a) + el.classList.add(b) + } + } +} diff --git a/packages/element3/src/components/Pagination/src/tools/makerArray.ts b/packages/element3/src/components/Pagination/src/tools/makerArray.ts new file mode 100644 index 000000000..68ff86429 --- /dev/null +++ b/packages/element3/src/components/Pagination/src/tools/makerArray.ts @@ -0,0 +1,5 @@ +export function makerArray(start: number, end: number): number[] { + const arr = [] + for (let i = start; i <= end; i++) arr.push(i) + return arr +} diff --git a/packages/element3/src/components/Pagination/src/tools/parseLayout.ts b/packages/element3/src/components/Pagination/src/tools/parseLayout.ts new file mode 100644 index 000000000..dc1b4778c --- /dev/null +++ b/packages/element3/src/components/Pagination/src/tools/parseLayout.ts @@ -0,0 +1,18 @@ +export function parseLayout(layout: string): string[] { + const recursion = (arr: string[], index: number): string[] => { + const result = [] + for (let i = index; i < arr.length; i++) { + const item = arr[i] + if (item === '->') { + result.push(recursion(arr, i + 1)) + break + } + result.push(item) + } + return result + } + return recursion( + layout.split(',').map((item) => item.trim()), + 0 + ) +} diff --git a/packages/element3/src/components/Pagination/tests/Pagination.spec.ts b/packages/element3/src/components/Pagination/tests/Pagination.spec.ts new file mode 100644 index 000000000..2c8f9d105 --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/Pagination.spec.ts @@ -0,0 +1,325 @@ +import { mount } from '@vue/test-utils' +import Pagination from '../src/Pagination.vue' +import Prev from '../src/parts/Prev.vue' +import Next from '../src/parts/Next.vue' +import Pager from '../src/parts/Pager.vue' +import Total from '../src/parts/Total.vue' +import { h, nextTick, ref } from 'vue' + +describe('Pagination.vue', () => { + it('Realize layout prev,pager,next', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'prev, pager, next, total', + currentPage: 2, + pageCount: 5 + } + }) + + expect(wrapper.findComponent(Prev).exists()).toBeTruthy() + expect(wrapper.findComponent(Next).exists()).toBeTruthy() + expect(wrapper.findComponent(Pager).exists()).toBeTruthy() + expect(wrapper.findComponent(Total).exists()).toBeTruthy() + }) + it('Realize simple paging display', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'prev, pager, next', + currentPage: 2, + pageCount: 5 + } + }) + + const pager = wrapper.vm.pager + + expect(wrapper.findComponent(Pager).vm.pager).toBe(pager) + expect(pager.current).toBe(2) + expect(pager.count).toBe(5) + }) + it('Calculate page numbers by Total and pageSize', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'prev, pager, next, total', + currentPage: 2, + pageSize: 10, + total: 100 + } + }) + + const pager = wrapper.vm.pager + + expect(wrapper.findComponent(Total).vm.pager).toBe(pager) + expect(pager.current).toBe(2) + expect(pager.count).toBe(10) + }) + + it('Hide when there is only one page', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: 1, + pageSize: 1, + total: 1, + hideOnSinglePage: true + } + }) + + expect(wrapper.findComponent(Pager).exists()).toBeFalsy() + }) + + it('click prev/next button currentPage', async () => { + const currentPage = ref(2) + const wrapper = mount(Pagination, { + props: { + layout: 'prev, next', + currentPage: (currentPage as unknown) as number, + pageCount: 10, + 'onUpdate:currentPage': (v) => (currentPage.value = v) + } + }) + + await wrapper.findComponent(Prev).trigger('click') + expect(currentPage.value).toBe(1) + await wrapper.findComponent(Next).trigger('click') + expect(currentPage.value).toBe(2) + }) + + it('vModel currentPage', async () => { + const currentPage = ref(2) + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: (currentPage as unknown) as number, + pageCount: 10, + 'onUpdate:currentPage': (v) => (currentPage.value = v) + } + }) + + currentPage.value = 3 + await nextTick() + expect(wrapper.find('.active').text()).toBe('3') + }) + + it('change size by ref', async () => { + const currentPage = ref(2) + const total = ref(100) + const size = ref(10) + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: (currentPage as unknown) as number, + total: (total as unknown) as number, + pageSize: (size as unknown) as number, + 'onUpdate:currentPage': (v) => (currentPage.value = v) + } + }) + + expect(wrapper.vm.pager.count).toBe(10) + size.value = 20 + await nextTick() + expect(wrapper.vm.pager.count).toBe(5) + }) + + it('click pager button currentPage', async () => { + const currentPage = ref(2) + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: (currentPage as unknown) as number, + pageCount: 100, + 'onUpdate:currentPage': (v) => (currentPage.value = v) + } + }) + const pages = wrapper.findAll('.number') + + await pages[0].trigger('click') + expect(currentPage.value).toBe(1) + + await wrapper.find('.btn-quicknext').trigger('click') + expect(currentPage.value).toBe(4) + }) + + it('click test sizes change pageSize', () => { + const currentPage = ref(2) + const total = ref(100) + const size = ref(10) + + const wrapper = mount(Pagination, { + props: { + layout: 'sizes', + currentPage: (currentPage as unknown) as number, + total: (total as unknown) as number, + pageSize: (size as unknown) as number, + pageSizes: [10, 20, 30], + 'onUpdate:currentPage': (v) => (currentPage.value = v), + 'onUpdate:pageSize': (v) => (size.value = v) + } + }) + + wrapper.vm.pager.size = 20 + + expect(wrapper.vm.pager.count).toBe(5) + }) + + it('sizes part popperClass', () => { + const currentPage = ref(2) + const total = ref(100) + const size = ref(10) + + const wrapper = mount(Pagination, { + props: { + layout: 'sizes', + currentPage: (currentPage as unknown) as number, + total: (total as unknown) as number, + pageSize: (size as unknown) as number, + pageSizes: [10, 20, 30], + popperClass: 'test', + 'onUpdate:currentPage': (v) => (currentPage.value = v), + 'onUpdate:pageSize': (v) => (size.value = v) + } + }) + + expect(wrapper.find('.test').exists()).toBeTruthy() + }) + + it('Achieve right-aligned layout', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'prev, pager, next, ->, total', + currentPage: 2, + pageCount: 5 + } + }) + + expect(wrapper.find('.btn-prev').exists()).toBeTruthy() + expect(wrapper.findAll('.el-pager .number')).toHaveLength(5) + expect(wrapper.find('.el-pager .number.active').text()).toBe('2') + expect(wrapper.find('.btn-next').exists()).toBeTruthy() + expect(wrapper.find('.el-pagination__rightwrapper').exists()).toBeTruthy() + expect(wrapper.find('.el-pagination__total').exists()).toBeTruthy() + }) + + it('When layout is set to slot, customize slots based on #default', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'slot', + currentPage: 2, + pageCount: 5 + }, + slots: { + default(pager) { + return h( + 'div', + { + class: 'slot' + }, + 'Current: ' + pager.current + ) + } + } + }) + + expect(wrapper.find('.slot').exists()).toBeTruthy() + expect(wrapper.find('.slot').text()).toBe('Current: 2') + }) + + it('Customize Prev and Next content', () => { + const wrapper = mount(Pagination, { + props: { + layout: 'prev, next', + currentPage: 2, + pageCount: 5, + prevText: 'PrevPage', + nextText: 'NextPage' + } + }) + + expect(wrapper.findComponent(Prev).text()).toBe('PrevPage') + expect(wrapper.findComponent(Next).text()).toBe('NextPage') + }) + + it('jump page number', async () => { + const currentPage = ref(1) + const wrapper = mount(Pagination, { + props: { + layout: 'jumper', + currentPage: (currentPage as unknown) as number, + 'onUpdate:currentPage': (v) => (currentPage.value = v), + pageCount: 5 + } + }) + + const jumperInput = wrapper.find('input') + await jumperInput.setValue('5') + + expect(currentPage.value).toBe(5) + }) + + it('test disable effect', async () => { + const disabled = ref(false) + const currentPage = ref(1) + const wrapper = mount(Pagination, { + props: { + currentPage: (currentPage as unknown) as number, + pageCount: 5, + disabled: (disabled as unknown) as boolean, + 'onUpdate:currentPage': (v) => (currentPage.value = v) + } + }) + + const [leftBtn, rightBtn] = wrapper.findAll('button') + + expect(leftBtn.element.disabled).toBeTruthy() + + currentPage.value = 5 + await nextTick() + expect(rightBtn.element.disabled).toBeTruthy() + + disabled.value = true + await nextTick() + expect(wrapper.vm.pager.style.disabled).toBeTruthy() + }) + + it('small pager', () => { + const currentPage = ref(1) + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: (currentPage as unknown) as number, + 'onUpdate:currentPage': (v) => (currentPage.value = v), + pageCount: 5, + small: true + } + }) + expect(wrapper.find('.el-pagination--small').exists()).toBeTruthy() + }) + + it('Pager with background', () => { + const currentPage = ref(1) + const wrapper = mount(Pagination, { + props: { + layout: 'pager', + currentPage: (currentPage as unknown) as number, + 'onUpdate:currentPage': (v) => (currentPage.value = v), + pageCount: 5, + background: true + } + }) + expect(wrapper.find('.is-background').exists()).toBeTruthy() + }) + + it('When the page number changes, so does the Jumper', async () => { + const currentPage = ref(1) + const wrapper = mount(Pagination, { + props: { + layout: 'jumper, next', + currentPage: (currentPage as unknown) as number, + 'onUpdate:currentPage': (v) => (currentPage.value = v), + pageCount: 5, + background: true + } + }) + await wrapper.find('button').trigger('click') + expect(wrapper.find('input').element.value).toBe('2') + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/entity/Pager.spec.ts b/packages/element3/src/components/Pagination/tests/entity/Pager.spec.ts new file mode 100644 index 000000000..29828c62c --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/entity/Pager.spec.ts @@ -0,0 +1,246 @@ +import { Pager, PagerEventType } from '../../src/entity/Pager' + +describe('Pager.ts', () => { + it('instance Pager', () => { + const pageCount = 6 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.pages).toHaveLength(6) + }) + + it('view pages', () => { + const pageCount = 10 + const currentPage = 1 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.midViewPages).toEqual([2, 3, 4, 5, 6]) + + pager.current = 2 + expect(pager.midViewPages).toEqual([2, 3, 4, 5, 6]) + + pager.current = 3 + expect(pager.midViewPages).toEqual([2, 3, 4, 5, 6]) + + pager.current = 5 + expect(pager.midViewPages).toEqual([3, 4, 5, 6, 7]) + + pager.current = 8 + expect(pager.midViewPages).toEqual([5, 6, 7, 8, 9]) + + pager.current = 9 + expect(pager.midViewPages).toEqual([5, 6, 7, 8, 9]) + + pager.current = 10 + expect(pager.midViewPages).toEqual([5, 6, 7, 8, 9]) + + expect(pager.leftCount).toBe(9) + expect(pager.rightCount).toBe(0) + }) + + it('test catOut method', () => { + const pageCount = 10 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.catOut(1, 2)).toEqual([1, 2]) + expect(pager.catOut(4, 7)).toEqual([4, 5, 6, 7]) + expect(pager.catOut(0, 11)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + }) + + it('test pageCount = pagerCount', () => { + const pageCount = 10 + const currentPage = 2 + const pagerCount = 10 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.viewPages).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + expect(pager.leftCount).toBe(1) + expect(pager.rightCount).toBe(8) + }) + + it('test viewPages', () => { + const pageCount = 10 + const currentPage = 1 + const pagerCount = 5 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.viewPages).toEqual([1, 2, 3, 4, 5]) + + pager.current = 2 + expect(pager.viewPages).toEqual([1, 2, 3, 4, 5]) + + pager.current = 3 + expect(pager.viewPages).toEqual([1, 2, 3, 4, 5]) + + pager.current = 4 + expect(pager.viewPages).toEqual([2, 3, 4, 5, 6]) + + pager.current = 5 + expect(pager.viewPages).toEqual([3, 4, 5, 6, 7]) + + pager.current = 6 + expect(pager.viewPages).toEqual([4, 5, 6, 7, 8]) + + pager.current = 7 + expect(pager.viewPages).toEqual([5, 6, 7, 8, 9]) + + pager.current = 8 + expect(pager.viewPages).toEqual([6, 7, 8, 9, 10]) + + pager.current = 9 + expect(pager.viewPages).toEqual([6, 7, 8, 9, 10]) + + pager.current = 10 + expect(pager.viewPages).toEqual([6, 7, 8, 9, 10]) + + pager.current = 0 + expect(pager.viewPages).toEqual([1, 2, 3, 4, 5]) + + pager.current = 11 + expect(pager.viewPages).toEqual([6, 7, 8, 9, 10]) + }) + it('test total', () => { + const total = 100 + const currentPage = 2 + const pagerCount = 7 + const pageSize = 10 + const pager = new Pager({ + total: total, + size: pageSize, + current: currentPage, + viewCount: pagerCount + }) + + expect(pager.count).toBe(10) + }) + + it('jump page', () => { + const pageCount = 6 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + pager.jump(5) + expect(pager.current).toBe(5) + }) + + it('jump page when currentPage Crossing the line', () => { + const pageCount = 6 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + pager.jump(7) + expect(pager.current).toBe(6) + pager.jump(0) + expect(pager.current).toBe(1) + }) + + it('change prev/next page', () => { + const pageCount = 6 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + pager.prev() + expect(pager.current).toBe(1) + pager.next() + expect(pager.current).toBe(2) + }) + + it('when current change, trigger event', () => { + const changeHandler = jest.fn() + const prevHandler = jest.fn() + const nextHandler = jest.fn() + + const pageCount = 6 + const currentPage = 2 + const pagerCount = 7 + const pager = new Pager({ + total: pageCount, + size: 1, + current: currentPage, + viewCount: pagerCount + }) + + pager.on(PagerEventType.CHANGE, changeHandler) + pager.on(PagerEventType.PREV, prevHandler) + pager.on(PagerEventType.NEXT, nextHandler) + + pager.jump(5) + pager.prev() + pager.next() + + expect(changeHandler).toBeCalledTimes(3) + expect(changeHandler).toHaveBeenNthCalledWith(1, 5) + expect(changeHandler).toHaveBeenNthCalledWith(2, 4) + expect(changeHandler).toHaveBeenNthCalledWith(3, 5) + + expect(prevHandler).toBeCalledTimes(1) + expect(prevHandler).toHaveBeenNthCalledWith(1, 4) + + expect(nextHandler).toBeCalledTimes(1) + expect(nextHandler).toHaveBeenNthCalledWith(1, 5) + }) + + it('update size', () => { + const sizeHandler = jest.fn() + + const pager = new Pager({ + total: 100, + size: 1, + current: 90, + viewCount: 7 + }) + + pager.on(PagerEventType.SIZE_CHANGE, sizeHandler) + pager.size = 10 + expect(sizeHandler).toBeCalledTimes(1) + expect(sizeHandler).toHaveBeenNthCalledWith(1, 10) + expect(pager.current).toBe(10) + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/parts/Pager.spec.ts b/packages/element3/src/components/Pagination/tests/parts/Pager.spec.ts new file mode 100644 index 000000000..ca4fda822 --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/parts/Pager.spec.ts @@ -0,0 +1,106 @@ +import { mount } from '@vue/test-utils' +import { Pager } from '../../src/entity/Pager' +import ElPager from '../../src/parts/Pager.vue' + +describe('Pager.vue', () => { + it('show page pageCount <= pagerCount', () => { + const pager = new Pager({ total: 5, size: 1, current: 3, viewCount: 7 }) + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + expect(wrapper.findAll('.number')).toHaveLength(5) + expect(wrapper.findAll('.number').map((item) => item.text())).toEqual([ + '1', + '2', + '3', + '4', + '5' + ]) + expect(wrapper.find('.number.active').text()).toBe('3') + expect(wrapper.findAll('.el-icon.more')).toHaveLength(0) + }) + it('show page pageCount > pagerCount currentPage is 4', () => { + const pager = new Pager({ total: 30, size: 1, current: 4, viewCount: 7 }) + + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + expect(wrapper.findAll('.number')).toHaveLength(7) + expect(wrapper.find('.el-icon.more.btn-quickprev').exists()).toBeFalsy() + expect(wrapper.find('.el-icon.more.btn-quicknext').exists()).toBeTruthy() + }) + it('show page pageCount > pagerCount currentPage is 27', () => { + const pager = new Pager({ total: 30, size: 1, current: 27, viewCount: 7 }) + + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + expect(wrapper.findAll('.number')).toHaveLength(7) + expect(wrapper.find('.el-icon.more.btn-quickprev').exists()).toBeTruthy() + expect(wrapper.find('.el-icon.more.btn-quicknext').exists()).toBeFalsy() + }) + it('show page pageCount > pagerCount', () => { + const pager = new Pager({ total: 30, size: 1, current: 10, viewCount: 7 }) + + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + expect(wrapper.findAll('.number')).toHaveLength(7) + expect(wrapper.findAll('.el-icon.more')).toHaveLength(2) + expect(wrapper.find('.number.active').text()).toBe('10') + }) + + it('when pageCount less', () => { + const pager = new Pager({ total: 2, size: 1, current: 1, viewCount: 7 }) + + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + expect(wrapper.findAll('.number')).toHaveLength(2) + expect(wrapper.findAll('.number').map((item) => item.text())).toEqual([ + '1', + '2' + ]) + expect(wrapper.find('.number.active').text()).toBe('1') + }) + + it('more btn mouse enter and leave', async () => { + const pager = new Pager({ total: 100, size: 1, current: 50, viewCount: 7 }) + + const wrapper = mount(ElPager, { + props: { + pager + } + }) + + const quickPrev = wrapper.find('.btn-quickprev') + const quickNext = wrapper.find('.btn-quicknext') + + await quickPrev.trigger('mouseenter') + await quickNext.trigger('mouseenter') + + expect(quickPrev.classes()).toContain('el-icon-d-arrow-left') + expect(quickNext.classes()).toContain('el-icon-d-arrow-right') + + await quickPrev.trigger('mouseleave') + await quickNext.trigger('mouseleave') + + expect(quickPrev.classes()).toContain('el-icon-more') + expect(quickNext.classes()).toContain('el-icon-more') + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/parts/Total.spec.ts b/packages/element3/src/components/Pagination/tests/parts/Total.spec.ts new file mode 100644 index 000000000..1e28db18e --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/parts/Total.spec.ts @@ -0,0 +1,20 @@ +import { mount } from '@vue/test-utils' +import { Pager } from '../../src/entity/Pager' +import Total from '../../src/parts/Total.vue' + +describe('Total.vue', () => { + it('show total', () => { + const wrapper = mount(Total, { + props: { + pager: new Pager({ + total: 10, + size: 1, + current: 2, + viewCount: 7 + }) + } + }) + + expect(wrapper.text()).toBe(`共 ${10} 条`) + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/tools/element.spec.ts b/packages/element3/src/components/Pagination/tests/tools/element.spec.ts new file mode 100644 index 000000000..61decbdc1 --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/tools/element.spec.ts @@ -0,0 +1,14 @@ +import { switchClass } from '../../src/tools/element' + +describe('element.ts', () => { + it('switch tow class state', () => { + const element = document.createElement('div') + const switchTrigger = switchClass(['a', 'b']) + + switchTrigger(element) + expect(element.className).toBe('a') + + switchTrigger(element) + expect(element.className).toBe('b') + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/tools/makerArray.spec.ts b/packages/element3/src/components/Pagination/tests/tools/makerArray.spec.ts new file mode 100644 index 000000000..053e1cd7a --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/tools/makerArray.spec.ts @@ -0,0 +1,7 @@ +import { makerArray } from '../../src/tools/makerArray' + +describe('makerArray.ts', () => { + it('test create 2-6 array', () => { + expect(makerArray(2, 6)).toEqual([2, 3, 4, 5, 6]) + }) +}) diff --git a/packages/element3/src/components/Pagination/tests/tools/parseLayout.spec.ts b/packages/element3/src/components/Pagination/tests/tools/parseLayout.spec.ts new file mode 100644 index 000000000..5f9782bb9 --- /dev/null +++ b/packages/element3/src/components/Pagination/tests/tools/parseLayout.spec.ts @@ -0,0 +1,13 @@ +import { parseLayout } from '../../src/tools/parseLayout' + +describe('parseLayout.ts', () => { + it('parse a layout string', () => { + expect(parseLayout('prev, pager, next ')).toEqual(['prev', 'pager', 'next']) + }) + + it('parse -> flag', () => { + const layoutStr = 'prev, pager, next, -> , jumper, ->, total' + const result = parseLayout(layoutStr) + expect(result).toEqual(['prev', 'pager', 'next', ['jumper', ['total']]]) + }) +}) diff --git a/packages/element3/src/components/Pagination/types.ts b/packages/element3/src/components/Pagination/types.ts new file mode 100644 index 000000000..8f4d0791a --- /dev/null +++ b/packages/element3/src/components/Pagination/types.ts @@ -0,0 +1,26 @@ +export interface ElPaginationProps { + layout?: string + pagerCount?: number + currentPage?: number + pageCount?: number + total?: number + pageSize?: number + hideOnSinglePage?: boolean + pageSizes?: number[] + popperClass?: string + nextText?: string + prevText?: string + disabled?: boolean + small?: boolean + background?: boolean +} + +declare class ElPagination { + $props: ElPaginationProps +} + +export type Keep = { + [key in keyof ElPaginationProps & S]?: ElPaginationProps[key] +} + +export default ElPagination diff --git a/packages/element3/src/index.js b/packages/element3/src/index.js index cb7532c22..35b3bc7b1 100644 --- a/packages/element3/src/index.js +++ b/packages/element3/src/index.js @@ -47,7 +47,7 @@ import { ElNewTableColumn } from '../src/components/TableColumn' import { ElTag } from './components/Tag' import { ElProgress } from './components/Progress' import ElTree from '../packages/tree' -import ElPagination from '../packages/pagination' +import { ElPagination } from './components/Pagination' import { ElBadge } from './components/Badge' import { ElAvatar } from './components/Avatar' // Notice