// === File: my-message-widget.js
angular.module('my-module').directive('myMessageWidget', function() {
return {
scope: {
message: '='
},
replace: true,
restrict: 'E',
template: "<span class='my-message'>{{ message }}</span>"
};
});
// === File: directive-spec-boilerplate.module.js
// Define a module containing the definition of a Given environment for testing
// Angular directives.
angular.module('directive-spec-boilerplate', []).service 'directiveSpec', function($compile, $rootScope) {
return function(spec) {
var given = Given(spec);
given({
// Returns a compiled and linked HTML element.
element: function() {
var element = angular.element(this.template);
$compile(element)(this.scopeObject);
scopeObject.$digest();
return element;
},
// The Angular scope.
scopeObject: function() {
var scope = $rootScope.$new();
if (this.scope) {
_.extend(scope, this.scope);
}
return scope;
},
// Returns the element's isolated scope.
isolateScope: function() {
return this.element.isolateScope();
},
// Defines your template. This is just a placeholder. If you forget to
// override the definition in your own spec, it will error out with
// a helpful message.
template: function() {
throw new Error 'You must override the "template" definition to define your template'
}
});
return given;
};
};
// === File: my-message-widget.spec.js
// Then make use of it in your spec for your directive.
describe('Directive: myMessageWidget', function() {
var given = undefined;
beforeEach(function() {
module('my-module');
module('directive-spec-boilerplate');
});
beforeEach(inject(function(directiveSpec) {
// Creates the Given environment, pre-populated with Angular JS directive
// spec boilerplate. The 'this' is the 'this' of the spec itself, which
// means all variables defined via given are actually properties of the
// spec.
given = directiveSpec(this);
given({
template: function() {
return '<my-message-widget message="message"></my-message-widget>';
},
scope: function() {
return { message: "Hello from James!" };
}
});
}));
it('displays the message', function() {
// Accessing 'this.element' causes lazy evaluation of the element as defined
// in the boilerplate helper.
expect(this.element.find(".my-message")).toHaveText('Hello from James!');
});
});
Example: an Angular.js directive spec
Download example
Using an given environment made specifically for testing Angular.js directives means lesss boilerplate in your specs. In this example all that the spec must define is a template and any necessary scope variables required by the directive, yet the boilerplate derives scopeObject
, element
and isolateScope
for you.
You can download the code and use the directive spec boilerplate in your own Angular projects!