1 import { Component, NgModule, TemplateRef, ViewChild } from '@angular/core';
2 import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3 import { NgForm, ReactiveFormsModule } from '@angular/forms';
5 import { Observable, Subscriber, timer as observableTimer } from 'rxjs';
7 import { DirectivesModule } from '~/app/shared/directives/directives.module';
8 import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper';
9 import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
10 import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
11 import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
12 import { CheckboxModule, ModalService, PlaceholderService } from 'carbon-components-angular';
13 import { ModalCdsService } from '../../services/modal-cds.service';
14 import { DeletionImpact } from '../../enum/critical-confirmation-modal-impact.enum';
17 export class MockModule {}
21 <button type="button" class="btn btn-danger" (click)="openCtrlDriven()">
22 <i class="fa fa-times"></i>Deletion Ctrl-Test
23 <ng-template #ctrlDescription>
24 The spinner is handled by the controller if you have use the modal as ViewChild in order to
25 use it's functions to stop the spinner or close the dialog.
29 <button type="button" class="btn btn-danger" (click)="openModalDriven()">
30 <i class="fa fa-times"></i>Deletion Modal-Test
31 <ng-template #modalDescription>
32 The spinner is handled by the modal if your given deletion function returns a Observable.
38 @ViewChild('ctrlDescription', { static: true })
39 ctrlDescription: TemplateRef<any>;
40 @ViewChild('modalDescription', { static: true })
41 modalDescription: TemplateRef<any>;
42 someData = [1, 2, 3, 4, 5];
47 // Normally private - public was needed for the tests
48 constructor(public modalService: ModalCdsService) {}
51 this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
52 submitAction: this.fakeDeleteController.bind(this),
53 bodyTemplate: this.ctrlDescription
58 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
59 submitActionObservable: this.fakeDelete(),
60 bodyTemplate: this.modalDescription
65 this.finished = [6, 7, 8, 9];
69 return (): Observable<any> => {
70 return new Observable((observer: Subscriber<any>) => {
71 observableTimer(100).subscribe(() => {
72 observer.next(this.finish());
79 fakeDeleteController() {
80 observableTimer(100).subscribe(() => {
87 describe('CriticalConfirmationModalComponent', () => {
88 let mockComponent: MockComponent;
89 let component: CriticalConfirmationModalComponent;
90 let mockFixture: ComponentFixture<MockComponent>;
95 CriticalConfirmationModalComponent,
96 LoadingPanelComponent,
99 imports: [ReactiveFormsModule, MockModule, DirectivesModule, CheckboxModule],
103 { provide: 'itemNames', useValue: [] },
104 { provide: 'itemDescription', useValue: 'entry' },
105 { provide: 'actionDescription', useValue: 'delete' }
110 mockFixture = TestBed.createComponent(MockComponent);
111 mockComponent = mockFixture.componentInstance;
112 spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
113 const data = modalServiceShow(CriticalConfirmationModalComponent, config);
114 component = data.componentInstance;
117 mockComponent.openCtrlDriven();
118 mockFixture.detectChanges();
121 it('should create', () => {
122 expect(component).toBeTruthy();
125 it('should throw an error if no action is defined', () => {
126 component = Object.assign(component, {
128 submitActionObservable: null
130 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
133 it('should test if the ctrl driven mock is set correctly through mock component', () => {
134 expect(component.bodyTemplate).toBeTruthy();
135 expect(component.submitAction).toBeTruthy();
136 expect(component.submitActionObservable).not.toBeTruthy();
139 it('should test if the modal driven mock is set correctly through mock component', () => {
140 mockComponent.openModalDriven();
141 expect(component.bodyTemplate).toBeTruthy();
142 expect(component.submitActionObservable).toBeTruthy();
143 expect(component.submitAction).not.toBeTruthy();
146 describe('component functions', () => {
147 const changeValue = (formControl: string, value: any) => {
148 const ctrl = component.deletionForm.get(formControl);
149 ctrl.setValue(value);
151 ctrl.updateValueAndValidity();
154 it('should test hideModal', () => {
155 expect(component.hideModal).toBeTruthy();
156 spyOn(component, 'closeModal').and.callThrough();
157 expect(component.closeModal).not.toHaveBeenCalled();
158 component.hideModal();
159 expect(component.closeModal).toHaveBeenCalled();
162 describe('validate confirmation', () => {
163 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
165 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
170 component.deletionForm.reset();
171 const ctrl = component.deletionForm.get('impact');
172 ctrl.setValue(DeletionImpact.normal);
174 ctrl.updateValueAndValidity();
175 component.deletionForm.get('confirmation').updateValueAndValidity();
178 it('should test empty values', () => {
179 testValidation(true, 'required', true);
180 changeValue('confirmation', true);
181 changeValue('confirmation', false);
182 testValidation(true, 'required', true);
186 describe('validate confirmInput', () => {
187 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
189 component.deletionForm.showError('confirmInput', <NgForm>{ submitted: submitted }, error)
194 component.deletionForm.reset();
195 const ctrl = component.deletionForm.get('impact');
196 ctrl.setValue(DeletionImpact.high);
198 ctrl.updateValueAndValidity();
199 component.deletionForm.get('confirmInput').updateValueAndValidity();
202 it('should test empty values', () => {
203 testValidation(true, 'required', true);
204 changeValue('confirmInput', 'dummytext');
205 changeValue('confirmInput', '');
206 testValidation(true, 'required', true);
209 it('should give error, if entered resource name is wrong', () => {
210 component.itemNames = ['resource1'];
211 changeValue('confirmInput', 'dummytext');
212 testValidation(true, 'matchResource', true);
215 it('should give error, if entered resource name is correct', () => {
216 component.itemNames = ['resource1'];
217 changeValue('confirmInput', 'resource1');
218 testValidation(true, 'matchResource', false);
222 describe('deletion call', () => {
224 spyOn(component, 'stopLoadingSpinner').and.callThrough();
225 spyOn(component, 'hideModal').and.callThrough();
228 describe('Controller driven', () => {
230 spyOn(component, 'submitAction').and.callThrough();
231 spyOn(mockComponent.ctrlRef, 'close').and.callThrough();
234 it('should test fake deletion that closes modal', fakeAsync(() => {
235 // Before deletionCall
236 expect(component.submitAction).not.toHaveBeenCalled();
237 // During deletionCall
238 component.callSubmitAction();
239 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
240 expect(component.hideModal).not.toHaveBeenCalled();
241 expect(mockComponent.ctrlRef.close).not.toHaveBeenCalled();
242 expect(component.submitAction).toHaveBeenCalled();
243 expect(mockComponent.finished).toBe(undefined);
244 // After deletionCall
246 expect(component.hideModal).not.toHaveBeenCalled();
247 expect(mockComponent.ctrlRef.close).toHaveBeenCalled();
248 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
252 describe('Modal driven', () => {
254 mockComponent.openModalDriven();
255 spyOn(component, 'stopLoadingSpinner').and.callThrough();
256 spyOn(component, 'hideModal').and.callThrough();
257 spyOn(mockComponent, 'fakeDelete').and.callThrough();
260 it('should delete and close modal', fakeAsync(() => {
261 // During deletionCall
262 component.callSubmitAction();
263 expect(mockComponent.finished).toBe(undefined);
264 expect(component.hideModal).not.toHaveBeenCalled();
265 // After deletionCall
267 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
268 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
269 expect(component.hideModal).toHaveBeenCalled();