]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / components / critical-confirmation-modal / critical-confirmation-modal.component.spec.ts
CommitLineData
11fdf7f2
TL
1import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core';
2import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3import { NgForm, ReactiveFormsModule } from '@angular/forms';
11fdf7f2 4
f67539c2 5import { NgbActiveModal, NgbModalModule, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
11fdf7f2
TL
6import { Observable, Subscriber, timer as observableTimer } from 'rxjs';
7
f67539c2
TL
8import { DirectivesModule } from '~/app/shared/directives/directives.module';
9import { ModalService } from '~/app/shared/services/modal.service';
10import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper';
11import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
12import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
11fdf7f2
TL
13import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
14
f67539c2 15@NgModule({})
11fdf7f2
TL
16export class MockModule {}
17
18@Component({
19 template: `
f67539c2 20 <button type="button" class="btn btn-danger" (click)="openCtrlDriven()">
9f95a23c 21 <i class="fa fa-times"></i>Deletion Ctrl-Test
11fdf7f2
TL
22 <ng-template #ctrlDescription>
23 The spinner is handled by the controller if you have use the modal as ViewChild in order to
24 use it's functions to stop the spinner or close the dialog.
25 </ng-template>
26 </button>
27
f67539c2 28 <button type="button" class="btn btn-danger" (click)="openModalDriven()">
9f95a23c 29 <i class="fa fa-times"></i>Deletion Modal-Test
11fdf7f2
TL
30 <ng-template #modalDescription>
31 The spinner is handled by the modal if your given deletion function returns a Observable.
32 </ng-template>
33 </button>
34 `
35})
36class MockComponent {
9f95a23c 37 @ViewChild('ctrlDescription', { static: true })
11fdf7f2 38 ctrlDescription: TemplateRef<any>;
9f95a23c 39 @ViewChild('modalDescription', { static: true })
11fdf7f2
TL
40 modalDescription: TemplateRef<any>;
41 someData = [1, 2, 3, 4, 5];
42 finished: number[];
f67539c2
TL
43 ctrlRef: NgbModalRef;
44 modalRef: NgbModalRef;
11fdf7f2
TL
45
46 // Normally private - public was needed for the tests
f67539c2 47 constructor(public modalService: ModalService) {}
11fdf7f2
TL
48
49 openCtrlDriven() {
50 this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
f67539c2
TL
51 submitAction: this.fakeDeleteController.bind(this),
52 bodyTemplate: this.ctrlDescription
11fdf7f2
TL
53 });
54 }
55
56 openModalDriven() {
57 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
f67539c2
TL
58 submitActionObservable: this.fakeDelete(),
59 bodyTemplate: this.modalDescription
11fdf7f2
TL
60 });
61 }
62
63 finish() {
64 this.finished = [6, 7, 8, 9];
65 }
66
67 fakeDelete() {
68 return (): Observable<any> => {
69 return new Observable((observer: Subscriber<any>) => {
70 observableTimer(100).subscribe(() => {
71 observer.next(this.finish());
72 observer.complete();
73 });
74 });
75 };
76 }
77
78 fakeDeleteController() {
79 observableTimer(100).subscribe(() => {
80 this.finish();
f67539c2 81 this.ctrlRef.close();
11fdf7f2
TL
82 });
83 }
84}
85
86describe('CriticalConfirmationModalComponent', () => {
87 let mockComponent: MockComponent;
88 let component: CriticalConfirmationModalComponent;
89 let mockFixture: ComponentFixture<MockComponent>;
11fdf7f2 90
f67539c2
TL
91 configureTestBed(
92 {
93 declarations: [
94 MockComponent,
95 CriticalConfirmationModalComponent,
96 LoadingPanelComponent,
97 AlertPanelComponent
98 ],
99 schemas: [NO_ERRORS_SCHEMA],
100 imports: [ReactiveFormsModule, MockModule, DirectivesModule, NgbModalModule],
101 providers: [NgbActiveModal]
102 },
103 [CriticalConfirmationModalComponent]
104 );
11fdf7f2
TL
105
106 beforeEach(() => {
107 mockFixture = TestBed.createComponent(MockComponent);
108 mockComponent = mockFixture.componentInstance;
11fdf7f2 109 spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
9f95a23c 110 const data = modalServiceShow(CriticalConfirmationModalComponent, config);
f67539c2
TL
111 component = data.componentInstance;
112 return data;
11fdf7f2
TL
113 });
114 mockComponent.openCtrlDriven();
115 mockFixture.detectChanges();
116 });
117
118 it('should create', () => {
119 expect(component).toBeTruthy();
120 });
121
11fdf7f2
TL
122 it('should throw an error if no action is defined', () => {
123 component = Object.assign(component, {
124 submitAction: null,
125 submitActionObservable: null
126 });
127 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
128 });
129
130 it('should test if the ctrl driven mock is set correctly through mock component', () => {
131 expect(component.bodyTemplate).toBeTruthy();
132 expect(component.submitAction).toBeTruthy();
133 expect(component.submitActionObservable).not.toBeTruthy();
134 });
135
136 it('should test if the modal driven mock is set correctly through mock component', () => {
137 mockComponent.openModalDriven();
138 expect(component.bodyTemplate).toBeTruthy();
139 expect(component.submitActionObservable).toBeTruthy();
140 expect(component.submitAction).not.toBeTruthy();
141 });
142
143 describe('component functions', () => {
9f95a23c 144 const changeValue = (value: boolean) => {
11fdf7f2
TL
145 const ctrl = component.deletionForm.get('confirmation');
146 ctrl.setValue(value);
147 ctrl.markAsDirty();
148 ctrl.updateValueAndValidity();
f67539c2 149 mockFixture.detectChanges();
11fdf7f2
TL
150 };
151
152 it('should test hideModal', () => {
f67539c2 153 expect(component.activeModal).toBeTruthy();
11fdf7f2 154 expect(component.hideModal).toBeTruthy();
f67539c2
TL
155 spyOn(component.activeModal, 'close').and.callThrough();
156 expect(component.activeModal.close).not.toHaveBeenCalled();
11fdf7f2 157 component.hideModal();
f67539c2 158 expect(component.activeModal.close).toHaveBeenCalled();
11fdf7f2
TL
159 });
160
161 describe('validate confirmation', () => {
162 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
163 expect(
164 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
165 ).toBe(expected);
166 };
167
168 beforeEach(() => {
169 component.deletionForm.reset();
170 });
171
172 it('should test empty values', () => {
173 component.deletionForm.reset();
174 testValidation(false, undefined, false);
175 testValidation(true, 'required', true);
176 component.deletionForm.reset();
177 changeValue(true);
178 changeValue(false);
179 testValidation(true, 'required', true);
180 });
181 });
182
183 describe('deletion call', () => {
184 beforeEach(() => {
185 spyOn(component, 'stopLoadingSpinner').and.callThrough();
186 spyOn(component, 'hideModal').and.callThrough();
187 });
188
189 describe('Controller driven', () => {
190 beforeEach(() => {
191 spyOn(component, 'submitAction').and.callThrough();
f67539c2 192 spyOn(mockComponent.ctrlRef, 'close').and.callThrough();
11fdf7f2
TL
193 });
194
801d1391 195 it('should test fake deletion that closes modal', fakeAsync(() => {
11fdf7f2
TL
196 // Before deletionCall
197 expect(component.submitAction).not.toHaveBeenCalled();
198 // During deletionCall
199 component.callSubmitAction();
200 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
201 expect(component.hideModal).not.toHaveBeenCalled();
f67539c2 202 expect(mockComponent.ctrlRef.close).not.toHaveBeenCalled();
11fdf7f2
TL
203 expect(component.submitAction).toHaveBeenCalled();
204 expect(mockComponent.finished).toBe(undefined);
205 // After deletionCall
206 tick(2000);
207 expect(component.hideModal).not.toHaveBeenCalled();
f67539c2 208 expect(mockComponent.ctrlRef.close).toHaveBeenCalled();
11fdf7f2
TL
209 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
210 }));
211 });
212
213 describe('Modal driven', () => {
214 beforeEach(() => {
215 mockComponent.openModalDriven();
216 spyOn(component, 'stopLoadingSpinner').and.callThrough();
217 spyOn(component, 'hideModal').and.callThrough();
218 spyOn(mockComponent, 'fakeDelete').and.callThrough();
219 });
220
801d1391 221 it('should delete and close modal', fakeAsync(() => {
11fdf7f2
TL
222 // During deletionCall
223 component.callSubmitAction();
224 expect(mockComponent.finished).toBe(undefined);
225 expect(component.hideModal).not.toHaveBeenCalled();
226 // After deletionCall
227 tick(2000);
228 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
229 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
230 expect(component.hideModal).toHaveBeenCalled();
231 }));
232 });
233 });
234 });
235});