I am currently writing a service to control an upload flow. I am writing unit tests right now for the function which show and hide the upload modal box. In the tests, I am using angular.element.find
to look to see if the modal exists. In the second test, the number goes up from what I would expect, as though it isn't resetting.
The two tests are as follows:
describe('show', function() {
it('should initially not show the modal', function() {
expect(upload.isShowing()).toEqual(false);
expect(angular.element.find('.modal').length).toEqual(0);
});
it('should show the upload modal', function() {
expect(upload.isShowing()).toEqual(false);
expect(angular.element.find('.modal').length).toEqual(0);
upload.show();
$rootScope.$digest();
expect(upload.isShowing()).toEqual(true);
expect(angular.element.find('.modal').length).toEqual(1);
});
});
describe('cancel', function() {
it('should hide the upload form', function() {
expect(upload.isShowing()).toEqual(false);
expect(angular.element.find('.modal').length).toEqual(0);
upload.show();
$rootScope.$digest();
expect(upload.isShowing()).toEqual(true);
expect(angular.element.find('.modal').length).toEqual(1);
});
});
The first describe block passes fine, but the second one fails. It tells me that it Expected 1 to equal 0.
If I comment out the first expect with angular.element.find
in the test for cancel
it says 'Expected 2 to equal 1.'
All I can determine is that the html is all getting thrown into the same space, and is compounding after each test. Is there some way I can prevent this behaviour, or use an `afterEach' statement to flush the previous HTML?
Thanks!
Ammendment
Here is the full code for this suite of tests, if it helps:
describe('uploadService', function() {
var $rootScope,
upload;
beforeEach(module('upload'));
beforeEach(module('upload.service'));
beforeEach(module('bublNg.templates'));
beforeEach(module('ui.bootstrap.tpls'));
beforeEach(inject(function($injector) {
upload = $injector.get('upload');
$rootScope = $injector.get('$rootScope');
}));
describe('isShowing', function() {
it('should return true if the modal us showing', function() {
expect(upload.isShowing()).toEqual(false);
upload.show();
expect(upload.isShowing()).toEqual(true);
});
});
describe('show', function() {
it('should initially not show the modal', function() {
expect(upload.isShowing()).toEqual(false);
expect(angular.element.find('.modal').length).toEqual(0);
});
it('should show the upload modal', function() {
expect(upload.isShowing()).toEqual(false);
expect(angular.element.find('.modal').length).toEqual(0);
upload.show();
$rootScope.$digest();
expect(upload.isShowing()).toEqual(true);
expect(angular.element.find('.modal').length).toEqual(1);
});
});
describe('cancel', function() {
it('should hide the upload form', function() {
expect(upload.isShowing()).toEqual(false);
// expect(angular.element.find('.modal').length).toEqual(0);
upload.show();
$rootScope.$digest();
expect(upload.isShowing()).toEqual(true);
// expect(angular.element.find('.modal').length).toEqual(1);
upload.cancel();
expect(upload.isShowing()).toEqual(false);
});
});
});
Avoid testing html element presence for something like this. As you're using UI Bootstrap, you should inject the $modal
service into your tests and spy on its open
method. Then test your code's calls to it. This prevents DOM pollution during your tests.
This pattern should get you started:
var $modal;
beforeEach(inject(function($injector) {
$modal = $injector.get('$modal');
}));
beforeEach(function() {
spyOn($modal, 'open');
// or, to mock/fake a modal object so you can test close/dismiss handlers
// spyOn($modal, 'open').and.returnValue(mockModal);
// see: http://stackoverflow.com/a/21370703/2943490
});
describe('show', function() {
it('should initially not show the modal', function() {
expect($modal.open).not.toHaveBeenCalled();
});
it('should show the upload modal', function() {
upload.show();
$rootScope.$digest();
expect($modal.open).toHaveBeenCalledWith({
// your modal options
});
});
});