Add pagination component

This commit is contained in:
Giuseppe Digilio
2017-05-19 18:22:41 +02:00
parent e36ebcd72e
commit 412a3a3970
21 changed files with 783 additions and 27 deletions

View File

@@ -0,0 +1,321 @@
// ... test imports
import {
async,
ComponentFixture,
inject,
TestBed, fakeAsync, tick, getTestBed
} from '@angular/core/testing';
import {
Component,
CUSTOM_ELEMENTS_SCHEMA,
DebugElement
} from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { RouterTestingModule } from '@angular/router/testing';
import { By } from '@angular/platform-browser';
import Spy = jasmine.Spy;
import { TranslateModule, TranslateLoader } from "ng2-translate";
import { Store, StoreModule } from "@ngrx/store";
// Load the implementations that should be tested
import { CommonModule } from '@angular/common';
import { Ng2PaginationModule } from 'ng2-pagination';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { PaginationComponent } from './pagination.component';
import { PaginationOptions } from '../../core/shared/pagination-options.model';
import { MockTranslateLoader } from "../testing/mock-translate-loader";
import { GLOBAL_CONFIG, EnvConfig } from '../../../config';
import { MockStore, MockAction } from "../testing/mock-store";
import { ActivatedRouteStub, RouterStub } from "../testing/router-stubs";
function createTestComponent<T>(html: string, type: {new (...args: any[]): T}): ComponentFixture<T> {
TestBed.overrideComponent(type, {
set: { template: html }
});
let fixture = TestBed.createComponent(type);
fixture.detectChanges();
return fixture as ComponentFixture<T>;
}
function expectPages(fixture: ComponentFixture<any>, pagesDef: string[]): void {
let de = fixture.debugElement.query(By.css('.pagination'));
let pages = de.nativeElement.querySelectorAll('li');
expect(pages.length).toEqual(pagesDef.length);
for (let i = 0; i < pagesDef.length; i++) {
let pageDef = pagesDef[i];
let classIndicator = pageDef.charAt(0);
if (classIndicator === '+') {
expect(pages[i].classList.contains("active")).toBeTruthy();
expect(pages[i].classList.contains("disabled")).toBeFalsy();
expect(normalizeText(pages[i].textContent)).toEqual(pageDef.substr(1) + ' (current)');
} else if (classIndicator === '-') {
expect(pages[i].classList.contains("active")).toBeFalsy();
expect(pages[i].classList.contains("disabled")).toBeTruthy();
expect(normalizeText(pages[i].textContent)).toEqual(pageDef.substr(1));
if (normalizeText(pages[i].textContent) !== '...') {
expect(pages[i].querySelector('a').getAttribute('tabindex')).toEqual('-1');
}
} else {
expect(pages[i].classList.contains("active")).toBeFalsy();
expect(pages[i].classList.contains("disabled")).toBeFalsy();
expect(normalizeText(pages[i].textContent)).toEqual(pageDef);
if (normalizeText(pages[i].textContent) !== '...') {
expect(pages[i].querySelector('a').hasAttribute('tabindex')).toBeFalsy();
}
}
}
}
function changePageSize(fixture: ComponentFixture<any>, pageSize: string): void {
let buttonEl = fixture.nativeElement.querySelector('#paginationControls');
let activatedRouteStub: ActivatedRouteStub;
let routerStub: RouterStub;
buttonEl.click();
let dropdownMenu = fixture.debugElement.query(By.css('#paginationControlsDropdownMenu'));
let buttons = dropdownMenu.nativeElement.querySelectorAll('button');
for (let i = 0; i < buttons.length; i++) {
if (buttons[i].textContent.trim() == pageSize) {
buttons[i].click();
fixture.detectChanges();
break;
}
}
}
function changePage(fixture: ComponentFixture<any>, idx: number): void {
let de = fixture.debugElement.query(By.css('.pagination'));
let buttons = de.nativeElement.querySelectorAll('li');
buttons[idx].querySelector('a').click();
fixture.detectChanges();
}
function normalizeText(txt: string): string {
return txt.trim().replace(/\s+/g, ' ');
}
describe('Pagination component', () => {
let fixture: ComponentFixture<PaginationComponent>;
let comp: PaginationComponent;
let testComp: TestComponent;
let testFixture: ComponentFixture<TestComponent>;
let de: DebugElement;
let html;
let mockStore: any;
let activatedRouteStub: ActivatedRouteStub;
let routerStub: RouterStub;
//Define initial state and test state
let _initialState = { width: 1600, height: 770, breakPoint: 'xl' };
// async beforeEach
beforeEach(async(() => {
activatedRouteStub = new ActivatedRouteStub();
routerStub = new RouterStub();
mockStore = new MockStore(_initialState);
TestBed.configureTestingModule({
imports: [CommonModule, StoreModule.provideStore({}), TranslateModule.forRoot({
provide: TranslateLoader,
useClass: MockTranslateLoader
}), Ng2PaginationModule, NgbModule.forRoot(),
RouterTestingModule.withRoutes([
{path: 'home', component: TestComponent}
])],
declarations: [PaginationComponent, TestComponent], // declare the test component
providers: [
{ provide: ActivatedRoute, useValue: activatedRouteStub },
{ provide: GLOBAL_CONFIG, useValue: EnvConfig },
{ provide: Router, useValue: routerStub },
{ provide: Store, useValue: mockStore },
PaginationComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
}));
// synchronous beforeEach
beforeEach(() => {
html = `
<ds-pagination #p="paginationComponent"
[paginationOptions]="paginationOptions"
[collectionSize]="collectionSize"
(pageChange)="pageChanged($event)"
(pageSizeChange)="pageSizeChanged($event)">
<ul>
<li *ngFor="let item of collection | paginate: { itemsPerPage: paginationOptions.pageSize,
currentPage: paginationOptions.currentPage, totalItems: collectionSize }"> {{item}} </li>
</ul>
</ds-pagination>`;
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
testComp = testFixture.componentInstance;
});
it('should create Pagination Component', inject([PaginationComponent], (app: PaginationComponent) => {
expect(app).toBeDefined();
}));
it('should render', () => {
expect(testComp.paginationOptions.id).toEqual('test');
expect(testComp.paginationOptions.currentPage).toEqual(1);
expect(testComp.paginationOptions.pageSize).toEqual(10);
expectPages(testFixture, ['-«', '+1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '»']);
});
it('should render and respond to page change', () => {
testComp.collectionSize = 30;
changePage(testFixture, 3);
expectPages(testFixture, ['«', '1', '2', '+3', '-»']);
changePage(testFixture, 0);
expectPages(testFixture, ['«', '1', '+2', '3', '»']);
});
it('should render and respond to collectionSize change', () => {
testComp.collectionSize = 30;
testFixture.detectChanges();
expectPages(testFixture, ['-«', '+1', '2', '3', '»']);
testComp.collectionSize = 40;
testFixture.detectChanges();
expectPages(testFixture, ['-«', '+1', '2', '3', '4', '»']);
});
it('should render and respond to pageSize change', () => {
testComp.collectionSize = 30;
testFixture.detectChanges();
expectPages(testFixture, ['-«', '+1', '2', '3', '»']);
changePageSize(testFixture, '5');
expectPages(testFixture, ['-«', '+1', '2', '3', '4', '5', '6', '»']);
changePageSize(testFixture, '10');
expectPages(testFixture, ['-«', '+1', '2', '3', '»']);
changePageSize(testFixture, '20');
expectPages(testFixture, ['-«', '+1', '2', '»']);
});
it('should emit pageChange event with correct value', fakeAsync(() => {
spyOn(testComp, 'pageChanged');
changePage(testFixture, 3);
tick();
expect(testComp.pageChanged).toHaveBeenCalledWith(3);
}));
it('should emit pageSizeChange event with correct value', fakeAsync(() => {
spyOn(testComp, 'pageSizeChanged');
changePageSize(testFixture, '5');
tick();
expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5);
}));
it('should set correct route parameters', fakeAsync(() => {
let paginationComponent: PaginationComponent = testFixture
.debugElement.query(By.css('ds-pagination')).references['p'];
routerStub = testFixture.debugElement.injector.get(Router);
testComp.collectionSize = 60;
changePage(testFixture, 3);
tick();
expect(routerStub.navigate).toHaveBeenCalledWith([{pageId: 'test', page: 3, pageSize: 10}]);
expect(paginationComponent.currentPage).toEqual(3);
changePageSize(testFixture, '20');
tick();
expect(routerStub.navigate).toHaveBeenCalledWith([{pageId: 'test', page: 3, pageSize: 20}]);
expect(paginationComponent.pageSize).toEqual(20);
}));
it('should get parameters from route', () => {
activatedRouteStub = testFixture.debugElement.injector.get(ActivatedRoute);
activatedRouteStub.testParams = {
pageId: 'test',
page: 2,
pageSize: 20
};
testFixture.detectChanges();
expectPages(testFixture, ['«', '1', '+2', '3', '4', '5', '»']);
expect(testComp.paginationOptions.currentPage).toEqual(2);
expect(testComp.paginationOptions.pageSize).toEqual(20);
activatedRouteStub.testParams = {
pageId: 'test',
page: 3,
pageSize: 40
};
testFixture.detectChanges();
expectPages(testFixture, ['«', '1', '2', '+3', '-»']);
expect(testComp.paginationOptions.currentPage).toEqual(3);
expect(testComp.paginationOptions.pageSize).toEqual(40);
});
it('should respond to windows resize', () => {
let paginationComponent: PaginationComponent = testFixture
.debugElement.query(By.css('ds-pagination')).references['p'];
mockStore = testFixture.debugElement.injector.get(Store);
mockStore.nextState({ width: 400, height: 770, breakPoint: 'xs' });
mockStore.select('hostWindow').subscribe((state) => {
paginationComponent.windowBreakPoint = state;
testFixture.detectChanges();
expectPages(testFixture, ['-«', '+1', '2', '3', '4', '5', '-...', '10', '»']);
de = testFixture.debugElement.query(By.css('ul.pagination'));
expect(de.nativeElement.classList.contains("pagination-sm")).toBeTruthy();
});
});
});
// declare a test component
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
collection: string[] = [];
collectionSize: number;
paginationOptions = new PaginationOptions();
constructor() {
this.collection = Array.from(new Array(100), (x, i) => `item ${i + 1}`);
this.collectionSize = 100;
this.paginationOptions.id = 'test';
}
pageChanged(page) {
this.paginationOptions.currentPage = page;
}
pageSizeChanged(pageSize) {
this.paginationOptions.pageSize = pageSize;
}
}