diff --git a/src/RenderlessPagination.vue b/src/RenderlessPagination.vue index 1a6cc25..21ae47f 100644 --- a/src/RenderlessPagination.vue +++ b/src/RenderlessPagination.vue @@ -5,53 +5,73 @@ export default { props: { data: { type: Object, - default: () => {} + default: () => {}, }, limit: { type: Number, - default: 0 + default: 0, }, keepLength: { type: Boolean, - default: false + default: false, }, }, computed: { - isApiResource () { + isApiResource() { return !!this.data.meta; }, - currentPage () { - return this.isApiResource ? this.data.meta.current_page : this.data.current_page; - }, - firstPageUrl () { - return this.isApiResource ? this.data.links.first : null; - }, - from () { - return this.isApiResource ? this.data.meta.from : this.data.from; - }, - lastPage () { - return this.isApiResource ? this.data.meta.last_page : this.data.last_page; - }, - lastPageUrl () { - return this.isApiResource ? this.data.links.last : null; - }, - nextPageUrl () { - return this.isApiResource ? this.data.links.next : this.data.next_page_url; - }, - perPage () { - return this.isApiResource ? this.data.meta.per_page : this.data.per_page; - }, - prevPageUrl () { - return this.isApiResource ? this.data.links.prev : this.data.prev_page_url; - }, - to () { - return this.isApiResource ? this.data.meta.to : this.data.to; - }, - total () { - return this.isApiResource ? this.data.meta.total : this.data.total; - }, - pageRange () { + currentPage() { + return this.isApiResource + ? this.data.meta.current_page + : this.data.current_page ?? null; + }, + firstPageUrl() { + return this.isApiResource + ? this.data.links.first + : this.data.first_page_url ?? null; + }, + from() { + return this.isApiResource + ? this.data.meta.from + : this.data.from ?? null; + }, + lastPage() { + return this.isApiResource + ? this.data.meta.last_page + : this.data.last_page ?? null; + }, + lastPageUrl() { + return this.isApiResource + ? this.data.links.last + : this.data.last_page_url ?? null; + }, + nextPageUrl() { + return this.isApiResource + ? this.data.links.next + : this.data.next_page_url ?? null; + }, + perPage() { + return this.isApiResource + ? this.data.meta.per_page + : this.data.per_page ?? null; + }, + prevPageUrl() { + return this.isApiResource + ? this.data.links.prev + : this.data.prev_page_url ?? null; + }, + to() { + return this.isApiResource + ? this.data.meta.to + : this.data.to ?? null; + }, + total() { + return this.isApiResource + ? this.data.meta.total + : this.data.total ?? null; + }, + pageRange() { if (this.limit === -1) { return 0; } @@ -67,7 +87,7 @@ export default { var left = current - delta; var right = current + delta; var leftPad = (delta + 2) * 2; - var rightPad = ((delta + 2) * 2) - 1; + var rightPad = (delta + 2) * 2 - 1; var range = []; var pages = []; var l; @@ -86,7 +106,11 @@ export default { range.push(i); } // Item is after max right padding - else if (size && i > last - rightPad && current > last - rightPad + 2) { + else if ( + size && + i > last - rightPad && + current > last - rightPad + 2 + ) { range.push(i); } } @@ -104,26 +128,26 @@ export default { }); return pages; - } + }, }, methods: { - previousPage () { - this.selectPage((this.currentPage - 1)); + previousPage() { + this.selectPage(this.currentPage - 1); }, - nextPage () { - this.selectPage((this.currentPage + 1)); + nextPage() { + this.selectPage(this.currentPage + 1); }, - selectPage (page) { + selectPage(page) { if (page === '...' || page === this.currentPage) { return; } this.$emit('pagination-change-page', page); - } + }, }, - render () { + render() { return this.$slots.default({ data: this.data, limit: this.limit, @@ -139,27 +163,27 @@ export default { prevPageUrl: this.prevPageUrl, to: this.to, total: this.total, - pageRange: this.pageRange + pageRange: this.pageRange, }, prevButtonEvents: { click: (e) => { e.preventDefault(); this.previousPage(); - } + }, }, nextButtonEvents: { click: (e) => { e.preventDefault(); this.nextPage(); - } + }, }, - pageButtonEvents: page => ({ + pageButtonEvents: (page) => ({ click: (e) => { e.preventDefault(); this.selectPage(page); - } - }) + }, + }), }); - } -} + }, +}; diff --git a/tests/unit/RenderlessPagination.spec.mjs b/tests/unit/RenderlessPagination.spec.mjs new file mode 100644 index 0000000..ceb33a6 --- /dev/null +++ b/tests/unit/RenderlessPagination.spec.mjs @@ -0,0 +1,229 @@ +import { mount } from '@vue/test-utils'; +import RenderlessPagination from '@/RenderlessPagination.vue'; + +const paginateData = { + current_page: 1, + data: [...Array(10).keys()], + first_page_url: 'https://example.com/pagination?page=1', + from: 1, + last_page: 10, + last_page_url: 'https://example.com/pagination?page=10', + links: [ + { + url: null, + label: '\u00ab Previous', + active: false, + }, + { + url: 'https://example.com/pagination?page=1', + label: '1', + active: true, + }, + { + url: 'https://example.com/pagination?page=2', + label: '2', + active: false, + }, + { + url: 'https://example.com/pagination?page=3', + label: 'Next \u00bb', + active: false, + }, + ], + next_page_url: 'https://example.com/pagination?page=2', + path: 'https://example.com/pagination', + per_page: 10, + prev_page_url: null, + to: 10, + total: 100, +}; + +test('parses paginate data', function () { + const wrapper = mount(RenderlessPagination, { + slots: { + default: '
', + }, + propsData: { + data: paginateData, + }, + }); + + expect(wrapper.vm.isApiResource).toEqual(false); + expect(wrapper.vm.currentPage).toEqual(paginateData.current_page); + expect(wrapper.vm.firstPageUrl).toEqual(paginateData.first_page_url); + expect(wrapper.vm.from).toEqual(paginateData.from); + expect(wrapper.vm.lastPage).toEqual(paginateData.last_page); + expect(wrapper.vm.lastPageUrl).toEqual(paginateData.last_page_url); + expect(wrapper.vm.nextPageUrl).toEqual(paginateData.next_page_url); + expect(wrapper.vm.perPage).toEqual(paginateData.per_page); + expect(wrapper.vm.prevPageUrl).toEqual(paginateData.prev_page_url); + expect(wrapper.vm.to).toEqual(paginateData.to); + expect(wrapper.vm.total).toEqual(paginateData.total); + expect(wrapper.vm.pageRange).toEqual(10); +}); + +const simplePaginateData = { + current_page: 1, + data: [...Array(10).keys()], + first_page_url: 'https://example.com/pagination?page=1', + from: 1, + next_page_url: 'https://example.com/pagination?page=2', + path: 'https://example.com/pagination', + per_page: 10, + prev_page_url: null, + to: 10, +}; + +test('parses paginate data', function () { + const wrapper = mount(RenderlessPagination, { + slots: { + default: '', + }, + propsData: { + data: simplePaginateData, + }, + }); + + expect(wrapper.vm.isApiResource).toEqual(false); + expect(wrapper.vm.currentPage).toEqual(simplePaginateData.current_page); + expect(wrapper.vm.firstPageUrl).toEqual(simplePaginateData.first_page_url); + expect(wrapper.vm.from).toEqual(simplePaginateData.from); + expect(wrapper.vm.lastPage).toEqual(null); + expect(wrapper.vm.lastPageUrl).toEqual(null); + expect(wrapper.vm.nextPageUrl).toEqual(simplePaginateData.next_page_url); + expect(wrapper.vm.perPage).toEqual(simplePaginateData.per_page); + expect(wrapper.vm.prevPageUrl).toEqual(simplePaginateData.prev_page_url); + expect(wrapper.vm.to).toEqual(simplePaginateData.to); + expect(wrapper.vm.total).toEqual(null); + expect(wrapper.vm.pageRange).toEqual(null); +}); + +const resourcePaginateData = { + data: [...Array(10).keys()], + links: { + first: 'https://example.com/pagination?page=1', + last: 'https://example.com/pagination?page=10', + prev: null, + next: 'https://example.com/pagination?page=2', + }, + meta: { + current_page: 1, + from: 1, + last_page: 10, + links: [ + { + url: null, + label: '\u00ab Previous', + active: false, + }, + { + url: 'https://example.com/pagination?page=1', + label: '1', + active: true, + }, + { + url: 'https://example.com/pagination?page=2', + label: '2', + active: false, + }, + { + url: 'https://example.com/pagination?page=3', + label: 'Next \u00bb', + active: false, + }, + ], + path: 'https://example.com/pagination', + per_page: 10, + to: 10, + total: 100, + }, +}; + +test('parses paginate data', function () { + const wrapper = mount(RenderlessPagination, { + slots: { + default: '', + }, + propsData: { + data: resourcePaginateData, + }, + }); + + expect(wrapper.vm.isApiResource).toEqual(true); + expect(wrapper.vm.currentPage).toEqual( + resourcePaginateData.meta.current_page + ); + expect(wrapper.vm.firstPageUrl).toEqual(resourcePaginateData.links.first); + expect(wrapper.vm.from).toEqual(resourcePaginateData.meta.from); + expect(wrapper.vm.lastPage).toEqual(resourcePaginateData.meta.last_page); + expect(wrapper.vm.lastPageUrl).toEqual(resourcePaginateData.links.last); + expect(wrapper.vm.nextPageUrl).toEqual(resourcePaginateData.links.next); + expect(wrapper.vm.perPage).toEqual(resourcePaginateData.meta.per_page); + expect(wrapper.vm.prevPageUrl).toEqual(resourcePaginateData.links.prev); + expect(wrapper.vm.to).toEqual(resourcePaginateData.meta.to); + expect(wrapper.vm.total).toEqual(resourcePaginateData.meta.total); + expect(wrapper.vm.pageRange).toEqual(10); +}); + +const dataPaginateData = { + data: [...Array(10).keys()], + links: [ + { + url: null, + label: '\u00ab Previous', + active: false, + }, + { + url: 'https://example.com/pagination?page=1', + label: '1', + active: true, + }, + { + url: 'https://example.com/pagination?page=2', + label: '2', + active: false, + }, + { + url: 'https://example.com/pagination?page=3', + label: 'Next \u00bb', + active: false, + }, + ], + meta: { + current_page: 1, + first_page_url: 'https://example.com/pagination?page=1', + from: 1, + last_page: 10, + last_page_url: 'https://example.com/pagination?page=10', + next_page_url: 'https://example.com/pagination?page=2', + path: 'https://example.com/pagination', + per_page: 10, + prev_page_url: null, + to: 10, + total: 100, + }, +}; + +test('parses paginate data', function () { + const wrapper = mount(RenderlessPagination, { + slots: { + default: '', + }, + propsData: { + data: dataPaginateData, + }, + }); + + expect(wrapper.vm.isApiResource).toEqual(true); + expect(wrapper.vm.currentPage).toEqual(dataPaginateData.meta.current_page); + expect(wrapper.vm.firstPageUrl).toEqual(dataPaginateData.links.first); + expect(wrapper.vm.from).toEqual(dataPaginateData.meta.from); + expect(wrapper.vm.lastPage).toEqual(dataPaginateData.meta.last_page); + expect(wrapper.vm.lastPageUrl).toEqual(dataPaginateData.links.last); + expect(wrapper.vm.nextPageUrl).toEqual(dataPaginateData.links.next); + expect(wrapper.vm.perPage).toEqual(dataPaginateData.meta.per_page); + expect(wrapper.vm.prevPageUrl).toEqual(dataPaginateData.links.prev); + expect(wrapper.vm.to).toEqual(dataPaginateData.meta.to); + expect(wrapper.vm.total).toEqual(dataPaginateData.meta.total); + expect(wrapper.vm.pageRange).toEqual(10); +});