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 {}
21 class="btn btn-sm btn-primary"
22 (click)="openCtrlDriven()">
23 <i class="fa fa-fw fa-times"></i>Deletion Ctrl-Test
24 <ng-template #ctrlDescription>
25 The spinner is handled by the controller if you have use the modal as ViewChild in order to
26 use it's functions to stop the spinner or close the dialog.
31 class="btn btn-sm btn-primary"
32 (click)="openModalDriven()">
33 <i class="fa fa-fw fa-times"></i>Deletion Modal-Test
34 <ng-template #modalDescription>
35 The spinner is handled by the modal if your given deletion function returns a Observable.
41 @ViewChild('ctrlDescription')
42 ctrlDescription: TemplateRef<any>;
43 @ViewChild('modalDescription')
44 modalDescription: TemplateRef<any>;
45 someData = [1, 2, 3, 4, 5];
50 // Normally private - public was needed for the tests
51 constructor(public modalService: BsModalService) {}
54 this.ctrlRef = this.modalService.show(CriticalConfirmationModalComponent, {
56 submitAction: this.fakeDeleteController.bind(this),
57 bodyTemplate: this.ctrlDescription
63 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
65 submitActionObservable: this.fakeDelete(),
66 bodyTemplate: this.modalDescription
72 this.finished = [6, 7, 8, 9];
76 return (): Observable<any> => {
77 return new Observable((observer: Subscriber<any>) => {
78 observableTimer(100).subscribe(() => {
79 observer.next(this.finish());
86 fakeDeleteController() {
87 observableTimer(100).subscribe(() => {
94 describe('CriticalConfirmationModalComponent', () => {
95 let mockComponent: MockComponent;
96 let component: CriticalConfirmationModalComponent;
97 let mockFixture: ComponentFixture<MockComponent>;
98 let fixture: ComponentFixture<CriticalConfirmationModalComponent>;
101 declarations: [MockComponent, CriticalConfirmationModalComponent],
102 schemas: [NO_ERRORS_SCHEMA],
103 imports: [ModalModule.forRoot(), ReactiveFormsModule, MockModule, DirectivesModule],
104 providers: [BsModalRef]
108 mockFixture = TestBed.createComponent(MockComponent);
109 mockComponent = mockFixture.componentInstance;
110 // Mocking the modals as a lot would be left over
111 spyOn(mockComponent.modalService, 'show').and.callFake((modalComp, config) => {
112 const ref = new BsModalRef();
113 fixture = TestBed.createComponent(CriticalConfirmationModalComponent);
114 component = fixture.componentInstance;
115 if (config.initialState) {
116 component = Object.assign(component, config.initialState);
118 fixture.detectChanges();
119 ref.content = component;
122 mockComponent.openCtrlDriven();
123 mockFixture.detectChanges();
126 it('should create', () => {
127 expect(component).toBeTruthy();
130 it('should focus the checkbox form field', () => {
131 fixture.detectChanges();
132 fixture.whenStable().then(() => {
133 const focused = fixture.debugElement.query(By.css(':focus'));
134 expect(focused.attributes.id).toBe('confirmation');
135 expect(focused.attributes.type).toBe('checkbox');
136 const element = document.getElementById('confirmation');
137 expect(element === document.activeElement).toBeTruthy();
141 it('should throw an error if no action is defined', () => {
142 component = Object.assign(component, {
144 submitActionObservable: null
146 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
149 it('should test if the ctrl driven mock is set correctly through mock component', () => {
150 expect(component.bodyTemplate).toBeTruthy();
151 expect(component.submitAction).toBeTruthy();
152 expect(component.submitActionObservable).not.toBeTruthy();
155 it('should test if the modal driven mock is set correctly through mock component', () => {
156 mockComponent.openModalDriven();
157 expect(component.bodyTemplate).toBeTruthy();
158 expect(component.submitActionObservable).toBeTruthy();
159 expect(component.submitAction).not.toBeTruthy();
162 describe('component functions', () => {
163 const changeValue = (value) => {
164 const ctrl = component.deletionForm.get('confirmation');
165 ctrl.setValue(value);
167 ctrl.updateValueAndValidity();
168 fixture.detectChanges();
171 it('should test hideModal', () => {
172 expect(component.modalRef).toBeTruthy();
173 expect(component.hideModal).toBeTruthy();
174 spyOn(component.modalRef, 'hide').and.callThrough();
175 expect(component.modalRef.hide).not.toHaveBeenCalled();
176 component.hideModal();
177 expect(component.modalRef.hide).toHaveBeenCalled();
180 describe('validate confirmation', () => {
181 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
183 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
188 component.deletionForm.reset();
191 it('should test empty values', () => {
192 component.deletionForm.reset();
193 testValidation(false, undefined, false);
194 testValidation(true, 'required', true);
195 component.deletionForm.reset();
198 testValidation(true, 'required', true);
202 describe('deletion call', () => {
204 spyOn(component, 'stopLoadingSpinner').and.callThrough();
205 spyOn(component, 'hideModal').and.callThrough();
208 describe('Controller driven', () => {
210 spyOn(component, 'submitAction').and.callThrough();
211 spyOn(mockComponent.ctrlRef, 'hide').and.callThrough();
214 it('should test fake deletion that closes modal', <any>fakeAsync(() => {
215 // Before deletionCall
216 expect(component.submitAction).not.toHaveBeenCalled();
217 // During deletionCall
218 component.callSubmitAction();
219 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
220 expect(component.hideModal).not.toHaveBeenCalled();
221 expect(mockComponent.ctrlRef.hide).not.toHaveBeenCalled();
222 expect(component.submitAction).toHaveBeenCalled();
223 expect(mockComponent.finished).toBe(undefined);
224 // After deletionCall
226 expect(component.hideModal).not.toHaveBeenCalled();
227 expect(mockComponent.ctrlRef.hide).toHaveBeenCalled();
228 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
232 describe('Modal driven', () => {
234 mockComponent.openModalDriven();
235 spyOn(component, 'stopLoadingSpinner').and.callThrough();
236 spyOn(component, 'hideModal').and.callThrough();
237 spyOn(mockComponent, 'fakeDelete').and.callThrough();
240 it('should delete and close modal', <any>fakeAsync(() => {
241 // During deletionCall
242 component.callSubmitAction();
243 expect(mockComponent.finished).toBe(undefined);
244 expect(component.hideModal).not.toHaveBeenCalled();
245 // After deletionCall
247 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
248 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
249 expect(component.hideModal).toHaveBeenCalled();