I'm already some time in the development using AngularJS, and what I do write works, but know I've come to a point where I would like to run unit tests on my AngularJS code.
I have created a very simple service that will inject a stylesheet onto the page, see the example code below:
var OfficeSuiteStylesheetInjectorModule = angular.module('OfficeSuiteStylesheetInjectorModule', []);
OfficeSuiteStylesheetInjectorModule.factory('stylesheetInjectorService', ['$q', function($q) {
// Returns the service itself.
return {
inject: function(id, uri) {
var deferred = $q.defer();
// Embed the stylesheet into the page, but only when it's non-existing.
if (!angular.element('#' + id).length) {
var link = StylesheetFactory.Create(id, uri);
{
link.onload = deferred.resolve;
angular.element('head').append(link);
}
return deferred.promise;
}
}
}
}]);
It's not a big service, it's just dependend on $q
for promises so that I can run additional logic when the stylesheet has been embedded in the page.
Now, I'm using Jasmine (I'm quite new to this) for testing my JavaScript code and I would like to test this module.
I have a skeleton:
// Tests for the angular 'StylesheetInjectorService'.
describe('StylesheetInjectorService', function() {
var stylesheetInjectorService = {};
// This code is executed before every test.
beforeEach(function() {
// Tells jamine that the module we're working on is the 'OfficeSuiteStylesheetInjectorModule'.
angular.module('OfficeSuiteStylesheetInjectorModule');
});
// Ensures that it injects a stylesheet element into the page.
it('Should inject a stylesheet element into the page.', function() {
// How to test here that the stylesheet is injected?
});
});
});
How can I inject te service in the page and ensures that the stylesheet is loaded?
Edit: Loading service now works:
beforeEach(module('OfficeSuiteStylesheetInjectorModule'));
// This code is executed before every test.
beforeEach(function() {
// Inject the required dependencies into the page.
inject(function($injector) {
stylesheetInjectorService = $injector.get('stylesheetInjectorService');
});
});
The same question is still open however. How to test if a stylesheet was embedded in the page?
Any help is highly appreciated.
Kind regards
To write a spec for the attachment of a stylesheet to angular.element('head')
I would change the logic a bit to attach it to $document.head
.
If you dont want to do that, I would recommend that you change your service into a
directive
seeing as how injecting a script element, is manipulating the DOM. That way you would kill two birds with one stone, as you would need to inject$compile
to test your directive (which would enable you to $compile a customhead
element to boot). But this is slightly "over the top" for now.
if (!angular.element('#' + id).length) {
var link = StylesheetFactory.Create(id, uri);
link.onload = deferred.resolve;
$document.head.append(link);
return deferred.promise;
}
}
/**
* Sorry, this was previously $location which was just
* such a silly mistake.
*/
var $timeout;
beforeEach(function () {
inject(function ($injector) {
$timeout = $injector.get('$timeout');
});
});
it('attaches the stylesheet to $document.head', function () {
styleSheetInjectorService.inject('someId', '/path/to/some/stylesheet');
$timeout.flush(); // flush promises
expect(angular.element($document.head).lastChild[0].nodeName).to.eq('LINK');
});
Something along those lines should get you up and running. Bare in mind that the spec I wrote uses the chai#expect style assertions, and the mocha test framework. Edit the syntax to fit Jasmine if you mean to copy-paste.