Generates boilerplate Jasmine tests from annotated AngularJS components via Dgeni.
angular-jasmine-boilerplate [--save] [--base-path=path] [--test-path=path] [--config=path] [--non-interactive] [--force] [file ...]
Option | Type | Description |
---|---|---|
--save |
boolean | Saves the specified base and test paths to a config.json file in the root directory |
--base-path |
string | Absolute path to source directory |
--test-path |
string | Absolute path to test directory |
--config |
string | Path to configuration JSON file |
--non-interactive |
boolean | Disables interactive prompt when boilerplate file already exists, and immediately excludes file |
--force |
boolean | Forces the boilerplate to be generated, regardless of its previous existence |
Install dependencies:
npm install -g angular-jasmine-boilerplate
Save relevant paths:
angular-jasmine-boilerplate --save --base-path=/dev/project/src --test-path=/dev/project/tests
Generate Jasmine boilerplate:
angular-jasmine-boilerplate session/session.service.js
where the arguments are one or more paths to annotated AngularJS components, relative to base-path
.
This utility is also available for Sublime Text and Atom.
This utility leverages a handful of conventional ngdoc
tags to generate boilerplate Jasmine tests.
@ngdoc
Determines the template used to process an item.
When applied to an AngularJS core component, the value of this tag can be controller
, service
, or componentController
to specify a controller, service, or component’s controller respectively.
All public methods with an @ngdoc
value of method
generate a nested describe
block that will ultimately be used to test the particular method in isolation. Private methods not exposed on scope (and without an @ngdoc
tag) will not have a corresponding describe
block as they can only be tested via another public method.
@name
Specifies the name of the processed item.
The name of an AngularJS service or controller is used as the title of Jasmine’s outer describe
function.
Names of items that belong to an AngularJS component should be prefixed with the name of that component. For example, a public method foo
exposed in the service myService
should include the following annotation:
/**
* @ngdoc method
* @name myService#foo
*/
This annotated method name is called in the beforeEach
function of the method’s corresponding describe
block. This name is also included in a comment above the nested describe
block.
/**
* foo
*/
describe('When...', function() {
beforeEach(function() {
target.foo();
});
it('should ', function() {
});
});
@description
Specifies the description of the processed method.
The description of an annotated method is used to populate the name of the corresponding nested describe
block. The first word of a method’s description is expected to be a present tense verb which is ultimately conjugated to a gerund. For example, the description:
/**
* @description Acts on the specified argument
*/
is represented in the generated Jasmine boilerplate as:
describe('When acting on the specified argument', function() {
...
});
Descriptions that span multiple lines are truncated with an ellipsis.
@requires
Describes the name of an injected dependency.
All of the @requires
tags on a controller or service will generate a set of corresponding spy objects that will be used to mock dependencies during the test setup. The local variable names of these spies will be set to the name of the dependency, suffixed with “Spy”. The variable names of core AngularJS services strip the $
prefix.
For example, the following controller annotations:
/**
* @ngdoc controller
* @name MyCtrl
* @requires $scope
* @requires myService
*/
will generate:
var scopeSpy;
var myServiceSpy;
...
beforeEach(function() {
scopeSpy = jasmine.createSpyObj('$scope', ['']);
myServiceSpy = jasmine.createSpyObj('myService', ['']);
});
A rudimentary regular expression attempts to determine the methods used on each dependency. These methods are included as an alphabetized array of strings, passed to jasmine.createSpyObj
, creating the spies necessary for testing.
Additional spy objects will be created for dependency methods that apparently return a promise. For example, the following source code:
myService.fetch().then(function() {
...
});
will generate:
var myServiceSpy;
...
var myServiceFetchSpy;
...
beforeEach(function() {
myServiceSpy = jasmine.createSpyObj('myService', ['fetch']);
myServiceFetchSpy = jasmine.createSpyObj('myService.fetch', ['then']);
myServiceSpy.fetch.and.returnValue(myServiceFetchSpy);
});
This enables testing asynchronous functionality without relying on $q
, which requires manually triggering the digest cycle.
describe('...', function() {
beforeEach(function() {
target.fetchData();
});
...
describe('successfully', function() {
beforeEach(function() {
myServiceFetchSpy.then.calls.argsFor(0)[0]();
});
...
});
});
@module
Specifies the AngularJS module in which the controller or service exists.
The value of this tag is included in a beforeEach
function at the top of the generated boilerplate test:
beforeEach(module('myApp'));
@component
Specifies the name of the component associated with the processed component controller.
The name of the related component is passed as the first parameter to $componentController
during the test setup.