I am having some trouble writing unit tests for a confirmation modal I have in my app. Here is the piece of code I would like to test:
confirmModal(prompt = 'Are you sure?', title = 'Confirm'): Observable<boolean> {
const modal = this.ngbModal.open(
ConfirmModalComponent, { backdrop: 'static' });
modal.componentInstance.prompt = prompt;
modal.componentInstance.title = title;
return from(modal.result).pipe(
catchError(error => {
console.warn(error);
return of(undefined);
})
);
}
Any suggestions or examples?
compileComponents(); fixtureUnderTest = TestBed. createComponent(MyComponent); componentUnderTest = fixtureUnderTest. componentInstance; ngbModal = TestBed. get(NgbModal); }); it('should open modal', () => { spyOn(ngbModal, 'open').
Ng Bootstrap will help to easily use bootstrap ui. In this example we will simply create one model popup, so you can use in your angular 12 application.
I've written the following test class based on your code snippet:
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { ConfirmModalComponent } from './confirm-modal.component';
import { MyComponent } from './test';
// Mock class for NgbModalRef
export class MockNgbModalRef {
componentInstance = {
prompt: undefined,
title: undefined
};
result: Promise<any> = new Promise((resolve, reject) => resolve(true));
}
describe('MyComponent tests', () => {
let fixtureUnderTest: ComponentFixture<MyComponent>;
let componentUnderTest: MyComponent;
let ngbModal: NgbModal;
let mockModalRef: MockNgbModalRef = new MockNgbModalRef();
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
MyComponent
],
imports: [
NgbModule.forRoot()
]
}).compileComponents();
fixtureUnderTest = TestBed.createComponent(MyComponent);
componentUnderTest = fixtureUnderTest.componentInstance;
ngbModal = TestBed.get(NgbModal);
});
it('should open modal', () => {
spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
componentUnderTest.confirmModal();
expect(ngbModal.open).toHaveBeenCalledWith(ConfirmModalComponent, { backdrop: 'static' });
});
it('should set prompt and title to defaults', () => {
spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
componentUnderTest.confirmModal();
expect(mockModalRef.componentInstance.prompt).toBe('Are you sure?');
expect(mockModalRef.componentInstance.title).toBe('Confirm');
});
it('should return the result of the modal', (done: DoneFn) => {
spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
componentUnderTest.confirmModal().subscribe((result: boolean) => {
expect(result).toBe(true);
done();
});
});
it('should return undefined if there is an error', (done: DoneFn) => {
spyOn(ngbModal, 'open').and.returnValue(mockModalRef);
// Override the result returned from the modal so we can test what happens when the modal is dismissed
mockModalRef.result = new Promise((resolve, reject) => reject(false));
componentUnderTest.confirmModal().subscribe((result: boolean) => {
expect(result).toBeUndefined();
done();
});
});
});
The tests are as follows:
should open modal: Tests the ngbModal.open
method was called with the correct parameters.
should set prompt
and title
to defaults: Tests that prompt
and title
attributes are set correctly to their default values after the modal has opened. For this I had to add the following object to the MockNgbModalRef
so that the values for prompt and title can be updated by the component itself.
componentInstance = {
prompt: undefined,
title: undefined
};
should return the result of the modal: Tests that the value of modal.result
is returned from this method. With the method returning an Observable, I needed to subscribe to it and do the assert in within the subscribe. I've inject DoneFn
so that done()
gets called after the assertion. This means if the assertion never happens (e.g. there is an error in the component), done()
never gets called and the test will fail.
should return undefined if there is an error: Similar to #3, however it checks that if the result of the modal was rejected (i.e. there was an error) then undefined is returned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With