web/satellite: pagination component implemented (#2722)
This commit is contained in:
parent
02b7be74fb
commit
fc4c675ffa
78
web/satellite/src/components/common/PagesBlock.vue
Normal file
78
web/satellite/src/components/common/PagesBlock.vue
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="pages-container">
|
||||
<span
|
||||
v-for="page in pages"
|
||||
:class="{'selected': checkSelected(page.index)}"
|
||||
@click="page.select()"
|
||||
:key="page.index">{{page.index}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from 'vue-property-decorator';
|
||||
import { Page } from '@/types/pagination';
|
||||
|
||||
@Component
|
||||
export default class PagesBlock extends Vue {
|
||||
@Prop({default: []})
|
||||
public readonly pages: Page[];
|
||||
@Prop({default: () => false})
|
||||
public readonly checkSelected: CheckSelected;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pages-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.selected {
|
||||
color: #2379EC;
|
||||
font-family: 'font_bold';
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 0;
|
||||
width: 10px;
|
||||
height: 2px;
|
||||
background-color: #2379EC;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: 'font_medium';
|
||||
font-size: 16px;
|
||||
margin-right: 15px;
|
||||
width: 10px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
position: relative;
|
||||
transition: all .2s ease;
|
||||
|
||||
&:hover {
|
||||
color: #2379EC;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: #2379EC;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
262
web/satellite/src/components/common/Pagination.vue
Normal file
262
web/satellite/src/components/common/Pagination.vue
Normal file
@ -0,0 +1,262 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-container__pages">
|
||||
<div v-html="arrowLeft" @click="prevPage" class="pagination-container__button"></div>
|
||||
<div class="pagination-container__items">
|
||||
<PagesBlock :pages="firstBlockPages" :checkSelected="isSelected"/>
|
||||
<span v-if="isFirstDotsShown">...</span>
|
||||
<PagesBlock :pages="middleBlockPages" :checkSelected="isSelected"/>
|
||||
<span v-if="isSecondDotsShown">...</span>
|
||||
<PagesBlock :pages="lastBlockPages" :checkSelected="isSelected"/>
|
||||
</div>
|
||||
<div v-html="arrowRight" @click="nextPage" class="pagination-container__button"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from 'vue-property-decorator';
|
||||
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
import PagesBlock from '@/components/common/PagesBlock.vue';
|
||||
import { Page } from '@/types/pagination';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
PagesBlock,
|
||||
}
|
||||
})
|
||||
export default class Pagination extends Vue {
|
||||
// TODO: use svg loader
|
||||
public readonly arrowLeft: string = EMPTY_STATE_IMAGES.ARROW_LEFT;
|
||||
public readonly arrowRight: string = EMPTY_STATE_IMAGES.ARROW_RIGHT;
|
||||
private readonly MAX_PAGES_PER_BLOCK: number = 3;
|
||||
private readonly MAX_PAGES_OFF_BLOCKS: number = 6;
|
||||
private currentPageNumber: number = 1;
|
||||
public isLoading = false;
|
||||
public pagesArray: Page[] = [];
|
||||
public firstBlockPages: Page[] = [];
|
||||
public middleBlockPages: Page[] = [];
|
||||
public lastBlockPages: Page[] = [];
|
||||
|
||||
@Prop({default: 0})
|
||||
private readonly totalPageCount: number;
|
||||
@Prop({default: () => { return new Promise(() => false); }})
|
||||
private readonly onPageClickCallback: OnPageClickCallback;
|
||||
|
||||
public mounted() {
|
||||
this.populatePagesArray();
|
||||
}
|
||||
|
||||
public get isFirstPage(): boolean {
|
||||
return this.currentPageNumber === 1;
|
||||
}
|
||||
|
||||
public get isLastPage(): boolean {
|
||||
return this.currentPageNumber === this.totalPageCount;
|
||||
}
|
||||
|
||||
public get isFirstDotsShown(): boolean {
|
||||
return this.middleBlockPages.length <= this.MAX_PAGES_PER_BLOCK
|
||||
&& this.pagesArray.length > this.MAX_PAGES_OFF_BLOCKS;
|
||||
}
|
||||
|
||||
public get isSecondDotsShown(): boolean {
|
||||
return !!this.middleBlockPages.length;
|
||||
}
|
||||
|
||||
public isSelected(page: number): boolean {
|
||||
return page === this.currentPageNumber;
|
||||
}
|
||||
|
||||
public async onPageClick(page: number): Promise<void> {
|
||||
if (this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
await this.onPageClickCallback(page);
|
||||
this.setCurrentPage(page);
|
||||
this.reorganizePageBlocks();
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
public async nextPage(): Promise<void> {
|
||||
if (this.isLastPage || this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
await this.onPageClickCallback(this.currentPageNumber + 1);
|
||||
this.incrementCurrentPage();
|
||||
this.reorganizePageBlocks();
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
public async prevPage(): Promise<void> {
|
||||
if (this.isFirstPage || this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
await this.onPageClickCallback(this.currentPageNumber - 1);
|
||||
this.decrementCurrentPage();
|
||||
this.reorganizePageBlocks();
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
private populatePagesArray(): void {
|
||||
if (!this.totalPageCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$route.query.pageNumber) {
|
||||
const pageNumber = parseInt(this.$route.query.pageNumber as string);
|
||||
this.setCurrentPage(pageNumber);
|
||||
|
||||
// Here we need to set short timeout to let router to set up after page
|
||||
// hard reload before we can replace query with current page number
|
||||
setTimeout(this.updateRouterPathWithPageNumber, 1);
|
||||
}
|
||||
|
||||
for (let i = 1; i <= this.totalPageCount; i++) {
|
||||
this.pagesArray.push(new Page(i, this.onPageClick));
|
||||
}
|
||||
|
||||
if (this.isPagesTotalOffBlocks()) {
|
||||
this.firstBlockPages = this.pagesArray.slice();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.reorganizePageBlocks();
|
||||
}
|
||||
|
||||
private reorganizePageBlocks(): void {
|
||||
if (this.isPagesTotalOffBlocks()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isCurrentInFirstBlock()) {
|
||||
this.setBlocksIfCurrentInFirstBlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isCurrentInFirstBlock() && !this.isCurrentInLastBlock()) {
|
||||
this.setBlocksIfCurrentInMiddleBlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isCurrentInLastBlock()) {
|
||||
this.setBlocksIfCurrentInLastBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private setBlocksIfCurrentInFirstBlock(): void {
|
||||
this.firstBlockPages = this.pagesArray.slice(0, 3);
|
||||
this.middleBlockPages = [];
|
||||
this.lastBlockPages = this.pagesArray.slice(-1);
|
||||
}
|
||||
|
||||
private setBlocksIfCurrentInMiddleBlock(): void {
|
||||
this.firstBlockPages = this.pagesArray.slice(0, 1);
|
||||
this.middleBlockPages = this.pagesArray.slice(this.currentPageNumber - 2, this.currentPageNumber + 1);
|
||||
this.lastBlockPages = this.pagesArray.slice(-1);
|
||||
}
|
||||
|
||||
private setBlocksIfCurrentInLastBlock(): void {
|
||||
this.firstBlockPages = this.pagesArray.slice(0, 1);
|
||||
this.middleBlockPages = [];
|
||||
this.lastBlockPages = this.pagesArray.slice(-3);
|
||||
}
|
||||
|
||||
private isCurrentInFirstBlock(): boolean {
|
||||
return this.currentPageNumber < this.MAX_PAGES_PER_BLOCK;
|
||||
}
|
||||
|
||||
private isCurrentInLastBlock(): boolean {
|
||||
return this.totalPageCount - this.currentPageNumber < this.MAX_PAGES_PER_BLOCK - 1;
|
||||
}
|
||||
|
||||
private isPagesTotalOffBlocks(): boolean {
|
||||
return this.totalPageCount <= this.MAX_PAGES_OFF_BLOCKS;
|
||||
}
|
||||
|
||||
private incrementCurrentPage(): void {
|
||||
this.currentPageNumber++;
|
||||
this.updateRouterPathWithPageNumber();
|
||||
}
|
||||
|
||||
private decrementCurrentPage(): void {
|
||||
this.currentPageNumber--;
|
||||
this.updateRouterPathWithPageNumber();
|
||||
}
|
||||
|
||||
private setCurrentPage(pageNumber: number): void {
|
||||
this.currentPageNumber = pageNumber;
|
||||
this.updateRouterPathWithPageNumber();
|
||||
}
|
||||
|
||||
private updateRouterPathWithPageNumber() {
|
||||
this.$router.replace({ query: { pageNumber: this.currentPageNumber.toString() } });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 25px;
|
||||
margin-top: 25px;
|
||||
|
||||
&__pages {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__counter {
|
||||
|
||||
p {
|
||||
font-family: 'font_medium';
|
||||
font-size: 16px;
|
||||
color: #AFB7C1;
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: 1px solid #AFB7C1;
|
||||
border-radius: 6px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
&:hover {
|
||||
|
||||
svg {
|
||||
|
||||
path {
|
||||
fill: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__items {
|
||||
margin: 0 20px;
|
||||
display: flex;
|
||||
|
||||
span {
|
||||
margin: 0 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
4
web/satellite/src/types/fetch.d.ts
vendored
4
web/satellite/src/types/fetch.d.ts
vendored
@ -8,3 +8,7 @@ declare type Answer = {
|
||||
message: any;
|
||||
};
|
||||
};
|
||||
|
||||
declare type OnPageClickCallback = (index: number) => Promise<any>;
|
||||
|
||||
declare type CheckSelected = (index: number) => boolean;
|
||||
|
22
web/satellite/src/types/pagination.ts
Normal file
22
web/satellite/src/types/pagination.ts
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
declare type OnPageClickCallback = (search: number) => Promise<void>;
|
||||
|
||||
export class Page {
|
||||
private readonly pageIndex: number = 1;
|
||||
private readonly onClick: OnPageClickCallback;
|
||||
|
||||
constructor(index: number, callback: OnPageClickCallback) {
|
||||
this.pageIndex = index;
|
||||
this.onClick = callback;
|
||||
}
|
||||
|
||||
public get index() {
|
||||
return this.pageIndex;
|
||||
}
|
||||
|
||||
public async select(): Promise<void> {
|
||||
await this.onClick(this.pageIndex);
|
||||
}
|
||||
}
|
56
web/satellite/tests/unit/common/PagesBlock.spec.ts
Normal file
56
web/satellite/tests/unit/common/PagesBlock.spec.ts
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import * as sinon from 'sinon';
|
||||
import PagesBlock from '@/components/common/PagesBlock.vue';
|
||||
import { Page } from '@/types/pagination';
|
||||
|
||||
describe('Pagination.vue', () => {
|
||||
it('renders correctly without props', () => {
|
||||
const wrapper = shallowMount(PagesBlock);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with props', () => {
|
||||
const callbackSpy = sinon.spy();
|
||||
const pagesArray: Page[] = [];
|
||||
const SELECTED_PAGE_INDEX: number = 3;
|
||||
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
pagesArray.push(new Page(i, callbackSpy));
|
||||
}
|
||||
|
||||
const wrapper = shallowMount(PagesBlock, {
|
||||
propsData: {
|
||||
pages: pagesArray,
|
||||
checkSelected: (i: number) => i === SELECTED_PAGE_INDEX
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.findAll('span').length).toBe(4);
|
||||
expect(wrapper.findAll('span').at(2).classes().includes('selected')).toBe(true);
|
||||
});
|
||||
|
||||
it('behaves correctly on page click', async () => {
|
||||
const callbackSpy = sinon.spy();
|
||||
let pagesArray: Page[] = [];
|
||||
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
pagesArray.push(new Page(i, callbackSpy));
|
||||
}
|
||||
|
||||
const wrapper = shallowMount(PagesBlock, {
|
||||
propsData: {
|
||||
pages: pagesArray,
|
||||
checkSelected: () => false
|
||||
}
|
||||
});
|
||||
|
||||
wrapper.findAll('span').at(1).trigger('click');
|
||||
|
||||
expect(callbackSpy.callCount).toBe(1);
|
||||
});
|
||||
});
|
309
web/satellite/tests/unit/common/Pagination.spec.ts
Normal file
309
web/satellite/tests/unit/common/Pagination.spec.ts
Normal file
@ -0,0 +1,309 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import * as sinon from 'sinon';
|
||||
import Pagination from '@/components/common/Pagination.vue';
|
||||
|
||||
describe('Pagination.vue', () => {
|
||||
it('renders correctly', () => {
|
||||
const wrapper = shallowMount(Pagination);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with props', () => {
|
||||
const wrapper = shallowMount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 10,
|
||||
onPageClickCallback: () => new Promise(() => false)
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 2
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: () => false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('inits correctly with totalPageCount equals 10 and current pageNumber in first block', () => {
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 10,
|
||||
onPageClickCallback: () => new Promise(() => false)
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 2
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: () => false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
expect(wrapperData.currentPageNumber).toBe(2);
|
||||
expect(wrapperData.pagesArray.length).toBe(10);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(3);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
expect(wrapper.findAll('span').at(1).classes().includes('selected')).toBe(true);
|
||||
});
|
||||
|
||||
it('inits correctly with totalPageCount equals 10 and current pageNumber in middle block', () => {
|
||||
const wrapper = shallowMount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 12,
|
||||
onPageClickCallback: () => new Promise(() => false)
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 5
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: () => false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
expect(wrapperData.currentPageNumber).toBe(5);
|
||||
expect(wrapperData.pagesArray.length).toBe(12);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(1);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(3);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
});
|
||||
|
||||
it('inits correctly with totalPageCount equals 10 and current pageNumber in last block', () => {
|
||||
const wrapper = shallowMount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 13,
|
||||
onPageClickCallback: () => new Promise(() => false)
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 12
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: () => false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
expect(wrapperData.currentPageNumber).toBe(12);
|
||||
expect(wrapperData.pagesArray.length).toBe(13);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(1);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(3);
|
||||
});
|
||||
|
||||
it('inits correctly with totalPageCount equals 4 and no current pageNumber in query', () => {
|
||||
const wrapper = shallowMount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 4,
|
||||
onPageClickCallback: () => new Promise(() => false)
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: null
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: () => false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
expect(wrapperData.currentPageNumber).toBe(1);
|
||||
expect(wrapperData.pagesArray.length).toBe(4);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(4);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(0);
|
||||
});
|
||||
|
||||
it('behaves correctly on page click', async () => {
|
||||
const routerReplaceSpy = sinon.spy();
|
||||
const callbackSpy = sinon.stub();
|
||||
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 9,
|
||||
onPageClickCallback: callbackSpy
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: null
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: routerReplaceSpy
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
wrapper.findAll('span').at(2).trigger('click');
|
||||
await expect(callbackSpy.callCount).toBe(1);
|
||||
|
||||
expect(routerReplaceSpy.callCount).toBe(1);
|
||||
expect(wrapperData.currentPageNumber).toBe(3);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(1);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(3);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
});
|
||||
|
||||
it('behaves correctly on next page button click', async () => {
|
||||
const routerReplaceSpy = sinon.spy();
|
||||
const callbackSpy = sinon.stub();
|
||||
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 9,
|
||||
onPageClickCallback: callbackSpy
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: null
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: routerReplaceSpy
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
wrapper.findAll('.pagination-container__button').at(1).trigger('click');
|
||||
await expect(callbackSpy.callCount).toBe(1);
|
||||
|
||||
expect(routerReplaceSpy.callCount).toBe(1);
|
||||
expect(wrapperData.currentPageNumber).toBe(2);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(3);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
});
|
||||
|
||||
it('behaves correctly on previous page button click', async () => {
|
||||
const routerReplaceSpy = sinon.spy();
|
||||
const callbackSpy = sinon.stub();
|
||||
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 9,
|
||||
onPageClickCallback: callbackSpy
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 8
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: routerReplaceSpy
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
wrapper.findAll('.pagination-container__button').at(0).trigger('click');
|
||||
await expect(callbackSpy.callCount).toBe(1);
|
||||
|
||||
expect(routerReplaceSpy.callCount).toBe(2);
|
||||
expect(wrapperData.currentPageNumber).toBe(7);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(1);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(3);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
});
|
||||
|
||||
it('behaves correctly on previous page button click when current is 1', async () => {
|
||||
const routerReplaceSpy = sinon.spy();
|
||||
const callbackSpy = sinon.stub();
|
||||
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 9,
|
||||
onPageClickCallback: callbackSpy
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: null
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: routerReplaceSpy
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
wrapper.findAll('.pagination-container__button').at(0).trigger('click');
|
||||
await expect(callbackSpy.callCount).toBe(0);
|
||||
|
||||
expect(routerReplaceSpy.callCount).toBe(0);
|
||||
expect(wrapperData.currentPageNumber).toBe(1);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(3);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(1);
|
||||
});
|
||||
|
||||
it('behaves correctly on next page button click when current is last', async () => {
|
||||
const routerReplaceSpy = sinon.spy();
|
||||
const callbackSpy = sinon.stub();
|
||||
|
||||
const wrapper = mount(Pagination, {
|
||||
propsData: {
|
||||
totalPageCount: 9,
|
||||
onPageClickCallback: callbackSpy
|
||||
},
|
||||
mocks: {
|
||||
$route: {
|
||||
query: {
|
||||
pageNumber: 9
|
||||
}
|
||||
},
|
||||
$router: {
|
||||
replace: routerReplaceSpy
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const wrapperData = wrapper.vm.$data;
|
||||
|
||||
wrapper.findAll('.pagination-container__button').at(1).trigger('click');
|
||||
await expect(callbackSpy.callCount).toBe(0);
|
||||
|
||||
expect(routerReplaceSpy.callCount).toBe(1);
|
||||
expect(wrapperData.currentPageNumber).toBe(9);
|
||||
expect(wrapperData.firstBlockPages.length).toBe(1);
|
||||
expect(wrapperData.middleBlockPages.length).toBe(0);
|
||||
expect(wrapperData.lastBlockPages.length).toBe(3);
|
||||
});
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Pagination.vue renders correctly with props 1`] = `<div class="pages-container"><span class="">1</span><span class="">2</span><span class="selected">3</span><span class="">4</span></div>`;
|
||||
|
||||
exports[`Pagination.vue renders correctly without props 1`] = `<div class="pages-container"></div>`;
|
@ -0,0 +1,42 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Pagination.vue renders correctly 1`] = `
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-container__pages">
|
||||
<div class="pagination-container__button"><svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.80077e-07 4.26316L6 0L6 9L2.80077e-07 4.26316Z" fill="#354049"></path>
|
||||
</svg></div>
|
||||
<div class="pagination-container__items">
|
||||
<pagesblock-stub pages="" checkselected="function () { [native code] }"></pagesblock-stub>
|
||||
<!---->
|
||||
<pagesblock-stub pages="" checkselected="function () { [native code] }"></pagesblock-stub>
|
||||
<!---->
|
||||
<pagesblock-stub pages="" checkselected="function () { [native code] }"></pagesblock-stub>
|
||||
</div>
|
||||
<div class="pagination-container__button"><svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4.73684L0 9L1.20219e-06 -9.53674e-07L6 4.73684Z" fill="#354049"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Pagination.vue renders correctly with props 1`] = `
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-container__pages">
|
||||
<div class="pagination-container__button"><svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.80077e-07 4.26316L6 0L6 9L2.80077e-07 4.26316Z" fill="#354049"></path>
|
||||
</svg></div>
|
||||
<div class="pagination-container__items">
|
||||
<pagesblock-stub pages="[object Object],[object Object],[object Object]" checkselected="function () { [native code] }"></pagesblock-stub> <span>...</span>
|
||||
<pagesblock-stub pages="" checkselected="function () { [native code] }"></pagesblock-stub>
|
||||
<!---->
|
||||
<pagesblock-stub pages="[object Object]" checkselected="function () { [native code] }"></pagesblock-stub>
|
||||
</div>
|
||||
<div class="pagination-container__button"><svg width="6" height="9" viewBox="0 0 6 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4.73684L0 9L1.20219e-06 -9.53674e-07L6 4.73684Z" fill="#354049"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user