UNPKG

clr-angular-static-fix

Version:

1. Install Clarity Icons package through npm:

1,234 lines (1,038 loc) 62.8 kB
/* * Copyright (c) 2016-2018 VMware, Inc. All Rights Reserved. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { Component, DebugElement, QueryList, ViewChild, ViewChildren } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ClrAlert } from '../emphasis/alert/alert'; import { ClrAlertModule } from '../emphasis/alert/alert.module'; import { ClrIconModule } from '../icon/icon.module'; import { ButtonHubService } from './providers/button-hub.service'; import { PageCollectionService } from './providers/page-collection.service'; import { PageCollectionMock } from './providers/page-collection.service.mock'; import { WizardNavigationService } from './providers/wizard-navigation.service'; import { ClrWizard } from './wizard'; import { ClrWizardButton } from './wizard-button'; import { ClrWizardPage } from './wizard-page'; import { MockPage } from './wizard-page.mock'; import { ClrWizardModule } from './wizard.module'; class MyPageCollectionMock extends PageCollectionMock { public previousPage: MockPage; public getPreviousPage() { if (this.previousPage) { return this.previousPage; } return null; } } @Component({ template: ` <clr-wizard-page> <ng-template clrPageTitle>Mandatory Title</ng-template> Hello moto </clr-wizard-page> <clr-wizard-page> <ng-template clrPageTitle>Mandatory Title</ng-template> <ng-template clrPageNavTitle>Optional nav title</ng-template> <ng-template clrPageHeaderActions> <clr-wizard-header-action id="fhtagn">hi</clr-wizard-header-action> </ng-template> Other wizard page needed as competition in tests <ng-template clrPageButtons> <clr-wizard-button [type]="'cancel'">Cancel</clr-wizard-button> </ng-template> </clr-wizard-page> `, }) class TypescriptTestComponent { @ViewChildren(ClrWizardPage) wizardPageChildren: QueryList<ClrWizardPage>; } @Component({ template: ` <clr-wizard-page #nav [(clrWizardPageNextDisabled)]="navTestNextDisabled" [(clrWizardPagePreviousDisabled)]="navTestPreviousDisabled" [(clrWizardPagePreventDefaultCancel)]="navStopCancel" > <ng-template clrPageTitle>Tests of page nav inputs and outputs</ng-template> </clr-wizard-page> <clr-wizard-page #lifecycle> <ng-template clrPageTitle>Tests for lifecycle outputs and event handlers</ng-template> </clr-wizard-page> <clr-wizard-page #other [id]="testId" (clrWizardPageOnLoad)="onLoadCheck($event)" > <ng-template clrPageTitle>Other template API tests</ng-template> </clr-wizard-page> `, }) class TemplateTestComponent { @ViewChild('nav') navigationTemplateTester: ClrWizardPage; @ViewChild('lifecycle') lifecycleTemplateTester: ClrWizardPage; @ViewChild('other') otherTemplateTester: ClrWizardPage; public navTwoWayBindingPassed: boolean = false; public testId = 'ohai'; private _navTestNextDisabled: boolean = false; public get navTestNextDisabled(): boolean { return this._navTestNextDisabled; } public set navTestNextDisabled(val: boolean) { if (val !== this._navTestNextDisabled) { this.navTwoWayBindingPassed = true; this._navTestNextDisabled = val; } } private _navTestPreviousDisabled: boolean = true; public get navTestPreviousDisabled(): boolean { return this._navTestPreviousDisabled; } public set navTestPreviousDisabled(val: boolean) { if (val !== this._navTestPreviousDisabled) { this.navTwoWayBindingPassed = true; this._navTestPreviousDisabled = val; } } private _navStopCancel: boolean = false; public get navStopCancel(): boolean { return this._navStopCancel; } public set navStopCancel(val: boolean) { this.navTwoWayBindingPassed = true; this._navStopCancel = val; } public loadedPageId = ''; public onLoadCheck(pageId: string): void { this.loadedPageId = pageId; } } @Component({ template: ` <clr-wizard #viewTestWizard [(clrWizardOpen)]="open"> <clr-wizard-title>Wizard for Wizard Page View Tests</clr-wizard-title> <clr-wizard-button [type]="'cancel'" #wizardCancelBtn class="clr-test-wizard-cancel">Cancel</clr-wizard-button> <clr-wizard-button [type]="'previous'" class="clrtest-wizard-previous" #wizardPreviousBtn>Back</clr-wizard-button> <clr-wizard-button [type]="'custom-custom'" class="clrtest-wizard-custom">Custom</clr-wizard-button> <clr-wizard-button [type]="'next'" class="clrtest-wizard-next">Next</clr-wizard-button> <clr-wizard-button [type]="'danger'" class="clrtest-wizard-danger">Danger</clr-wizard-button> <clr-wizard-button [type]="'finish'" class="clrtest-wizard-finish">Finish</clr-wizard-button> <clr-wizard-header-action (actionClicked)="headerActionClicked($event)"> <clr-icon shape="cloud" class="is-solid"></clr-icon> </clr-wizard-header-action> <clr-wizard-page #viewTestWizardPageOne [id]="testId" [clrWizardPagePreventDefaultCancel]="preventCancel" > <ng-template clrPageTitle>View Page 1</ng-template> <ng-template clrPageHeaderActions> <clr-wizard-header-action (actionClicked)="headerActionClicked($event)" id="bell"> <clr-icon shape="bell" class="has-badge"></clr-icon> </clr-wizard-header-action> <clr-wizard-header-action (actionClicked)="headerActionClicked($event)" id="warning"> <clr-icon shape="warning"></clr-icon> </clr-wizard-header-action> </ng-template> <ng-template clrPageButtons> <clr-wizard-button [type]="'cancel'" class="clrtest-page-cancel" #pageCancelBtn>Cancel</clr-wizard-button> <clr-wizard-button [type]="'previous'" class="clrtest-page-previous-1">Previous</clr-wizard-button> <clr-wizard-button [type]="'danger'">Caution</clr-wizard-button> </ng-template> </clr-wizard-page> <clr-wizard-page #viewTestWizardPageTwo [(clrWizardPagePreviousDisabled)]="disablePrevious"> <ng-template clrPageTitle>View Page 2</ng-template> <p>{{projector}}</p> </clr-wizard-page> <clr-wizard-page #viewTestWizardPageThree [(clrWizardPagePreviousDisabled)]="disablePrevious"> <ng-template clrPageTitle>View Page 3</ng-template> <ng-template clrPageNavTitle>short title</ng-template> <p *ngIf="!asyncLoaded">Loading...</p> <p *ngIf="asyncLoaded">{{asyncContent}}</p> <ng-template clrPageButtons> <clr-wizard-button [type]="'cancel'">Cancel</clr-wizard-button> <clr-wizard-button [type]="'previous'" #pagePreviousBtn class="clrtest-page-previous-2">Previous</clr-wizard-button> <clr-wizard-button [type]="'danger'">Danger</clr-wizard-button> </ng-template> </clr-wizard-page> <clr-wizard-page #viewTestWizardPageFour [clrWizardPagePreventDefaultCancel]="preventCancel" (clrWizardPageOnCancel)="altCancel()" > <ng-template clrPageTitle>View Page 4</ng-template> <clr-alert [clrAlertClosable]="false"> <div class="alert-item"> <span class="alert-text"> i believe the answer is {{innerProjector/2}} </span> </div> </clr-alert> </clr-wizard-page> </clr-wizard> `, }) class ViewTestComponent { @ViewChild('viewTestWizard') testWizard: ClrWizard; @ViewChild('viewTestWizardPageOne') pageOne: ClrWizardPage; @ViewChild('viewTestWizardPageTwo') pageTwo: ClrWizardPage; @ViewChild('viewTestWizardPageThree') pageThree: ClrWizardPage; @ViewChild('viewTestWizardPageFour') pageFour: ClrWizardPage; @ViewChild('wizardPreviousBtn') wizardPreviousBtn: ClrWizardButton; @ViewChild('pagePreviousBtn') pagePreviousBtn: ClrWizardButton; @ViewChild('wizardCancelBtn') wizardCancelBtn: ClrWizardButton; @ViewChild('pageCancelBtn') pageCancelBtn: ClrWizardButton; public projector = 'my projected content'; public innerProjector = 12; public asyncLoaded = false; public asyncContent = ''; // wizard has to init to open or all the pages are hidden inside modal public open = true; public loadAsync(): void { setTimeout(() => { this.asyncLoaded = true; this.asyncContent = 'better late than never'; }, 100); } public testId = 'ohai'; public disablePrevious = false; public preventCancel = false; public altCancelRan = false; public altCancel() { this.altCancelRan = true; } } @Component({ template: ` <ng-container *ngFor="let page of [0, 1, 2, 3]"> <clr-wizard-page [id]="3 === page ? 'lastpage' : page"> Content for page {{ page }} </clr-wizard-page> </ng-container> `, }) class IdTestComponent { @ViewChildren(ClrWizardPage) pages: QueryList<ClrWizardPage>; } export default function(): void { describe('ClrWizardPage', () => { let fixture: ComponentFixture<any>; let testComponent: TypescriptTestComponent; let testWizardPage: ClrWizardPage; let otherWizardPage: ClrWizardPage; const pageCollection = new MyPageCollectionMock(); let navService: WizardNavigationService; describe('Numeric id bug', () => { let firstPage: ClrWizardPage; let secondPage: ClrWizardPage; let thirdPage: ClrWizardPage; let fourthPage: ClrWizardPage; let myTestComponent: IdTestComponent; beforeEach(() => { TestBed.configureTestingModule({ imports: [ClrWizardModule, ClrAlertModule, NoopAnimationsModule], declarations: [IdTestComponent], providers: [ WizardNavigationService, { provide: PageCollectionService, useValue: pageCollection }, ButtonHubService, ], }); fixture = TestBed.createComponent(IdTestComponent); fixture.detectChanges(); myTestComponent = fixture.componentInstance; firstPage = myTestComponent.pages.toArray()[0]; secondPage = myTestComponent.pages.toArray()[1]; thirdPage = myTestComponent.pages.toArray()[2]; fourthPage = myTestComponent.pages.toArray()[3]; }); afterEach(() => { fixture.destroy(); }); it('should not auto-assign an id of zero', () => { const myId = firstPage.id; let myMungedId: string[]; let generatedId: string; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).toBe('0', 'should pass 0 as id if specified'); }); it('should not pass an id of false', () => { let myId: string; let myMungedId: string[]; let generatedId: string; firstPage._id = false; myId = firstPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).not.toBe('false', 'should not pass false as an id'); }); it('should not pass an id of null', () => { let myId: string; let myMungedId: string[]; let generatedId: string; firstPage._id = null; myId = firstPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).not.toBe('null', 'should not pass null as an id'); }); it('should not pass an id of empty string', () => { let myId: string; let myMungedId: string[]; let generatedId: string; firstPage._id = ''; myId = firstPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).not.toBe('null', 'should not pass null as an id'); }); it('should not pass an undefined id', () => { let myId: string; let myMungedId: string[]; let generatedId: string; firstPage._id = undefined; myId = firstPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).not.toBe('undefined', 'should not pass undefined as an id'); }); it('should not pass a negative number as an id', () => { let myId: string; firstPage._id = -1; myId = firstPage.id; expect(myId).not.toBe('clr-wizard-page--1', 'should not pass a negative number as an id'); }); it('should match numeric ids if passed', () => { // had an issue here because ppl were using indexes as ids and our logic // was not awesome for that let myId = firstPage.id; let myMungedId: string[]; let generatedId: string; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).toBe('0', 'first page id should be 0'); myId = secondPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).toBe('1', 'should pass 1 as id if specified'); myId = thirdPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).toBe('2', 'should pass 2 as id if specified'); myId = fourthPage.id; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; myMungedId = myId.split('-').reverse(); generatedId = myMungedId[0]; expect(generatedId).toBe('lastpage', 'should pass string label as id'); }); }); describe('Typescript API', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ClrWizardModule, NoopAnimationsModule], declarations: [TypescriptTestComponent], providers: [ WizardNavigationService, { provide: PageCollectionService, useValue: pageCollection }, ButtonHubService, ], }); fixture = TestBed.createComponent(TypescriptTestComponent); fixture.detectChanges(); testComponent = fixture.componentInstance; navService = fixture.debugElement.injector.get(WizardNavigationService); testWizardPage = testComponent.wizardPageChildren.toArray()[0]; otherWizardPage = testComponent.wizardPageChildren.toArray()[1]; }); afterEach(() => { fixture.destroy(); }); describe('id', () => { it('should return an indexed id if none is specified', () => { const myId = testWizardPage.id; let myMungedId: string[]; let mungedIdNaN: boolean; expect(myId).toContain('clr-wizard-page-', 'id should contain prefix'); myMungedId = myId.split('-').reverse(); mungedIdNaN = isNaN(Number(myMungedId[0])); expect(mungedIdNaN).toBe(false, 'index should be a number'); }); it('should return expected id', () => { expect(testWizardPage.id).toContain('clr-wizard-page-', 'verify default'); testWizardPage._id = 'ohai'; fixture.detectChanges(); expect(testWizardPage.id).toBe('clr-wizard-page-ohai', 'verify custom id'); }); }); describe('readyToComplete', () => { it('should reflect nextStepDisabled state', () => { // testcomponent's wizard page isn't a part of a wizard so it doesn't preset // nextStepDisabled's value expect(testWizardPage.nextStepDisabled).toBe(false, 'nextStepDisabled initialized to false'); expect(testWizardPage.readyToComplete).toBe(true, 'readyToComplete ' + 'initialized to true'); testWizardPage.nextStepDisabled = true; fixture.detectChanges(); expect(testWizardPage.readyToComplete).toBe( false, 'readyToComplete ' + 'reflect update to nextStepDisabled, part 2' ); }); }); describe('completed', () => { it('should be true if complete and readyToComplete are true', () => { testWizardPage.nextStepDisabled = false; testWizardPage.completed = true; fixture.detectChanges(); expect(testWizardPage.completed).toBe(true); }); it('should return false if not complete', () => { testWizardPage.nextStepDisabled = false; testWizardPage.completed = false; fixture.detectChanges(); expect(testWizardPage.completed).toBe(false); }); it('should return false if not readyToComplete', () => { testWizardPage.nextStepDisabled = true; testWizardPage.completed = true; fixture.detectChanges(); expect(testWizardPage.completed).toBe(false); }); }); describe('current', () => { it('should return false if not current', () => { // make sure another page is current navService.currentPage = otherWizardPage; fixture.detectChanges(); expect(testWizardPage.current).toBe(false); }); it('should be true if page is current', () => { navService.currentPage = testWizardPage; fixture.detectChanges(); expect(testWizardPage.current).toBe(true); }); }); describe('disabled', () => { it('should be reflect enabled status', () => { // enabled full coverage below const dummyPreviousPage = new MockPage(99); pageCollection.previousPage = dummyPreviousPage; dummyPreviousPage.completed = false; navService.currentPage = otherWizardPage; testWizardPage.completed = false; fixture.detectChanges(); expect(testWizardPage.enabled).toBe(false, 'enabled is set to false'); expect(testWizardPage.disabled).toBe(true, 'disabled is true when enabled is false'); navService.currentPage = testWizardPage; expect(testWizardPage.enabled).toBe(true, 'enabled is set to true'); expect(testWizardPage.disabled).toBe(false, 'disabled is false when enabled is true'); }); }); describe('enabled', () => { it('should return true if page is current', () => { navService.currentPage = testWizardPage; fixture.detectChanges(); expect(testWizardPage.enabled).toBe(true); }); it('should return true if page is completed', () => { testWizardPage.completed = true; fixture.detectChanges(); expect(testWizardPage.enabled).toBe(true); }); it('should return true if previous page is completed', () => { const dummyPreviousPage = new MockPage(99); pageCollection.previousPage = dummyPreviousPage; dummyPreviousPage.completed = true; navService.currentPage = otherWizardPage; testWizardPage.completed = false; fixture.detectChanges(); expect(testWizardPage.enabled).toBe(true); }); it('should return false if page is not current or completed or if ' + 'previous page is not completed', () => { const dummyPreviousPage = new MockPage(99); pageCollection.previousPage = dummyPreviousPage; dummyPreviousPage.completed = false; navService.currentPage = otherWizardPage; testWizardPage.completed = false; fixture.detectChanges(); expect(testWizardPage.enabled).toBe(false); }); }); describe('previousCompleted', () => { it('should return true if there is no previous page', () => { pageCollection.previousPage = null; // explicitly remove previous page fixture.detectChanges(); expect(testWizardPage.previousCompleted).toBe(true); }); it('should return true if previous page is completed', () => { const dummyPreviousPage = new MockPage(99); pageCollection.previousPage = dummyPreviousPage; dummyPreviousPage.completed = true; fixture.detectChanges(); expect(testWizardPage.previousCompleted).toBe(true); }); it('should return false if previous page is NOT completed', () => { const dummyPreviousPage = new MockPage(99); pageCollection.previousPage = dummyPreviousPage; dummyPreviousPage.completed = false; // set explicitly fixture.detectChanges(); expect(testWizardPage.previousCompleted).toBe(false); }); }); describe('title', () => { it('should return page title template ref', () => { const testMe = testWizardPage.title; expect(testMe).toBeDefined('title template ref should be a thing'); // expect(testMe).toEqual(jasmine.any(TemplateRef), "page title should be a template ref"); }); }); describe('navTitle', () => { it('should return page nav title template ref instead of page title, if it exists', () => { const testMe = otherWizardPage.navTitle; const notToBe = otherWizardPage.title; // otherpage has a nav title expect(testMe).toBeDefined('nav title template ref should be a thing'); // view piece is covered below; for now, we want to test just the API expect(testMe).not.toBe(notToBe, 'expect titles to be different'); }); it('should return page title if no page nav title is specified', () => { const testMe = testWizardPage.navTitle; const expected = testWizardPage.title; // testpage has no nav title expect(testMe).toBeDefined('nav title template ref should be a thing'); // view piece is covered below; for now, we want to test just the API expect(testMe).toBe(expected, 'expect titles to be the same'); }); }); describe('headerActions', () => { it('should return page header actions if they are present', () => { // other wizard page has header actions const testMe = otherWizardPage.headerActions; expect(testMe).toBeDefined('header actions exist'); }); it('should return undefined if page header actions are not present', () => { // test wizard page has no header actions const testMe = testWizardPage.headerActions; expect(testMe).not.toBeDefined(); }); }); describe('hasHeaderActions', () => { it('should return true if page header actions exist', () => { // other wizard page has header actions const test = otherWizardPage.hasHeaderActions; expect(test).toBe(true); }); it('should return false if no page header actions are present', () => { // test wizard page has no header actions const test = testWizardPage.hasHeaderActions; expect(test).toBe(false); }); }); describe('buttons', () => { it('should return buttons template ref if page has buttons in it', () => { // other wizard page has custom buttons const test = otherWizardPage.buttons; expect(test).toBeDefined('custom buttons exist'); }); it('should return undefined if the page does not have buttons', () => { // test wizard page has no custom buttons const test = testWizardPage.buttons; expect(test).not.toBeDefined(); }); }); describe('hasButtons', () => { it('should return true if page has buttons in it', () => { // other wizard page has custom buttons const test = otherWizardPage.hasButtons; expect(test).toBe(true); }); it('should return false if the page does not have buttons', () => { // test wizard page has no custom buttons const test = testWizardPage.hasButtons; expect(test).toBe(false); }); }); describe('makeCurrent', () => { it('should call the navService to make the page current', () => { testWizardPage.makeCurrent(); expect(navService.currentPage).toBe(testWizardPage); }); it('should emit onLoad event', () => { const eventSpy = spyOn(otherWizardPage.onLoad, 'emit'); otherWizardPage.makeCurrent(); fixture.detectChanges(); expect(eventSpy).toHaveBeenCalled(); }); }); describe('stepItemId', () => { it('calls to page collection service to retrieve related stepnav item id', () => { const testId = testWizardPage.stepItemId; const wasCalled = pageCollection.stepItemIdWasCalled; expect(testId).toBe('mock-id', 'make sure it grabbed id as expected'); expect(wasCalled).toBe(true, 'page routine went through the page collection'); }); }); }); let templateTestComponent: TemplateTestComponent; let lifecycleWizardPage: ClrWizardPage; let navWizardPage: ClrWizardPage; describe('Template API', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ClrWizardModule, NoopAnimationsModule], declarations: [TemplateTestComponent], providers: [ WizardNavigationService, { provide: PageCollectionService, useValue: pageCollection }, ButtonHubService, ], }); fixture = TestBed.createComponent(TemplateTestComponent); fixture.detectChanges(); templateTestComponent = fixture.componentInstance; navService = fixture.debugElement.injector.get(WizardNavigationService); navWizardPage = templateTestComponent.navigationTemplateTester; lifecycleWizardPage = templateTestComponent.lifecycleTemplateTester; otherWizardPage = templateTestComponent.otherTemplateTester; }); afterEach(() => { fixture.destroy(); }); describe('nextStepDisabled input/output/binding', () => { it('should allow for setting input through component', () => { let nextDisabledVal = templateTestComponent.navTestNextDisabled; let wizardPageNextDisabled = navWizardPage.nextStepDisabled; expect(nextDisabledVal).toBe(false, 'expect init value to be false'); expect(wizardPageNextDisabled).toBe( nextDisabledVal, 'expect component value and wizard page value to be the same' ); templateTestComponent.navTestNextDisabled = true; fixture.detectChanges(); // get new values nextDisabledVal = templateTestComponent.navTestNextDisabled; wizardPageNextDisabled = navWizardPage.nextStepDisabled; expect(nextDisabledVal).toBe(true, 'expect updated value to be true'); expect(wizardPageNextDisabled).toBe( nextDisabledVal, 'expect component value and wizard page value to be the same after update' ); }); it('should notify host component when set from somewhere else', () => { const newValue = !templateTestComponent.navTestNextDisabled; const emitSpy = spyOn(navWizardPage.nextStepDisabledChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have passed up from page'); expect(emitSpy).not.toHaveBeenCalled(); navWizardPage.nextStepDisabled = newValue; fixture.detectChanges(); // get new value twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); it('should emit when set through host component', () => { const newValue = !templateTestComponent.navTestNextDisabled; const emitSpy = spyOn(navWizardPage.nextStepDisabledChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have executed'); expect(emitSpy).not.toHaveBeenCalled(); templateTestComponent.navTestNextDisabled = newValue; fixture.detectChanges(); // get new value twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); }); describe('previousStepDisabled', () => { it('should allow for setting input through component', () => { let hostVal = templateTestComponent.navTestPreviousDisabled; let testVal = navWizardPage.previousStepDisabled; expect(hostVal).toBe(true, 'expect init value to be true'); expect(navWizardPage.previousStepDisabled).toBe( hostVal, 'expect component value and wizard page value to be the same' ); templateTestComponent.navTestPreviousDisabled = false; fixture.detectChanges(); // get new values hostVal = templateTestComponent.navTestPreviousDisabled; testVal = navWizardPage.previousStepDisabled; expect(hostVal).toBe(false, 'expect updated value to be false'); expect(testVal).toBe(hostVal, 'expect component value and wizard page value to be the same after update'); }); it('should notify host component when set from somewhere else', () => { const newValue = !templateTestComponent.navTestPreviousDisabled; const emitSpy = spyOn(navWizardPage.previousStepDisabledChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have passed up from page'); expect(emitSpy).not.toHaveBeenCalled(); navWizardPage.previousStepDisabled = newValue; fixture.detectChanges(); // get new vals twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); it('should emit when set through host component', () => { const newValue = !templateTestComponent.navTestPreviousDisabled; const emitSpy = spyOn(navWizardPage.previousStepDisabledChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have executed'); expect(emitSpy).not.toHaveBeenCalled(); templateTestComponent.navTestPreviousDisabled = newValue; fixture.detectChanges(); // new vals twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); }); describe('stopCancel', () => { it('should initialize as false', () => { // not set on other page const test = otherWizardPage.stopCancel; expect(test).toBe(false); }); it('should allow for setting input through component', () => { let hostVal = templateTestComponent.navStopCancel; let testVal = navWizardPage.stopCancel; expect(hostVal).toBe(false, 'expect init value to be false'); expect(testVal).toBe(hostVal, 'expect component value and wizard page value to be the same'); templateTestComponent.navStopCancel = false; fixture.detectChanges(); hostVal = templateTestComponent.navStopCancel; testVal = navWizardPage.stopCancel; expect(hostVal).toBe(false, 'expect updated value to be false'); expect(testVal).toBe(hostVal, 'expect component value and wizard page value to be the same after update'); }); it('should notify host component when set from somewhere else', () => { const newValue = !templateTestComponent.navStopCancel; const emitSpy = spyOn(navWizardPage.stopCancelChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have passed up from page'); expect(emitSpy).not.toHaveBeenCalled(); navWizardPage.stopCancel = newValue; fixture.detectChanges(); twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); it('should emit when set through host component', () => { const newValue = !templateTestComponent.navStopCancel; const emitSpy = spyOn(navWizardPage.stopCancelChange, 'emit').and.callThrough(); let twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(false, 'do not expect binding to have executed'); expect(emitSpy).not.toHaveBeenCalled(); templateTestComponent.navStopCancel = newValue; fixture.detectChanges(); twoWayBindingTest = templateTestComponent.navTwoWayBindingPassed; expect(twoWayBindingTest).toBe(true, 'two-way binding should have notified host'); expect(emitSpy).toHaveBeenCalledWith(newValue); }); }); // TODO: HAVE TO TEST ONCOMMIT AS PART OF PAGE-COLLECTION B/C IT IS ONLY USED THERE // JUST MAKE SURE IT PASSES THE PAGE.ID... describe('onLoad', () => { it('should emit when page is made current and pass page id when emitted', () => { const emitSpy = spyOn(otherWizardPage.onLoad, 'emit').and.callThrough(); expect(templateTestComponent.loadedPageId).not.toBe( otherWizardPage.id, 'other wizard page should not be the current page starting out' ); emitSpy.calls.reset(); otherWizardPage.makeCurrent(); fixture.detectChanges(); expect(emitSpy).toHaveBeenCalledWith(otherWizardPage.id); expect(templateTestComponent.loadedPageId).toBe(otherWizardPage.id); }); it('should not emit when another page is made current', () => { const emitSpy = spyOn(otherWizardPage.onLoad, 'emit').and.callThrough(); lifecycleWizardPage.makeCurrent(); fixture.detectChanges(); expect(emitSpy).not.toHaveBeenCalled(); expect(templateTestComponent.loadedPageId).not.toBe(otherWizardPage.id); }); }); // TODO: BUILD THESE TESTS OUT AT THE WIZARD LEVEL. ONLY WIZARD HANDLES CANCEL/CLOSE // BECAUSE IT NEEDS TO COMMUNICATE WITH MODAL PROPERTIES xdescribe('pageOnCancel', () => { it('should pass page id when emitted', () => {}); it('should only emit once by default', () => {}); it('should only emit once if overridden at page level', () => {}); it('should only emit once if overridden at wizard level', () => {}); }); describe('id', () => { it('should use custom id when defined in input', () => { expect(otherWizardPage.id).toBe('clr-wizard-page-ohai'); }); it('should update id when input is updated', () => { templateTestComponent.testId = 'onoez'; fixture.detectChanges(); expect(otherWizardPage.id).toBe('clr-wizard-page-onoez'); }); it('should use numeric index when input is not defined', () => { const idToTest = navWizardPage.id; const idSplitAndFlipped = idToTest.split('-').reverse(); const idIndex = Number(idSplitAndFlipped[0]); expect(idToTest).toContain('clr-wizard-page-', 'default id should include expected prefix'); expect(isNaN(idIndex)).toBe(false, 'default id should have numeric index'); }); }); describe('onInit', () => { it('should make page current if no current page is defined in navService', () => { // first page in list should be made current when wizard starts up const currentPage = navService.currentPage; expect(currentPage).toBe(navWizardPage); }); it('should not make page current if current page is defined in navService', () => { const currentPage = navService.currentPage; expect(currentPage).not.toBe(otherWizardPage); }); }); }); let viewTestComponent: ViewTestComponent; let allTestPages: DebugElement[]; let pageOne: DebugElement; let pageTwo: DebugElement; let pageThree: DebugElement; let pageFour: DebugElement; describe('View and Behavior', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ClrWizardModule, ClrIconModule, ClrAlertModule, NoopAnimationsModule], declarations: [ViewTestComponent], providers: [WizardNavigationService, PageCollectionService, ButtonHubService], }); fixture = TestBed.createComponent(ViewTestComponent); fixture.detectChanges(); viewTestComponent = fixture.componentInstance; navService = fixture.debugElement.injector.get(WizardNavigationService); allTestPages = fixture.debugElement.queryAll(By.directive(ClrWizardPage)); allTestPages.forEach(thisPage => { switch (thisPage.componentInstance) { case viewTestComponent.pageOne: pageOne = thisPage; break; case viewTestComponent.pageTwo: pageTwo = thisPage; break; case viewTestComponent.pageThree: pageThree = thisPage; break; case viewTestComponent.pageFour: pageFour = thisPage; break; default: break; } }); }); afterEach(() => { fixture.destroy(); }); describe('content', () => { it('should display projected content', () => { expect(pageTwo).toBeTruthy('test page should be in wizard'); expect(pageTwo.nativeElement.textContent.trim()).toBe( viewTestComponent.projector, 'projected content should match content in host component' ); }); it('should update projected content', () => { const oldContent = viewTestComponent.projector; const newContent = 'my updated content'; viewTestComponent.projector = newContent; fixture.detectChanges(); const updatedContent = pageTwo.nativeElement.textContent.trim(); expect(updatedContent).not.toBe(oldContent, 'old content should not be there'); expect(updatedContent).toBe(newContent, 'projected content should be updated'); }); it('should be able to project other components', () => { let myInnerComponent: DebugElement; myInnerComponent = pageFour.query(By.directive(ClrAlert)); expect(myInnerComponent).toBeDefined('inner alert component should exist'); expect(myInnerComponent.nativeElement.textContent.trim()).toContain( 'i believe the answer is 6', 'content should project through to inner components' ); }); it( 'should allow for asynchronous content', fakeAsync(() => { expect(pageThree.nativeElement.textContent.trim()).toBe('Loading...'); viewTestComponent.loadAsync(); tick(120); fixture.detectChanges(); expect(viewTestComponent.asyncLoaded).toBe(true, 'make sure async routine ran'); expect(pageThree.nativeElement.textContent.trim()).toBe('better late than never'); }) ); }); describe('id', () => { let idToTest: string; let idSplitAndFlipped: string[]; let idIndex: number; it('should have its id in the id attribute', () => { expect(pageOne.nativeElement.id).toBe('clr-wizard-page-ohai'); }); it('updating id input should update id attribute', () => { viewTestComponent.testId = 'onoez'; fixture.detectChanges(); expect(pageOne.nativeElement.id).toBe('clr-wizard-page-onoez'); }); it('should have an id even if the id input is not defined', () => { idToTest = pageTwo.nativeElement.id; expect(idToTest).toBeDefined('page id is defined by default'); idSplitAndFlipped = idToTest.split('-').reverse(); idIndex = Number(idSplitAndFlipped[0]); expect(idToTest).toContain('clr-wizard-page-', 'default id should include expected prefix'); expect(isNaN(idIndex)).toBe(false, 'default id should have numeric index'); }); it('should have an id even if id input is changed to falsy', () => { viewTestComponent.testId = null; fixture.detectChanges(); idToTest = pageOne.nativeElement.id; idSplitAndFlipped = idToTest.split('-').reverse(); idIndex = Number(idSplitAndFlipped[0]); expect(idToTest).toBeDefined('id should still exist'); expect(idToTest).not.toBe('clr-wizard-page-null', 'id should not use string value of falsy input'); expect(idToTest).toContain('clr-wizard-page-', 'default id should include expected prefix'); expect(isNaN(idIndex)).toBe(false, 'default id should have numeric index'); }); }); describe('view', () => { it('should have a role of tabpanel', () => { const testMe = pageOne.nativeElement.getAttribute('role'); expect(testMe).toBe('tabpanel'); }); it('aria-hidden should reflect if page is not current', () => { // explicitly set a page to current const expectedPage = pageTwo.componentInstance; let currentPage: ClrWizardPage; let pageOneTest: string; let pageTwoTest: string; let currentPageIdTest: boolean; viewTestComponent.testWizard.next(); fixture.detectChanges(); currentPage = viewTestComponent.testWizard.navService.currentPage; pageOneTest = pageOne.nativeElement.getAttribute('aria-hidden'); pageTwoTest = pageTwo.nativeElement.getAttribute('aria-hidden'); currentPageIdTest = currentPage.id === expectedPage.id; expect(currentPageIdTest).toBe(true, 'make sure current page got set as expected'); // check aria-hidden on non-current page expect(pageOneTest).toBe('true', 'non-current page has aria-hidden true'); expect(pageTwoTest).toBe('false', 'current page has aria-hidden false'); }); it("aria-labelledby should reflect page's stepItemId", () => { const pageColl = viewTestComponent.testWizard.pageCollection; const test = pageOne.nativeElement.getAttribute('aria-labelledby'); const expected = pageColl.getStepItemIdForPage(pageOne.componentInstance); expect(test).toBe(expected); }); it("aria-labelledby should update if page's id is changed", () => { const pageColl = viewTestComponent.testWizard.pageCollection; let labelToTest: string; let expected: string; viewTestComponent.testId = 'onoez'; fixture.detectChanges(); labelToTest = pageOne.nativeElement.getAttribute('aria-labelledby'); expected = pageColl.getStepItemIdForPage(pageOne.componentInstance); expect(labelToTest).toBe(expected, 'updated label should be reflected in component view'); expect(labelToTest).toContain('onoez', 'aria-labelledBy should update'); }); it('should have .clr-wizard-page class', () => { const test = pageThree.nativeElement.classList.contains('clr-wizard-page'); expect(test).toBe(true); }); }); describe('previousStepDisabled', () => { it('should disable previous button at wizard level when set ' + 'and page is the current page', () => { // verify button is not disabled at this point const pageToTest = pageTwo.componentInstance; const wizard = viewTestComponent.testWizard; const debugWiz = fixture.debugElement.query(By.directive(ClrWizard)); let previousBtn: Node; let testIfCurrent: boolean; let wizardBtnDisabled: boolean; // setup wizard.navService.next(); fixture.detectChanges(); testIfCurrent = wizard.navService.currentPage === pageToTest; expect(testIfCurrent).toBe(true, 'expect page to have been made current'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-wizard-previous > button'); expect(previousBtn).not.toBe(null, 'expect wizard buttons to be present'); wizardBtnDisabled = viewTestComponent.wizardPreviousBtn.isDisabled; expect(wizardBtnDisabled).toBe(false, 'expect wizard level button not to be disabled'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-wizard-previous > button.disabled'); expect(previousBtn).toBe(null, 'expect wizard level button to not have disabled class'); viewTestComponent.disablePrevious = true; fixture.detectChanges(); wizardBtnDisabled = viewTestComponent.wizardPreviousBtn.isDisabled; expect(wizardBtnDisabled).toBe(true, 'expect wizard level button to be disabled'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-wizard-previous > button.disabled'); expect(previousBtn).not.toBe(null, 'expect wizard level button to have disabled class'); }); it('should disable previous button at page level when set ' + 'and page is the current page', () => { // verify button is not disabled at this point const pageToTest = pageThree.componentInstance; const wizard = viewTestComponent.testWizard; const debugWiz = fixture.debugElement.query(By.directive(ClrWizard)); let previousBtn: DebugElement; let testIfCurrent: boolean; let wizardBtnDisabled: boolean; // setup -- going to page three wizard.next(); wizard.next(); fixture.detectChanges(); testIfCurrent = wizard.navService.currentPage === pageToTest; expect(testIfCurrent).toBe(true, 'expect page to have been made current'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-page-previous-2'); expect(previousBtn).not.toBe(null, 'expect page buttons to be present'); wizardBtnDisabled = viewTestComponent.pagePreviousBtn.isDisabled; expect(wizardBtnDisabled).toBe(false, 'expect page level button not to be disabled'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-page-previous-2 > button.disabled'); expect(previousBtn).toBe(null, 'expect page level button to not have disabled class'); viewTestComponent.disablePrevious = true; fixture.detectChanges(); wizardBtnDisabled = viewTestComponent.pagePreviousBtn.isDisabled; expect(wizardBtnDisabled).toBe(true, 'expect page level button to be disabled'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-page-previous-2 > button.disabled'); expect(previousBtn).not.toBe(null, 'expect page level button to have disabled class'); }); }); describe('buttons', () => { it('should not show page-level buttons when page is not current', () => { const pageToTest = pageThree.componentInstance; const wizard = viewTestComponent.testWizard; const debugWiz = fixture.debugElement.query(By.directive(ClrWizard)); let previousBtn: HTMLElement; let testIfCurrent: boolean; // setup wizard.next(); viewTestComponent.disablePrevious = true; fixture.detectChanges(); testIfCurrent = wizard.navService.currentPage === pageToTest; expect(testIfCurrent).not.toBe(true, 'expect page not to be current'); previousBtn = debugWiz.nativeElement.querySelector('.clrtest-page-previous-2 > button'); // absent query result is null expect(previousBtn).toBeNull('page-level buttons should not be here'); }); }); descri