1 import { Component, NgModule, NO_ERRORS_SCHEMA, 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 { DeleteConfirmationModalComponent } from './delete-confirmation-modal.component';
12 import { ModalService, PlaceholderService } from 'carbon-components-angular';
13 import { ModalCdsService } from '../../services/modal-cds.service';
14 import { DeletionImpact } from '../../enum/delete-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.
39 @ViewChild('ctrlDescription', { static: true })
40 ctrlDescription: TemplateRef<any>;
41 @ViewChild('modalDescription', { static: true })
42 modalDescription: TemplateRef<any>;
43 someData = [1, 2, 3, 4, 5];
48 // Normally private - public was needed for the tests
49 constructor(public modalService: ModalCdsService) {}
52 this.ctrlRef = this.modalService.show(DeleteConfirmationModalComponent, {
53 submitAction: this.fakeDeleteController.bind(this),
54 bodyTemplate: this.ctrlDescription
59 this.modalRef = this.modalService.show(DeleteConfirmationModalComponent, {
60 submitActionObservable: this.fakeDelete(),
61 bodyTemplate: this.modalDescription
66 this.finished = [6, 7, 8, 9];
70 return (): Observable<any> => {
71 return new Observable((observer: Subscriber<any>) => {
72 observableTimer(100).subscribe(() => {
73 observer.next(this.finish());
80 fakeDeleteController() {
81 observableTimer(100).subscribe(() => {
88 describe('DeleteConfirmationModalComponent', () => {
89 let mockComponent: MockComponent;
90 let component: DeleteConfirmationModalComponent;
91 let mockFixture: ComponentFixture<MockComponent>;
96 DeleteConfirmationModalComponent,
97 LoadingPanelComponent,
100 schemas: [NO_ERRORS_SCHEMA],
101 imports: [ReactiveFormsModule, MockModule, DirectivesModule],
105 { provide: 'itemNames', useValue: [] },
106 { provide: 'itemDescription', useValue: 'entry' },
107 { provide: 'actionDescription', useValue: 'delete' },
108 { provide: 'impact', useValue: DeletionImpact.medium }
113 mockFixture = TestBed.createComponent(MockComponent);
114 mockComponent = mockFixture.componentInstance;
115 spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
116 const data = modalServiceShow(DeleteConfirmationModalComponent, config);
117 component = data.componentInstance;
120 mockComponent.openCtrlDriven();
121 mockFixture.detectChanges();
124 it('should create', () => {
125 expect(component).toBeTruthy();
128 it('should throw an error if no action is defined', () => {
129 component = Object.assign(component, {
131 submitActionObservable: null
133 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
136 it('should test if the ctrl driven mock is set correctly through mock component', () => {
137 expect(component.bodyTemplate).toBeTruthy();
138 expect(component.submitAction).toBeTruthy();
139 expect(component.submitActionObservable).not.toBeTruthy();
142 it('should test if the modal driven mock is set correctly through mock component', () => {
143 mockComponent.openModalDriven();
144 expect(component.bodyTemplate).toBeTruthy();
145 expect(component.submitActionObservable).toBeTruthy();
146 expect(component.submitAction).not.toBeTruthy();
149 describe('component functions', () => {
150 const changeValue = (formControl: string, value: string | boolean) => {
151 const ctrl = component.deletionForm.get(formControl);
152 ctrl.setValue(value);
154 ctrl.updateValueAndValidity();
157 it('should test hideModal', () => {
158 expect(component.hideModal).toBeTruthy();
159 spyOn(component, 'closeModal').and.callThrough();
160 expect(component.closeModal).not.toHaveBeenCalled();
161 component.hideModal();
162 expect(component.closeModal).toHaveBeenCalled();
165 describe('validate confirmation', () => {
166 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
168 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
173 component.deletionForm.reset();
174 const ctrl = component.deletionForm.get('impact');
175 ctrl.setValue(DeletionImpact.medium);
177 ctrl.updateValueAndValidity();
178 component.deletionForm.get('confirmation').updateValueAndValidity();
181 it('should test empty values', () => {
182 testValidation(true, 'required', true);
183 changeValue('confirmation', true);
184 changeValue('confirmation', false);
185 testValidation(true, 'required', true);
189 describe('validate confirmInput', () => {
190 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
192 component.deletionForm.showError('confirmInput', <NgForm>{ submitted: submitted }, error)
197 component.deletionForm.reset();
198 const ctrl = component.deletionForm.get('impact');
199 ctrl.setValue(DeletionImpact.high);
201 ctrl.updateValueAndValidity();
202 component.deletionForm.get('confirmInput').updateValueAndValidity();
205 it('should test empty values', () => {
206 testValidation(true, 'required', true);
207 changeValue('confirmInput', 'dummytext');
208 changeValue('confirmInput', '');
209 testValidation(true, 'required', true);
212 it('should give error, if entered resource name is wrong', () => {
213 component.itemNames = ['resource1'];
214 changeValue('confirmInput', 'dummytext');
215 testValidation(true, 'matchResource', true);
218 it('should give error, if entered resource name is correct', () => {
219 component.itemNames = ['resource1'];
220 changeValue('confirmInput', 'resource1');
221 testValidation(true, 'matchResource', false);
225 describe('deletion call', () => {
227 spyOn(component, 'stopLoadingSpinner').and.callThrough();
228 spyOn(component, 'hideModal').and.callThrough();
231 describe('Controller driven', () => {
233 spyOn(component, 'submitAction').and.callThrough();
234 spyOn(mockComponent.ctrlRef, 'close').and.callThrough();
237 it('should test fake deletion that closes modal', fakeAsync(() => {
238 // Before deletionCall
239 expect(component.submitAction).not.toHaveBeenCalled();
240 // During deletionCall
241 component.callSubmitAction();
242 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
243 expect(component.hideModal).not.toHaveBeenCalled();
244 expect(mockComponent.ctrlRef.close).not.toHaveBeenCalled();
245 expect(component.submitAction).toHaveBeenCalled();
246 expect(mockComponent.finished).toBe(undefined);
247 // After deletionCall
249 expect(component.hideModal).not.toHaveBeenCalled();
250 expect(mockComponent.ctrlRef.close).toHaveBeenCalled();
251 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
255 describe('Modal driven', () => {
257 mockComponent.openModalDriven();
258 spyOn(component, 'stopLoadingSpinner').and.callThrough();
259 spyOn(component, 'hideModal').and.callThrough();
260 spyOn(mockComponent, 'fakeDelete').and.callThrough();
263 it('should delete and close modal', fakeAsync(() => {
264 // During deletionCall
265 component.callSubmitAction();
266 expect(mockComponent.finished).toBe(undefined);
267 expect(component.hideModal).not.toHaveBeenCalled();
268 // After deletionCall
270 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
271 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
272 expect(component.hideModal).toHaveBeenCalled();