1 import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core';
2 import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
5 import { BsModalRef, BsModalService, ModalModule } from 'ngx-bootstrap';
6 import { Observable } from 'rxjs/Observable';
7 import { Subscriber } from 'rxjs/Subscriber';
9 import { ModalComponent } from '../modal/modal.component';
10 import { DeletionModalComponent } from './deletion-modal.component';
13 entryComponents: [DeletionModalComponent]
15 export class MockModule {}
20 class="btn btn-sm btn-primary"
21 (click)="openCtrlDriven()">
22 <i class="fa fa-fw fa-trash"></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.
30 class="btn btn-sm btn-primary"
31 (click)="openModalDriven()">
32 <i class="fa fa-fw fa-trash"></i>Deletion Modal-Test
33 <ng-template #modalDescription>
34 The spinner is handled by the modal if your given deletion function returns a Observable.
40 @ViewChild('ctrlDescription') ctrlDescription: TemplateRef<any>;
41 @ViewChild('modalDescription') modalDescription: TemplateRef<any>;
42 someData = [1, 2, 3, 4, 5];
47 // Normally private - public was needed for the tests
48 constructor(public modalService: BsModalService) {}
51 this.ctrlRef = this.modalService.show(DeletionModalComponent);
52 this.ctrlRef.content.setUp({
53 metaType: 'Controller delete handling',
55 deletionMethod: this.fakeDeleteController.bind(this),
56 description: this.ctrlDescription,
57 modalRef: this.ctrlRef
62 this.modalRef = this.modalService.show(DeletionModalComponent);
63 this.modalRef.content.setUp({
64 metaType: 'Modal delete handling',
65 pattern: 'modal-test',
66 deletionObserver: this.fakeDelete(),
67 description: this.modalDescription,
68 modalRef: this.modalRef
73 this.finished = [6, 7, 8, 9];
77 return (): Observable<any> => {
78 return new Observable((observer: Subscriber<any>) => {
79 Observable.timer(100).subscribe(() => {
80 observer.next(this.finish());
87 fakeDeleteController() {
88 Observable.timer(100).subscribe(() => {
95 describe('DeletionModalComponent', () => {
96 let mockComponent: MockComponent;
97 let component: DeletionModalComponent;
98 let mockFixture: ComponentFixture<MockComponent>;
99 let fixture: ComponentFixture<DeletionModalComponent>;
101 beforeEach(async(() => {
102 TestBed.configureTestingModule({
103 declarations: [MockComponent, DeletionModalComponent],
104 schemas: [NO_ERRORS_SCHEMA],
105 imports: [ModalModule.forRoot(), ReactiveFormsModule, MockModule]
106 }).compileComponents();
110 mockFixture = TestBed.createComponent(MockComponent);
111 mockComponent = mockFixture.componentInstance;
112 // Mocking the modals as a lot would be left over
113 spyOn(mockComponent.modalService, 'show').and.callFake(() => {
114 const ref = new BsModalRef();
115 fixture = TestBed.createComponent(DeletionModalComponent);
116 component = fixture.componentInstance;
117 fixture.detectChanges();
118 ref.content = component;
121 mockComponent.openCtrlDriven();
122 mockFixture.detectChanges();
125 it('should create', () => {
126 expect(component).toBeTruthy();
129 describe('setUp', () => {
130 const clearSetup = () => {
131 component.metaType = undefined;
132 component.pattern = 'yes';
133 component.deletionObserver = undefined;
134 component.description = undefined;
135 component.modalRef = undefined;
138 const expectSetup = (
145 expect(component.modalRef).toBeTruthy();
146 expect(component.metaType).toBe(metaType);
147 expect(!!component.deletionObserver).toBe(observer);
148 expect(!!component.deletionMethod).toBe(method);
149 expect(component.pattern).toBe(pattern);
150 expect(!!component.description).toBe(template);
157 it('should throw error if no modal reference is given', () => {
163 ).toThrowError('No modal reference');
166 it('should throw error if no meta type is given', () => {
170 modalRef: mockComponent.ctrlRef
172 ).toThrowError('No meta type');
175 it('should throw error if no deletion method is given', () => {
179 modalRef: mockComponent.ctrlRef
181 ).toThrowError('No deletion method');
184 it('should throw no errors if metaType, modalRef and a deletion method were given', () => {
186 metaType: 'Observer',
187 modalRef: mockComponent.ctrlRef,
188 deletionObserver: mockComponent.fakeDelete()
190 expectSetup('Observer', true, false, 'yes', false);
193 metaType: 'Controller',
194 modalRef: mockComponent.ctrlRef,
195 deletionMethod: mockComponent.fakeDeleteController
197 expectSetup('Controller', false, true, 'yes', false);
200 it('should test optional parameters - pattern and description', () => {
202 metaType: 'Pattern only',
203 modalRef: mockComponent.ctrlRef,
204 deletionObserver: mockComponent.fakeDelete(),
205 pattern: '{sth/!$_8()'
207 expectSetup('Pattern only', true, false, '{sth/!$_8()', false);
210 metaType: 'Description only',
211 modalRef: mockComponent.ctrlRef,
212 deletionObserver: mockComponent.fakeDelete(),
213 description: mockComponent.modalDescription
215 expectSetup('Description only', true, false, 'yes', true);
218 metaType: 'Description and pattern',
219 modalRef: mockComponent.ctrlRef,
220 deletionObserver: mockComponent.fakeDelete(),
221 description: mockComponent.modalDescription,
222 pattern: '{sth/!$_8()'
224 expectSetup('Description and pattern', true, false, '{sth/!$_8()', true);
228 it('should test if the ctrl driven mock is set correctly through mock component', () => {
229 expect(component.metaType).toBe('Controller delete handling');
230 expect(component.pattern).toBe('ctrl-test');
231 expect(component.description).toBeTruthy();
232 expect(component.modalRef).toBeTruthy();
233 expect(component.deletionMethod).toBeTruthy();
234 expect(component.deletionObserver).not.toBeTruthy();
237 it('should test if the modal driven mock is set correctly through mock component', () => {
238 mockComponent.openModalDriven();
239 expect(component.metaType).toBe('Modal delete handling');
240 expect(component.pattern).toBe('modal-test');
241 expect(component.description).toBeTruthy();
242 expect(component.modalRef).toBeTruthy();
243 expect(component.deletionObserver).toBeTruthy();
244 expect(component.deletionMethod).not.toBeTruthy();
247 describe('component functions', () => {
248 const changeValue = (value) => {
249 component.confirmation.setValue(value);
250 component.confirmation.markAsDirty();
251 component.confirmation.updateValueAndValidity();
252 fixture.detectChanges();
255 it('should test hideModal', () => {
256 expect(component.modalRef).toBeTruthy();
257 expect(component.hideModal).toBeTruthy();
258 spyOn(component.modalRef, 'hide').and.callThrough();
259 expect(component.modalRef.hide).not.toHaveBeenCalled();
260 component.hideModal();
261 expect(component.modalRef.hide).toHaveBeenCalled();
264 describe('invalid control', () => {
265 const testInvalidControl = (submitted: boolean, error: string, expected: boolean) => {
266 expect(component.invalidControl(submitted, error)).toBe(expected);
270 component.deletionForm.reset();
273 it('should test empty values', () => {
274 expect(component.invalidControl).toBeTruthy();
275 component.deletionForm.reset();
276 testInvalidControl(false, undefined, false);
277 testInvalidControl(true, 'required', true);
278 component.deletionForm.reset();
279 changeValue('let-me-pass');
281 testInvalidControl(true, 'required', true);
284 it('should test pattern', () => {
285 changeValue('let-me-pass');
286 testInvalidControl(false, 'pattern', true);
287 changeValue('ctrl-test');
288 testInvalidControl(false, undefined, false);
289 testInvalidControl(true, undefined, false);
293 describe('deletion call', () => {
295 spyOn(component, 'stopLoadingSpinner').and.callThrough();
296 spyOn(component, 'hideModal').and.callThrough();
299 describe('Controller driven', () => {
301 spyOn(component, 'deletionMethod').and.callThrough();
302 spyOn(mockComponent.ctrlRef, 'hide').and.callThrough();
305 it('should test fake deletion that closes modal', <any>fakeAsync(() => {
306 // Before deletionCall
307 expect(component.deletionMethod).not.toHaveBeenCalled();
308 // During deletionCall
309 component.deletionCall();
310 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
311 expect(component.hideModal).not.toHaveBeenCalled();
312 expect(mockComponent.ctrlRef.hide).not.toHaveBeenCalled();
313 expect(component.deletionMethod).toHaveBeenCalled();
314 expect(mockComponent.finished).toBe(undefined);
315 // After deletionCall
317 expect(component.hideModal).not.toHaveBeenCalled();
318 expect(mockComponent.ctrlRef.hide).toHaveBeenCalled();
319 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
323 describe('Modal driven', () => {
325 mockComponent.openModalDriven();
326 spyOn(mockComponent.modalRef, 'hide').and.callThrough();
327 spyOn(component, 'stopLoadingSpinner').and.callThrough();
328 spyOn(component, 'hideModal').and.callThrough();
329 spyOn(mockComponent, 'fakeDelete').and.callThrough();
332 it('should delete and close modal', <any>fakeAsync(() => {
333 // During deletionCall
334 component.deletionCall();
335 expect(mockComponent.finished).toBe(undefined);
336 expect(component.hideModal).not.toHaveBeenCalled();
337 expect(mockComponent.modalRef.hide).not.toHaveBeenCalled();
338 // After deletionCall
340 expect(mockComponent.finished).toEqual([6, 7, 8, 9]);
341 expect(mockComponent.modalRef.hide).toHaveBeenCalled();
342 expect(component.stopLoadingSpinner).not.toHaveBeenCalled();
343 expect(component.hideModal).toHaveBeenCalled();