From fc78aeacc9b9c0da9c0fd13ed0b036892810b7a5 Mon Sep 17 00:00:00 2001 From: sshijun Date: Mon, 6 Jan 2020 15:58:36 +0800 Subject: [PATCH] Add more UT Signed-off-by: sshijun --- .../confirmation-dialog.component.spec.ts | 105 ++++++++++++++++++ .../operation/operation.component.spec.ts | 86 ++++++++++++++ .../operation/operation.component.ts | 6 +- .../operation/operation.service.spec.ts | 23 ++++ 4 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 src/portal/src/lib/components/confirmation-dialog/confirmation-dialog.component.spec.ts create mode 100644 src/portal/src/lib/components/operation/operation.component.spec.ts create mode 100644 src/portal/src/lib/components/operation/operation.service.spec.ts diff --git a/src/portal/src/lib/components/confirmation-dialog/confirmation-dialog.component.spec.ts b/src/portal/src/lib/components/confirmation-dialog/confirmation-dialog.component.spec.ts new file mode 100644 index 000000000..cb248288c --- /dev/null +++ b/src/portal/src/lib/components/confirmation-dialog/confirmation-dialog.component.spec.ts @@ -0,0 +1,105 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { HarborLibraryModule } from '../../harbor-library.module'; +import { ConfirmationDialogComponent } from './confirmation-dialog.component'; +import { IServiceConfig, SERVICE_CONFIG } from '../../entities/service.config'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ConfirmationTargets } from '../../entities/shared.const'; +import { ConfirmationMessage } from './confirmation-message'; +import { BatchInfo } from './confirmation-batch-message'; + + +describe('ConfirmationDialogComponent', () => { + + let comp: ConfirmationDialogComponent; + let fixture: ComponentFixture; + let config: IServiceConfig = { + configurationEndpoint: '/api/configurations/testing' + }; + const deletionMessage: ConfirmationMessage = new ConfirmationMessage( + "MEMBER.DELETION_TITLE", + "MEMBER.DELETION_SUMMARY", + "user1", + {}, + ConfirmationTargets.CONFIG + ); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + HarborLibraryModule, + BrowserAnimationsModule + ], + providers: [ + {provide: SERVICE_CONFIG, useValue: config} + ] + }); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfirmationDialogComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(comp).toBeTruthy(); + }); + it('should open dialog and show right buttons', async () => { + let message = deletionMessage; + let buttons: HTMLElement; + comp.open(message); + fixture.detectChanges(); + await fixture.whenStable(); + buttons = fixture.nativeElement.querySelector('.modal-footer button'); + expect(buttons.textContent).toEqual('BUTTON.CANCEL'); + message.buttons = 1; + comp.open(message); + fixture.detectChanges(); + await fixture.whenStable(); + buttons = fixture.nativeElement.querySelector('.modal-footer button'); + expect(buttons.textContent).toEqual('BUTTON.NO'); + message.buttons = 3; + comp.open(message); + fixture.detectChanges(); + await fixture.whenStable(); + buttons = fixture.nativeElement.querySelector('.modal-footer button'); + expect(buttons.textContent).toEqual('BUTTON.CLOSE'); + }); + it('check cancel and confirm function', async () => { + let buttons: HTMLElement; + comp.opened = true; + comp.message = null; + fixture.detectChanges(); + await fixture.whenStable(); + comp.cancel(); + fixture.detectChanges(); + await fixture.whenStable(); + buttons = fixture.nativeElement.querySelector('.modal-footer button'); + expect(buttons).toBeFalsy(); + comp.open(deletionMessage); + fixture.detectChanges(); + await fixture.whenStable(); + comp.confirm(); + fixture.detectChanges(); + await fixture.whenStable(); + buttons = fixture.nativeElement.querySelector('.modal-footer button'); + expect(buttons).toBeFalsy(); + }); + it('check colorChange and toggleErrorTitle functions', () => { + let batchInfo = new BatchInfo(); + const resultColor1: string = comp.colorChange(batchInfo); + expect(resultColor1).toEqual("green"); + batchInfo.errorState = true; + const resultColor2: string = comp.colorChange(batchInfo); + expect(resultColor2).toEqual("red"); + batchInfo.loading = true; + const resultColor3: string = comp.colorChange(batchInfo); + expect(resultColor3).toEqual("#666"); + const errorSpan: HTMLSpanElement = document.createElement('span'); + errorSpan.style.display = "none"; + comp.toggleErrorTitle(errorSpan); + expect(errorSpan.style.display).toEqual('block'); + comp.toggleErrorTitle(errorSpan); + expect(errorSpan.style.display).toEqual('none'); + }); +}); diff --git a/src/portal/src/lib/components/operation/operation.component.spec.ts b/src/portal/src/lib/components/operation/operation.component.spec.ts new file mode 100644 index 000000000..98419e10b --- /dev/null +++ b/src/portal/src/lib/components/operation/operation.component.spec.ts @@ -0,0 +1,86 @@ +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { TranslateService } from "@ngx-translate/core"; +import { OperationComponent } from './operation.component'; +import { OperationService } from './operation.service'; +import { HarborLibraryModule } from '../../harbor-library.module'; +import { IServiceConfig, SERVICE_CONFIG } from '../../entities/service.config'; +import { OperateInfo } from './operate'; + +describe('OperationComponent', () => { + + let component: OperationComponent; + let fixture: ComponentFixture; + let config: IServiceConfig = { + configurationEndpoint: '/api/configurations/testing' + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HarborLibraryModule, + BrowserAnimationsModule, + ], + providers: [ + OperationService, + TranslateService, + {provide: SERVICE_CONFIG, useValue: config} + ] + }); + }); + beforeEach(() => { + fixture = TestBed.createComponent(OperationComponent); + component = fixture.componentInstance; + component.animationState = 'out'; + fixture.detectChanges(); + }); + it('should create', () => { + expect(component).toBeTruthy(); + }); + it('should automatically close', fakeAsync(async () => { + component.animationState = "in"; + fixture.detectChanges(); + // wait animation finishing + tick(1000); + await fixture.whenStable(); + const container: HTMLDivElement = fixture.nativeElement.querySelector(".operDiv"); + container.dispatchEvent(new Event('mouseleave')); + fixture.detectChanges(); + // wait animation finishing + tick(10000); + await fixture.whenStable(); + const right: string = getComputedStyle(fixture.nativeElement.querySelector(".operDiv")).right; + expect(right).toEqual("-325px"); + })); + it("should show '50+' after pushing 60 new operateInfos", fakeAsync(() => { + const operationService: OperationService = TestBed.get(OperationService); + for (let i = 0; i < 60; i++) { + let operateInfo = new OperateInfo(); + if (i > 19) { + operateInfo.state = "progressing"; + } + if ( i > 39 ) { + operateInfo.state = "failure"; + } + tick(50000); + operationService.publishInfo(operateInfo); + } + fixture.detectChanges(); + const toolBar: HTMLAnchorElement = fixture.nativeElement.querySelector(".toolBar"); + expect(toolBar.textContent).toContain('50+'); + })); + it('check toggleTitle function', () => { + const errorSpan: HTMLSpanElement = document.createElement('span'); + errorSpan.style.display = "none"; + component.toggleTitle(errorSpan); + expect(errorSpan.style.display).toEqual('block'); + component.toggleTitle(errorSpan); + expect(errorSpan.style.display).toEqual('none'); + }); + it('check calculateTime function', () => { + expect(component.calculateTime(1000)).toEqual('less than 1 minute'); + expect(component.calculateTime(61000)).toEqual('1 minute(s) ago'); + expect(component.calculateTime(3601000)).toEqual('1 hour(s) ago'); + expect(component.calculateTime(24 * 3601000)).toEqual('1 day(s) ago'); + }); +}); diff --git a/src/portal/src/lib/components/operation/operation.component.ts b/src/portal/src/lib/components/operation/operation.component.ts index 4042cfdc9..bfe78d8ac 100644 --- a/src/portal/src/lib/components/operation/operation.component.ts +++ b/src/portal/src/lib/components/operation/operation.component.ts @@ -47,7 +47,7 @@ export class OperationComponent implements OnInit, OnDestroy { getNewMessageCountStr(): string { if (this._newMessageCount) { if (this._newMessageCount > 50) { - return this._newMessageCount + '+'; + return 50 + '+'; } return this._newMessageCount.toString(); } @@ -154,9 +154,9 @@ export class OperationComponent implements OnInit, OnDestroy { } else if (dist >= 60 && Math.floor(dist / 60) < 24) { return Math.floor(dist / 60) + ' hour(s) ago'; } else if (Math.floor(dist / 60) >= 24) { - return Math.floor(dist / 60 / 24) + ' day ago'; + return Math.floor(dist / 60 / 24) + ' day(s) ago'; } else { - return 'less 1 minute'; + return 'less than 1 minute'; } } diff --git a/src/portal/src/lib/components/operation/operation.service.spec.ts b/src/portal/src/lib/components/operation/operation.service.spec.ts new file mode 100644 index 000000000..51e29d7a6 --- /dev/null +++ b/src/portal/src/lib/components/operation/operation.service.spec.ts @@ -0,0 +1,23 @@ +import { OperationService } from './operation.service'; +import { Subscription } from 'rxjs'; +import { OperateInfo } from './operate'; + +let sub: Subscription; + +describe('OperationService', () => { + afterEach(() => { + if (sub) { + sub.unsubscribe(); + sub = null; + } + }); + it('should be created', () => { + let operateInfo: OperateInfo; + const operationService = new OperationService(); + sub = operationService.operationInfo$.subscribe(res => { + operateInfo = res; + }); + operationService.publishInfo(new OperateInfo()); + expect(operateInfo.timeDiff).toEqual("less 1 minute"); + }); +});