diff --git a/ui/src/app/metadata/domain/entity/filter/entity-attributes-filter.spec.ts b/ui/src/app/metadata/domain/entity/filter/entity-attributes-filter.spec.ts index 04d1234be..22eae4cda 100644 --- a/ui/src/app/metadata/domain/entity/filter/entity-attributes-filter.spec.ts +++ b/ui/src/app/metadata/domain/entity/filter/entity-attributes-filter.spec.ts @@ -13,5 +13,9 @@ describe('EntityAttributesFilter Entity', () => { expect(entity).toBeDefined(); expect(entity.resourceId).toBe('foo'); expect(entity.enabled).toBe(entity.filterEnabled); + expect(entity.id).toBe(entity.resourceId); + expect(entity.getId()).toBe(entity.entityId); + expect(entity.getDisplayId()).toBe(entity.entityId); + expect(entity.isDraft()).toBe(false); }); }); diff --git a/ui/src/app/metadata/provider/component/unsaved-provider.dialog.spec.ts b/ui/src/app/metadata/provider/component/unsaved-provider.dialog.spec.ts new file mode 100644 index 000000000..e9f0e4554 --- /dev/null +++ b/ui/src/app/metadata/provider/component/unsaved-provider.dialog.spec.ts @@ -0,0 +1,46 @@ +import { Component, ViewChild } from '@angular/core'; +import { TestBed, async, ComponentFixture} from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { SharedModule } from '../../../shared/shared.module'; +import { UnsavedProviderComponent } from './unsaved-provider.dialog'; +import { NgbActiveModalStub } from '../../../../testing/modal.stub'; + +@Component({ + template: ` + + ` +}) +class TestHostComponent { + @ViewChild(UnsavedProviderComponent) + public componentUnderTest: UnsavedProviderComponent; +} + +describe('Unsaved Provider Dialog Component', () => { + + let fixture: ComponentFixture; + let instance: TestHostComponent; + let cmp: UnsavedProviderComponent; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [], + declarations: [ + UnsavedProviderComponent, + TestHostComponent + ], + providers: [ + { provide: NgbActiveModal, useClass: NgbActiveModalStub } + ] + }).compileComponents(); + + fixture = TestBed.createComponent(TestHostComponent); + instance = fixture.componentInstance; + cmp = instance.componentUnderTest; + fixture.detectChanges(); + })); + + it('should instantiate the component', async(() => { + expect(cmp).toBeTruthy(); + })); +}); diff --git a/ui/src/app/metadata/provider/component/unsaved-provider.dialog.ts b/ui/src/app/metadata/provider/component/unsaved-provider.dialog.ts index beafacf87..4b8d12da3 100644 --- a/ui/src/app/metadata/provider/component/unsaved-provider.dialog.ts +++ b/ui/src/app/metadata/provider/component/unsaved-provider.dialog.ts @@ -14,8 +14,7 @@ export class UnsavedProviderComponent { readonly subject: Subject = new Subject(); constructor( - public activeModal: NgbActiveModal, - private store: Store + public activeModal: NgbActiveModal ) { } close(): void { diff --git a/ui/src/app/metadata/provider/container/provider-edit.component.spec.ts b/ui/src/app/metadata/provider/container/provider-edit.component.spec.ts index a62734833..05cb75832 100644 --- a/ui/src/app/metadata/provider/container/provider-edit.component.spec.ts +++ b/ui/src/app/metadata/provider/container/provider-edit.component.spec.ts @@ -1,10 +1,10 @@ import { Component, ViewChild } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, ActivatedRouteSnapshot } from '@angular/router'; import { APP_BASE_HREF } from '@angular/common'; -import { TestBed, async, ComponentFixture } from '@angular/core/testing'; +import { TestBed, async, ComponentFixture, fakeAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { StoreModule, Store, combineReducers } from '@ngrx/store'; -import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgbDropdownModule, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ProviderEditComponent } from './provider-edit.component'; import * as fromRoot from '../reducer'; import * as fromWizard from '../../../wizard/reducer'; @@ -12,6 +12,9 @@ import { SharedModule } from '../../../shared/shared.module'; import { ActivatedRouteStub } from '../../../../testing/activated-route.stub'; import { FileBackedHttpMetadataProviderEditor } from '../model'; import { ProviderEditorNavComponent } from '../component/provider-editor-nav.component'; +import { NgbModalStub } from '../../../../testing/modal.stub'; +import { MetadataProvider } from '../../domain/model'; +import { of } from 'rxjs'; @Component({ template: ` @@ -32,6 +35,7 @@ describe('Provider Edit Component', () => { let router: Router; let activatedRoute: ActivatedRouteStub = new ActivatedRouteStub(); let child: ActivatedRouteStub = new ActivatedRouteStub(); + let modal: NgbModal; child.testParamMap = { form: 'common' }; activatedRoute.firstChild = child; @@ -60,6 +64,7 @@ describe('Provider Edit Component', () => { ProviderEditorNavComponent ], providers: [ + { provide: NgbModal, useClass: NgbModalStub }, { provide: ActivatedRoute, useValue: activatedRoute }, { provide: APP_BASE_HREF, useValue: '/' } ] @@ -67,6 +72,7 @@ describe('Provider Edit Component', () => { store = TestBed.get(Store); router = TestBed.get(Router); + modal = TestBed.get(NgbModal); spyOn(store, 'dispatch'); fixture = TestBed.createComponent(TestHostComponent); @@ -104,8 +110,46 @@ describe('Provider Edit Component', () => { describe('cancel method', () => { it('should route to the metadata manager', () => { spyOn(router, 'navigate'); + spyOn(app, 'clear'); app.cancel(); expect(router.navigate).toHaveBeenCalled(); + expect(app.clear).toHaveBeenCalled(); + }); + }); + + describe('clear method', () => { + it('should dispatch actions to clear the reducer state', () => { + app.clear(); + expect(store.dispatch).toHaveBeenCalled(); + }); + }); + + describe('canDeactivate method', () => { + it('should check if the current route is another edit page', (done) => { + let route = new ActivatedRouteStub(), + snapshot = route.snapshot; + let result = app.canDeactivate(null, { url: 'edit', root: null }, { url: 'edit', root: null }); + result.subscribe(can => { + expect(can).toBe(true); + done(); + }); + fixture.detectChanges(); + }); + + it('should open a modal', (done) => { + app.latest = { name: 'bar' }; + spyOn(store, 'select').and.returnValue(of(false)); + spyOn(modal, 'open').and.returnValue({ result: Promise.resolve('closed') }); + fixture.detectChanges(); + let route = new ActivatedRouteStub(), + snapshot = route.snapshot; + let result = app.canDeactivate(null, { url: 'edit', root: null }, { url: 'foo', root: null }); + result.subscribe(can => { + expect(can).toBe(false); + expect(modal.open).toHaveBeenCalled(); + done(); + }); + fixture.detectChanges(); }); }); }); diff --git a/ui/src/app/metadata/provider/container/provider-edit.component.ts b/ui/src/app/metadata/provider/container/provider-edit.component.ts index ea7114022..56616fa8b 100644 --- a/ui/src/app/metadata/provider/container/provider-edit.component.ts +++ b/ui/src/app/metadata/provider/container/provider-edit.component.ts @@ -15,6 +15,7 @@ import { NAV_FORMATS } from '../component/provider-editor-nav.component'; import { NgbModal } from '../../../../../node_modules/@ng-bootstrap/ng-bootstrap'; import { UnsavedDialogComponent } from '../../resolver/component/unsaved-dialog.component'; import { UnsavedProviderComponent } from '../component/unsaved-provider.dialog'; +import { CanComponentDeactivate } from '../../../core/service/can-deactivate.guard'; @Component({ selector: 'provider-edit', @@ -22,7 +23,7 @@ import { UnsavedProviderComponent } from '../component/unsaved-provider.dialog'; styleUrls: [] }) -export class ProviderEditComponent implements OnDestroy { +export class ProviderEditComponent implements OnDestroy, CanComponentDeactivate { provider$: Observable; definition$: Observable>; diff --git a/ui/src/app/wizard/component/wizard.component.spec.ts b/ui/src/app/wizard/component/wizard.component.spec.ts index e69de29bb..ef513015e 100644 --- a/ui/src/app/wizard/component/wizard.component.spec.ts +++ b/ui/src/app/wizard/component/wizard.component.spec.ts @@ -0,0 +1,64 @@ +import { Component, ViewChild } from '@angular/core'; +import { TestBed, async, ComponentFixture } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { StoreModule, Store, combineReducers } from '@ngrx/store'; + +import * as fromWizard from '../reducer'; +import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { WizardComponent, ICONS } from './wizard.component'; + +@Component({ + template: ` + + ` +}) +class TestHostComponent { + @ViewChild(WizardComponent) + public componentUnderTest: WizardComponent; +} + +describe('Wizard Component', () => { + + let fixture: ComponentFixture; + let instance: TestHostComponent; + let app: WizardComponent; + let store: Store; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + NgbDropdownModule.forRoot(), + RouterTestingModule, + StoreModule.forRoot({ + wizard: combineReducers(fromWizard.reducers) + }) + ], + declarations: [ + WizardComponent, + TestHostComponent + ], + }).compileComponents(); + + store = TestBed.get(Store); + spyOn(store, 'dispatch'); + + fixture = TestBed.createComponent(TestHostComponent); + instance = fixture.componentInstance; + app = instance.componentUnderTest; + fixture.detectChanges(); + })); + + it('should compile without error', () => { + expect(app).toBeTruthy(); + }); + + describe('getIcon method', () => { + it('should return the check string for the last index', () => { + expect(app.getIcon({ index: 'foo' }, { index: 'foo' })).toEqual(ICONS.CHECK); + }); + it('should return the index icon for other indexes', () => { + expect(app.getIcon({ index: 'foo' }, { index: 'bar' })).toEqual(ICONS.INDEX); + expect(app.getIcon({ index: 'foo' }, null)).toEqual(ICONS.INDEX); + }); + }); +}); diff --git a/ui/src/app/wizard/component/wizard.component.ts b/ui/src/app/wizard/component/wizard.component.ts index a75a3bb2d..7b4aa8ff4 100644 --- a/ui/src/app/wizard/component/wizard.component.ts +++ b/ui/src/app/wizard/component/wizard.component.ts @@ -53,9 +53,11 @@ export class WizardComponent { this.currentIcon$ = this.current$.pipe( withLatestFrom(this.last$), - map(([current, last]) => { - return (last && current.index === last.index) ? ICONS.CHECK : ICONS.INDEX; - }) + map(([current, last]) => this.getIcon(current, last)) ); } + + getIcon(current, last): string { + return (last && current.index === last.index) ? ICONS.CHECK : ICONS.INDEX; + } }