ng-wedge
Version:
Intercept $http request from the website without modifying code or installing plugins.
105 lines (95 loc) • 3.35 kB
JavaScript
(function ngWedge(root, angular, document) {
if (typeof angular === 'undefined') {
throw new Error('missing angular');
}
if (typeof document === 'undefined') {
throw new Error('missing document');
}
root.wedge = function wedge(selector, scopeMethodName) {
var el = angular.element(document.querySelector(selector));
var scope = el.scope() || el.isolateScope();
var originalMethod = scope[scopeMethodName];
if (!angular.isFunction(originalMethod)) {
throw new Error('Cannot find ' + scopeMethodName + ' on scope for ' + selector);
}
if (originalMethod.__wedged) {
return;
}
var injector = el.injector();
// fake lexical scope from original method, see
// http://bahmutov.calepin.co/faking-lexical-scope.html
var $scope = scope;
var $timeout = injector.get('$timeout');
var _$http = injector.get('$http');
var $q = injector.get('$q');
var mockMethods = {
get: {},
post: {}
};
function isSuccess(status) {
return Number(status) >= 200 && Number(status) < 300;
}
var $http = {
get: function (url) {
if (mockMethods.get[url]) {
var mock = mockMethods.get[url];
return {
then: function (success, error) {
var wrappedCb;
if (isSuccess(mock.status)) {
wrappedCb = angular.bind(null, success, mock.data);
return $timeout(wrappedCb, mock.timeout || 0);
} else {
wrappedCb = angular.bind(null, error, mock.data);
return $timeout(wrappedCb, mock.timeout || 0);
}
}
};
}
return _$http.get.apply(_$http, arguments);
},
post: function (url) {
if (mockMethods.post[url]) {
var mock = mockMethods.post[url];
return {
then: function (success) {
var wrappedCb = angular.bind(null, success, mock.data);
return $timeout(wrappedCb, mock.timeout || 0);
}
};
}
return _$http.post.apply(_$http, arguments);
}
};
/* jshint -W061 */
var originalMethodString = eval('(' + originalMethod.toString() + ')');
scope[scopeMethodName] = function replacedLoad() {
// TODO retry the function if there is reference error and load variable from injector
// TODO or we could try parsing the scope / invoke queue to see which variables are injected
// see http://bahmutov.calepin.co/building-runtime-tree-of-angular-modules.html
console.log('calling original method');
originalMethodString();
};
scope[scopeMethodName].__wedged = true;
function clearWedges() {
mockMethods = {
get: {},
post: {}
};
console.log('cleared wedges');
}
return function wedger(method, url, status, data, timeoutMs) {
if (!arguments.length) {
return clearWedges();
}
console.log('wedging', method, url, 'to return', status, data);
console.assert(method === 'get' || method === 'post', 'invalid method ' + method);
// allow regular expression for url
mockMethods[method][url] = {
status: status,
data: data,
timeout: timeoutMs
};
};
};
}(this, this.angular, this.document));