angular-gem 1.1.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/lib/angular-gem/version.rb +1 -1
  2. data/lib/tasks/copy.rake +22 -11
  3. data/lib/tasks/tag.rake +2 -11
  4. data/vendor/assets/javascripts/1.2.0/angular-animate.js +1226 -0
  5. data/vendor/assets/javascripts/1.2.0/angular-animate.min.js +21 -0
  6. data/vendor/assets/javascripts/1.2.0/angular-animate.min.js.map +8 -0
  7. data/vendor/assets/javascripts/{angular-cookies-unstable.js → 1.2.0/angular-cookies.js} +21 -4
  8. data/vendor/assets/javascripts/1.2.0/angular-cookies.min.js +8 -0
  9. data/vendor/assets/javascripts/1.2.0/angular-cookies.min.js.map +8 -0
  10. data/vendor/assets/javascripts/1.2.0/angular-csp.css +24 -0
  11. data/vendor/assets/javascripts/{angular-loader-unstable.js → 1.2.0/angular-loader.js} +48 -29
  12. data/vendor/assets/javascripts/1.2.0/angular-loader.min.js +8 -0
  13. data/vendor/assets/javascripts/1.2.0/angular-loader.min.js.map +8 -0
  14. data/vendor/assets/javascripts/{angular-mocks-unstable.js → 1.2.0/angular-mocks.js} +460 -216
  15. data/vendor/assets/javascripts/{angular-resource-unstable.js → 1.2.0/angular-resource.js} +189 -148
  16. data/vendor/assets/javascripts/1.2.0/angular-resource.min.js +12 -0
  17. data/vendor/assets/javascripts/1.2.0/angular-resource.min.js.map +8 -0
  18. data/vendor/assets/javascripts/1.2.0/angular-route.js +880 -0
  19. data/vendor/assets/javascripts/1.2.0/angular-route.min.js +14 -0
  20. data/vendor/assets/javascripts/1.2.0/angular-route.min.js.map +8 -0
  21. data/vendor/assets/javascripts/{angular-sanitize-unstable.js → 1.2.0/angular-sanitize.js} +142 -123
  22. data/vendor/assets/javascripts/1.2.0/angular-sanitize.min.js +14 -0
  23. data/vendor/assets/javascripts/1.2.0/angular-sanitize.min.js.map +8 -0
  24. data/vendor/assets/javascripts/{angular-scenario-unstable.js → 1.2.0/angular-scenario.js} +15978 -12405
  25. data/vendor/assets/javascripts/{angular-mobile-unstable.js → 1.2.0/angular-touch.js} +214 -111
  26. data/vendor/assets/javascripts/1.2.0/angular-touch.min.js +13 -0
  27. data/vendor/assets/javascripts/1.2.0/angular-touch.min.js.map +8 -0
  28. data/vendor/assets/javascripts/{angular-unstable.js → 1.2.0/angular.js} +10167 -7012
  29. data/vendor/assets/javascripts/1.2.0/angular.min.js +200 -0
  30. data/vendor/assets/javascripts/1.2.0/angular.min.js.map +8 -0
  31. data/vendor/assets/javascripts/1.2.0/errors.json +1 -0
  32. data/vendor/assets/javascripts/1.2.0/version.json +1 -0
  33. data/vendor/assets/javascripts/1.2.0/version.txt +1 -0
  34. data/vendor/assets/javascripts/angular-animate.js +1226 -0
  35. data/vendor/assets/javascripts/angular-animate.min.js +21 -0
  36. data/vendor/assets/javascripts/angular-cookies.js +21 -4
  37. data/vendor/assets/javascripts/angular-cookies.min.js +8 -0
  38. data/vendor/assets/javascripts/angular-loader.js +63 -17
  39. data/vendor/assets/javascripts/angular-loader.min.js +8 -0
  40. data/vendor/assets/javascripts/angular-mocks.js +553 -211
  41. data/vendor/assets/javascripts/angular-resource.js +268 -147
  42. data/vendor/assets/javascripts/angular-resource.min.js +12 -0
  43. data/vendor/assets/javascripts/angular-route.js +880 -0
  44. data/vendor/assets/javascripts/angular-route.min.js +14 -0
  45. data/vendor/assets/javascripts/angular-sanitize.js +165 -125
  46. data/vendor/assets/javascripts/angular-sanitize.min.js +14 -0
  47. data/vendor/assets/javascripts/angular-scenario.js +16615 -10889
  48. data/vendor/assets/javascripts/angular-touch.js +563 -0
  49. data/vendor/assets/javascripts/angular-touch.min.js +13 -0
  50. data/vendor/assets/javascripts/angular.js +9717 -4533
  51. data/vendor/assets/javascripts/angular.min.js +200 -0
  52. metadata +44 -21
  53. data/test/dummy/log/test.log +0 -2
  54. data/test/dummy/tmp/cache/assets/D65/250/sprockets%2F54a960d46bb0b354e8bd46fa03f5e0e4 +0 -0
  55. data/test/dummy/tmp/cache/assets/D6A/FB0/sprockets%2F92721e9941b77adcfdfba3d060622de2 +0 -0
  56. data/test/dummy/tmp/cache/assets/E07/040/sprockets%2Ff55b8ce9d0f28ce36b768a1c7aeb2ef3 +0 -0
  57. data/test/tmp/app/assets/javascripts/application.js +0 -5
