tentacle.js
Version:
Auto mock/inject dependencies for Angular tests
152 lines (133 loc) • 4.16 kB
JavaScript
;
var _ = require('lodash');
module.exports = init;
function init(window, angular) {
var dirtyProperties = [];
var mockExceptions = [
'$http',
'$httpBackend',
'$rootScope',
'$q',
'$scope',
'$filter'
];
var globalInjects = [
'$rootScope',
'$q',
'$httpBackend',
'$templateCache',
'$compile'
];
addToWindow('tentacle', {});
addToWindow('async', async);
window.tentacle.mock = mock;
window.tentacle.injectGlobals = injectGlobals;
window.tentacle.mockExceptions = mockExceptions;
window.tentacle.globalInjects = globalInjects;
window.tentacle.injectAll = injectAll;
window.tentacle.controller = controller;
window.tentacle.directive = directive;
window.tentacle.service = service;
window.tentacle.factory = service;
window.tentacle.reset = reset;
function mock(module, name, override, defaultMock) {
angular.mock.module(module);
var mocksObject = createMocksObject(module, name, override, defaultMock);
_.forEach(mocksObject, provideValue);
return mocksObject;
}
function injectGlobals() {
_.forEach(globalInjects, injectDependency);
}
function injectAll(module, name) {
window.tentacle.injectGlobals();
var deps = getDependencies(module, name);
var allDependencies = _.union(deps, globalInjects);
_.forEach(allDependencies, injectDependency);
injectDependency(name);
}
function controller(module, name, override, defaultMock) {
angular.mock.module(module);
window.tentacle.injectGlobals();
injectDependency('$controller');
var mocksObject = createMocksObject(module, name, override, defaultMock);
addToWindow('$scope', window.$rootScope.$new());
_.extend(mocksObject, {
$scope: window.$scope
});
window.tentacle.controller.run = function () {
var ctrl = window.$controller(name, mocksObject);
window.$scope.$digest();
return ctrl;
};
return mocksObject;
}
function directive(module, name, override, defaultMock) {
var mocksObject = window.tentacle.mock(module, name, override, defaultMock);
window.tentacle.injectGlobals();
addToWindow('$scope', window.$rootScope.$new());
_.extend(mocksObject, {
$scope: window.$scope
});
window.tentacle.directive.run = function (element) {
element = window.$compile(element)(window.$scope);
window.$scope.$digest();
return element;
};
return mocksObject;
}
function service(module, name, override, defaultMock) {
var mocksObject = window.tentacle.mock(module, name, override, defaultMock);
window.tentacle.injectGlobals();
injectDependency(name);
return mocksObject;
}
function async(x) {
if (!window.$q) {
injectDependency('$q');
}
return window.$q.when(x);
}
function addToWindow(propertyName, value) {
window[propertyName] = value;
dirtyProperties.push(propertyName);
}
function reset() {
_.forEach(dirtyProperties, function (prop) {
delete window[prop];
});
}
function injectDependency(dependency) {
angular.mock.inject([dependency, function (_dependency_) {
addToWindow(dependency, _dependency_);
}]);
}
function createMocksObject(module, name, override, defaultMock) {
override = override || {};
var dependencies = getDependencies(module, name);
dependencies = _.difference(dependencies, mockExceptions);
return _.chain(dependencies)
.reduce(function (mocksObject, dependency) {
mocksObject[dependency] = defaultMock || {};
return mocksObject;
}, {})
.assign(override)
.value();
}
function getDependencies(module, name) {
var invokeQueue = angular.module(module)._invokeQueue;
// depArr is an array-like object
// it has no length property
var depArr = _.chain(invokeQueue)
.unzip().last()
.find(function (config) {
return _.isEqual(config[0], name);
}).value();
return _.initial(depArr[1]);
}
function provideValue(mock, dependency) {
angular.mock.module(function ($provide) {
$provide.value(dependency, mock);
});
}
}