summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts')
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
new file mode 100644
index 000000000..e501d9f32
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
@@ -0,0 +1,235 @@
+import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { NgForm, ReactiveFormsModule } from '@angular/forms';
+
+import { NgbActiveModal, NgbModalModule, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { Observable, Subscriber, timer as observableTimer } from 'rxjs';
+
+import { DirectivesModule } from '~/app/shared/directives/directives.module';
+import { ModalService } from '~/app/shared/services/modal.service';
+import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper';
+import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
+import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
+import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
+
+@NgModule({})
+export class MockModule {}
+
+@Component({
+ template: `
+ <button type="button" class="btn btn-danger" (click)="openCtrlDriven()">
+ <i class="fa fa-times"></i>Deletion Ctrl-Test
+ <ng-template #ctrlDescription>
+ The spinner is handled by the controller if you have use the modal as ViewChild in order to
+ use it's functions to stop the spinner or close the dialog.
+ </ng-template>
+ </button>
+
+ <button type="button" class="btn btn-danger" (click)="openModalDriven()">
+ <i class="fa fa-times"></i>Deletion Modal-Test
+ <ng-template #modalDescription>
+ The spinner is handled by the modal if your given deletion function returns a Observable.
+ </ng-template>
+ </button>
+ `
+})
+class MockComponent {
+ @ViewChild('ctrlDescription', { static: true })
+ ctrlDescription: TemplateRef<any>;
+ @ViewChild('modalDescription', { static: true })
+ modalDescription: TemplateRef<any>;
+ someData = [1, 2, 3, 4, 5];
+ finished: number[];
+ ctrlRef: NgbModalRef;
+ modalRef: NgbModalRef;
+
+ // Normally private - public was needed for the tests
+ constructor(public modalService: ModalService) {}
+
+ openCtrlDriven() {
+ this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ submitAction: this.fakeDeleteController.bind(this),
+ bodyTemplate: this.ctrlDescription
+ });
+ }
+
+ openModalDriven() {
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ submitActionObservable: this.fakeDelete(),
+ bodyTemplate: this.modalDescription
+ });
+ }
+
+ finish() {
+ this.finished = [6, 7, 8, 9];
+ }
+
+ fakeDelete() {
+ return (): Observable<any> => {
+ return new Observable((observer: Subscriber<any>) => {
+ observableTimer(100).subscribe(() => {
+ observer.next(this.finish());
+ observer.complete();
+ });
+ });
+ };
+ }
+
+ fakeDeleteController() {
+ observableTimer(100).subscribe(() => {
+ this.finish();
+ this.ctrlRef.close();
+ });
+ }
+}
+
+describe('CriticalConfirmationModalComponent', () => {
+ let mockComponent: MockComponent;
+ let component: CriticalConfirmationModalComponent;
+ let mockFixture: ComponentFixture<MockComponent>;
+
+ configureTestBed(
+ {
+ declarations: [
+ MockComponent,
+ CriticalConfirmationModalComponent,
+ LoadingPanelComponent,
+ AlertPanelComponent
+ ],
+ schemas: [NO_ERRORS_SCHEMA],
+ imports: [ReactiveFormsModule, MockModule, DirectivesModule, NgbModalModule],
+ providers: [NgbActiveModal]
+ },
+ [CriticalConfirmationModalComponent]
+ );
+
+ beforeEach(() => {
+ mockFixture = TestBed.createComponent(MockComponent);
+ mockComponent = mockFixture.componentInstance;
+ spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
+ const data = modalServiceShow(CriticalConfirmationModalComponent, config);
+ component = data.componentInstance;
+ return data;
+ });
+ mockComponent.openCtrlDriven();
+ mockFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should throw an error if no action is defined', () => {
+ component = Object.assign(component, {
+ submitAction: null,
+ submitActionObservable: null
+ });
+ expect(() => component.ngOnInit()).toThrowError('No submit action defined');
+ });
+
+ it('should test if the ctrl driven mock is set correctly through mock component', () => {
+ expect(component.bodyTemplate).toBeTruthy();
+ expect(component.submitAction).toBeTruthy();
+ expect(component.submitActionObservable).not.toBeTruthy();
+ });
+
+ it('should test if the modal driven mock is set correctly through mock component', () => {
+ mockComponent.openModalDriven();
+ expect(component.bodyTemplate).toBeTruthy();
+ expect(component.submitActionObservable).toBeTruthy();
+ expect(component.submitAction).not.toBeTruthy();
+ });
+
+ describe('component functions', () => {
+ const changeValue = (value: boolean) => {
+ const ctrl = component.deletionForm.get('confirmation');
+ ctrl.setValue(value);
+ ctrl.markAsDirty();
+ ctrl.updateValueAndValidity();
+ mockFixture.detectChanges();
+ };
+
+ it('should test hideModal', () => {
+ expect(component.activeModal).toBeTruthy();
+ expect(component.hideModal).toBeTruthy();
+ spyOn(component.activeModal, 'close').and.callThrough();
+ expect(component.activeModal.close).not.toHaveBeenCalled();
+ component.hideModal();
+ expect(component.activeModal.close).toHaveBeenCalled();
+ });
+
+ describe('validate confirmation', () => {
+ const testValidation = (submitted: boolean, error: string, expected: boolean) => {
+ expect(
+ component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
+ ).toBe(expected);
+ };
+
+ beforeEach(() => {
+ component.deletionForm.reset();
+ });
+
+ it('should test empty values', () => {
+ component.deletionForm.reset();
+ testValidation(false, undefined, false);
+ testValidation(true, 'required', true);
+ component.deletionForm.reset();
+ changeValue(true);
+ changeValue(false);
+ testValidation(true, 'required', true);
+ });
+ });
+
+ describe('deletion call', () => {
+ beforeEach(() => {
+ spyOn(component, 'stopLoadingSpinner').and.callThrough();
+ spyOn(component, 'hideModal').and.callThrough();
+ });
+
+ describe('Controller driven', () => {
+ beforeEach(() => {
+ spyOn(component, 'submitAction').and.callThrough();
+ spyOn(mockComponent.ctrlRef, 'close').and.callThrough();
+ });
+
+ it('should test fake deletion that closes modal', fakeAsync(() => {
+ // Before deletionCall
+ expect(component.submitAction).not.toHaveBeenCalled();
+ // During deletionCall
+ component.callSubmitAction();
+ expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
+ expect(component.hideModal).not.toHaveBeenCalled();
+ expect(mockComponent.ctrlRef.close).not.toHaveBeenCalled();
+ expect(component.submitAction).toHaveBeenCalled();
+ expect(mockComponent.finished).toBe(undefined);
+ // After deletionCall
+ tick(2000);
+ expect(component.hideModal).not.toHaveBeenCalled();
+ expect(mockComponent.ctrlRef.close).toHaveBeenCalled();
+ expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
+ }));
+ });
+
+ describe('Modal driven', () => {
+ beforeEach(() => {
+ mockComponent.openModalDriven();
+ spyOn(component, 'stopLoadingSpinner').and.callThrough();
+ spyOn(component, 'hideModal').and.callThrough();
+ spyOn(mockComponent, 'fakeDelete').and.callThrough();
+ });
+
+ it('should delete and close modal', fakeAsync(() => {
+ // During deletionCall
+ component.callSubmitAction();
+ expect(mockComponent.finished).toBe(undefined);
+ expect(component.hideModal).not.toHaveBeenCalled();
+ // After deletionCall
+ tick(2000);
+ expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
+ expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
+ expect(component.hideModal).toHaveBeenCalled();
+ }));
+ });
+ });
+ });
+});