// ... test imports import { async, ComponentFixture, inject, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; import { By } from '@angular/platform-browser'; import { Observable } from "rxjs"; import { RouterTestingModule } from '@angular/router/testing'; import Spy = jasmine.Spy; import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { 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 { PaginationComponentOptions } from './pagination-component-options.model'; import { MockTranslateLoader } from "../testing/mock-translate-loader"; import { GLOBAL_CONFIG, EnvConfig } from '../../../config'; import { ActivatedRouteStub, RouterStub } from "../testing/router-stubs"; import { HostWindowService } from "../host-window.service"; import { EnumKeysPipe } from "../utils/enum-keys-pipe"; import { SortOptions } from "../../core/cache/models/sort-options.model"; function createTestComponent(html: string, type: {new (...args: any[]): T}): ComponentFixture { TestBed.overrideComponent(type, { set: { template: html } }); let fixture = TestBed.createComponent(type); fixture.detectChanges(); return fixture as ComponentFixture; } function expectPages(fixture: ComponentFixture, 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)); } 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, 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, 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; let comp: PaginationComponent; let testComp: TestComponent; let testFixture: ComponentFixture; let de: DebugElement; let html; let hostWindowServiceStub: HostWindowServiceStub; let activatedRouteStub: ActivatedRouteStub; let routerStub: RouterStub; //Define initial state and test state let _initialState = { width: 1600, height: 770 }; // async beforeEach beforeEach(async(() => { activatedRouteStub = new ActivatedRouteStub(); routerStub = new RouterStub(); hostWindowServiceStub = new HostWindowServiceStub(_initialState.width); TestBed.configureTestingModule({ imports: [CommonModule, StoreModule.provideStore({}), TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: MockTranslateLoader } }), Ng2PaginationModule, NgbModule.forRoot(), RouterTestingModule.withRoutes([ {path: 'home', component: TestComponent} ])], declarations: [PaginationComponent, TestComponent, EnumKeysPipe], // declare the test component providers: [ { provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: GLOBAL_CONFIG, useValue: EnvConfig }, { provide: Router, useValue: routerStub }, { provide: HostWindowService, useValue: hostWindowServiceStub }, PaginationComponent ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); })); // synchronous beforeEach beforeEach(() => { html = `
  • {{item}}
`; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; 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, ['-« Previous', '+1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '» Next']); }); it('should render and respond to page change', () => { testComp.collectionSize = 30; changePage(testFixture, 3); expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); changePage(testFixture, 0); expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']); }); it('should render and respond to collectionSize change', () => { testComp.collectionSize = 30; testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); testComp.collectionSize = 40; testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '» Next']); }); it('should render and respond to pageSize change', () => { testComp.collectionSize = 30; testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); changePageSize(testFixture, '5'); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']); changePageSize(testFixture, '10'); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); changePageSize(testFixture, '20'); expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']); }); 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([], { queryParams: { pageId: 'test', page: 3, pageSize: 10, sortDirection: 0, sortField: 'name' } }); expect(paginationComponent.currentPage).toEqual(3); changePageSize(testFixture, '20'); tick(); expect(routerStub.navigate).toHaveBeenCalledWith([], { queryParams: { pageId: 'test', page: 3, pageSize: 20, sortDirection: 0, sortField: 'name' } }); 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, ['« Previous', '1', '+2', '3', '4', '5', '» Next']); expect(testComp.paginationOptions.currentPage).toEqual(2); expect(testComp.paginationOptions.pageSize).toEqual(20); activatedRouteStub.testParams = { pageId: 'test', page: 3, pageSize: 40 }; testFixture.detectChanges(); expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); 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']; hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService); hostWindowServiceStub.setWidth(400); hostWindowServiceStub.isXs().subscribe((status) => { paginationComponent.isXs = status; testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '-...', '10', '» Next']); de = testFixture.debugElement.query(By.css('ul.pagination')); expect(de.nativeElement.classList.contains("pagination-sm")).toBeTruthy(); }); }); }); // declare a test component @Component({selector: 'ds-test-cmp', template: ''}) class TestComponent { collection: string[] = []; collectionSize: number; paginationOptions = new PaginationComponentOptions(); sortOptions = new SortOptions(); 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; } } // declare a stub service class HostWindowServiceStub { private width: number; constructor(width) { this.setWidth(width); } setWidth(width) { this.width = width; } isXs(): Observable { return Observable.of(this.width < 576); } }