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, modalServiceShow } 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-secondary" (click)="openCtrlDriven()">
21 <i class="fa 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-secondary" (click)="openModalDriven()">
29 <i class="fa 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', { static: true })
38 ctrlDescription: TemplateRef<any>;
39 @ViewChild('modalDescription', { static: true })
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 spyOn(mockComponent.modalService, 'show').and.callFake((_modalComp, config) => {
107 const data = modalServiceShow(CriticalConfirmationModalComponent, config);
108 fixture = data.fixture;
109 component = data.component;
112 mockComponent.openCtrlDriven();
113 mockFixture.detectChanges();
116 it('should create', () => {
117 expect(component).toBeTruthy();
120 it('should focus the checkbox form field', (done) => {
121 fixture.detectChanges();
122 fixture.whenStable().then(() => {
123 const focused = fixture.debugElement.query(By.css(':focus'));
124 expect(focused.attributes.id).toBe('confirmation');
125 expect(focused.attributes.type).toBe('checkbox');
126 const element = document.getElementById('confirmation');
127 expect(element === document.activeElement).toBeTruthy();
132 it('should throw an error if no action is defined', () => {
133 component = Object.assign(component, {
135 submitActionObservable: null
137 expect(() => component.ngOnInit()).toThrowError('No submit action defined');
140 it('should test if the ctrl driven mock is set correctly through mock component', () => {
141 expect(component.bodyTemplate).toBeTruthy();
142 expect(component.submitAction).toBeTruthy();
143 expect(component.submitActionObservable).not.toBeTruthy();
146 it('should test if the modal driven mock is set correctly through mock component', () => {
147 mockComponent.openModalDriven();
148 expect(component.bodyTemplate).toBeTruthy();
149 expect(component.submitActionObservable).toBeTruthy();
150 expect(component.submitAction).not.toBeTruthy();
153 describe('component functions', () => {
154 const changeValue = (value: boolean) => {
155 const ctrl = component.deletionForm.get('confirmation');
156 ctrl.setValue(value);
158 ctrl.updateValueAndValidity();
159 fixture.detectChanges();
162 it('should test hideModal', () => {
163 expect(component.modalRef).toBeTruthy();
164 expect(component.hideModal).toBeTruthy();
165 spyOn(component.modalRef, 'hide').and.callThrough();
166 expect(component.modalRef.hide).not.toHaveBeenCalled();
167 component.hideModal();
168 expect(component.modalRef.hide).toHaveBeenCalled();
171 describe('validate confirmation', () => {
172 const testValidation = (submitted: boolean, error: string, expected: boolean) => {
174 component.deletionForm.showError('confirmation', <NgForm>{ submitted: submitted }, error)
179 component.deletionForm.reset();
182 it('should test empty values', () => {
183 component.deletionForm.reset();
184 testValidation(false, undefined, false);
185 testValidation(true, 'required', true);
186 component.deletionForm.reset();
189 testValidation(true, 'required', true);
193 describe('deletion call', () => {
195 spyOn(component, 'stopLoadingSpinner').and.callThrough();
196 spyOn(component, 'hideModal').and.callThrough();
199 describe('Controller driven', () => {
201 spyOn(component, 'submitAction').and.callThrough();
202 spyOn(mockComponent.ctrlRef, 'hide').and.callThrough();
205 it('should test fake deletion that closes modal', fakeAsync(() => {
206 // Before deletionCall
207 expect(component.submitAction).not.toHaveBeenCalled();
208 // During deletionCall
209 component.callSubmitAction();
210 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
211 expect(component.hideModal).not.toHaveBeenCalled();
212 expect(mockComponent.ctrlRef.hide).not.toHaveBeenCalled();
213 expect(component.submitAction).toHaveBeenCalled();
214 expect(mockComponent.finished).toBe(undefined);
215 // After deletionCall
217 expect(component.hideModal).not.toHaveBeenCalled();
218 expect(mockComponent.ctrlRef.hide).toHaveBeenCalled();
219 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
223 describe('Modal driven', () => {
225 mockComponent.openModalDriven();
226 spyOn(component, 'stopLoadingSpinner').and.callThrough();
227 spyOn(component, 'hideModal').and.callThrough();
228 spyOn(mockComponent, 'fakeDelete').and.callThrough();
231 it('should delete and close modal', fakeAsync(() => {
232 // During deletionCall
233 component.callSubmitAction();
234 expect(mockComponent.finished).toBe(undefined);
235 expect(component.hideModal).not.toHaveBeenCalled();
236 // After deletionCall
238 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
239 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
240 expect(component.hideModal).toHaveBeenCalled();