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';
4 import { By } from '@angular/platform-browser';
6 import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap/modal';
7 import { Observable, Subscriber, timer as observableTimer } from 'rxjs';
9 import { configureTestBed } from '../../../../testing/unit-test-helper';
10 import { DirectivesModule } from '../../directives/directives.module';
11 import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
14 entryComponents: [CriticalConfirmationModalComponent]
16 export class MockModule {}
20 <button type="button" class="btn btn-sm btn-primary" (click)="openCtrlDriven()">
21 <i class="fa fa-fw fa-times"></i>Deletion Ctrl-Test
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.
28 <button type="button" class="btn btn-sm btn-primary" (click)="openModalDriven()">
29 <i class="fa fa-fw fa-times"></i>Deletion Modal-Test
30 <ng-template #modalDescription>
31 The spinner is handled by the modal if your given deletion function returns a Observable.
37 @ViewChild('ctrlDescription')
38 ctrlDescription: TemplateRef<any>;
39 @ViewChild('modalDescription')
40 modalDescription: TemplateRef<any>;
41 someData = [1, 2, 3, 4, 5];
46 // Normally private - public was needed for the tests
47 constructor(public modalService: BsModalService) {}
50 this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
52 submitAction: this.fakeDeleteController.bind(this),
53 bodyTemplate: this.ctrlDescription
59 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
61 submitActionObservable: this.fakeDelete(),
62 bodyTemplate: this.modalDescription
68 this.finished = [6, 7, 8, 9];
72 return (): Observable<any> => {
73 return new Observable((observer: Subscriber<any>) => {
74 observableTimer(100).subscribe(() => {
75 observer.next(this.finish());
82 fakeDeleteController() {
83 observableTimer(100).subscribe(() => {
90 describe('CriticalConfirmationModalComponent', () => {
91 let mockComponent: MockComponent;
92 let component: CriticalConfirmationModalComponent;
93 let mockFixture: ComponentFixture<MockComponent>;
94 let fixture: ComponentFixture<CriticalConfirmationModalComponent>;
97 declarations: [MockComponent, CriticalConfirmationModalComponent],
98 schemas: [NO_ERRORS_SCHEMA],
99 imports: [ModalModule.forRoot(), ReactiveFormsModule, MockModule, DirectivesModule],
100 providers: [BsModalRef]
104 mockFixture = TestBed.createComponent(MockComponent);
105 mockComponent = mockFixture.componentInstance;
106 // Mocking the modals as a lot would be left over
107 spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
108 const ref = new BsModalRef();
109 fixture = TestBed.createComponent(CriticalConfirmationModalComponent);
110 component = fixture.componentInstance;
111 if (config.initialState) {
112 component = Object.assign(component, config.initialState);
114 fixture.detectChanges();
115 ref.content = component;
118 mockComponent.openCtrlDriven();
119 mockFixture.detectChanges();
122 it('should create', () => {
123 expect(component).toBeTruthy();
126 it('should focus the checkbox form field', () => {
127 fixture.detectChanges();
128 fixture.whenStable().then(() => {
129 const focused = fixture.debugElement.query(By.css(':focus'));
130 expect(focused.attributes.id).toBe('confirmation');
131 expect(focused.attributes.type).toBe('checkbox');
132 const element = document.getElementById('confirmation');
133 expect(element === document.activeElement).toBeTruthy();
137 it('should throw an error if no action is defined', () => {
138 component = Object.assign(component, {
140 submitActionObservable: null
142 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
145 it('should test if the ctrl driven mock is set correctly through mock component', () => {
146 expect(component.bodyTemplate).toBeTruthy();
147 expect(component.submitAction).toBeTruthy();
148 expect(component.submitActionObservable).not.toBeTruthy();
151 it('should test if the modal driven mock is set correctly through mock component', () => {
152 mockComponent.openModalDriven();
153 expect(component.bodyTemplate).toBeTruthy();
154 expect(component.submitActionObservable).toBeTruthy();
155 expect(component.submitAction).not.toBeTruthy();
158 describe('component functions', () => {
159 const changeValue = (value) => {
160 const ctrl = component.deletionForm.get('confirmation');
161 ctrl.setValue(value);
163 ctrl.updateValueAndValidity();
164 fixture.detectChanges();
167 it('should test hideModal', () => {
168 expect(component.modalRef).toBeTruthy();
169 expect(component.hideModal).toBeTruthy();
170 spyOn(component.modalRef, 'hide').and.callThrough();
171 expect(component.modalRef.hide).not.toHaveBeenCalled();
172 component.hideModal();
173 expect(component.modalRef.hide).toHaveBeenCalled();
176 describe('validate confirmation', () => {
177 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
179 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
184 component.deletionForm.reset();
187 it('should test empty values', () => {
188 component.deletionForm.reset();
189 testValidation(false, undefined, false);
190 testValidation(true, 'required', true);
191 component.deletionForm.reset();
194 testValidation(true, 'required', true);
198 describe('deletion call', () => {
200 spyOn(component, 'stopLoadingSpinner').and.callThrough();
201 spyOn(component, 'hideModal').and.callThrough();
204 describe('Controller driven', () => {
206 spyOn(component, 'submitAction').and.callThrough();
207 spyOn(mockComponent.ctrlRef, 'hide').and.callThrough();
210 it('should test fake deletion that closes modal', <any>fakeAsync(() => {
211 // Before deletionCall
212 expect(component.submitAction).not.toHaveBeenCalled();
213 // During deletionCall
214 component.callSubmitAction();
215 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
216 expect(component.hideModal).not.toHaveBeenCalled();
217 expect(mockComponent.ctrlRef.hide).not.toHaveBeenCalled();
218 expect(component.submitAction).toHaveBeenCalled();
219 expect(mockComponent.finished).toBe(undefined);
220 // After deletionCall
222 expect(component.hideModal).not.toHaveBeenCalled();
223 expect(mockComponent.ctrlRef.hide).toHaveBeenCalled();
224 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
228 describe('Modal driven', () => {
230 mockComponent.openModalDriven();
231 spyOn(component, 'stopLoadingSpinner').and.callThrough();
232 spyOn(component, 'hideModal').and.callThrough();
233 spyOn(mockComponent, 'fakeDelete').and.callThrough();
236 it('should delete and close modal', <any>fakeAsync(() => {
237 // During deletionCall
238 component.callSubmitAction();
239 expect(mockComponent.finished).toBe(undefined);
240 expect(component.hideModal).not.toHaveBeenCalled();
241 // After deletionCall
243 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
244 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
245 expect(component.hideModal).toHaveBeenCalled();