Upgrade to angularjs 1.2.0 rc1

This commit is contained in:
Colin Frei 2013-08-21 19:46:51 +02:00
parent d223dfd662
commit d6b021bfaf
674 changed files with 79667 additions and 62269 deletions

View file

@ -1,5 +1,5 @@
/**
* @license AngularJS v1.1.4
* @license AngularJS v1.2.0rc1
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*
@ -29,7 +29,7 @@ angular.mock = {};
* that there are several helper methods available which can be used in tests.
*/
angular.mock.$BrowserProvider = function() {
this.$get = function(){
this.$get = function() {
return new angular.mock.$Browser();
};
};
@ -118,6 +118,22 @@ angular.mock.$Browser = function() {
self.deferredFns.shift().fn();
}
};
/**
* @name ngMock.$browser#defer.flushNext
* @methodOf ngMock.$browser
*
* @description
* Flushes next pending request and compares it to the provided delay
*
* @param {number=} expectedDelay the delay value that will be asserted against the delay of the next timeout function
*/
self.defer.flushNext = function(expectedDelay) {
var tick = self.deferredFns.shift();
expect(tick.time).toEqual(expectedDelay);
tick.fn();
};
/**
* @name ngMock.$browser#defer.now
* @propertyOf ngMock.$browser
@ -241,7 +257,7 @@ angular.mock.$ExceptionHandlerProvider = function() {
*
* @param {string} mode Mode of operation, defaults to `rethrow`.
*
* - `rethrow`: If any errors are are passed into the handler in tests, it typically
* - `rethrow`: If any errors are passed into the handler in tests, it typically
* means that there is a bug in the application or test, so this mock will
* make these tests fail.
* - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` mode stores an
@ -293,18 +309,32 @@ angular.mock.$ExceptionHandlerProvider = function() {
*
*/
angular.mock.$LogProvider = function() {
var debug = true;
function concat(array1, array2, index) {
return array1.concat(Array.prototype.slice.call(array2, index));
}
this.debugEnabled = function(flag) {
if (isDefined(flag)) {
debug = flag;
return this;
} else {
return debug;
}
};
this.$get = function () {
var $log = {
log: function() { $log.log.logs.push(concat([], arguments, 0)); },
warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
info: function() { $log.info.logs.push(concat([], arguments, 0)); },
error: function() { $log.error.logs.push(concat([], arguments, 0)); }
error: function() { $log.error.logs.push(concat([], arguments, 0)); },
debug: function() {
if (debug) {
$log.debug.logs.push(concat([], arguments, 0));
}
}
};
/**
@ -322,36 +352,75 @@ angular.mock.$LogProvider = function() {
* @propertyOf ngMock.$log
*
* @description
* Array of logged messages.
* Array of messages logged using {@link ngMock.$log#log}.
*
* @example
* <pre>
* $log.log('Some Log');
* var first = $log.log.logs.unshift();
* </pre>
*/
$log.log.logs = [];
/**
* @ngdoc property
* @name ngMock.$log#warn.logs
* @propertyOf ngMock.$log
*
* @description
* Array of logged messages.
*/
$log.warn.logs = [];
/**
* @ngdoc property
* @name ngMock.$log#info.logs
* @propertyOf ngMock.$log
*
* @description
* Array of logged messages.
* Array of messages logged using {@link ngMock.$log#info}.
*
* @example
* <pre>
* $log.info('Some Info');
* var first = $log.info.logs.unshift();
* </pre>
*/
$log.info.logs = [];
/**
* @ngdoc property
* @name ngMock.$log#warn.logs
* @propertyOf ngMock.$log
*
* @description
* Array of messages logged using {@link ngMock.$log#warn}.
*
* @example
* <pre>
* $log.warn('Some Warning');
* var first = $log.warn.logs.unshift();
* </pre>
*/
$log.warn.logs = [];
/**
* @ngdoc property
* @name ngMock.$log#error.logs
* @propertyOf ngMock.$log
*
* @description
* Array of logged messages.
* Array of messages logged using {@link ngMock.$log#error}.
*
* @example
* <pre>
* $log.log('Some Error');
* var first = $log.error.logs.unshift();
* </pre>
*/
$log.error.logs = [];
/**
* @ngdoc property
* @name ngMock.$log#debug.logs
* @propertyOf ngMock.$log
*
* @description
* Array of messages logged using {@link ngMock.$log#debug}.
*
* @example
* <pre>
* $log.debug('Some Error');
* var first = $log.debug.logs.unshift();
* </pre>
*/
$log.debug.logs = []
};
/**
@ -364,7 +433,7 @@ angular.mock.$LogProvider = function() {
*/
$log.assertEmpty = function() {
var errors = [];
angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
angular.forEach($log[logLevel].logs, function(log) {
angular.forEach(log, function (logItem) {
errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
@ -388,7 +457,7 @@ angular.mock.$LogProvider = function() {
(function() {
var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
function jsonStringToDate(string){
function jsonStringToDate(string) {
var match;
if (match = string.match(R_ISO8061_STR)) {
var date = new Date(0),
@ -587,57 +656,43 @@ angular.mock.$LogProvider = function() {
angular.mock.TzDate.prototype = Date.prototype;
})();
/**
* @ngdoc function
* @name angular.mock.createMockWindow
* @description
*
* This function creates a mock window object useful for controlling access ot setTimeout, but mocking out
* sufficient window's properties to allow Angular to execute.
*
* @example
*
* <pre>
beforeEach(module(function($provide) {
$provide.value('$window', window = angular.mock.createMockWindow());
}));
angular.mock.animate = angular.module('mock.animate', ['ng'])
it('should do something', inject(function($window) {
var val = null;
$window.setTimeout(function() { val = 123; }, 10);
expect(val).toEqual(null);
window.setTimeout.expect(10).process();
expect(val).toEqual(123);
});
* </pre>
*
*/
angular.mock.createMockWindow = function() {
var mockWindow = {};
var setTimeoutQueue = [];
.config(['$provide', function($provide) {
mockWindow.document = window.document;
mockWindow.getComputedStyle = angular.bind(window, window.getComputedStyle);
mockWindow.scrollTo = angular.bind(window, window.scrollTo);
mockWindow.navigator = window.navigator;
mockWindow.setTimeout = function(fn, delay) {
setTimeoutQueue.push({fn: fn, delay: delay});
};
mockWindow.setTimeout.queue = setTimeoutQueue;
mockWindow.setTimeout.expect = function(delay) {
if (setTimeoutQueue.length > 0) {
return {
process: function() {
setTimeoutQueue.shift().fn();
$provide.decorator('$animate', function($delegate) {
var animate = {
queue : [],
enabled : $delegate.enabled,
flushNext : function(name) {
var tick = animate.queue.shift();
expect(tick.method).toBe(name);
tick.fn();
return tick;
}
};
} else {
expect('SetTimoutQueue empty. Expecting delay of ').toEqual(delay);
}
};
return mockWindow;
};
forEach(['enter','leave','move','addClass','removeClass'], function(method) {
animate[method] = function() {
var params = arguments;
animate.queue.push({
method : method,
params : params,
element : angular.isElement(params[0]) && params[0],
parent : angular.isElement(params[1]) && params[1],
after : angular.isElement(params[2]) && params[2],
fn : function() {
$delegate[method].apply($delegate, params);
}
});
};
});
return animate;
});
}]);
/**
* @ngdoc function
@ -678,6 +733,7 @@ angular.mock.dump = function(object) {
} else if (object instanceof Error) {
out = object.stack || ('' + object.name + ': ' + object.message);
} else {
// TODO(i): this prevents methods to be logged, we should have a better way to serialize objects
out = angular.toJson(object, true);
}
} else {
@ -709,10 +765,10 @@ angular.mock.dump = function(object) {
* @ngdoc object
* @name ngMock.$httpBackend
* @description
* Fake HTTP backend implementation suitable for unit testing application that use the
* Fake HTTP backend implementation suitable for unit testing applications that use the
* {@link ng.$http $http service}.
*
* *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less
* *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
* development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
*
* During unit testing, we want our unit tests to run quickly and have no external dependencies so
@ -805,75 +861,100 @@ angular.mock.dump = function(object) {
*
*
* # Unit testing with mock $httpBackend
* The following code shows how to setup and use the mock backend in unit testing a controller.
* First we create the controller under test
*
* <pre>
// controller
function MyController($scope, $http) {
$http.get('/auth.py').success(function(data) {
$scope.user = data;
});
<pre>
// The controller code
function MyController($scope, $http) {
var authToken;
this.saveMessage = function(message) {
$scope.status = 'Saving...';
$http.post('/add-msg.py', message).success(function(response) {
$scope.status = '';
}).error(function() {
$scope.status = 'ERROR!';
$http.get('/auth.py').success(function(data, status, headers) {
authToken = headers('A-Token');
$scope.user = data;
});
$scope.saveMessage = function(message) {
var headers = { 'Authorization': authToken };
$scope.status = 'Saving...';
$http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
$scope.status = '';
}).error(function() {
$scope.status = 'ERROR!';
});
};
}
</pre>
*
* Now we setup the mock backend and create the test specs.
*
<pre>
// testing controller
describe('MyController', function() {
var $httpBackend, $rootScope, createController;
beforeEach(inject(function($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
$httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
// The $controller service is used to create instances of controllers
var $controller = $injector.get('$controller');
createController = function() {
return $controller('MyController', {'$scope' : $rootScope });
};
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
};
}
// testing controller
var $httpBackend;
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
$httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should fetch authentication token', function() {
$httpBackend.expectGET('/auth.py');
var controller = createController();
$httpBackend.flush();
});
it('should fetch authentication token', function() {
$httpBackend.expectGET('/auth.py');
var controller = scope.$new(MyController);
$httpBackend.flush();
});
it('should send msg to server', function() {
var controller = createController();
$httpBackend.flush();
// now you dont care about the authentication, but
// the controller will still send the request and
// $httpBackend will respond without you having to
// specify the expectation and response for this request
$httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
$rootScope.saveMessage('message content');
expect($rootScope.status).toBe('Saving...');
$httpBackend.flush();
expect($rootScope.status).toBe('');
});
it('should send msg to server', function() {
// now you dont care about the authentication, but
// the controller will still send the request and
// $httpBackend will respond without you having to
// specify the expectation and response for this request
$httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
it('should send auth header', function() {
var controller = createController();
$httpBackend.flush();
var controller = scope.$new(MyController);
$httpBackend.flush();
controller.saveMessage('message content');
expect(controller.status).toBe('Saving...');
$httpBackend.flush();
expect(controller.status).toBe('');
});
$httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
// check if the header was send, if it wasn't the expectation won't
// match the request and the test will fail
return headers['Authorization'] == 'xxx';
}).respond(201, '');
it('should send auth header', function() {
$httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
// check if the header was send, if it wasn't the expectation won't
// match the request and the test will fail
return headers['Authorization'] == 'xxx';
}).respond(201, '');
var controller = scope.$new(MyController);
controller.saveMessage('whatever');
$httpBackend.flush();
});
$rootScope.saveMessage('whatever');
$httpBackend.flush();
});
});
</pre>
*/
angular.mock.$HttpBackendProvider = function() {
@ -911,7 +992,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
}
// TODO(vojta): change params to: method, url, data, headers, callback
function $httpBackend(method, url, data, callback, headers) {
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
var xhr = new MockXhr(),
expectation = expectations[0],
wasExpected = false;
@ -922,24 +1003,41 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
: angular.toJson(data);
}
function wrapResponse(wrapped) {
if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
return handleResponse;
function handleResponse() {
var response = wrapped.response(method, url, data, headers);
xhr.$$respHeaders = response[2];
callback(response[0], response[1], xhr.getAllResponseHeaders());
}
function handleTimeout() {
for (var i = 0, ii = responses.length; i < ii; i++) {
if (responses[i] === handleResponse) {
responses.splice(i, 1);
callback(-1, undefined, '');
break;
}
}
}
}
if (expectation && expectation.match(method, url)) {
if (!expectation.matchData(data))
throw Error('Expected ' + expectation + ' with different data\n' +
throw new Error('Expected ' + expectation + ' with different data\n' +
'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
if (!expectation.matchHeaders(headers))
throw Error('Expected ' + expectation + ' with different headers\n' +
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
prettyPrint(headers));
throw new Error('Expected ' + expectation + ' with different headers\n' +
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + prettyPrint(headers));
expectations.shift();
if (expectation.response) {
responses.push(function() {
var response = expectation.response(method, url, data, headers);
xhr.$$respHeaders = response[2];
callback(response[0], response[1], xhr.getAllResponseHeaders());
});
responses.push(wrapResponse(expectation));
return;
}
wasExpected = true;
@ -950,21 +1048,17 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
if (definition.match(method, url, data, headers || {})) {
if (definition.response) {
// if $browser specified, we do auto flush all requests
($browser ? $browser.defer : responsesPush)(function() {
var response = definition.response(method, url, data, headers);
xhr.$$respHeaders = response[2];
callback(response[0], response[1], xhr.getAllResponseHeaders());
});
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
} else if (definition.passThrough) {
$delegate(method, url, data, callback, headers);
$delegate(method, url, data, callback, headers, timeout, withCredentials);
} else throw Error('No response defined !');
return;
}
}
throw wasExpected ?
Error('No response defined !') :
Error('Unexpected request: ' + method + ' ' + url + '\n' +
(expectation ? 'Expected ' + expectation : 'No more request expected'));
new Error('No response defined !') :
new Error('Unexpected request: ' + method + ' ' + url + '\n' +
(expectation ? 'Expected ' + expectation : 'No more request expected'));
}
/**
@ -976,7 +1070,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
*
* @param {string} method HTTP method.
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current definition.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
@ -1052,7 +1147,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* Creates a new backend definition for POST requests. For more info see `when()`.
*
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
@ -1066,7 +1162,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* Creates a new backend definition for PUT requests. For more info see `when()`.
*
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
* data string and returns true if the data is as expected.
* @param {(Object|function(Object))=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
@ -1095,7 +1192,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
*
* @param {string} method HTTP method.
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
* object and returns true if the headers match the current expectation.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
@ -1164,7 +1263,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* Creates a new request expectation for POST requests. For more info see `expect()`.
*
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
@ -1178,7 +1279,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* Creates a new request expectation for PUT requests. For more info see `expect()`.
*
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
@ -1192,7 +1295,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* Creates a new request expectation for PATCH requests. For more info see `expect()`.
*
* @param {string|RegExp} url HTTP url.
* @param {(string|RegExp)=} data HTTP request body.
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
* receives data string and returns true if the data is as expected, or Object if request body
* is in JSON format.
* @param {Object=} headers HTTP headers.
* @returns {requestHandler} Returns an object with `respond` method that control how a matched
* request is handled.
@ -1253,13 +1358,13 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
* "afterEach" clause.
*
* <pre>
* afterEach($httpBackend.verifyExpectations);
* afterEach($httpBackend.verifyNoOutstandingExpectation);
* </pre>
*/
$httpBackend.verifyNoOutstandingExpectation = function() {
$rootScope.$digest();
if (expectations.length) {
throw Error('Unsatisfied requests: ' + expectations.join(', '));
throw new Error('Unsatisfied requests: ' + expectations.join(', '));
}
};
@ -1345,6 +1450,7 @@ function MockHttpExpectation(method, url, data, headers) {
this.matchData = function(d) {
if (angular.isUndefined(data)) return true;
if (data && angular.isFunction(data.test)) return data.test(d);
if (data && angular.isFunction(data)) return data(d);
if (data && !angular.isString(data)) return angular.toJson(data) == d;
return data == d;
};
@ -1411,7 +1517,7 @@ function MockXhr() {
*
* This service is just a simple decorator for {@link ng.$timeout $timeout} service
* that adds a "flush" and "verifyNoPendingTasks" methods.
*/
*/
angular.mock.$TimeoutDecorator = function($delegate, $browser) {
@ -1422,9 +1528,25 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
* @description
*
* Flushes the queue of pending tasks.
*
* @param {number=} delay maximum timeout amount to flush up until
*/
$delegate.flush = function() {
$browser.defer.flush();
$delegate.flush = function(delay) {
$browser.defer.flush(delay);
};
/**
* @ngdoc method
* @name ngMock.$timeout#flushNext
* @methodOf ngMock.$timeout
* @description
*
* Flushes the next timeout in the queue and compares it to the provided delay
*
* @param {number=} expectedDelay the delay value that will be asserted against the delay of the next timeout function
*/
$delegate.flushNext = function(expectedDelay) {
$browser.defer.flushNext(expectedDelay);
};
/**
@ -1437,7 +1559,7 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
*/
$delegate.verifyNoPendingTasks = function() {
if ($browser.deferredFns.length) {
throw Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
formatPendingTasksAsString($browser.deferredFns));
}
};
@ -1532,7 +1654,7 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
*
* // adds a new phone to the phones array
* $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
* phones.push(angular.fromJSON(data));
* phones.push(angular.fromJson(data));
* });
* $httpBackend.whenGET(/^\/templates\//).passThrough();
* //...
@ -1670,29 +1792,13 @@ angular.mock.clearDataCache = function() {
if (cache.hasOwnProperty(key)) {
var handle = cache[key].handle;
handle && angular.element(handle.elem).unbind();
handle && angular.element(handle.elem).off();
delete cache[key];
}
}
};
window.jstestdriver && (function(window) {
/**
* Global method to output any number of objects into JSTD console. Useful for debugging.
*/
window.dump = function() {
var args = [];
angular.forEach(arguments, function(arg) {
args.push(angular.mock.dump(arg));
});
jstestdriver.console.log.apply(jstestdriver.console, args);
if (window.console) {
window.console.log.apply(window.console, args);
}
};
})(window);
(window.jasmine || window.mocha) && (function(window) {
@ -1710,7 +1816,7 @@ window.jstestdriver && (function(window) {
currentSpec = null;
if (injector) {
injector.get('$rootElement').unbind();
injector.get('$rootElement').off();
injector.get('$browser').pollFns.length = 0;
}