@@ -0,0 +1,21 @@
1
+ /*
2
+ AngularJS v1.2.0
3
+ (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ License: MIT
5
+ */
6
+ (function(A,s,B){'use strict';s.module("ngAnimate",["ng"]).config(["$provide","$animateProvider",function(N,D){var z=s.noop,k=s.forEach,X=D.$$selectors,T=1,f="$$ngAnimateState",E="ng-animate",g={running:!0};N.decorator("$animate",["$delegate","$injector","$sniffer","$rootElement","$timeout","$rootScope","$document",function(t,A,F,m,G,p,H){function B(a){if(a){var d=[],b={};a=a.substr(1).split(".");(F.transitions||F.animations)&&a.push("");for(var c=0;c<a.length;c++){var h=a[c],f=X[h];f&&!b[h]&&(d.push(A.get(f)),
7
+ b[h]=!0)}return d}}function n(a,d,b,c,h,g,m){function p(a){g();if(!0===a)u();else{if(a=b.data(f))a.done=u,b.data(f,a);s(v,"after",u)}}function s(c,h,g){var f=h+"End";k(c,function(k,t){var e=function(){a:{var e=h+"Complete",a=c[t];a[e]=!0;(a[f]||z)();for(a=0;a<c.length;a++)if(!c[a][e])break a;g()}};"before"!=h||"enter"!=a&&"move"!=a?k[h]?k[f]=n?k[h](b,d,e):k[h](b,e):e():e()})}function t(){m&&G(m,0,!1)}function u(){if(!u.hasBeenRun){u.hasBeenRun=!0;var a=b.data(f);a&&(n?q(b):(a.closeAnimationTimeout=
8
+ G(function(){q(b)},0,!1),b.data(f,a)));t()}}var r=(" "+((b.attr("class")||"")+" "+d)).replace(/\s+/g,".");c||(c=h?h.parent():b.parent());h=B(r);var n="addClass"==a||"removeClass"==a,r=b.data(f)||{};if(J(b,c)||0===h.length)g(),u();else{var v=[];r.running&&n&&r.structural||k(h,function(c){if(!c.allowCancel||c.allowCancel(b,a,d)){var h=c[a];"leave"==a?(c=h,h=null):c=c["before"+a.charAt(0).toUpperCase()+a.substr(1)];v.push({before:c,after:h})}});0===v.length?(g(),t()):(r.running&&(G.cancel(r.closeAnimationTimeout),
9
+ q(b),K(r.animations),(r.done||z)(!0)),"addClass"==a&&b.hasClass(d)||"removeClass"==a&&!b.hasClass(d)?(g(),t()):(b.addClass(E),b.data(f,{running:!0,structural:!n,animations:v,done:p}),s(v,"before",p)))}}function L(a){a=a[0];a.nodeType==T&&k(a.querySelectorAll("."+E),function(a){a=s.element(a);var b=a.data(f);b&&(K(b.animations),q(a))})}function K(a){k(a,function(d){a.beforeComplete||(d.beforeEnd||z)(!0);a.afterComplete||(d.afterEnd||z)(!0)})}function q(a){a[0]==m[0]?g.disabled||(g.running=!1,g.structural=
10
+ !1):(a.removeClass(E),a.removeData(f))}function J(a,d){if(g.disabled)return!0;if(a[0]==m[0])return g.disabled||g.running;do{if(0===d.length)break;var b=d[0]==m[0],c=b?g:d.data(f),c=c&&(!!c.disabled||!!c.running);if(b||c)return c;if(b)break}while(d=d.parent());return!0}m.data(f,g);p.$$postDigest(function(){g.running=!1});return{enter:function(a,d,b,c){this.enabled(!1,a);t.enter(a,d,b);p.$$postDigest(function(){n("enter","ng-enter",a,d,b,z,c)})},leave:function(a,d){L(a);this.enabled(!1,a);p.$$postDigest(function(){n("leave",
11
+ "ng-leave",a,null,null,function(){t.leave(a)},d)})},move:function(a,d,b,c){L(a);this.enabled(!1,a);t.move(a,d,b);p.$$postDigest(function(){n("move","ng-move",a,d,b,z,c)})},addClass:function(a,d,b){n("addClass",d,a,null,null,function(){t.addClass(a,d)},b)},removeClass:function(a,d,b){n("removeClass",d,a,null,null,function(){t.removeClass(a,d)},b)},enabled:function(a,d){switch(arguments.length){case 2:if(a)q(d);else{var b=d.data(f)||{};b.disabled=!0;d.data(f,b)}break;case 1:g.disabled=!a;break;default:a=
12
+ !g.disabled}return!!a}}}]);D.register("",["$window","$sniffer","$timeout",function(f,g,F){function m(e){Q.push(e);F.cancel(R);R=F(function(){k(Q,function(e){e()});Q=[];R=null;C={}},10,!1)}function G(e,a){var w=e.getAttribute("style")||"";e.setAttribute("style",(0<w.length?"; ":"")+a);return w}function p(e,a){var w=a?C[a]:null;if(!w){var b=0,d=0,c=0,l=0,g,n,m,p;k(e,function(e){if(e.nodeType==T){e=f.getComputedStyle(e)||{};m=e[h+D];b=Math.max(H(m),b);p=e[h+S];g=e[h+u];d=Math.max(H(g),d);n=e[I+u];l=
13
+ Math.max(H(n),l);var a=H(e[I+D]);0<a&&(a*=parseInt(e[I+r],10)||1);c=Math.max(a,c)}});w={total:0,transitionPropertyStyle:p,transitionDurationStyle:m,transitionDelayStyle:g,transitionDelay:d,transitionDuration:b,animationDelayStyle:n,animationDelay:l,animationDuration:c};a&&(C[a]=w)}return w}function H(e){var a=0;e=s.isString(e)?e.split(/\s*,\s*/):[];k(e,function(e){a=Math.max(parseFloat(e)||0,a)});return a}function E(e){var a=e.parent(),b=a.data(W);b||(a.data(W,++V),b=V);return b+"-"+e[0].className}
14
+ function n(e,a){var b=E(e),d=b+" "+a,c={},g=C[d]?++C[d].total:0;if(0<g){var l=a+"-stagger",c=b+" "+l;(b=!C[c])&&e.addClass(l);c=p(e,c);b&&e.removeClass(l)}e.addClass(a);d=p(e,d);l=Math.max(d.transitionDuration,d.animationDuration);if(0===l)return e.removeClass(a),!1;var b=e[0],f="";0<d.transitionDuration&&(e.addClass(U),f+=N+" ",b.style[h+S]="none");k(a.split(" "),function(a,e){f+=(0<e?" ":"")+a+"-active"});e.data(v,{className:a,activeClassName:f,maxDuration:l,classes:a+" "+f,timings:d,stagger:c,
15
+ ii:g});return!0}function L(a,b,w){function f(a){a.stopPropagation();a=a.originalEvent||a;var e=a.$manualTimeStamp||a.timeStamp||Date.now();Math.max(e-t,0)>=p&&a.elapsedTime>=n&&w()}var x=a.data(v);if(a.hasClass(b)&&x){var M=a[0],l=x.timings,k=x.stagger,n=x.maxDuration,m=x.activeClassName,p=1E3*Math.max(l.transitionDelay,l.animationDelay),t=Date.now(),s=P+" "+O,r,x=x.ii,u,y="";if(0<l.transitionDuration){M.style[h+S]="";var q=l.transitionPropertyStyle;-1==q.indexOf("all")&&(u=!0,y+=c+"transition-property: "+
16
+ q+", "+(g.msie?"-ms-zoom":"clip")+"; ",y+=c+"transition-duration: "+l.transitionDurationStyle+", "+l.transitionDuration+"s; ")}0<x&&(0<k.transitionDelay&&0===k.transitionDuration&&(q=l.transitionDelayStyle,u&&(q+=", "+l.transitionDelay+"s"),y+=c+"transition-delay: "+K(q,k.transitionDelay,x)+"; "),0<k.animationDelay&&0===k.animationDuration&&(y+=c+"animation-delay: "+K(l.animationDelayStyle,k.animationDelay,x)+"; "));0<y.length&&(r=G(M,y));a.on(s,f);a.addClass(m);return function(c){a.off(s,f);a.removeClass(m);
17
+ d(a,b);null!=r&&(0<r.length?M.setAttribute("style",r):M.removeAttribute("style"))}}w()}function K(a,b,d){var c="";k(a.split(","),function(a,e){c+=(0<e?",":"")+(d*b+parseInt(a,10))+"s"});return c}function q(a,b){if(n(a,b))return function(c){c&&d(a,b)}}function J(a,b,c){if(a.data(v))return L(a,b,c);d(a,b);c()}function a(a,b,c){var d=q(a,b);if(d){var f=d;m(function(){f=J(a,b,c)});return function(a){(f||z)(a)}}c()}function d(a,b){a.removeClass(b);a.removeClass(U);a.removeData(v)}function b(a,b){var c=
18
+ "";a=s.isArray(a)?a:a.split(/\s+/);k(a,function(a,e){a&&0<a.length&&(c+=(0<e?" ":"")+a+b)});return c}var c="",h,O,I,P;A.ontransitionend===B&&A.onwebkittransitionend!==B?(c="-webkit-",h="WebkitTransition",O="webkitTransitionEnd transitionend"):(h="transition",O="transitionend");A.onanimationend===B&&A.onwebkitanimationend!==B?(c="-webkit-",I="WebkitAnimation",P="webkitAnimationEnd animationend"):(I="animation",P="animationend");var D="Duration",S="Property",u="Delay",r="IterationCount",W="$$ngAnimateKey",
19
+ v="$$ngAnimateCSS3Data",U="ng-animate-start",N="ng-animate-active",C={},V=0,Q=[],R;return{allowCancel:function(a,c,d){var f=(a.data(v)||{}).classes;if(!f||0<=["enter","leave","move"].indexOf(c))return!0;var h=a.parent(),g=s.element(a[0].cloneNode());g.attr("style","position:absolute; top:-9999px; left:-9999px");g.removeAttr("id");g.html("");k(f.split(" "),function(a){g.removeClass(a)});g.addClass(b(d,"addClass"==c?"-add":"-remove"));h.append(g);a=p(g);g.remove();return 0<Math.max(a.transitionDuration,
20
+ a.animationDuration)},enter:function(b,c){return a(b,"ng-enter",c)},leave:function(b,c){return a(b,"ng-leave",c)},move:function(b,c){return a(b,"ng-move",c)},beforeAddClass:function(a,c,d){if(a=q(a,b(c,"-add")))return m(d),a;d()},addClass:function(a,c,d){return J(a,b(c,"-add"),d)},beforeRemoveClass:function(a,c,d){if(a=q(a,b(c,"-remove")))return m(d),a;d()},removeClass:function(a,c,d){return J(a,b(c,"-remove"),d)}}}])}])})(window,window.angular);
21
+ //# sourceMappingURL=angular-animate.min.js.map
@@ -1,14 +1,25 @@
1
1
  /**
2
- * @license AngularJS v1.0.7
2
+ * @license AngularJS v1.2.0
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
- (function(window, angular, undefined) {
7
- 'use strict';
6
+ (function(window, angular, undefined) {'use strict';
8
7
 
9
8
  /**
10
9
  * @ngdoc overview
11
10
  * @name ngCookies
11
+ * @description
12
+ *
13
+ * # ngCookies
14
+ *
15
+ * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
16
+ *
17
+ * {@installModule cookies}
18
+ *
19
+ * <div doc-module-components="ngCookies"></div>
20
+ *
21
+ * See {@link ngCookies.$cookies `$cookies`} and
22
+ * {@link ngCookies.$cookieStore `$cookieStore`} for usage.
12
23
  */
13
24
 
14
25
 
@@ -24,6 +35,8 @@ angular.module('ngCookies', ['ng']).
24
35
  * Only a simple Object is exposed and by adding or removing properties to/from
25
36
  * this object, new cookies are created/deleted at the end of current $eval.
26
37
  *
38
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
39
+ *
27
40
  * @example
28
41
  <doc:example>
29
42
  <doc:source>
@@ -68,7 +81,8 @@ angular.module('ngCookies', ['ng']).
68
81
 
69
82
 
70
83
  /**
71
- * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
84
+ * Pushes all the cookies from the service to the browser and verifies if all cookies were
85
+ * stored.
72
86
  */
