71712: Test fixes: eventemitter to subject in confirmation modal

This commit is contained in:
Marie Verdonck
2020-07-28 01:41:55 +02:00
parent 3e0f4a54e6
commit 26905860ba
6 changed files with 66 additions and 36 deletions

View File

@@ -46,27 +46,27 @@ describe('ConfirmationModalComponent', () => {
describe('confirmPressed', () => { describe('confirmPressed', () => {
beforeEach(() => { beforeEach(() => {
spyOn(component.response, 'emit'); spyOn(component.response, 'next');
component.confirmPressed(); component.confirmPressed();
}); });
it('should call the close method on the active modal', () => { it('should call the close method on the active modal', () => {
expect(modalStub.close).toHaveBeenCalled(); expect(modalStub.close).toHaveBeenCalled();
}); });
it('event emitter should emit true', () => { it('behaviour subject should have true as next', () => {
expect(component.response.emit).toHaveBeenCalledWith(true); expect(component.response.next).toHaveBeenCalledWith(true);
}); });
}); });
describe('cancelPressed', () => { describe('cancelPressed', () => {
beforeEach(() => { beforeEach(() => {
spyOn(component.response, 'emit'); spyOn(component.response, 'next');
component.cancelPressed(); component.cancelPressed();
}); });
it('should call the close method on the active modal', () => { it('should call the close method on the active modal', () => {
expect(modalStub.close).toHaveBeenCalled(); expect(modalStub.close).toHaveBeenCalled();
}); });
it('event emitter should emit false', () => { it('behaviour subject should have false as next', () => {
expect(component.response.emit).toHaveBeenCalledWith(false); expect(component.response.next).toHaveBeenCalledWith(false);
}); });
}); });
@@ -85,7 +85,7 @@ describe('ConfirmationModalComponent', () => {
describe('when the click method emits on cancel button', () => { describe('when the click method emits on cancel button', () => {
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
spyOn(component, 'close'); spyOn(component, 'close');
spyOn(component.response, 'emit'); spyOn(component.response, 'next');
debugElement.query(By.css('button.cancel')).triggerEventHandler('click', {}); debugElement.query(By.css('button.cancel')).triggerEventHandler('click', {});
tick(); tick();
fixture.detectChanges(); fixture.detectChanges();
@@ -93,15 +93,15 @@ describe('ConfirmationModalComponent', () => {
it('should call the close method on the component', () => { it('should call the close method on the component', () => {
expect(component.close).toHaveBeenCalled(); expect(component.close).toHaveBeenCalled();
}); });
it('event emitter should emit false', () => { it('behaviour subject should have false as next', () => {
expect(component.response.emit).toHaveBeenCalledWith(false); expect(component.response.next).toHaveBeenCalledWith(false);
}); });
}); });
describe('when the click method emits on confirm button', () => { describe('when the click method emits on confirm button', () => {
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
spyOn(component, 'close'); spyOn(component, 'close');
spyOn(component.response, 'emit'); spyOn(component.response, 'next');
debugElement.query(By.css('button.confirm')).triggerEventHandler('click', {}); debugElement.query(By.css('button.confirm')).triggerEventHandler('click', {});
tick(); tick();
fixture.detectChanges(); fixture.detectChanges();
@@ -109,8 +109,8 @@ describe('ConfirmationModalComponent', () => {
it('should call the close method on the component', () => { it('should call the close method on the component', () => {
expect(component.close).toHaveBeenCalled(); expect(component.close).toHaveBeenCalled();
}); });
it('event emitter should emit true', () => { it('behaviour subject should have true as next', () => {
expect(component.response.emit).toHaveBeenCalledWith(true); expect(component.response.next).toHaveBeenCalledWith(true);
}); });
}); });

View File

@@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Component, Input, Output } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs/internal/Subject';
import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model';
@Component({ @Component({
@@ -18,7 +18,7 @@ export class ConfirmationModalComponent {
* An event fired when the cancel or confirm button is clicked, with respectively false or true * An event fired when the cancel or confirm button is clicked, with respectively false or true
*/ */
@Output() @Output()
response = new EventEmitter<boolean>(); response: Subject<boolean> = new Subject();
constructor(protected activeModal: NgbActiveModal) { constructor(protected activeModal: NgbActiveModal) {
} }
@@ -27,7 +27,7 @@ export class ConfirmationModalComponent {
* Confirm the action that led to the modal * Confirm the action that led to the modal
*/ */
confirmPressed() { confirmPressed() {
this.response.emit(true); this.response.next(true);
this.close(); this.close();
} }
@@ -35,7 +35,7 @@ export class ConfirmationModalComponent {
* Cancel the action that led to the modal and close modal * Cancel the action that led to the modal and close modal
*/ */
cancelPressed() { cancelPressed() {
this.response.emit(false); this.response.next(false);
this.close(); this.close();
} }

View File

@@ -1,24 +1,45 @@
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { DebugElement, NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal, NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { METADATA_EXPORT_SCRIPT_NAME, ScriptDataService } from '../../../../core/data/processes/script-data.service'; import { METADATA_EXPORT_SCRIPT_NAME, ScriptDataService } from '../../../../core/data/processes/script-data.service';
import { Collection } from '../../../../core/shared/collection.model'; import { Collection } from '../../../../core/shared/collection.model';
import { Community } from '../../../../core/shared/community.model'; import { Community } from '../../../../core/shared/community.model';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ProcessParameter } from '../../../../process-page/processes/process-parameter.model'; import { ProcessParameter } from '../../../../process-page/processes/process-parameter.model';
import { ConfirmationModalComponent } from '../../../confirmation-modal/confirmation-modal.component';
import { TranslateLoaderMock } from '../../../mocks/translate-loader.mock';
import { NotificationsService } from '../../../notifications/notifications.service'; import { NotificationsService } from '../../../notifications/notifications.service';
import { NotificationsServiceStub } from '../../../testing/notifications-service.stub'; import { NotificationsServiceStub } from '../../../testing/notifications-service.stub';
import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils'; import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils';
import { ExportMetadataSelectorComponent } from './export-metadata-selector.component'; import { ExportMetadataSelectorComponent } from './export-metadata-selector.component';
// No way to add entryComponents yet to testbed; alternative implemented; source: https://stackoverflow.com/questions/41689468/how-to-shallow-test-a-component-with-an-entrycomponents
@NgModule({
imports: [ NgbModalModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
}),
],
exports: [],
declarations: [ConfirmationModalComponent],
providers: [],
entryComponents: [ConfirmationModalComponent],
})
class ModelTestModule { }
describe('ExportMetadataSelectorComponent', () => { describe('ExportMetadataSelectorComponent', () => {
let component: ExportMetadataSelectorComponent; let component: ExportMetadataSelectorComponent;
let fixture: ComponentFixture<ExportMetadataSelectorComponent>; let fixture: ComponentFixture<ExportMetadataSelectorComponent>;
let debugElement: DebugElement; let debugElement: DebugElement;
let modalRef;
let router; let router;
let notificationService: NotificationsServiceStub; let notificationService: NotificationsServiceStub;
@@ -61,7 +82,7 @@ describe('ExportMetadataSelectorComponent', () => {
} }
); );
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), ModelTestModule],
declarations: [ExportMetadataSelectorComponent], declarations: [ExportMetadataSelectorComponent],
providers: [ providers: [
{ provide: NgbActiveModal, useValue: modalStub }, { provide: NgbActiveModal, useValue: modalStub },
@@ -92,6 +113,9 @@ describe('ExportMetadataSelectorComponent', () => {
fixture = TestBed.createComponent(ExportMetadataSelectorComponent); fixture = TestBed.createComponent(ExportMetadataSelectorComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
debugElement = fixture.debugElement; debugElement = fixture.debugElement;
const modalService = TestBed.get(NgbModal);
modalRef = modalService.open(ConfirmationModalComponent);
modalRef.componentInstance.response = observableOf(true);
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -116,6 +140,7 @@ describe('ExportMetadataSelectorComponent', () => {
describe('if collection is selected', () => { describe('if collection is selected', () => {
let scriptRequestSucceeded; let scriptRequestSucceeded;
beforeEach((done) => { beforeEach((done) => {
spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
component.navigate(mockCollection).subscribe((succeeded: boolean) => { component.navigate(mockCollection).subscribe((succeeded: boolean) => {
scriptRequestSucceeded = succeeded; scriptRequestSucceeded = succeeded;
done() done()
@@ -140,6 +165,7 @@ describe('ExportMetadataSelectorComponent', () => {
describe('if community is selected', () => { describe('if community is selected', () => {
let scriptRequestSucceeded; let scriptRequestSucceeded;
beforeEach((done) => { beforeEach((done) => {
spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
component.navigate(mockCommunity).subscribe((succeeded: boolean) => { component.navigate(mockCommunity).subscribe((succeeded: boolean) => {
scriptRequestSucceeded = succeeded; scriptRequestSucceeded = succeeded;
done() done()
@@ -164,6 +190,7 @@ describe('ExportMetadataSelectorComponent', () => {
describe('if community/collection is selected; but script invoke fails', () => { describe('if community/collection is selected; but script invoke fails', () => {
let scriptRequestSucceeded; let scriptRequestSucceeded;
beforeEach((done) => { beforeEach((done) => {
spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
jasmine.getEnv().allowRespy(true); jasmine.getEnv().allowRespy(true);
spyOn(scriptService, 'invoke').and.returnValue(observableOf({ spyOn(scriptService, 'invoke').and.returnValue(observableOf({
response: response:

View File

@@ -2,9 +2,8 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { take, map } from 'rxjs/operators'; import { take, map, switchMap } from 'rxjs/operators';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { AuthService } from '../../../../core/auth/auth.service';
import { METADATA_EXPORT_SCRIPT_NAME, ScriptDataService } from '../../../../core/data/processes/script-data.service'; import { METADATA_EXPORT_SCRIPT_NAME, ScriptDataService } from '../../../../core/data/processes/script-data.service';
import { RequestEntry } from '../../../../core/data/request.reducer'; import { RequestEntry } from '../../../../core/data/request.reducer';
import { Collection } from '../../../../core/shared/collection.model'; import { Collection } from '../../../../core/shared/collection.model';
@@ -47,21 +46,25 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp
if (dso instanceof Collection || dso instanceof Community) { if (dso instanceof Collection || dso instanceof Community) {
const modalRef = this.modalService.open(ConfirmationModalComponent); const modalRef = this.modalService.open(ConfirmationModalComponent);
modalRef.componentInstance.dso = dso; modalRef.componentInstance.dso = dso;
modalRef.componentInstance.headerLabel = "confirmation-modal.export-metadata.header"; modalRef.componentInstance.headerLabel = 'confirmation-modal.export-metadata.header';
modalRef.componentInstance.infoLabel = "confirmation-modal.export-metadata.info"; modalRef.componentInstance.infoLabel = 'confirmation-modal.export-metadata.info';
modalRef.componentInstance.cancelLabel = "confirmation-modal.export-metadata.cancel"; modalRef.componentInstance.cancelLabel = 'confirmation-modal.export-metadata.cancel';
modalRef.componentInstance.confirmLabel = "confirmation-modal.export-metadata.confirm"; modalRef.componentInstance.confirmLabel = 'confirmation-modal.export-metadata.confirm';
const resp$ = modalRef.componentInstance.response.pipe(switchMap((confirm: boolean) => {
modalRef.componentInstance.response.subscribe((confirm: boolean) => {
if (confirm) { if (confirm) {
const startScriptSucceeded = this.startScriptNotifyAndRedirect(dso, dso.handle); const startScriptSucceeded$ = this.startScriptNotifyAndRedirect(dso, dso.handle);
startScriptSucceeded.pipe(take(1)).subscribe(); return startScriptSucceeded$.pipe(
return startScriptSucceeded; switchMap((r: boolean) => {
return observableOf(r);
})
)
} else { } else {
const modalRef = this.modalService.open(ExportMetadataSelectorComponent); const modalRef = this.modalService.open(ExportMetadataSelectorComponent);
modalRef.componentInstance.dsoRD = createSuccessfulRemoteDataObject(dso); modalRef.componentInstance.dsoRD = createSuccessfulRemoteDataObject(dso);
} }
}); }));
resp$.subscribe();
return resp$;
} else { } else {
this.notificationsService.error(this.translationService.get('dso-selector.export-metadata.notValidDSO')); this.notificationsService.error(this.translationService.get('dso-selector.export-metadata.notValidDSO'));
return observableOf(false); return observableOf(false);

View File

@@ -3,7 +3,7 @@ import { Observable } from 'rxjs/internal/Observable';
import { MenuService } from './menu.service'; import { MenuService } from './menu.service';
import { MenuID } from './initial-menus-state'; import { MenuID } from './initial-menus-state';
import { MenuSection } from './menu.reducer'; import { MenuSection } from './menu.reducer';
import { distinctUntilChanged, first, map, tap, switchMap, take } from 'rxjs/operators'; import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { GenericConstructor } from '../../core/shared/generic-constructor'; import { GenericConstructor } from '../../core/shared/generic-constructor';
import { hasValue } from '../empty.util'; import { hasValue } from '../empty.util';
import { MenuSectionComponent } from './menu-section/menu-section.component'; import { MenuSectionComponent } from './menu-section/menu-section.component';

View File

@@ -105,7 +105,7 @@ export const environment: Partial<GlobalConfig> = {
}, },
// Angular Universal settings // Angular Universal settings
universal: { universal: {
preboot: false, preboot: true,
async: true, async: true,
time: false time: false
}, },