angular-gem 1.1.5 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);