73
87
  function push() {
74
88
  var name,
@@ -128,6 +142,9 @@ angular.module('ngCookies', ['ng']).
128
142
  * Provides a key-value (string-object) storage, that is backed by session cookies.
129
143
  * Objects put or retrieved from this storage are automatically serialized or
130
144
  * deserialized by angular's toJson/fromJson.
145
+ *
146
+ * Requires the {@link ngCookies `ngCookies`} module to be installed.
147
+ *
131
148
  * @example
132
149
  */
133
150
  factory('$cookieStore', ['$cookies', function($cookies) {
@@ -0,0 +1,8 @@
1
+ /*
2
+ AngularJS v1.2.0
3
+ (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ License: MIT
5
+ */
6
+ (function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&d.$apply())})();k=!0;d.$watch(function(){var a,e,d;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)(e=c[a],f.isString(e))?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(m(e[a])?delete c[a]:c[a]=e[a])});
7
+ return c}]).factory("$cookieStore",["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular);
8
+ //# sourceMappingURL=angular-cookies.min.js.map
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.7
2
+ * @license AngularJS v1.2.0
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -16,6 +16,8 @@
16
16
 
17
17
  function setupModuleLoader(window) {
18
18
 
19
+ var $injectorMinErr = minErr('$injector');
20
+
19
21
  function ensure(obj, name, factory) {
20
22
  return obj[name] || (obj[name] = factory());
21
23
  }
@@ -29,15 +31,19 @@ function setupModuleLoader(window) {
29
31
  * @name angular.module
30
32
  * @description
31
33
  *
32
- * The `angular.module` is a global place for creating and registering Angular modules. All
33
- * modules (angular core or 3rd party) that should be available to an application must be
34
+ * The `angular.module` is a global place for creating, registering and retrieving Angular
35
+ * modules.
36
+ * All modules (angular core or 3rd party) that should be available to an application must be
34
37
  * registered using this mechanism.
35
38
  *
39
+ * When passed two or more arguments, a new module is created. If passed only one argument, an
40
+ * existing module (the name passed as the first argument to `module`) is retrieved.
41
+ *
36
42
  *
37
43
  * # Module
38
44
  *
39
- * A module is a collocation of services, directives, filters, and configuration information. Module
40
- * is used to configure the {@link AUTO.$injector $injector}.
45
+ * A module is a collection of services, directives, filters, and configuration information.
46
+ * `angular.module` is used to configure the {@link AUTO.$injector $injector}.
41
47
  *
42
48
  * <pre>
43
49
  * // Create a new module
@@ -47,8 +53,7 @@ function setupModuleLoader(window) {
47
53
  * myModule.value('appName', 'MyCoolApp');
48
54
  *
49
55
  * // configure existing services inside initialization blocks.
50
- * myModule.config(function($locationProvider) {
51
- 'use strict';
56
+ * myModule.config(function($locationProvider) {'use strict';
52
57
  * // Configure existing providers
53
58
  * $locationProvider.hashPrefix('!');
54
59
  * });
@@ -65,19 +70,22 @@ function setupModuleLoader(window) {
65
70
  * {@link angular.bootstrap} to simplify this process for you.
66
71
  *
67
72
  * @param {!string} name The name of the module to create or retrieve.
68
- * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
69
- * the module is being retrieved for further configuration.
73
+ * @param {Array.<string>=} requires If specified then new module is being created. If
74
+ * unspecified then the the module is being retrieved for further configuration.
70
75
  * @param {Function} configFn Optional configuration function for the module. Same as
71
- * {@link angular.Module#config Module#config()}.
76
+ * {@link angular.Module#methods_config Module#config()}.
72
77
  * @returns {module} new module with the {@link angular.Module} api.
73
78
  */
74
79
  return function module(name, requires, configFn) {
80
+ assertNotHasOwnProperty(name, 'module');
75
81
  if (requires && modules.hasOwnProperty(name)) {
76
82
  modules[name] = null;
77
83
  }
78
84
  return ensure(modules, name, function() {
79
85
  if (!requires) {
80
- throw Error('No module: ' + name);
86
+ throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
87
+ "the module name or forgot to load it. If registering a module ensure that you " +
88
+ "specify the dependencies as the second argument.", name);
81
89
  }
82
90
 
83
91
  /** @type {!Array.<Array.<*>>} */
@@ -100,7 +108,8 @@ function setupModuleLoader(window) {
100
108
  * @propertyOf angular.Module
101
109
  * @returns {Array.<string>} List of module names which must be loaded before this module.
102
110
  * @description
103
- * Holds the list of modules which the injector will load before the current module is loaded.
111
+ * Holds the list of modules which the injector will load before the current module is
112
+ * loaded.
104
113
  */
105
114
  requires: requires,
106
115
 
@@ -119,7 +128,8 @@ function setupModuleLoader(window) {
119
128
  * @name angular.Module#provider
120
129
  * @methodOf angular.Module
121
130
  * @param {string} name service name
122
- * @param {Function} providerType Construction function for creating new instance of the service.
131
+ * @param {Function} providerType Construction function for creating new instance of the
132
+ * service.
123
133
  * @description
124
134
  * See {@link AUTO.$provide#provider $provide.provider()}.
125
135
  */
@@ -170,6 +180,40 @@ function setupModuleLoader(window) {
170
180
  */
171
181
  constant: invokeLater('$provide', 'constant', 'unshift'),
172
182
 
183
+ /**
184
+ * @ngdoc method
185
+ * @name angular.Module#animation
186
+ * @methodOf angular.Module
187
+ * @param {string} name animation name
188
+ * @param {Function} animationFactory Factory function for creating new instance of an
189
+ * animation.
190
+ * @description
191
+ *
192
+ * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
193
+ *
194
+ *
195
+ * Defines an animation hook that can be later used with
196
+ * {@link ngAnimate.$animate $animate} service and directives that use this service.
197
+ *
198
+ * <pre>
199
+ * module.animation('.animation-name', function($inject1, $inject2) {
200
+ * return {
201
+ * eventName : function(element, done) {
202
+ * //code to run the animation
203
+ * //once complete, then run done()
204
+ * return function cancellationFunction(element) {
205
+ * //code to cancel the animation
206
+ * }
207
+ * }
208
+ * }
209
+ * })
210
+ * </pre>
211
+ *
212
+ * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
213
+ * {@link ngAnimate ngAnimate module} for more information.
214
+ */
215
+ animation: invokeLater('$animateProvider', 'register'),
216
+
173
217
  /**
174
218
  * @ngdoc method
175
219
  * @name angular.Module#filter
@@ -185,7 +229,8 @@ function setupModuleLoader(window) {
185
229
  * @ngdoc method
186
230
  * @name angular.Module#controller
187
231
  * @methodOf angular.Module
188
- * @param {string} name Controller name.
232
+ * @param {string|Object} name Controller name, or an object map of controllers where the
233
+ * keys are the names and the values are the constructors.
189
234
  * @param {Function} constructor Controller constructor function.
190
235
  * @description
191
236
  * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
@@ -196,11 +241,12 @@ function setupModuleLoader(window) {
196
241
  * @ngdoc method
197
242
  * @name angular.Module#directive
198
243
  * @methodOf angular.Module
199
- * @param {string} name directive name
244
+ * @param {string|Object} name Directive name, or an object map of directives where the
245
+ * keys are the names and the values are the factories.
200
246
  * @param {Function} directiveFactory Factory function for creating new instance of
201
247
  * directives.
202
248
  * @description
203
- * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
249
+ * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}.
204
250
  */
205
251
  directive: invokeLater('$compileProvider', 'directive'),
206
252
 
@@ -247,7 +293,7 @@ function setupModuleLoader(window) {
247
293
  return function() {
248
294
  invokeQueue[insertMethod || 'push']([provider, method, arguments]);
249
295
  return moduleInstance;
250
- }
296
+ };
251
297
  }
252
298
  });
253
299
  };
@@ -0,0 +1,8 @@
1
+ /*
2
+ AngularJS v1.2.0
3
+ (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ License: MIT
5
+ */
6
+ (function(k){'use strict';function d(c,b,e){return c[b]||(c[b]=e())}var l=minErr("$injector");return d(d(k,"angular",Object),"module",function(){var c={};return function(b,e,f){assertNotHasOwnProperty(b,"module");e&&c.hasOwnProperty(b)&&(c[b]=null);return d(c,b,function(){function a(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw l("nomod",b);var c=[],d=[],h=a("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:b,provider:a("$provide","provider"),factory:a("$provide",
7
+ "factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);
8
+ //# sourceMappingURL=angular-loader.min.js.map
@@ -1,5 +1,7 @@
1
+ 'use strict';
2
+
1
3
  /**
2
- * @license AngularJS v1.0.7
4
+ * @license AngularJS v1.2.0
3
5
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
6
  * License: MIT
5
7
  *
@@ -29,7 +31,7 @@ angular.mock = {};
29
31
  * that there are several helper methods available which can be used in tests.
30
32
  */
31
33
  angular.mock.$BrowserProvider = function() {
32
- this.$get = function(){
34
+ this.$get = function() {
33
35
  return new angular.mock.$Browser();
34
36
  };
35
37
  };
@@ -75,6 +77,13 @@ angular.mock.$Browser = function() {
75
77
  };
76
78
 
77
79
 
80
+ /**
81
+ * @name ngMock.$browser#defer.now
82
+ * @propertyOf ngMock.$browser
83
+ *
84
+ * @description
85
+ * Current milliseconds mock time.
86
+ */
78
87
  self.defer.now = 0;
79
88
 
80
89
 
@@ -110,7 +119,7 @@ angular.mock.$Browser = function() {
110
119
  if (self.deferredFns.length) {
111
120
  self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
112
121
  } else {
113
- throw Error('No deferred tasks to be flushed');
122
+ throw new Error('No deferred tasks to be flushed');
114
123
  }
115
124
  }
116
125
 
@@ -118,13 +127,6 @@ angular.mock.$Browser = function() {
118
127
  self.deferredFns.shift().fn();
119
128
  }
120
129
  };
121
- /**
122
- * @name ngMock.$browser#defer.now
123
- * @propertyOf ngMock.$browser
124
- *
125
- * @description
126
- * Current milliseconds mock time.
127
- */
128
130
 
129
131
  self.$$baseHref = '';
130
132
  self.baseHref = function() {
@@ -162,7 +164,7 @@ angular.mock.$Browser.prototype = {
162
164
 
163
165
  cookies: function(name, value) {
164
166
  if (name) {
165
- if (value == undefined) {
167
+ if (angular.isUndefined(value)) {
166
168
  delete this.cookieHash[name];
167
169
  } else {
168
170
  if (angular.isString(value) && //strings only
@@ -190,8 +192,8 @@ angular.mock.$Browser.prototype = {
190
192
  * @name ngMock.$exceptionHandlerProvider
191
193
  *
192
194
  * @description
193
- * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed
194
- * into the `$exceptionHandler`.
195
+ * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
196
+ * passed into the `$exceptionHandler`.
195
197
  */
196
198
 
197
199
  /**
@@ -244,10 +246,10 @@ angular.mock.$ExceptionHandlerProvider = function() {
244
246
  * - `rethrow`: If any errors are passed into the handler in tests, it typically
245
247
  * means that there is a bug in the application or test, so this mock will
246
248
  * make these tests fail.
247
- * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` mode stores an
248
- * array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
249
- * See {@link ngMock.$log#assertEmpty assertEmpty()} and
250
- * {@link ngMock.$log#reset reset()}
249
+ * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
250
+ * mode stores an array of errors in `$exceptionHandler.errors`, to allow later
251
+ * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
252
+ * {@link ngMock.$log#reset reset()}
251
253
  */
252
254
  this.mode = function(mode) {
253
255
  switch(mode) {
@@ -270,7 +272,7 @@ angular.mock.$ExceptionHandlerProvider = function() {
270
272
  handler.errors = errors;
271
273
  break;
272
274
  default:
273
- throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
275
+ throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
274
276
  }
275
277
  };
276
278
 
@@ -293,18 +295,32 @@ angular.mock.$ExceptionHandlerProvider = function() {
293
295
  *
294
296
  */
295
297
  angular.mock.$LogProvider = function() {
298
+ var debug = true;
296
299
 
297
300
  function concat(array1, array2, index) {
298
301
  return array1.concat(Array.prototype.slice.call(array2, index));
299
302
  }
300
303
 
304
+ this.debugEnabled = function(flag) {
305
+ if (angular.isDefined(flag)) {
306
+ debug = flag;
307
+ return this;
308
+ } else {
309
+ return debug;
310
+ }
311
+ };
301
312
 
302
313
  this.$get = function () {
303
314
  var $log = {
304
315
  log: function() { $log.log.logs.push(concat([], arguments, 0)); },
305
316
  warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
306
317
  info: function() { $log.info.logs.push(concat([], arguments, 0)); },
307
- error: function() { $log.error.logs.push(concat([], arguments, 0)); }
318
+ error: function() { $log.error.logs.push(concat([], arguments, 0)); },
319
+ debug: function() {
320
+ if (debug) {
321
+ $log.debug.logs.push(concat([], arguments, 0));
322
+ }
323
+ }
308
324
  };
309
325
 
310
326
  /**
@@ -333,34 +349,34 @@ angular.mock.$LogProvider = function() {
333
349
  $log.log.logs = [];
334
350
  /**
335
351
  * @ngdoc property
336
- * @name ngMock.$log#warn.logs
352
+ * @name ngMock.$log#info.logs
337
353
  * @propertyOf ngMock.$log
338
354
  *
339
355
  * @description
340
- * Array of messages logged using {@link ngMock.$log#warn}.
356
+ * Array of messages logged using {@link ngMock.$log#info}.
341
357
  *
342
358
  * @example
343
359
  * <pre>
344
- * $log.warn('Some Warning');
345
- * var first = $log.warn.logs.unshift();
360
+ * $log.info('Some Info');
361
+ * var first = $log.info.logs.unshift();
346
362
  * </pre>
347
363
  */
348
- $log.warn.logs = [];
364
+ $log.info.logs = [];
349
365
  /**
350
366
  * @ngdoc property
351
- * @name ngMock.$log#info.logs
367
+ * @name ngMock.$log#warn.logs
352
368
  * @propertyOf ngMock.$log
353
369
  *
354
370
  * @description
355
- * Array of messages logged using {@link ngMock.$log#info}.
371
+ * Array of messages logged using {@link ngMock.$log#warn}.
356
372
  *
357
373
  * @example
358
374
  * <pre>
359
- * $log.info('Some Info');
360
- * var first = $log.info.logs.unshift();
375
+ * $log.warn('Some Warning');
376
+ * var first = $log.warn.logs.unshift();
361
377
  * </pre>
362
378
  */
363
- $log.info.logs = [];
379
+ $log.warn.logs = [];
364
380
  /**
365
381
  * @ngdoc property
366
382
  * @name ngMock.$log#error.logs
@@ -376,6 +392,21 @@ angular.mock.$LogProvider = function() {
376
392
  * </pre>
377
393
  */
378
394
  $log.error.logs = [];
395
+ /**
396
+ * @ngdoc property
397
+ * @name ngMock.$log#debug.logs
398
+ * @propertyOf ngMock.$log
399
+ *
400
+ * @description
401
+ * Array of messages logged using {@link ngMock.$log#debug}.
402
+ *
403
+ * @example
404
+ * <pre>
405
+ * $log.debug('Some Error');
406
+ * var first = $log.debug.logs.unshift();
407
+ * </pre>
408
+ */
409
+ $log.debug.logs = [];
379
410
  };
380
411
 
381
412
  /**
@@ -384,20 +415,22 @@ angular.mock.$LogProvider = function() {
384
415
  * @methodOf ngMock.$log
385
416
  *
386
417
  * @description
387
- * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
418
+ * Assert that the all of the logging methods have no logged messages. If messages present, an
419
+ * exception is thrown.
388
420
  */
389
421
  $log.assertEmpty = function() {
390
422
  var errors = [];
391
- angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
423
+ angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
392
424
  angular.forEach($log[logLevel].logs, function(log) {
393
425
  angular.forEach(log, function (logItem) {
394
- errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
426
+ errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
427
+ (logItem.stack || ''));
395
428
  });
396
429
  });
397
430
  });
398
431
  if (errors.length) {
399
- errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " +
400
- "log message was not checked and removed:");
432
+ errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+
433
+ "an expected log message was not checked and removed:");
401
434
  errors.push('');
402
435
  throw new Error(errors.join('\n---------\n'));
403
436
  }
@@ -409,10 +442,128 @@ angular.mock.$LogProvider = function() {
409
442
  };
410
443
 
411
444
 
445
+ /**
446
+ * @ngdoc service
447
+ * @name ngMock.$interval
448
+ *
449
+ * @description
450
+ * Mock implementation of the $interval service.
451
+ *
452
+ * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to
453
+ * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
454
+ * time.
455
+ *
456
+ * @param {function()} fn A function that should be called repeatedly.
457
+ * @param {number} delay Number of milliseconds between each function call.
458
+ * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
459
+ * indefinitely.
460
+ * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
461
+ * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
462
+ * @returns {promise} A promise which will be notified on each iteration.
463
+ */
464
+ angular.mock.$IntervalProvider = function() {
465
+ this.$get = ['$rootScope', '$q',
466
+ function($rootScope, $q) {
467
+ var repeatFns = [],
468
+ nextRepeatId = 0,
469
+ now = 0;
470
+
471
+ var $interval = function(fn, delay, count, invokeApply) {
472
+ var deferred = $q.defer(),
473
+ promise = deferred.promise,
474
+ iteration = 0,
475
+ skipApply = (angular.isDefined(invokeApply) && !invokeApply);
476
+
477
+ count = (angular.isDefined(count)) ? count : 0,
478
+ promise.then(null, null, fn);
479
+
480
+ promise.$$intervalId = nextRepeatId;
481
+
482
+ function tick() {
483
+ deferred.notify(iteration++);
484
+
485
+ if (count > 0 && iteration >= count) {
486
+ var fnIndex;
487
+ deferred.resolve(iteration);
488
+
489
+ angular.forEach(repeatFns, function(fn, index) {
490
+ if (fn.id === promise.$$intervalId) fnIndex = index;
491
+ });
492
+
493
+ if (fnIndex !== undefined) {
494
+ repeatFns.splice(fnIndex, 1);
495
+ }
496
+ }
497
+
498
+ if (!skipApply) $rootScope.$apply();
499
+ }
500
+
501
+ repeatFns.push({
502
+ nextTime:(now + delay),
503
+ delay: delay,
504
+ fn: tick,
505
+ id: nextRepeatId,
506
+ deferred: deferred
507
+ });
508
+ repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
509
+
510
+ nextRepeatId++;
511
+ return promise;
512
+ };
513
+
514
+ $interval.cancel = function(promise) {
515
+ var fnIndex;
516
+
517
+ angular.forEach(repeatFns, function(fn, index) {
518
+ if (fn.id === promise.$$intervalId) fnIndex = index;
519
+ });
520
+
521
+ if (fnIndex !== undefined) {
522
+ repeatFns[fnIndex].deferred.reject('canceled');
523
+ repeatFns.splice(fnIndex, 1);
524
+ return true;
525
+ }
526
+
527
+ return false;
528
+ };
529
+
530
+ /**
531
+ * @ngdoc method
532
+ * @name ngMock.$interval#flush
533
+ * @methodOf ngMock.$interval
534
+ * @description
535
+ *
536
+ * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
537
+ *
538
+ * @param {number=} millis maximum timeout amount to flush up until.
539
+ *
540
+ * @return {number} The amount of time moved forward.
541
+ */
542
+ $interval.flush = function(millis) {
543
+ now += millis;
544
+ while (repeatFns.length && repeatFns[0].nextTime <= now) {
545
+ var task = repeatFns[0];
546
+ task.fn();
547
+ task.nextTime += task.delay;
548
+ repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
549
+ }
550
+ return millis;
551
+ };
552
+
553
+ return $interval;
554
+ }];
555
+ };
556
+
557
+
558
+ /* jshint -W101 */
559
+ /* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
560
+ * This directive should go inside the anonymous function but a bug in JSHint means that it would
561
+ * not be enacted early enough to prevent the warning.
562
+ */
412
563
  (function() {
413
564
  var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
414
565
 
415
- function jsonStringToDate(string){
566
+ function jsonStringToDate(string) {
416
567
  var match;
417
568
  if (match = string.match(R_ISO8061_STR)) {
418
569
  var date = new Date(0),
@@ -423,7 +574,10 @@ angular.mock.$LogProvider = function() {
423
574
  tzMin = int(match[9] + match[11]);
424
575
  }
425
576
  date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
426
- date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
577
+ date.setUTCHours(int(match[4]||0) - tzHour,
578
+ int(match[5]||0) - tzMin,
579
+ int(match[6]||0),
580
+ int(match[7]||0));
427
581
  return date;
428
582
  }
429
583
  return string;
@@ -480,6 +634,7 @@ angular.mock.$LogProvider = function() {
480
634
  * newYearInBratislava.getDate() => 1;
481
635
  * newYearInBratislava.getHours() => 0;
482
636
  * newYearInBratislava.getMinutes() => 0;
637
+ * newYearInBratislava.getSeconds() => 0;
483
638
  * </pre>
484
639
  *
485
640
  */
@@ -536,6 +691,10 @@ angular.mock.$LogProvider = function() {
536
691
  return self.date.getSeconds();
537
692
  };
538
693
 
694
+ self.getMilliseconds = function() {
695
+ return self.date.getMilliseconds();
696
+ };
697
+
539
698
  self.getTimezoneOffset = function() {
540
699
  return offset * 60;
541
700
  };
@@ -581,12 +740,12 @@ angular.mock.$LogProvider = function() {
581
740
  padNumber(self.origDate.getUTCHours(), 2) + ':' +
582
741
  padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
583
742
  padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
584
- padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
585
- }
743
+ padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
744
+ };
586
745
  }
587
746
 
588
747
  //hide all methods not implemented in this mock that the Date prototype exposes
589
- var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
748
+ var unimplementedMethods = ['getUTCDay',
590
749
  'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
591
750
  'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
592
751
  'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
@@ -595,7 +754,7 @@ angular.mock.$LogProvider = function() {
595
754
 
596
755
  angular.forEach(unimplementedMethods, function(methodName) {
597
756
  self[methodName] = function() {
598
- throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
757
+ throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
599
758
  };
600
759
  });
601
760
 
@@ -605,6 +764,49 @@ angular.mock.$LogProvider = function() {
605
764
  //make "tzDateInstance instanceof Date" return true
606
765
  angular.mock.TzDate.prototype = Date.prototype;
607
766
  })();
767
+ /* jshint +W101 */
768
+
769
+ angular.mock.animate = angular.module('mock.animate', ['ng'])
770
+
771
+ .config(['$provide', function($provide) {
772
+
773
+ $provide.decorator('$animate', function($delegate) {
774
+ var animate = {
775
+ queue : [],
776
+ enabled : $delegate.enabled,
777
+ flushNext : function(name) {
778
+ var tick = animate.queue.shift();
779
+
780
+ if (!tick) throw new Error('No animation to be flushed');
781
+ if(tick.method !== name) {
782
+ throw new Error('The next animation is not "' + name +
783
+ '", but is "' + tick.method + '"');
784
+ }
785
+ tick.fn();
786
+ return tick;
787
+ }
788
+ };
789
+
790
+ angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) {
791
+ animate[method] = function() {
792
+ var params = arguments;
793
+ animate.queue.push({
794
+ method : method,
795
+ params : params,
796
+ element : angular.isElement(params[0]) && params[0],
797
+ parent : angular.isElement(params[1]) && params[1],
798
+ after : angular.isElement(params[2]) && params[2],
799
+ fn : function() {
800
+ $delegate[method].apply($delegate, params);
801
+ }
802
+ });
803
+ };
804
+ });
805
+
806
+ return animate;
807
+ });
808
+
809
+ }]);
608
810
 
609
811
 
610
812
  /**
@@ -614,9 +816,11 @@ angular.mock.$LogProvider = function() {
614
816
  *
615
817
  * *NOTE*: this is not an injectable instance, just a globally available function.
616
818
  *
617
- * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
819
+ * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
820
+ * debugging.
618
821
  *
619
- * This method is also available on window, where it can be used to display objects on debug console.
822
+ * This method is also available on window, where it can be used to display objects on debug
823
+ * console.
620
824
  *
621
825
  * @param {*} object - any object to turn into string.
622
826
  * @return {string} a serialized string of the argument
@@ -646,6 +850,8 @@ angular.mock.dump = function(object) {
646
850
  } else if (object instanceof Error) {
647
851
  out = object.stack || ('' + object.name + ': ' + object.message);
648
852
  } else {
853
+ // TODO(i): this prevents methods being logged,
854
+ // we should have a better way to serialize objects
649
855
  out = angular.toJson(object, true);
650
856
  }
651
857
  } else {
@@ -659,7 +865,7 @@ angular.mock.dump = function(object) {
659
865
  offset = offset || ' ';
660
866
  var log = [offset + 'Scope(' + scope.$id + '): {'];
661
867
  for ( var key in scope ) {
662
- if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
868
+ if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
663
869
  log.push(' ' + key + ': ' + angular.toJson(scope[key]));
664
870
  }
665
871
  }
@@ -773,79 +979,104 @@ angular.mock.dump = function(object) {
773
979
  *
774
980
  *
775
981
  * # Unit testing with mock $httpBackend
982
+ * The following code shows how to setup and use the mock backend in unit testing a controller.
983
+ * First we create the controller under test
776
984
  *
777
- * <pre>
778
- // controller
779
- function MyController($scope, $http) {
780
- $http.get('/auth.py').success(function(data) {
781
- $scope.user = data;
782
- });
783
-
784
- this.saveMessage = function(message) {
785
- $scope.status = 'Saving...';
786
- $http.post('/add-msg.py', message).success(function(response) {
787
- $scope.status = '';
788
- }).error(function() {
789
- $scope.status = 'ERROR!';
790
- });
791
- };
792
- }
985
+ <pre>
986
+ // The controller code
987
+ function MyController($scope, $http) {
988
+ var authToken;
793
989
 
794
- // testing controller
795
- var $httpBackend;
990
+ $http.get('/auth.py').success(function(data, status, headers) {
991
+ authToken = headers('A-Token');
992
+ $scope.user = data;
993
+ });
796
994
 
797
- beforeEach(inject(function($injector) {
798
- $httpBackend = $injector.get('$httpBackend');
995
+ $scope.saveMessage = function(message) {
996
+ var headers = { 'Authorization': authToken };
997
+ $scope.status = 'Saving...';
799
998
 
800
- // backend definition common for all tests
801
- $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
802
- }));
999
+ $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
1000
+ $scope.status = '';
1001
+ }).error(function() {
1002
+ $scope.status = 'ERROR!';
1003
+ });
1004
+ };
1005
+ }
1006
+ </pre>
1007
+ *
1008
+ * Now we setup the mock backend and create the test specs.
1009
+ *
1010
+ <pre>
1011
+ // testing controller
1012
+ describe('MyController', function() {
1013
+ var $httpBackend, $rootScope, createController;
803
1014
 
1015
+ beforeEach(inject(function($injector) {
1016
+ // Set up the mock http service responses
1017
+ $httpBackend = $injector.get('$httpBackend');
1018
+ // backend definition common for all tests
1019
+ $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
804
1020
 
805
- afterEach(function() {
806
- $httpBackend.verifyNoOutstandingExpectation();
807
- $httpBackend.verifyNoOutstandingRequest();
808
- });
1021
+ // Get hold of a scope (i.e. the root scope)
1022
+ $rootScope = $injector.get('$rootScope');
1023
+ // The $controller service is used to create instances of controllers
1024
+ var $controller = $injector.get('$controller');
809
1025
 
1026
+ createController = function() {
1027
+ return $controller('MyController', {'$scope' : $rootScope });
1028
+ };
1029
+ }));
810
1030
 
811
- it('should fetch authentication token', function() {
812
- $httpBackend.expectGET('/auth.py');
813
- var controller = scope.$new(MyController);
814
- $httpBackend.flush();
815
- });
816
1031
 
1032
+ afterEach(function() {
1033
+ $httpBackend.verifyNoOutstandingExpectation();
1034
+ $httpBackend.verifyNoOutstandingRequest();
1035
+ });
817
1036
 
818
- it('should send msg to server', function() {
819
- // now you don’t care about the authentication, but
820
- // the controller will still send the request and
821
- // $httpBackend will respond without you having to
822
- // specify the expectation and response for this request
823
- $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
824
1037
 
825
- var controller = scope.$new(MyController);
826
- $httpBackend.flush();
827
- controller.saveMessage('message content');
828
- expect(controller.status).toBe('Saving...');
829
- $httpBackend.flush();
830
- expect(controller.status).toBe('');
831
- });
1038
+ it('should fetch authentication token', function() {
1039
+ $httpBackend.expectGET('/auth.py');
1040
+ var controller = createController();
1041
+ $httpBackend.flush();
1042
+ });
832
1043
 
833
1044
 
834
- it('should send auth header', function() {
835
- $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
836
- // check if the header was send, if it wasn't the expectation won't
837
- // match the request and the test will fail
838
- return headers['Authorization'] == 'xxx';
839
- }).respond(201, '');
1045
+ it('should send msg to server', function() {
1046
+ var controller = createController();
1047
+ $httpBackend.flush();
1048
+
1049
+ // now you don’t care about the authentication, but
1050
+ // the controller will still send the request and
1051
+ // $httpBackend will respond without you having to
1052
+ // specify the expectation and response for this request
1053
+
1054
+ $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
1055
+ $rootScope.saveMessage('message content');
1056
+ expect($rootScope.status).toBe('Saving...');
1057
+ $httpBackend.flush();
1058
+ expect($rootScope.status).toBe('');
1059
+ });
840
1060
 
841
- var controller = scope.$new(MyController);
842
- controller.saveMessage('whatever');
843
- $httpBackend.flush();
844
- });
1061
+
1062
+ it('should send auth header', function() {
1063
+ var controller = createController();
1064
+ $httpBackend.flush();
1065
+
1066
+ $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
1067
+ // check if the header was send, if it wasn't the expectation won't
1068
+ // match the request and the test will fail
1069
+ return headers['Authorization'] == 'xxx';
1070
+ }).respond(201, '');
1071
+
1072
+ $rootScope.saveMessage('whatever');
1073
+ $httpBackend.flush();
1074
+ });
1075
+ });
845
1076
  </pre>
846
1077
  */
847
1078
  angular.mock.$HttpBackendProvider = function() {
848
- this.$get = [createHttpBackendMock];
1079
+ this.$get = ['$rootScope', createHttpBackendMock];
849
1080
  };
850
1081
 
851
1082
  /**
@@ -862,7 +1093,7 @@ angular.mock.$HttpBackendProvider = function() {
862
1093
  * @param {Object=} $browser Auto-flushing enabled if specified
863
1094
  * @return {Object} Instance of $httpBackend mock
864
1095
  */
865
- function createHttpBackendMock($delegate, $browser) {
1096
+ function createHttpBackendMock($rootScope, $delegate, $browser) {
866
1097
  var definitions = [],
867
1098
  expectations = [],
868
1099
  responses = [],
@@ -879,7 +1110,7 @@ function createHttpBackendMock($delegate, $browser) {
879
1110
  }
880
1111
 
881
1112
  // TODO(vojta): change params to: method, url, data, headers, callback
882
- function $httpBackend(method, url, data, callback, headers) {
1113
+ function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
883
1114
  var xhr = new MockXhr(),
884
1115
  expectation = expectations[0],
885
1116
  wasExpected = false;
@@ -890,24 +1121,42 @@ function createHttpBackendMock($delegate, $browser) {
890
1121
  : angular.toJson(data);
891
1122
  }
892
1123
 
1124
+ function wrapResponse(wrapped) {
1125
+ if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
1126
+
1127
+ return handleResponse;
1128
+
1129
+ function handleResponse() {
1130
+ var response = wrapped.response(method, url, data, headers);
1131
+ xhr.$$respHeaders = response[2];
1132
+ callback(response[0], response[1], xhr.getAllResponseHeaders());
1133
+ }
1134
+
1135
+ function handleTimeout() {
1136
+ for (var i = 0, ii = responses.length; i < ii; i++) {
1137
+ if (responses[i] === handleResponse) {
1138
+ responses.splice(i, 1);
1139
+ callback(-1, undefined, '');
1140
+ break;
1141
+ }
1142
+ }
1143
+ }
1144
+ }
1145
+
893
1146
  if (expectation && expectation.match(method, url)) {
894
1147
  if (!expectation.matchData(data))
895
- throw Error('Expected ' + expectation + ' with different data\n' +
1148
+ throw new Error('Expected ' + expectation + ' with different data\n' +
896
1149
  'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
897
1150
 
898
1151
  if (!expectation.matchHeaders(headers))
899
- throw Error('Expected ' + expectation + ' with different headers\n' +
900
- 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
901
- prettyPrint(headers));
1152
+ throw new Error('Expected ' + expectation + ' with different headers\n' +
1153
+ 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
1154
+ prettyPrint(headers));
902
1155
 
903
1156
  expectations.shift();
904
1157
 
905
1158
  if (expectation.response) {
906
- responses.push(function() {
907
- var response = expectation.response(method, url, data, headers);
908
- xhr.$$respHeaders = response[2];
909
- callback(response[0], response[1], xhr.getAllResponseHeaders());
910
- });
1159
+ responses.push(wrapResponse(expectation));
911
1160
  return;
912
1161
  }
913
1162
  wasExpected = true;
@@ -918,21 +1167,17 @@ function createHttpBackendMock($delegate, $browser) {
918
1167
  if (definition.match(method, url, data, headers || {})) {
919
1168
  if (definition.response) {
920
1169
  // if $browser specified, we do auto flush all requests
921
- ($browser ? $browser.defer : responsesPush)(function() {
922
- var response = definition.response(method, url, data, headers);
923
- xhr.$$respHeaders = response[2];
924
- callback(response[0], response[1], xhr.getAllResponseHeaders());
925
- });
1170
+ ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
926
1171
  } else if (definition.passThrough) {
927
- $delegate(method, url, data, callback, headers);
928
- } else throw Error('No response defined !');
1172
+ $delegate(method, url, data, callback, headers, timeout, withCredentials);
1173
+ } else throw new Error('No response defined !');
929
1174
  return;
930
1175
  }
931
1176
  }
932
1177
  throw wasExpected ?
933
- Error('No response defined !') :
934
- Error('Unexpected request: ' + method + ' ' + url + '\n' +
935
- (expectation ? 'Expected ' + expectation : 'No more request expected'));
1178
+ new Error('No response defined !') :
1179
+ new Error('Unexpected request: ' + method + ' ' + url + '\n' +
1180
+ (expectation ? 'Expected ' + expectation : 'No more request expected'));
936
1181
  }
937
1182
 
938
1183
  /**
@@ -944,13 +1189,15 @@ function createHttpBackendMock($delegate, $browser) {
944
1189
  *
945
1190
  * @param {string} method HTTP method.
946
1191
  * @param {string|RegExp} url HTTP url.
947
- * @param {(string|RegExp)=} data HTTP request body.
1192
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1193
+ * data string and returns true if the data is as expected.
948
1194
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
949
1195
  * object and returns true if the headers match the current definition.
950
- * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1196
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
951
1197
  * request is handled.
952
1198
  *
953
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1199
+ * - respond –
1200
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
954
1201
  * – The respond method takes a set of static data to be returned or a function that can return
955
1202
  * an array containing response status (number), response data (string) and response headers
956
1203
  * (Object).
@@ -1020,7 +1267,8 @@ function createHttpBackendMock($delegate, $browser) {
1020
1267
  * Creates a new backend definition for POST requests. For more info see `when()`.
1021
1268
  *
1022
1269
  * @param {string|RegExp} url HTTP url.
1023
- * @param {(string|RegExp)=} data HTTP request body.
1270
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1271
+ * data string and returns true if the data is as expected.
1024
1272
  * @param {(Object|function(Object))=} headers HTTP headers.
1025
1273
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1026
1274
  * request is handled.
@@ -1034,7 +1282,8 @@ function createHttpBackendMock($delegate, $browser) {
1034
1282
  * Creates a new backend definition for PUT requests. For more info see `when()`.
1035
1283
  *
1036
1284
  * @param {string|RegExp} url HTTP url.
1037
- * @param {(string|RegExp)=} data HTTP request body.
1285
+ * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1286
+ * data string and returns true if the data is as expected.
1038
1287
  * @param {(Object|function(Object))=} headers HTTP headers.
1039
1288
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1040
1289
  * request is handled.
@@ -1063,13 +1312,16 @@ function createHttpBackendMock($delegate, $browser) {
1063
1312
  *
1064
1313
  * @param {string} method HTTP method.
1065
1314
  * @param {string|RegExp} url HTTP url.
1066
- * @param {(string|RegExp)=} data HTTP request body.
1315
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1316
+ * receives data string and returns true if the data is as expected, or Object if request body
1317
+ * is in JSON format.
1067
1318
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1068
1319
  * object and returns true if the headers match the current expectation.
1069
1320
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1070
1321
  * request is handled.
1071
1322
  *
1072
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1323
+ * - respond –
1324
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1073
1325
  * – The respond method takes a set of static data to be returned or a function that can return
1074
1326
  * an array containing response status (number), response data (string) and response headers
1075
1327
  * (Object).
@@ -1132,7 +1384,9 @@ function createHttpBackendMock($delegate, $browser) {
1132
1384
  * Creates a new request expectation for POST requests. For more info see `expect()`.
1133
1385
  *
1134
1386
  * @param {string|RegExp} url HTTP url.
1135
- * @param {(string|RegExp)=} data HTTP request body.
1387
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1388
+ * receives data string and returns true if the data is as expected, or Object if request body
1389
+ * is in JSON format.
1136
1390
  * @param {Object=} headers HTTP headers.
1137
1391
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1138
1392
  * request is handled.
@@ -1146,7 +1400,9 @@ function createHttpBackendMock($delegate, $browser) {
1146
1400
  * Creates a new request expectation for PUT requests. For more info see `expect()`.
1147
1401
  *
1148
1402
  * @param {string|RegExp} url HTTP url.
1149
- * @param {(string|RegExp)=} data HTTP request body.
1403
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1404
+ * receives data string and returns true if the data is as expected, or Object if request body
1405
+ * is in JSON format.
1150
1406
  * @param {Object=} headers HTTP headers.
1151
1407
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1152
1408
  * request is handled.
@@ -1160,7 +1416,9 @@ function createHttpBackendMock($delegate, $browser) {
1160
1416
  * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1161
1417
  *
1162
1418
  * @param {string|RegExp} url HTTP url.
1163
- * @param {(string|RegExp)=} data HTTP request body.
1419
+ * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1420
+ * receives data string and returns true if the data is as expected, or Object if request body
1421
+ * is in JSON format.
1164
1422
  * @param {Object=} headers HTTP headers.
1165
1423
  * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1166
1424
  * request is handled.
@@ -1192,11 +1450,12 @@ function createHttpBackendMock($delegate, $browser) {
1192
1450
  * is called an exception is thrown (as this typically a sign of programming error).
1193
1451
  */
1194
1452
  $httpBackend.flush = function(count) {
1195
- if (!responses.length) throw Error('No pending request to flush !');
1453
+ $rootScope.$digest();
1454
+ if (!responses.length) throw new Error('No pending request to flush !');
1196
1455
 
1197
1456
  if (angular.isDefined(count)) {
1198
1457
  while (count--) {
1199
- if (!responses.length) throw Error('No more pending request to flush !');
1458
+ if (!responses.length) throw new Error('No more pending request to flush !');
1200
1459
  responses.shift()();
1201
1460
  }
1202
1461
  } else {
@@ -1220,12 +1479,13 @@ function createHttpBackendMock($delegate, $browser) {
1220
1479
  * "afterEach" clause.
1221
1480
  *
1222
1481
  * <pre>
1223
- * afterEach($httpBackend.verifyExpectations);
1482
+ * afterEach($httpBackend.verifyNoOutstandingExpectation);
1224
1483
  * </pre>
1225
1484
  */
1226
1485
  $httpBackend.verifyNoOutstandingExpectation = function() {
1486
+ $rootScope.$digest();
1227
1487
  if (expectations.length) {
1228
- throw Error('Unsatisfied requests: ' + expectations.join(', '));
1488
+ throw new Error('Unsatisfied requests: ' + expectations.join(', '));
1229
1489
  }
1230
1490
  };
1231
1491
 
@@ -1246,7 +1506,7 @@ function createHttpBackendMock($delegate, $browser) {
1246
1506
  */
1247
1507
  $httpBackend.verifyNoOutstandingRequest = function() {
1248
1508
  if (responses.length) {
1249
- throw Error('Unflushed requests: ' + responses.length);
1509
+ throw new Error('Unflushed requests: ' + responses.length);
1250
1510
  }
1251
1511
  };
1252
1512
 
@@ -1271,14 +1531,14 @@ function createHttpBackendMock($delegate, $browser) {
1271
1531
  function createShortMethods(prefix) {
1272
1532
  angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
1273
1533
  $httpBackend[prefix + method] = function(url, headers) {
1274
- return $httpBackend[prefix](method, url, undefined, headers)
1275
- }
1534
+ return $httpBackend[prefix](method, url, undefined, headers);
1535
+ };
1276
1536
  });
1277
1537
 
1278
1538
  angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
1279
1539
  $httpBackend[prefix + method] = function(url, data, headers) {
1280
- return $httpBackend[prefix](method, url, data, headers)
1281
- }
1540
+ return $httpBackend[prefix](method, url, data, headers);
1541
+ };
1282
1542
  });
1283
1543
  }
1284
1544
  }
@@ -1311,6 +1571,7 @@ function MockHttpExpectation(method, url, data, headers) {
1311
1571
  this.matchData = function(d) {
1312
1572
  if (angular.isUndefined(data)) return true;
1313
1573
  if (data && angular.isFunction(data.test)) return data.test(d);
1574
+ if (data && angular.isFunction(data)) return data(d);
1314
1575
  if (data && !angular.isString(data)) return angular.toJson(data) == d;
1315
1576
  return data == d;
1316
1577
  };
@@ -1342,7 +1603,8 @@ function MockXhr() {
1342
1603
  };
1343
1604
 
1344
1605
  this.getResponseHeader = function(name) {
1345
- // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last
1606
+ // the lookup must be case insensitive,
1607
+ // that's why we try two quick lookups first and full scan last
1346
1608
  var header = this.$$respHeaders[name];
1347
1609
  if (header) return header;
1348
1610
 
@@ -1376,17 +1638,66 @@ function MockXhr() {
1376
1638
  * @description
1377
1639
  *
1378
1640
  * This service is just a simple decorator for {@link ng.$timeout $timeout} service
1379
- * that adds a "flush" method.
1641
+ * that adds a "flush" and "verifyNoPendingTasks" methods.
1380
1642
  */
1381
1643
 
1382
- /**
1383
- * @ngdoc method
1384
- * @name ngMock.$timeout#flush
1385
- * @methodOf ngMock.$timeout
1386
- * @description
1387
- *
1388
- * Flushes the queue of pending tasks.
1389
- */
1644
+ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
1645
+
1646
+ /**
1647
+ * @ngdoc method
1648
+ * @name ngMock.$timeout#flush
1649
+ * @methodOf ngMock.$timeout
1650
+ * @description
1651
+ *
1652
+ * Flushes the queue of pending tasks.
1653
+ *
1654
+ * @param {number=} delay maximum timeout amount to flush up until
1655
+ */
1656
+ $delegate.flush = function(delay) {
1657
+ $browser.defer.flush(delay);
1658
+ };
1659
+
1660
+ /**
1661
+ * @ngdoc method
1662
+ * @name ngMock.$timeout#flushNext
1663
+ * @methodOf ngMock.$timeout
1664
+ * @description
1665
+ *
1666
+ * Flushes the next timeout in the queue and compares it to the provided delay
1667
+ *
1668
+ * @param {number=} expectedDelay the delay value that will be asserted against the delay of the
1669
+ * next timeout function
1670
+ */
1671
+ $delegate.flushNext = function(expectedDelay) {
1672
+ $browser.defer.flushNext(expectedDelay);
1673
+ };
1674
+
1675
+ /**
1676
+ * @ngdoc method
1677
+ * @name ngMock.$timeout#verifyNoPendingTasks
1678
+ * @methodOf ngMock.$timeout
1679
+ * @description
1680
+ *
1681
+ * Verifies that there are no pending tasks that need to be flushed.
1682
+ */
1683
+ $delegate.verifyNoPendingTasks = function() {
1684
+ if ($browser.deferredFns.length) {
1685
+ throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
1686
+ formatPendingTasksAsString($browser.deferredFns));
1687
+ }
1688
+ };
1689
+
1690
+ function formatPendingTasksAsString(tasks) {
1691
+ var result = [];
1692
+ angular.forEach(tasks, function(task) {
1693
+ result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
1694
+ });
1695
+
1696
+ return result.join(', ');
1697
+ }
1698
+
1699
+ return $delegate;
1700
+ };
1390
1701
 
1391
1702
  /**
1392
1703
  *
@@ -1394,7 +1705,7 @@ function MockXhr() {
1394
1705
  angular.mock.$RootElementProvider = function() {
1395
1706
  this.$get = function() {
1396
1707
  return angular.element('<div ng-app></div>');
1397
- }
1708
+ };
1398
1709
  };
1399
1710
 
1400
1711
  /**
@@ -1402,24 +1713,27 @@ angular.mock.$RootElementProvider = function() {
1402
1713
  * @name ngMock
1403
1714
  * @description
1404
1715
  *
1405
- * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful
1406
- * mocks to the {@link AUTO.$injector $injector}.
1716
+ * # ngMock
1717
+ *
1718
+ * The `ngMock` module providers support to inject and mock Angular services into unit tests.
1719
+ * In addition, ngMock also extends various core ng services such that they can be
1720
+ * inspected and controlled in a synchronous manner within test code.
1721
+ *
1722
+ * {@installModule mocks}
1723
+ *
1724
+ * <div doc-module-components="ngMock"></div>
1725
+ *
1407
1726
  */
1408
1727
  angular.module('ngMock', ['ng']).provider({
1409
1728
  $browser: angular.mock.$BrowserProvider,
1410
1729
  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
1411
1730
  $log: angular.mock.$LogProvider,
1731
+ $interval: angular.mock.$IntervalProvider,
1412
1732
  $httpBackend: angular.mock.$HttpBackendProvider,
1413
1733
  $rootElement: angular.mock.$RootElementProvider
1414
- }).config(function($provide) {
1415
- $provide.decorator('$timeout', function($delegate, $browser) {
1416
- $delegate.flush = function() {
1417
- $browser.defer.flush();
1418
- };
1419
- return $delegate;
1420
- });
1421
- });
1422
-
1734
+ }).config(['$provide', function($provide) {
1735
+ $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
1736
+ }]);
1423
1737
 
1424
1738
  /**
1425
1739
  * @ngdoc overview
@@ -1430,9 +1744,9 @@ angular.module('ngMock', ['ng']).provider({
1430
1744
  * Currently there is only one mock present in this module -
1431
1745
  * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
1432
1746
  */
1433
- angular.module('ngMockE2E', ['ng']).config(function($provide) {
1747
+ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1434
1748
  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
1435
- });
1749
+ }]);
1436
1750
 
1437
1751
  /**
1438
1752
  * @ngdoc object
@@ -1472,7 +1786,7 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
1472
1786
  *
1473
1787
  * // adds a new phone to the phones array
1474
1788
  * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
1475
- * phones.push(angular.fromJSON(data));
1789
+ * phones.push(angular.fromJson(data));
1476
1790
  * });
1477
1791
  * $httpBackend.whenGET(/^\/templates\//).passThrough();
1478
1792
  * //...
@@ -1497,7 +1811,8 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
1497
1811
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1498
1812
  * control how a matched request is handled.
1499
1813
  *
1500
- * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1814
+ * - respond –
1815
+ * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1501
1816
  * – The respond method takes a set of static data to be returned or a function that can return
1502
1817
  * an array containing response status (number), response data (string) and response headers
1503
1818
  * (Object).
@@ -1599,7 +1914,8 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
1599
1914
  * control how a matched request is handled.
1600
1915
  */
1601
1916
  angular.mock.e2e = {};
1602
- angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
1917
+ angular.mock.e2e.$httpBackendDecorator =
1918
+ ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
1603
1919
 
1604
1920
 
1605
1921
  angular.mock.clearDataCache = function() {
@@ -1607,44 +1923,34 @@ angular.mock.clearDataCache = function() {
1607
1923
  cache = angular.element.cache;
1608
1924
 
1609
1925
  for(key in cache) {
1610
- if (cache.hasOwnProperty(key)) {
1926
+ if (Object.prototype.hasOwnProperty.call(cache,key)) {
1611
1927
  var handle = cache[key].handle;
1612
1928
 
1613
- handle && angular.element(handle.elem).unbind();
1929
+ handle && angular.element(handle.elem).off();
1614
1930
  delete cache[key];
1615
1931
  }
1616
1932
  }
1617
1933
  };
1618
1934
 
1619
1935
 
1620
- window.jstestdriver && (function(window) {
1621
- /**
1622
- * Global method to output any number of objects into JSTD console. Useful for debugging.
1623
- */
1624
- window.dump = function() {
1625
- var args = [];
1626
- angular.forEach(arguments, function(arg) {
1627
- args.push(angular.mock.dump(arg));
1628
- });
1629
- jstestdriver.console.log.apply(jstestdriver.console, args);
1630
- if (window.console) {
1631
- window.console.log.apply(window.console, args);
1632
- }
1633
- };
1634
- })(window);
1635
1936
 
1937
+ (window.jasmine || window.mocha) && (function(window) {
1938
+
1939
+ var currentSpec = null;
1636
1940
 
1637
- window.jasmine && (function(window) {
1941
+ beforeEach(function() {
1942
+ currentSpec = this;
1943
+ });
1638
1944
 
1639
1945
  afterEach(function() {
1640
- var spec = getCurrentSpec();
1641
- var injector = spec.$injector;
1946
+ var injector = currentSpec.$injector;
1642
1947
 
1643
- spec.$injector = null;
1644
- spec.$modules = null;
1948
+ currentSpec.$injector = null;
1949
+ currentSpec.$modules = null;
1950
+ currentSpec = null;
1645
1951
 
1646
1952
  if (injector) {
1647
- injector.get('$rootElement').unbind();
1953
+ injector.get('$rootElement').off();
1648
1954
  injector.get('$browser').pollFns.length = 0;
1649
1955
  }
1650
1956
 
@@ -1663,13 +1969,8 @@ window.jasmine && (function(window) {
1663
1969
  angular.callbacks.counter = 0;
1664
1970
  });
1665
1971
 
1666
- function getCurrentSpec() {
1667
- return jasmine.getEnv().currentSpec;
1668
- }
1669
-
1670
1972
  function isSpecRunning() {
1671
- var spec = getCurrentSpec();
1672
- return spec && spec.queue.running;
1973
+ return currentSpec && (window.mocha || currentSpec.queue.running);
1673
1974
  }
1674
1975
 
1675
1976
  /**
@@ -1678,29 +1979,37 @@ window.jasmine && (function(window) {
1678
1979
  * @description
1679
1980
  *
1680
1981
  * *NOTE*: This function is also published on window for easy access.<br>
1681
- * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
1682
1982
  *
1683
1983
  * This function registers a module configuration code. It collects the configuration information
1684
1984
  * which will be used when the injector is created by {@link angular.mock.inject inject}.
1685
1985
  *
1686
1986
  * See {@link angular.mock.inject inject} for usage example
1687
1987
  *
1688
- * @param {...(string|Function)} fns any number of modules which are represented as string
1988
+ * @param {...(string|Function|Object)} fns any number of modules which are represented as string
1689
1989
  * aliases or as anonymous module initialization functions. The modules are used to
1690
- * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
1990
+ * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
1991
+ * object literal is passed they will be register as values in the module, the key being
1992
+ * the module name and the value being what is returned.
1691
1993
  */
1692
1994
  window.module = angular.mock.module = function() {
1693
1995
  var moduleFns = Array.prototype.slice.call(arguments, 0);
1694
1996
  return isSpecRunning() ? workFn() : workFn;
1695
1997
  /////////////////////
1696
1998
  function workFn() {
1697
- var spec = getCurrentSpec();
1698
- if (spec.$injector) {
1699
- throw Error('Injector already created, can not register a module!');
1999
+ if (currentSpec.$injector) {
2000
+ throw new Error('Injector already created, can not register a module!');
1700
2001
  } else {
1701
- var modules = spec.$modules || (spec.$modules = []);
2002
+ var modules = currentSpec.$modules || (currentSpec.$modules = []);
1702
2003
  angular.forEach(moduleFns, function(module) {
1703
- modules.push(module);
2004
+ if (angular.isObject(module) && !angular.isArray(module)) {
2005
+ modules.push(function($provide) {
2006
+ angular.forEach(module, function(value, key) {
2007
+ $provide.value(key, value);
2008
+ });
2009
+ });
2010
+ } else {
2011
+ modules.push(module);
2012
+ }
1704
2013
  });
1705
2014
  }
1706
2015
  }
@@ -1712,14 +2021,45 @@ window.jasmine && (function(window) {
1712
2021
  * @description
1713
2022
  *
1714
2023
  * *NOTE*: This function is also published on window for easy access.<br>
1715
- * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
1716
2024
  *
1717
2025
  * The inject function wraps a function into an injectable function. The inject() creates new
1718
2026
  * instance of {@link AUTO.$injector $injector} per test, which is then used for
1719
2027
  * resolving references.
1720
2028
  *
1721
- * See also {@link angular.mock.module module}
1722
2029
  *
2030
+ * ## Resolving References (Underscore Wrapping)
2031
+ * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
2032
+ * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
2033
+ * that is declared in the scope of the `describe()` block. Since we would, most likely, want
2034
+ * the variable to have the same name of the reference we have a problem, since the parameter
2035
+ * to the `inject()` function would hide the outer variable.
2036
+ *
2037
+ * To help with this, the injected parameters can, optionally, be enclosed with underscores.
2038
+ * These are ignored by the injector when the reference name is resolved.
2039
+ *
2040
+ * For example, the parameter `_myService_` would be resolved as the reference `myService`.
2041
+ * Since it is available in the function body as _myService_, we can then assign it to a variable
2042
+ * defined in an outer scope.
2043
+ *
2044
+ * ```
2045
+ * // Defined out reference variable outside
2046
+ * var myService;
2047
+ *
2048
+ * // Wrap the parameter in underscores
2049
+ * beforeEach( inject( function(_myService_){
2050
+ * myService = _myService_;
2051
+ * }));
2052
+ *
2053
+ * // Use myService in a series of tests.
2054
+ * it('makes use of myService', function() {
2055
+ * myService.doStuff();
2056
+ * });
2057
+ *
2058
+ * ```
2059
+ *
2060
+ * See also {@link angular.mock.module angular.mock.module}
2061
+ *
2062
+ * ## Example
1723
2063
  * Example of what a typical jasmine tests looks like with the inject method.
1724
2064
  * <pre>
1725
2065
  *
@@ -1752,7 +2092,7 @@ window.jasmine && (function(window) {
1752
2092
  * inject(function(version) {
1753
2093
  * expect(version).toEqual('overridden');
1754
2094
  * });
1755
- * ));
2095
+ * });
1756
2096
  * });
1757
2097
  *
1758
2098
  * </pre>
@@ -1765,17 +2105,19 @@ window.jasmine && (function(window) {
1765
2105
  return isSpecRunning() ? workFn() : workFn;
1766
2106
  /////////////////////
1767
2107
  function workFn() {
1768
- var spec = getCurrentSpec();
1769
- var modules = spec.$modules || [];
2108
+ var modules = currentSpec.$modules || [];
2109
+
1770
2110
  modules.unshift('ngMock');
1771
2111
  modules.unshift('ng');
1772
- var injector = spec.$injector;
2112
+ var injector = currentSpec.$injector;
1773
2113
  if (!injector) {
1774
- injector = spec.$injector = angular.injector(modules);
2114
+ injector = currentSpec.$injector = angular.injector(modules);
1775
2115
  }
1776
2116
  for(var i = 0, ii = blockFns.length; i < ii; i++) {
1777
2117
  try {
2118
+ /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
1778
2119
  injector.invoke(blockFns[i] || angular.noop, this);
2120
+ /* jshint +W040 */
1779
2121
  } catch (e) {
1780
2122
  if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack;
1781
2123
  throw e;
@@ -1785,4 +2127,4 @@ window.jasmine && (function(window) {
1785
2127
  }
1786
2128
  }
1787
2129
  };
1788
- })(window);
2130
+ })(window);