Digital Office Automation System Backend
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

angular-mocks.js 66KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136
  1. /**
  2. * @license AngularJS v1.2.13
  3. * (c) 2010-2014 Google, Inc. http://angularjs.org
  4. * License: MIT
  5. */
  6. (function(window, angular, undefined) {
  7. 'use strict';
  8. /**
  9. * @ngdoc overview
  10. * @name angular.mock
  11. * @description
  12. *
  13. * Namespace from 'angular-mocks.js' which contains testing related code.
  14. */
  15. angular.mock = {};
  16. /**
  17. * ! This is a private undocumented service !
  18. *
  19. * @name ngMock.$browser
  20. *
  21. * @description
  22. * This service is a mock implementation of {@link ng.$browser}. It provides fake
  23. * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
  24. * cookies, etc...
  25. *
  26. * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
  27. * that there are several helper methods available which can be used in tests.
  28. */
  29. angular.mock.$BrowserProvider = function() {
  30. this.$get = function() {
  31. return new angular.mock.$Browser();
  32. };
  33. };
  34. angular.mock.$Browser = function() {
  35. var self = this;
  36. this.isMock = true;
  37. self.$$url = "http://server/";
  38. self.$$lastUrl = self.$$url; // used by url polling fn
  39. self.pollFns = [];
  40. // TODO(vojta): remove this temporary api
  41. self.$$completeOutstandingRequest = angular.noop;
  42. self.$$incOutstandingRequestCount = angular.noop;
  43. // register url polling fn
  44. self.onUrlChange = function(listener) {
  45. self.pollFns.push(
  46. function() {
  47. if (self.$$lastUrl != self.$$url) {
  48. self.$$lastUrl = self.$$url;
  49. listener(self.$$url);
  50. }
  51. }
  52. );
  53. return listener;
  54. };
  55. self.cookieHash = {};
  56. self.lastCookieHash = {};
  57. self.deferredFns = [];
  58. self.deferredNextId = 0;
  59. self.defer = function(fn, delay) {
  60. delay = delay || 0;
  61. self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
  62. self.deferredFns.sort(function(a,b){ return a.time - b.time;});
  63. return self.deferredNextId++;
  64. };
  65. /**
  66. * @name ngMock.$browser#defer.now
  67. * @propertyOf ngMock.$browser
  68. *
  69. * @description
  70. * Current milliseconds mock time.
  71. */
  72. self.defer.now = 0;
  73. self.defer.cancel = function(deferId) {
  74. var fnIndex;
  75. angular.forEach(self.deferredFns, function(fn, index) {
  76. if (fn.id === deferId) fnIndex = index;
  77. });
  78. if (fnIndex !== undefined) {
  79. self.deferredFns.splice(fnIndex, 1);
  80. return true;
  81. }
  82. return false;
  83. };
  84. /**
  85. * @name ngMock.$browser#defer.flush
  86. * @methodOf ngMock.$browser
  87. *
  88. * @description
  89. * Flushes all pending requests and executes the defer callbacks.
  90. *
  91. * @param {number=} number of milliseconds to flush. See {@link #defer.now}
  92. */
  93. self.defer.flush = function(delay) {
  94. if (angular.isDefined(delay)) {
  95. self.defer.now += delay;
  96. } else {
  97. if (self.deferredFns.length) {
  98. self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
  99. } else {
  100. throw new Error('No deferred tasks to be flushed');
  101. }
  102. }
  103. while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
  104. self.deferredFns.shift().fn();
  105. }
  106. };
  107. self.$$baseHref = '';
  108. self.baseHref = function() {
  109. return this.$$baseHref;
  110. };
  111. };
  112. angular.mock.$Browser.prototype = {
  113. /**
  114. * @name ngMock.$browser#poll
  115. * @methodOf ngMock.$browser
  116. *
  117. * @description
  118. * run all fns in pollFns
  119. */
  120. poll: function poll() {
  121. angular.forEach(this.pollFns, function(pollFn){
  122. pollFn();
  123. });
  124. },
  125. addPollFn: function(pollFn) {
  126. this.pollFns.push(pollFn);
  127. return pollFn;
  128. },
  129. url: function(url, replace) {
  130. if (url) {
  131. this.$$url = url;
  132. return this;
  133. }
  134. return this.$$url;
  135. },
  136. cookies: function(name, value) {
  137. if (name) {
  138. if (angular.isUndefined(value)) {
  139. delete this.cookieHash[name];
  140. } else {
  141. if (angular.isString(value) && //strings only
  142. value.length <= 4096) { //strict cookie storage limits
  143. this.cookieHash[name] = value;
  144. }
  145. }
  146. } else {
  147. if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
  148. this.lastCookieHash = angular.copy(this.cookieHash);
  149. this.cookieHash = angular.copy(this.cookieHash);
  150. }
  151. return this.cookieHash;
  152. }
  153. },
  154. notifyWhenNoOutstandingRequests: function(fn) {
  155. fn();
  156. }
  157. };
  158. /**
  159. * @ngdoc object
  160. * @name ngMock.$exceptionHandlerProvider
  161. *
  162. * @description
  163. * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
  164. * passed into the `$exceptionHandler`.
  165. */
  166. /**
  167. * @ngdoc object
  168. * @name ngMock.$exceptionHandler
  169. *
  170. * @description
  171. * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
  172. * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
  173. * information.
  174. *
  175. *
  176. * <pre>
  177. * describe('$exceptionHandlerProvider', function() {
  178. *
  179. * it('should capture log messages and exceptions', function() {
  180. *
  181. * module(function($exceptionHandlerProvider) {
  182. * $exceptionHandlerProvider.mode('log');
  183. * });
  184. *
  185. * inject(function($log, $exceptionHandler, $timeout) {
  186. * $timeout(function() { $log.log(1); });
  187. * $timeout(function() { $log.log(2); throw 'banana peel'; });
  188. * $timeout(function() { $log.log(3); });
  189. * expect($exceptionHandler.errors).toEqual([]);
  190. * expect($log.assertEmpty());
  191. * $timeout.flush();
  192. * expect($exceptionHandler.errors).toEqual(['banana peel']);
  193. * expect($log.log.logs).toEqual([[1], [2], [3]]);
  194. * });
  195. * });
  196. * });
  197. * </pre>
  198. */
  199. angular.mock.$ExceptionHandlerProvider = function() {
  200. var handler;
  201. /**
  202. * @ngdoc method
  203. * @name ngMock.$exceptionHandlerProvider#mode
  204. * @methodOf ngMock.$exceptionHandlerProvider
  205. *
  206. * @description
  207. * Sets the logging mode.
  208. *
  209. * @param {string} mode Mode of operation, defaults to `rethrow`.
  210. *
  211. * - `rethrow`: If any errors are passed into the handler in tests, it typically
  212. * means that there is a bug in the application or test, so this mock will
  213. * make these tests fail.
  214. * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
  215. * mode stores an array of errors in `$exceptionHandler.errors`, to allow later
  216. * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
  217. * {@link ngMock.$log#reset reset()}
  218. */
  219. this.mode = function(mode) {
  220. switch(mode) {
  221. case 'rethrow':
  222. handler = function(e) {
  223. throw e;
  224. };
  225. break;
  226. case 'log':
  227. var errors = [];
  228. handler = function(e) {
  229. if (arguments.length == 1) {
  230. errors.push(e);
  231. } else {
  232. errors.push([].slice.call(arguments, 0));
  233. }
  234. };
  235. handler.errors = errors;
  236. break;
  237. default:
  238. throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
  239. }
  240. };
  241. this.$get = function() {
  242. return handler;
  243. };
  244. this.mode('rethrow');
  245. };
  246. /**
  247. * @ngdoc service
  248. * @name ngMock.$log
  249. *
  250. * @description
  251. * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
  252. * (one array per logging level). These arrays are exposed as `logs` property of each of the
  253. * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
  254. *
  255. */
  256. angular.mock.$LogProvider = function() {
  257. var debug = true;
  258. function concat(array1, array2, index) {
  259. return array1.concat(Array.prototype.slice.call(array2, index));
  260. }
  261. this.debugEnabled = function(flag) {
  262. if (angular.isDefined(flag)) {
  263. debug = flag;
  264. return this;
  265. } else {
  266. return debug;
  267. }
  268. };
  269. this.$get = function () {
  270. var $log = {
  271. log: function() { $log.log.logs.push(concat([], arguments, 0)); },
  272. warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
  273. info: function() { $log.info.logs.push(concat([], arguments, 0)); },
  274. error: function() { $log.error.logs.push(concat([], arguments, 0)); },
  275. debug: function() {
  276. if (debug) {
  277. $log.debug.logs.push(concat([], arguments, 0));
  278. }
  279. }
  280. };
  281. /**
  282. * @ngdoc method
  283. * @name ngMock.$log#reset
  284. * @methodOf ngMock.$log
  285. *
  286. * @description
  287. * Reset all of the logging arrays to empty.
  288. */
  289. $log.reset = function () {
  290. /**
  291. * @ngdoc property
  292. * @name ngMock.$log#log.logs
  293. * @propertyOf ngMock.$log
  294. *
  295. * @description
  296. * Array of messages logged using {@link ngMock.$log#log}.
  297. *
  298. * @example
  299. * <pre>
  300. * $log.log('Some Log');
  301. * var first = $log.log.logs.unshift();
  302. * </pre>
  303. */
  304. $log.log.logs = [];
  305. /**
  306. * @ngdoc property
  307. * @name ngMock.$log#info.logs
  308. * @propertyOf ngMock.$log
  309. *
  310. * @description
  311. * Array of messages logged using {@link ngMock.$log#info}.
  312. *
  313. * @example
  314. * <pre>
  315. * $log.info('Some Info');
  316. * var first = $log.info.logs.unshift();
  317. * </pre>
  318. */
  319. $log.info.logs = [];
  320. /**
  321. * @ngdoc property
  322. * @name ngMock.$log#warn.logs
  323. * @propertyOf ngMock.$log
  324. *
  325. * @description
  326. * Array of messages logged using {@link ngMock.$log#warn}.
  327. *
  328. * @example
  329. * <pre>
  330. * $log.warn('Some Warning');
  331. * var first = $log.warn.logs.unshift();
  332. * </pre>
  333. */
  334. $log.warn.logs = [];
  335. /**
  336. * @ngdoc property
  337. * @name ngMock.$log#error.logs
  338. * @propertyOf ngMock.$log
  339. *
  340. * @description
  341. * Array of messages logged using {@link ngMock.$log#error}.
  342. *
  343. * @example
  344. * <pre>
  345. * $log.error('Some Error');
  346. * var first = $log.error.logs.unshift();
  347. * </pre>
  348. */
  349. $log.error.logs = [];
  350. /**
  351. * @ngdoc property
  352. * @name ngMock.$log#debug.logs
  353. * @propertyOf ngMock.$log
  354. *
  355. * @description
  356. * Array of messages logged using {@link ngMock.$log#debug}.
  357. *
  358. * @example
  359. * <pre>
  360. * $log.debug('Some Error');
  361. * var first = $log.debug.logs.unshift();
  362. * </pre>
  363. */
  364. $log.debug.logs = [];
  365. };
  366. /**
  367. * @ngdoc method
  368. * @name ngMock.$log#assertEmpty
  369. * @methodOf ngMock.$log
  370. *
  371. * @description
  372. * Assert that the all of the logging methods have no logged messages. If messages present, an
  373. * exception is thrown.
  374. */
  375. $log.assertEmpty = function() {
  376. var errors = [];
  377. angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
  378. angular.forEach($log[logLevel].logs, function(log) {
  379. angular.forEach(log, function (logItem) {
  380. errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
  381. (logItem.stack || ''));
  382. });
  383. });
  384. });
  385. if (errors.length) {
  386. errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+
  387. "an expected log message was not checked and removed:");
  388. errors.push('');
  389. throw new Error(errors.join('\n---------\n'));
  390. }
  391. };
  392. $log.reset();
  393. return $log;
  394. };
  395. };
  396. /**
  397. * @ngdoc service
  398. * @name ngMock.$interval
  399. *
  400. * @description
  401. * Mock implementation of the $interval service.
  402. *
  403. * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to
  404. * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
  405. * time.
  406. *
  407. * @param {function()} fn A function that should be called repeatedly.
  408. * @param {number} delay Number of milliseconds between each function call.
  409. * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
  410. * indefinitely.
  411. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
  412. * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
  413. * @returns {promise} A promise which will be notified on each iteration.
  414. */
  415. angular.mock.$IntervalProvider = function() {
  416. this.$get = ['$rootScope', '$q',
  417. function($rootScope, $q) {
  418. var repeatFns = [],
  419. nextRepeatId = 0,
  420. now = 0;
  421. var $interval = function(fn, delay, count, invokeApply) {
  422. var deferred = $q.defer(),
  423. promise = deferred.promise,
  424. iteration = 0,
  425. skipApply = (angular.isDefined(invokeApply) && !invokeApply);
  426. count = (angular.isDefined(count)) ? count : 0,
  427. promise.then(null, null, fn);
  428. promise.$$intervalId = nextRepeatId;
  429. function tick() {
  430. deferred.notify(iteration++);
  431. if (count > 0 && iteration >= count) {
  432. var fnIndex;
  433. deferred.resolve(iteration);
  434. angular.forEach(repeatFns, function(fn, index) {
  435. if (fn.id === promise.$$intervalId) fnIndex = index;
  436. });
  437. if (fnIndex !== undefined) {
  438. repeatFns.splice(fnIndex, 1);
  439. }
  440. }
  441. if (!skipApply) $rootScope.$apply();
  442. }
  443. repeatFns.push({
  444. nextTime:(now + delay),
  445. delay: delay,
  446. fn: tick,
  447. id: nextRepeatId,
  448. deferred: deferred
  449. });
  450. repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
  451. nextRepeatId++;
  452. return promise;
  453. };
  454. $interval.cancel = function(promise) {
  455. if(!promise) return false;
  456. var fnIndex;
  457. angular.forEach(repeatFns, function(fn, index) {
  458. if (fn.id === promise.$$intervalId) fnIndex = index;
  459. });
  460. if (fnIndex !== undefined) {
  461. repeatFns[fnIndex].deferred.reject('canceled');
  462. repeatFns.splice(fnIndex, 1);
  463. return true;
  464. }
  465. return false;
  466. };
  467. /**
  468. * @ngdoc method
  469. * @name ngMock.$interval#flush
  470. * @methodOf ngMock.$interval
  471. * @description
  472. *
  473. * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
  474. *
  475. * @param {number=} millis maximum timeout amount to flush up until.
  476. *
  477. * @return {number} The amount of time moved forward.
  478. */
  479. $interval.flush = function(millis) {
  480. now += millis;
  481. while (repeatFns.length && repeatFns[0].nextTime <= now) {
  482. var task = repeatFns[0];
  483. task.fn();
  484. task.nextTime += task.delay;
  485. repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
  486. }
  487. return millis;
  488. };
  489. return $interval;
  490. }];
  491. };
  492. /* jshint -W101 */
  493. /* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
  494. * This directive should go inside the anonymous function but a bug in JSHint means that it would
  495. * not be enacted early enough to prevent the warning.
  496. */
  497. var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
  498. function jsonStringToDate(string) {
  499. var match;
  500. if (match = string.match(R_ISO8061_STR)) {
  501. var date = new Date(0),
  502. tzHour = 0,
  503. tzMin = 0;
  504. if (match[9]) {
  505. tzHour = int(match[9] + match[10]);
  506. tzMin = int(match[9] + match[11]);
  507. }
  508. date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
  509. date.setUTCHours(int(match[4]||0) - tzHour,
  510. int(match[5]||0) - tzMin,
  511. int(match[6]||0),
  512. int(match[7]||0));
  513. return date;
  514. }
  515. return string;
  516. }
  517. function int(str) {
  518. return parseInt(str, 10);
  519. }
  520. function padNumber(num, digits, trim) {
  521. var neg = '';
  522. if (num < 0) {
  523. neg = '-';
  524. num = -num;
  525. }
  526. num = '' + num;
  527. while(num.length < digits) num = '0' + num;
  528. if (trim)
  529. num = num.substr(num.length - digits);
  530. return neg + num;
  531. }
  532. /**
  533. * @ngdoc object
  534. * @name angular.mock.TzDate
  535. * @description
  536. *
  537. * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
  538. *
  539. * Mock of the Date type which has its timezone specified via constructor arg.
  540. *
  541. * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
  542. * offset, so that we can test code that depends on local timezone settings without dependency on
  543. * the time zone settings of the machine where the code is running.
  544. *
  545. * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
  546. * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
  547. *
  548. * @example
  549. * !!!! WARNING !!!!!
  550. * This is not a complete Date object so only methods that were implemented can be called safely.
  551. * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
  552. *
  553. * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
  554. * incomplete we might be missing some non-standard methods. This can result in errors like:
  555. * "Date.prototype.foo called on incompatible Object".
  556. *
  557. * <pre>
  558. * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
  559. * newYearInBratislava.getTimezoneOffset() => -60;
  560. * newYearInBratislava.getFullYear() => 2010;
  561. * newYearInBratislava.getMonth() => 0;
  562. * newYearInBratislava.getDate() => 1;
  563. * newYearInBratislava.getHours() => 0;
  564. * newYearInBratislava.getMinutes() => 0;
  565. * newYearInBratislava.getSeconds() => 0;
  566. * </pre>
  567. *
  568. */
  569. angular.mock.TzDate = function (offset, timestamp) {
  570. var self = new Date(0);
  571. if (angular.isString(timestamp)) {
  572. var tsStr = timestamp;
  573. self.origDate = jsonStringToDate(timestamp);
  574. timestamp = self.origDate.getTime();
  575. if (isNaN(timestamp))
  576. throw {
  577. name: "Illegal Argument",
  578. message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
  579. };
  580. } else {
  581. self.origDate = new Date(timestamp);
  582. }
  583. var localOffset = new Date(timestamp).getTimezoneOffset();
  584. self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
  585. self.date = new Date(timestamp + self.offsetDiff);
  586. self.getTime = function() {
  587. return self.date.getTime() - self.offsetDiff;
  588. };
  589. self.toLocaleDateString = function() {
  590. return self.date.toLocaleDateString();
  591. };
  592. self.getFullYear = function() {
  593. return self.date.getFullYear();
  594. };
  595. self.getMonth = function() {
  596. return self.date.getMonth();
  597. };
  598. self.getDate = function() {
  599. return self.date.getDate();
  600. };
  601. self.getHours = function() {
  602. return self.date.getHours();
  603. };
  604. self.getMinutes = function() {
  605. return self.date.getMinutes();
  606. };
  607. self.getSeconds = function() {
  608. return self.date.getSeconds();
  609. };
  610. self.getMilliseconds = function() {
  611. return self.date.getMilliseconds();
  612. };
  613. self.getTimezoneOffset = function() {
  614. return offset * 60;
  615. };
  616. self.getUTCFullYear = function() {
  617. return self.origDate.getUTCFullYear();
  618. };
  619. self.getUTCMonth = function() {
  620. return self.origDate.getUTCMonth();
  621. };
  622. self.getUTCDate = function() {
  623. return self.origDate.getUTCDate();
  624. };
  625. self.getUTCHours = function() {
  626. return self.origDate.getUTCHours();
  627. };
  628. self.getUTCMinutes = function() {
  629. return self.origDate.getUTCMinutes();
  630. };
  631. self.getUTCSeconds = function() {
  632. return self.origDate.getUTCSeconds();
  633. };
  634. self.getUTCMilliseconds = function() {
  635. return self.origDate.getUTCMilliseconds();
  636. };
  637. self.getDay = function() {
  638. return self.date.getDay();
  639. };
  640. // provide this method only on browsers that already have it
  641. if (self.toISOString) {
  642. self.toISOString = function() {
  643. return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
  644. padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
  645. padNumber(self.origDate.getUTCDate(), 2) + 'T' +
  646. padNumber(self.origDate.getUTCHours(), 2) + ':' +
  647. padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
  648. padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
  649. padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
  650. };
  651. }
  652. //hide all methods not implemented in this mock that the Date prototype exposes
  653. var unimplementedMethods = ['getUTCDay',
  654. 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
  655. 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
  656. 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
  657. 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
  658. 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
  659. angular.forEach(unimplementedMethods, function(methodName) {
  660. self[methodName] = function() {
  661. throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
  662. };
  663. });
  664. return self;
  665. };
  666. //make "tzDateInstance instanceof Date" return true
  667. angular.mock.TzDate.prototype = Date.prototype;
  668. /* jshint +W101 */
  669. angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
  670. .config(['$provide', function($provide) {
  671. var reflowQueue = [];
  672. $provide.value('$$animateReflow', function(fn) {
  673. reflowQueue.push(fn);
  674. return angular.noop;
  675. });
  676. $provide.decorator('$animate', function($delegate) {
  677. var animate = {
  678. queue : [],
  679. enabled : $delegate.enabled,
  680. triggerReflow : function() {
  681. if(reflowQueue.length === 0) {
  682. throw new Error('No animation reflows present');
  683. }
  684. angular.forEach(reflowQueue, function(fn) {
  685. fn();
  686. });
  687. reflowQueue = [];
  688. }
  689. };
  690. angular.forEach(
  691. ['enter','leave','move','addClass','removeClass','setClass'], function(method) {
  692. animate[method] = function() {
  693. animate.queue.push({
  694. event : method,
  695. element : arguments[0],
  696. args : arguments
  697. });
  698. $delegate[method].apply($delegate, arguments);
  699. };
  700. });
  701. return animate;
  702. });
  703. }]);
  704. /**
  705. * @ngdoc function
  706. * @name angular.mock.dump
  707. * @description
  708. *
  709. * *NOTE*: this is not an injectable instance, just a globally available function.
  710. *
  711. * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
  712. * debugging.
  713. *
  714. * This method is also available on window, where it can be used to display objects on debug
  715. * console.
  716. *
  717. * @param {*} object - any object to turn into string.
  718. * @return {string} a serialized string of the argument
  719. */
  720. angular.mock.dump = function(object) {
  721. return serialize(object);
  722. function serialize(object) {
  723. var out;
  724. if (angular.isElement(object)) {
  725. object = angular.element(object);
  726. out = angular.element('<div></div>');
  727. angular.forEach(object, function(element) {
  728. out.append(angular.element(element).clone());
  729. });
  730. out = out.html();
  731. } else if (angular.isArray(object)) {
  732. out = [];
  733. angular.forEach(object, function(o) {
  734. out.push(serialize(o));
  735. });
  736. out = '[ ' + out.join(', ') + ' ]';
  737. } else if (angular.isObject(object)) {
  738. if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
  739. out = serializeScope(object);
  740. } else if (object instanceof Error) {
  741. out = object.stack || ('' + object.name + ': ' + object.message);
  742. } else {
  743. // TODO(i): this prevents methods being logged,
  744. // we should have a better way to serialize objects
  745. out = angular.toJson(object, true);
  746. }
  747. } else {
  748. out = String(object);
  749. }
  750. return out;
  751. }
  752. function serializeScope(scope, offset) {
  753. offset = offset || ' ';
  754. var log = [offset + 'Scope(' + scope.$id + '): {'];
  755. for ( var key in scope ) {
  756. if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
  757. log.push(' ' + key + ': ' + angular.toJson(scope[key]));
  758. }
  759. }
  760. var child = scope.$$childHead;
  761. while(child) {
  762. log.push(serializeScope(child, offset + ' '));
  763. child = child.$$nextSibling;
  764. }
  765. log.push('}');
  766. return log.join('\n' + offset);
  767. }
  768. };
  769. /**
  770. * @ngdoc object
  771. * @name ngMock.$httpBackend
  772. * @description
  773. * Fake HTTP backend implementation suitable for unit testing applications that use the
  774. * {@link ng.$http $http service}.
  775. *
  776. * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
  777. * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
  778. *
  779. * During unit testing, we want our unit tests to run quickly and have no external dependencies so
  780. * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
  781. * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
  782. * to verify whether a certain request has been sent or not, or alternatively just let the
  783. * application make requests, respond with pre-trained responses and assert that the end result is
  784. * what we expect it to be.
  785. *
  786. * This mock implementation can be used to respond with static or dynamic responses via the
  787. * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
  788. *
  789. * When an Angular application needs some data from a server, it calls the $http service, which
  790. * sends the request to a real server using $httpBackend service. With dependency injection, it is
  791. * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
  792. * the requests and respond with some testing data without sending a request to real server.
  793. *
  794. * There are two ways to specify what test data should be returned as http responses by the mock
  795. * backend when the code under test makes http requests:
  796. *
  797. * - `$httpBackend.expect` - specifies a request expectation
  798. * - `$httpBackend.when` - specifies a backend definition
  799. *
  800. *
  801. * # Request Expectations vs Backend Definitions
  802. *
  803. * Request expectations provide a way to make assertions about requests made by the application and
  804. * to define responses for those requests. The test will fail if the expected requests are not made
  805. * or they are made in the wrong order.
  806. *
  807. * Backend definitions allow you to define a fake backend for your application which doesn't assert
  808. * if a particular request was made or not, it just returns a trained response if a request is made.
  809. * The test will pass whether or not the request gets made during testing.
  810. *
  811. *
  812. * <table class="table">
  813. * <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
  814. * <tr>
  815. * <th>Syntax</th>
  816. * <td>.expect(...).respond(...)</td>
  817. * <td>.when(...).respond(...)</td>
  818. * </tr>
  819. * <tr>
  820. * <th>Typical usage</th>
  821. * <td>strict unit tests</td>
  822. * <td>loose (black-box) unit testing</td>
  823. * </tr>
  824. * <tr>
  825. * <th>Fulfills multiple requests</th>
  826. * <td>NO</td>
  827. * <td>YES</td>
  828. * </tr>
  829. * <tr>
  830. * <th>Order of requests matters</th>
  831. * <td>YES</td>
  832. * <td>NO</td>
  833. * </tr>
  834. * <tr>
  835. * <th>Request required</th>
  836. * <td>YES</td>
  837. * <td>NO</td>
  838. * </tr>
  839. * <tr>
  840. * <th>Response required</th>
  841. * <td>optional (see below)</td>
  842. * <td>YES</td>
  843. * </tr>
  844. * </table>
  845. *
  846. * In cases where both backend definitions and request expectations are specified during unit
  847. * testing, the request expectations are evaluated first.
  848. *
  849. * If a request expectation has no response specified, the algorithm will search your backend
  850. * definitions for an appropriate response.
  851. *
  852. * If a request didn't match any expectation or if the expectation doesn't have the response
  853. * defined, the backend definitions are evaluated in sequential order to see if any of them match
  854. * the request. The response from the first matched definition is returned.
  855. *
  856. *
  857. * # Flushing HTTP requests
  858. *
  859. * The $httpBackend used in production always responds to requests with responses asynchronously.
  860. * If we preserved this behavior in unit testing we'd have to create async unit tests, which are
  861. * hard to write, understand, and maintain. However, the testing mock can't respond
  862. * synchronously because that would change the execution of the code under test. For this reason the
  863. * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
  864. * requests and thus preserve the async api of the backend while allowing the test to execute
  865. * synchronously.
  866. *
  867. *
  868. * # Unit testing with mock $httpBackend
  869. * The following code shows how to setup and use the mock backend when unit testing a controller.
  870. * First we create the controller under test:
  871. *
  872. <pre>
  873. // The controller code
  874. function MyController($scope, $http) {
  875. var authToken;
  876. $http.get('/auth.py').success(function(data, status, headers) {
  877. authToken = headers('A-Token');
  878. $scope.user = data;
  879. });
  880. $scope.saveMessage = function(message) {
  881. var headers = { 'Authorization': authToken };
  882. $scope.status = 'Saving...';
  883. $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
  884. $scope.status = '';
  885. }).error(function() {
  886. $scope.status = 'ERROR!';
  887. });
  888. };
  889. }
  890. </pre>
  891. *
  892. * Now we setup the mock backend and create the test specs:
  893. *
  894. <pre>
  895. // testing controller
  896. describe('MyController', function() {
  897. var $httpBackend, $rootScope, createController;
  898. beforeEach(inject(function($injector) {
  899. // Set up the mock http service responses
  900. $httpBackend = $injector.get('$httpBackend');
  901. // backend definition common for all tests
  902. $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
  903. // Get hold of a scope (i.e. the root scope)
  904. $rootScope = $injector.get('$rootScope');
  905. // The $controller service is used to create instances of controllers
  906. var $controller = $injector.get('$controller');
  907. createController = function() {
  908. return $controller('MyController', {'$scope' : $rootScope });
  909. };
  910. }));
  911. afterEach(function() {
  912. $httpBackend.verifyNoOutstandingExpectation();
  913. $httpBackend.verifyNoOutstandingRequest();
  914. });
  915. it('should fetch authentication token', function() {
  916. $httpBackend.expectGET('/auth.py');
  917. var controller = createController();
  918. $httpBackend.flush();
  919. });
  920. it('should send msg to server', function() {
  921. var controller = createController();
  922. $httpBackend.flush();
  923. // now you don’t care about the authentication, but
  924. // the controller will still send the request and
  925. // $httpBackend will respond without you having to
  926. // specify the expectation and response for this request
  927. $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
  928. $rootScope.saveMessage('message content');
  929. expect($rootScope.status).toBe('Saving...');
  930. $httpBackend.flush();
  931. expect($rootScope.status).toBe('');
  932. });
  933. it('should send auth header', function() {
  934. var controller = createController();
  935. $httpBackend.flush();
  936. $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
  937. // check if the header was send, if it wasn't the expectation won't
  938. // match the request and the test will fail
  939. return headers['Authorization'] == 'xxx';
  940. }).respond(201, '');
  941. $rootScope.saveMessage('whatever');
  942. $httpBackend.flush();
  943. });
  944. });
  945. </pre>
  946. */
  947. angular.mock.$HttpBackendProvider = function() {
  948. this.$get = ['$rootScope', createHttpBackendMock];
  949. };
  950. /**
  951. * General factory function for $httpBackend mock.
  952. * Returns instance for unit testing (when no arguments specified):
  953. * - passing through is disabled
  954. * - auto flushing is disabled
  955. *
  956. * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
  957. * - passing through (delegating request to real backend) is enabled
  958. * - auto flushing is enabled
  959. *
  960. * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
  961. * @param {Object=} $browser Auto-flushing enabled if specified
  962. * @return {Object} Instance of $httpBackend mock
  963. */
  964. function createHttpBackendMock($rootScope, $delegate, $browser) {
  965. var definitions = [],
  966. expectations = [],
  967. responses = [],
  968. responsesPush = angular.bind(responses, responses.push),
  969. copy = angular.copy;
  970. function createResponse(status, data, headers) {
  971. if (angular.isFunction(status)) return status;
  972. return function() {
  973. return angular.isNumber(status)
  974. ? [status, data, headers]
  975. : [200, status, data];
  976. };
  977. }
  978. // TODO(vojta): change params to: method, url, data, headers, callback
  979. function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
  980. var xhr = new MockXhr(),
  981. expectation = expectations[0],
  982. wasExpected = false;
  983. function prettyPrint(data) {
  984. return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
  985. ? data
  986. : angular.toJson(data);
  987. }
  988. function wrapResponse(wrapped) {
  989. if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
  990. return handleResponse;
  991. function handleResponse() {
  992. var response = wrapped.response(method, url, data, headers);
  993. xhr.$$respHeaders = response[2];
  994. callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders());
  995. }
  996. function handleTimeout() {
  997. for (var i = 0, ii = responses.length; i < ii; i++) {
  998. if (responses[i] === handleResponse) {
  999. responses.splice(i, 1);
  1000. callback(-1, undefined, '');
  1001. break;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. if (expectation && expectation.match(method, url)) {
  1007. if (!expectation.matchData(data))
  1008. throw new Error('Expected ' + expectation + ' with different data\n' +
  1009. 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
  1010. if (!expectation.matchHeaders(headers))
  1011. throw new Error('Expected ' + expectation + ' with different headers\n' +
  1012. 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
  1013. prettyPrint(headers));
  1014. expectations.shift();
  1015. if (expectation.response) {
  1016. responses.push(wrapResponse(expectation));
  1017. return;
  1018. }
  1019. wasExpected = true;
  1020. }
  1021. var i = -1, definition;
  1022. while ((definition = definitions[++i])) {
  1023. if (definition.match(method, url, data, headers || {})) {
  1024. if (definition.response) {
  1025. // if $browser specified, we do auto flush all requests
  1026. ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
  1027. } else if (definition.passThrough) {
  1028. $delegate(method, url, data, callback, headers, timeout, withCredentials);
  1029. } else throw new Error('No response defined !');
  1030. return;
  1031. }
  1032. }
  1033. throw wasExpected ?
  1034. new Error('No response defined !') :
  1035. new Error('Unexpected request: ' + method + ' ' + url + '\n' +
  1036. (expectation ? 'Expected ' + expectation : 'No more request expected'));
  1037. }
  1038. /**
  1039. * @ngdoc method
  1040. * @name ngMock.$httpBackend#when
  1041. * @methodOf ngMock.$httpBackend
  1042. * @description
  1043. * Creates a new backend definition.
  1044. *
  1045. * @param {string} method HTTP method.
  1046. * @param {string|RegExp} url HTTP url.
  1047. * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
  1048. * data string and returns true if the data is as expected.
  1049. * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
  1050. * object and returns true if the headers match the current definition.
  1051. * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
  1052. * request is handled.
  1053. *
  1054. * - respond –
  1055. * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
  1056. * – The respond method takes a set of static data to be returned or a function that can return
  1057. * an array containing response status (number), response data (string) and response headers
  1058. * (Object).
  1059. */
  1060. $httpBackend.when = function(method, url, data, headers) {
  1061. var definition = new MockHttpExpectation(method, url, data, headers),
  1062. chain = {
  1063. respond: function(status, data, headers) {
  1064. definition.response = createResponse(status, data, headers);
  1065. }
  1066. };
  1067. if ($browser) {
  1068. chain.passThrough = function() {
  1069. definition.passThrough = true;
  1070. };
  1071. }
  1072. definitions.push(definition);
  1073. return chain;
  1074. };
  1075. /**
  1076. * @ngdoc method
  1077. * @name ngMock.$httpBackend#whenGET
  1078. * @methodOf ngMock.$httpBackend
  1079. * @description
  1080. * Creates a new backend definition for GET requests. For more info see `when()`.
  1081. *
  1082. * @param {string|RegExp} url HTTP url.
  1083. * @param {(Object|function(Object))=} headers HTTP headers.
  1084. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1085. * request is handled.
  1086. */
  1087. /**
  1088. * @ngdoc method
  1089. * @name ngMock.$httpBackend#whenHEAD
  1090. * @methodOf ngMock.$httpBackend
  1091. * @description
  1092. * Creates a new backend definition for HEAD requests. For more info see `when()`.
  1093. *
  1094. * @param {string|RegExp} url HTTP url.
  1095. * @param {(Object|function(Object))=} headers HTTP headers.
  1096. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1097. * request is handled.
  1098. */
  1099. /**
  1100. * @ngdoc method
  1101. * @name ngMock.$httpBackend#whenDELETE
  1102. * @methodOf ngMock.$httpBackend
  1103. * @description
  1104. * Creates a new backend definition for DELETE requests. For more info see `when()`.
  1105. *
  1106. * @param {string|RegExp} url HTTP url.
  1107. * @param {(Object|function(Object))=} headers HTTP headers.
  1108. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1109. * request is handled.
  1110. */
  1111. /**
  1112. * @ngdoc method
  1113. * @name ngMock.$httpBackend#whenPOST
  1114. * @methodOf ngMock.$httpBackend
  1115. * @description
  1116. * Creates a new backend definition for POST requests. For more info see `when()`.
  1117. *
  1118. * @param {string|RegExp} url HTTP url.
  1119. * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
  1120. * data string and returns true if the data is as expected.
  1121. * @param {(Object|function(Object))=} headers HTTP headers.
  1122. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1123. * request is handled.
  1124. */
  1125. /**
  1126. * @ngdoc method
  1127. * @name ngMock.$httpBackend#whenPUT
  1128. * @methodOf ngMock.$httpBackend
  1129. * @description
  1130. * Creates a new backend definition for PUT requests. For more info see `when()`.
  1131. *
  1132. * @param {string|RegExp} url HTTP url.
  1133. * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
  1134. * data string and returns true if the data is as expected.
  1135. * @param {(Object|function(Object))=} headers HTTP headers.
  1136. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1137. * request is handled.
  1138. */
  1139. /**
  1140. * @ngdoc method
  1141. * @name ngMock.$httpBackend#whenJSONP
  1142. * @methodOf ngMock.$httpBackend
  1143. * @description
  1144. * Creates a new backend definition for JSONP requests. For more info see `when()`.
  1145. *
  1146. * @param {string|RegExp} url HTTP url.
  1147. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1148. * request is handled.
  1149. */
  1150. createShortMethods('when');
  1151. /**
  1152. * @ngdoc method
  1153. * @name ngMock.$httpBackend#expect
  1154. * @methodOf ngMock.$httpBackend
  1155. * @description
  1156. * Creates a new request expectation.
  1157. *
  1158. * @param {string} method HTTP method.
  1159. * @param {string|RegExp} url HTTP url.
  1160. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
  1161. * receives data string and returns true if the data is as expected, or Object if request body
  1162. * is in JSON format.
  1163. * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
  1164. * object and returns true if the headers match the current expectation.
  1165. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1166. * request is handled.
  1167. *
  1168. * - respond –
  1169. * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
  1170. * – The respond method takes a set of static data to be returned or a function that can return
  1171. * an array containing response status (number), response data (string) and response headers
  1172. * (Object).
  1173. */
  1174. $httpBackend.expect = function(method, url, data, headers) {
  1175. var expectation = new MockHttpExpectation(method, url, data, headers);
  1176. expectations.push(expectation);
  1177. return {
  1178. respond: function(status, data, headers) {
  1179. expectation.response = createResponse(status, data, headers);
  1180. }
  1181. };
  1182. };
  1183. /**
  1184. * @ngdoc method
  1185. * @name ngMock.$httpBackend#expectGET
  1186. * @methodOf ngMock.$httpBackend
  1187. * @description
  1188. * Creates a new request expectation for GET requests. For more info see `expect()`.
  1189. *
  1190. * @param {string|RegExp} url HTTP url.
  1191. * @param {Object=} headers HTTP headers.
  1192. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1193. * request is handled. See #expect for more info.
  1194. */
  1195. /**
  1196. * @ngdoc method
  1197. * @name ngMock.$httpBackend#expectHEAD
  1198. * @methodOf ngMock.$httpBackend
  1199. * @description
  1200. * Creates a new request expectation for HEAD requests. For more info see `expect()`.
  1201. *
  1202. * @param {string|RegExp} url HTTP url.
  1203. * @param {Object=} headers HTTP headers.
  1204. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1205. * request is handled.
  1206. */
  1207. /**
  1208. * @ngdoc method
  1209. * @name ngMock.$httpBackend#expectDELETE
  1210. * @methodOf ngMock.$httpBackend
  1211. * @description
  1212. * Creates a new request expectation for DELETE requests. For more info see `expect()`.
  1213. *
  1214. * @param {string|RegExp} url HTTP url.
  1215. * @param {Object=} headers HTTP headers.
  1216. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1217. * request is handled.
  1218. */
  1219. /**
  1220. * @ngdoc method
  1221. * @name ngMock.$httpBackend#expectPOST
  1222. * @methodOf ngMock.$httpBackend
  1223. * @description
  1224. * Creates a new request expectation for POST requests. For more info see `expect()`.
  1225. *
  1226. * @param {string|RegExp} url HTTP url.
  1227. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
  1228. * receives data string and returns true if the data is as expected, or Object if request body
  1229. * is in JSON format.
  1230. * @param {Object=} headers HTTP headers.
  1231. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1232. * request is handled.
  1233. */
  1234. /**
  1235. * @ngdoc method
  1236. * @name ngMock.$httpBackend#expectPUT
  1237. * @methodOf ngMock.$httpBackend
  1238. * @description
  1239. * Creates a new request expectation for PUT requests. For more info see `expect()`.
  1240. *
  1241. * @param {string|RegExp} url HTTP url.
  1242. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
  1243. * receives data string and returns true if the data is as expected, or Object if request body
  1244. * is in JSON format.
  1245. * @param {Object=} headers HTTP headers.
  1246. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1247. * request is handled.
  1248. */
  1249. /**
  1250. * @ngdoc method
  1251. * @name ngMock.$httpBackend#expectPATCH
  1252. * @methodOf ngMock.$httpBackend
  1253. * @description
  1254. * Creates a new request expectation for PATCH requests. For more info see `expect()`.
  1255. *
  1256. * @param {string|RegExp} url HTTP url.
  1257. * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
  1258. * receives data string and returns true if the data is as expected, or Object if request body
  1259. * is in JSON format.
  1260. * @param {Object=} headers HTTP headers.
  1261. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1262. * request is handled.
  1263. */
  1264. /**
  1265. * @ngdoc method
  1266. * @name ngMock.$httpBackend#expectJSONP
  1267. * @methodOf ngMock.$httpBackend
  1268. * @description
  1269. * Creates a new request expectation for JSONP requests. For more info see `expect()`.
  1270. *
  1271. * @param {string|RegExp} url HTTP url.
  1272. * @returns {requestHandler} Returns an object with `respond` method that control how a matched
  1273. * request is handled.
  1274. */
  1275. createShortMethods('expect');
  1276. /**
  1277. * @ngdoc method
  1278. * @name ngMock.$httpBackend#flush
  1279. * @methodOf ngMock.$httpBackend
  1280. * @description
  1281. * Flushes all pending requests using the trained responses.
  1282. *
  1283. * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
  1284. * all pending requests will be flushed. If there are no pending requests when the flush method
  1285. * is called an exception is thrown (as this typically a sign of programming error).
  1286. */
  1287. $httpBackend.flush = function(count) {
  1288. $rootScope.$digest();
  1289. if (!responses.length) throw new Error('No pending request to flush !');
  1290. if (angular.isDefined(count)) {
  1291. while (count--) {
  1292. if (!responses.length) throw new Error('No more pending request to flush !');
  1293. responses.shift()();
  1294. }
  1295. } else {
  1296. while (responses.length) {
  1297. responses.shift()();
  1298. }
  1299. }
  1300. $httpBackend.verifyNoOutstandingExpectation();
  1301. };
  1302. /**
  1303. * @ngdoc method
  1304. * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
  1305. * @methodOf ngMock.$httpBackend
  1306. * @description
  1307. * Verifies that all of the requests defined via the `expect` api were made. If any of the
  1308. * requests were not made, verifyNoOutstandingExpectation throws an exception.
  1309. *
  1310. * Typically, you would call this method following each test case that asserts requests using an
  1311. * "afterEach" clause.
  1312. *
  1313. * <pre>
  1314. * afterEach($httpBackend.verifyNoOutstandingExpectation);
  1315. * </pre>
  1316. */
  1317. $httpBackend.verifyNoOutstandingExpectation = function() {
  1318. $rootScope.$digest();
  1319. if (expectations.length) {
  1320. throw new Error('Unsatisfied requests: ' + expectations.join(', '));
  1321. }
  1322. };
  1323. /**
  1324. * @ngdoc method
  1325. * @name ngMock.$httpBackend#verifyNoOutstandingRequest
  1326. * @methodOf ngMock.$httpBackend
  1327. * @description
  1328. * Verifies that there are no outstanding requests that need to be flushed.
  1329. *
  1330. * Typically, you would call this method following each test case that asserts requests using an
  1331. * "afterEach" clause.
  1332. *
  1333. * <pre>
  1334. * afterEach($httpBackend.verifyNoOutstandingRequest);
  1335. * </pre>
  1336. */
  1337. $httpBackend.verifyNoOutstandingRequest = function() {
  1338. if (responses.length) {
  1339. throw new Error('Unflushed requests: ' + responses.length);
  1340. }
  1341. };
  1342. /**
  1343. * @ngdoc method
  1344. * @name ngMock.$httpBackend#resetExpectations
  1345. * @methodOf ngMock.$httpBackend
  1346. * @description
  1347. * Resets all request expectations, but preserves all backend definitions. Typically, you would
  1348. * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
  1349. * $httpBackend mock.
  1350. */
  1351. $httpBackend.resetExpectations = function() {
  1352. expectations.length = 0;
  1353. responses.length = 0;
  1354. };
  1355. return $httpBackend;
  1356. function createShortMethods(prefix) {
  1357. angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
  1358. $httpBackend[prefix + method] = function(url, headers) {
  1359. return $httpBackend[prefix](method, url, undefined, headers);
  1360. };
  1361. });
  1362. angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
  1363. $httpBackend[prefix + method] = function(url, data, headers) {
  1364. return $httpBackend[prefix](method, url, data, headers);
  1365. };
  1366. });
  1367. }
  1368. }
  1369. function MockHttpExpectation(method, url, data, headers) {
  1370. this.data = data;
  1371. this.headers = headers;
  1372. this.match = function(m, u, d, h) {
  1373. if (method != m) return false;
  1374. if (!this.matchUrl(u)) return false;
  1375. if (angular.isDefined(d) && !this.matchData(d)) return false;
  1376. if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
  1377. return true;
  1378. };
  1379. this.matchUrl = function(u) {
  1380. if (!url) return true;
  1381. if (angular.isFunction(url.test)) return url.test(u);
  1382. return url == u;
  1383. };
  1384. this.matchHeaders = function(h) {
  1385. if (angular.isUndefined(headers)) return true;
  1386. if (angular.isFunction(headers)) return headers(h);
  1387. return angular.equals(headers, h);
  1388. };
  1389. this.matchData = function(d) {
  1390. if (angular.isUndefined(data)) return true;
  1391. if (data && angular.isFunction(data.test)) return data.test(d);
  1392. if (data && angular.isFunction(data)) return data(d);
  1393. if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d));
  1394. return data == d;
  1395. };
  1396. this.toString = function() {
  1397. return method + ' ' + url;
  1398. };
  1399. }
  1400. function createMockXhr() {
  1401. return new MockXhr();
  1402. }
  1403. function MockXhr() {
  1404. // hack for testing $http, $httpBackend
  1405. MockXhr.$$lastInstance = this;
  1406. this.open = function(method, url, async) {
  1407. this.$$method = method;
  1408. this.$$url = url;
  1409. this.$$async = async;
  1410. this.$$reqHeaders = {};
  1411. this.$$respHeaders = {};
  1412. };
  1413. this.send = function(data) {
  1414. this.$$data = data;
  1415. };
  1416. this.setRequestHeader = function(key, value) {
  1417. this.$$reqHeaders[key] = value;
  1418. };
  1419. this.getResponseHeader = function(name) {
  1420. // the lookup must be case insensitive,
  1421. // that's why we try two quick lookups first and full scan last
  1422. var header = this.$$respHeaders[name];
  1423. if (header) return header;
  1424. name = angular.lowercase(name);
  1425. header = this.$$respHeaders[name];
  1426. if (header) return header;
  1427. header = undefined;
  1428. angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
  1429. if (!header && angular.lowercase(headerName) == name) header = headerVal;
  1430. });
  1431. return header;
  1432. };
  1433. this.getAllResponseHeaders = function() {
  1434. var lines = [];
  1435. angular.forEach(this.$$respHeaders, function(value, key) {
  1436. lines.push(key + ': ' + value);
  1437. });
  1438. return lines.join('\n');
  1439. };
  1440. this.abort = angular.noop;
  1441. }
  1442. /**
  1443. * @ngdoc function
  1444. * @name ngMock.$timeout
  1445. * @description
  1446. *
  1447. * This service is just a simple decorator for {@link ng.$timeout $timeout} service
  1448. * that adds a "flush" and "verifyNoPendingTasks" methods.
  1449. */
  1450. angular.mock.$TimeoutDecorator = function($delegate, $browser) {
  1451. /**
  1452. * @ngdoc method
  1453. * @name ngMock.$timeout#flush
  1454. * @methodOf ngMock.$timeout
  1455. * @description
  1456. *
  1457. * Flushes the queue of pending tasks.
  1458. *
  1459. * @param {number=} delay maximum timeout amount to flush up until
  1460. */
  1461. $delegate.flush = function(delay) {
  1462. $browser.defer.flush(delay);
  1463. };
  1464. /**
  1465. * @ngdoc method
  1466. * @name ngMock.$timeout#verifyNoPendingTasks
  1467. * @methodOf ngMock.$timeout
  1468. * @description
  1469. *
  1470. * Verifies that there are no pending tasks that need to be flushed.
  1471. */
  1472. $delegate.verifyNoPendingTasks = function() {
  1473. if ($browser.deferredFns.length) {
  1474. throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
  1475. formatPendingTasksAsString($browser.deferredFns));
  1476. }
  1477. };
  1478. function formatPendingTasksAsString(tasks) {
  1479. var result = [];
  1480. angular.forEach(tasks, function(task) {
  1481. result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
  1482. });
  1483. return result.join(', ');
  1484. }
  1485. return $delegate;
  1486. };
  1487. /**
  1488. *
  1489. */
  1490. angular.mock.$RootElementProvider = function() {
  1491. this.$get = function() {
  1492. return angular.element('<div ng-app></div>');
  1493. };
  1494. };
  1495. /**
  1496. * @ngdoc overview
  1497. * @name ngMock
  1498. * @description
  1499. *
  1500. * # ngMock
  1501. *
  1502. * The `ngMock` module providers support to inject and mock Angular services into unit tests.
  1503. * In addition, ngMock also extends various core ng services such that they can be
  1504. * inspected and controlled in a synchronous manner within test code.
  1505. *
  1506. * {@installModule mock}
  1507. *
  1508. * <div doc-module-components="ngMock"></div>
  1509. *
  1510. */
  1511. angular.module('ngMock', ['ng']).provider({
  1512. $browser: angular.mock.$BrowserProvider,
  1513. $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
  1514. $log: angular.mock.$LogProvider,
  1515. $interval: angular.mock.$IntervalProvider,
  1516. $httpBackend: angular.mock.$HttpBackendProvider,
  1517. $rootElement: angular.mock.$RootElementProvider
  1518. }).config(['$provide', function($provide) {
  1519. $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
  1520. }]);
  1521. /**
  1522. * @ngdoc overview
  1523. * @name ngMockE2E
  1524. * @description
  1525. *
  1526. * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
  1527. * Currently there is only one mock present in this module -
  1528. * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
  1529. */
  1530. angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
  1531. $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
  1532. }]);
  1533. /**
  1534. * @ngdoc object
  1535. * @name ngMockE2E.$httpBackend
  1536. * @description
  1537. * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
  1538. * applications that use the {@link ng.$http $http service}.
  1539. *
  1540. * *Note*: For fake http backend implementation suitable for unit testing please see
  1541. * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
  1542. *
  1543. * This implementation can be used to respond with static or dynamic responses via the `when` api
  1544. * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
  1545. * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
  1546. * templates from a webserver).
  1547. *
  1548. * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
  1549. * is being developed with the real backend api replaced with a mock, it is often desirable for
  1550. * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
  1551. * templates or static files from the webserver). To configure the backend with this behavior
  1552. * use the `passThrough` request handler of `when` instead of `respond`.
  1553. *
  1554. * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
  1555. * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
  1556. * automatically, closely simulating the behavior of the XMLHttpRequest object.
  1557. *
  1558. * To setup the application to run with this http backend, you have to create a module that depends
  1559. * on the `ngMockE2E` and your application modules and defines the fake backend:
  1560. *
  1561. * <pre>
  1562. * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
  1563. * myAppDev.run(function($httpBackend) {
  1564. * phones = [{name: 'phone1'}, {name: 'phone2'}];
  1565. *
  1566. * // returns the current list of phones
  1567. * $httpBackend.whenGET('/phones').respond(phones);
  1568. *
  1569. * // adds a new phone to the phones array
  1570. * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
  1571. * phones.push(angular.fromJson(data));
  1572. * });
  1573. * $httpBackend.whenGET(/^\/templates\//).passThrough();
  1574. * //...
  1575. * });
  1576. * </pre>
  1577. *
  1578. * Afterwards, bootstrap your app with this new module.
  1579. */
  1580. /**
  1581. * @ngdoc method
  1582. * @name ngMockE2E.$httpBackend#when
  1583. * @methodOf ngMockE2E.$httpBackend
  1584. * @description
  1585. * Creates a new backend definition.
  1586. *
  1587. * @param {string} method HTTP method.
  1588. * @param {string|RegExp} url HTTP url.
  1589. * @param {(string|RegExp)=} data HTTP request body.
  1590. * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
  1591. * object and returns true if the headers match the current definition.
  1592. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1593. * control how a matched request is handled.
  1594. *
  1595. * - respond –
  1596. * `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
  1597. * – The respond method takes a set of static data to be returned or a function that can return
  1598. * an array containing response status (number), response data (string) and response headers
  1599. * (Object).
  1600. * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
  1601. * handler, will be pass through to the real backend (an XHR request will be made to the
  1602. * server.
  1603. */
  1604. /**
  1605. * @ngdoc method
  1606. * @name ngMockE2E.$httpBackend#whenGET
  1607. * @methodOf ngMockE2E.$httpBackend
  1608. * @description
  1609. * Creates a new backend definition for GET requests. For more info see `when()`.
  1610. *
  1611. * @param {string|RegExp} url HTTP url.
  1612. * @param {(Object|function(Object))=} headers HTTP headers.
  1613. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1614. * control how a matched request is handled.
  1615. */
  1616. /**
  1617. * @ngdoc method
  1618. * @name ngMockE2E.$httpBackend#whenHEAD
  1619. * @methodOf ngMockE2E.$httpBackend
  1620. * @description
  1621. * Creates a new backend definition for HEAD requests. For more info see `when()`.
  1622. *
  1623. * @param {string|RegExp} url HTTP url.
  1624. * @param {(Object|function(Object))=} headers HTTP headers.
  1625. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1626. * control how a matched request is handled.
  1627. */
  1628. /**
  1629. * @ngdoc method
  1630. * @name ngMockE2E.$httpBackend#whenDELETE
  1631. * @methodOf ngMockE2E.$httpBackend
  1632. * @description
  1633. * Creates a new backend definition for DELETE requests. For more info see `when()`.
  1634. *
  1635. * @param {string|RegExp} url HTTP url.
  1636. * @param {(Object|function(Object))=} headers HTTP headers.
  1637. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1638. * control how a matched request is handled.
  1639. */
  1640. /**
  1641. * @ngdoc method
  1642. * @name ngMockE2E.$httpBackend#whenPOST
  1643. * @methodOf ngMockE2E.$httpBackend
  1644. * @description
  1645. * Creates a new backend definition for POST requests. For more info see `when()`.
  1646. *
  1647. * @param {string|RegExp} url HTTP url.
  1648. * @param {(string|RegExp)=} data HTTP request body.
  1649. * @param {(Object|function(Object))=} headers HTTP headers.
  1650. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1651. * control how a matched request is handled.
  1652. */
  1653. /**
  1654. * @ngdoc method
  1655. * @name ngMockE2E.$httpBackend#whenPUT
  1656. * @methodOf ngMockE2E.$httpBackend
  1657. * @description
  1658. * Creates a new backend definition for PUT requests. For more info see `when()`.
  1659. *
  1660. * @param {string|RegExp} url HTTP url.
  1661. * @param {(string|RegExp)=} data HTTP request body.
  1662. * @param {(Object|function(Object))=} headers HTTP headers.
  1663. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1664. * control how a matched request is handled.
  1665. */
  1666. /**
  1667. * @ngdoc method
  1668. * @name ngMockE2E.$httpBackend#whenPATCH
  1669. * @methodOf ngMockE2E.$httpBackend
  1670. * @description
  1671. * Creates a new backend definition for PATCH requests. For more info see `when()`.
  1672. *
  1673. * @param {string|RegExp} url HTTP url.
  1674. * @param {(string|RegExp)=} data HTTP request body.
  1675. * @param {(Object|function(Object))=} headers HTTP headers.
  1676. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1677. * control how a matched request is handled.
  1678. */
  1679. /**
  1680. * @ngdoc method
  1681. * @name ngMockE2E.$httpBackend#whenJSONP
  1682. * @methodOf ngMockE2E.$httpBackend
  1683. * @description
  1684. * Creates a new backend definition for JSONP requests. For more info see `when()`.
  1685. *
  1686. * @param {string|RegExp} url HTTP url.
  1687. * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
  1688. * control how a matched request is handled.
  1689. */
  1690. angular.mock.e2e = {};
  1691. angular.mock.e2e.$httpBackendDecorator =
  1692. ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
  1693. angular.mock.clearDataCache = function() {
  1694. var key,
  1695. cache = angular.element.cache;
  1696. for(key in cache) {
  1697. if (Object.prototype.hasOwnProperty.call(cache,key)) {
  1698. var handle = cache[key].handle;
  1699. handle && angular.element(handle.elem).off();
  1700. delete cache[key];
  1701. }
  1702. }
  1703. };
  1704. if(window.jasmine || window.mocha) {
  1705. var currentSpec = null,
  1706. isSpecRunning = function() {
  1707. return !!currentSpec;
  1708. };
  1709. beforeEach(function() {
  1710. currentSpec = this;
  1711. });
  1712. afterEach(function() {
  1713. var injector = currentSpec.$injector;
  1714. currentSpec.$injector = null;
  1715. currentSpec.$modules = null;
  1716. currentSpec = null;
  1717. if (injector) {
  1718. injector.get('$rootElement').off();
  1719. injector.get('$browser').pollFns.length = 0;
  1720. }
  1721. angular.mock.clearDataCache();
  1722. // clean up jquery's fragment cache
  1723. angular.forEach(angular.element.fragments, function(val, key) {
  1724. delete angular.element.fragments[key];
  1725. });
  1726. MockXhr.$$lastInstance = null;
  1727. angular.forEach(angular.callbacks, function(val, key) {
  1728. delete angular.callbacks[key];
  1729. });
  1730. angular.callbacks.counter = 0;
  1731. });
  1732. /**
  1733. * @ngdoc function
  1734. * @name angular.mock.module
  1735. * @description
  1736. *
  1737. * *NOTE*: This function is also published on window for easy access.<br>
  1738. *
  1739. * This function registers a module configuration code. It collects the configuration information
  1740. * which will be used when the injector is created by {@link angular.mock.inject inject}.
  1741. *
  1742. * See {@link angular.mock.inject inject} for usage example
  1743. *
  1744. * @param {...(string|Function|Object)} fns any number of modules which are represented as string
  1745. * aliases or as anonymous module initialization functions. The modules are used to
  1746. * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
  1747. * object literal is passed they will be register as values in the module, the key being
  1748. * the module name and the value being what is returned.
  1749. */
  1750. window.module = angular.mock.module = function() {
  1751. var moduleFns = Array.prototype.slice.call(arguments, 0);
  1752. return isSpecRunning() ? workFn() : workFn;
  1753. /////////////////////
  1754. function workFn() {
  1755. if (currentSpec.$injector) {
  1756. throw new Error('Injector already created, can not register a module!');
  1757. } else {
  1758. var modules = currentSpec.$modules || (currentSpec.$modules = []);
  1759. angular.forEach(moduleFns, function(module) {
  1760. if (angular.isObject(module) && !angular.isArray(module)) {
  1761. modules.push(function($provide) {
  1762. angular.forEach(module, function(value, key) {
  1763. $provide.value(key, value);
  1764. });
  1765. });
  1766. } else {
  1767. modules.push(module);
  1768. }
  1769. });
  1770. }
  1771. }
  1772. };
  1773. /**
  1774. * @ngdoc function
  1775. * @name angular.mock.inject
  1776. * @description
  1777. *
  1778. * *NOTE*: This function is also published on window for easy access.<br>
  1779. *
  1780. * The inject function wraps a function into an injectable function. The inject() creates new
  1781. * instance of {@link AUTO.$injector $injector} per test, which is then used for
  1782. * resolving references.
  1783. *
  1784. *
  1785. * ## Resolving References (Underscore Wrapping)
  1786. * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
  1787. * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
  1788. * that is declared in the scope of the `describe()` block. Since we would, most likely, want
  1789. * the variable to have the same name of the reference we have a problem, since the parameter
  1790. * to the `inject()` function would hide the outer variable.
  1791. *
  1792. * To help with this, the injected parameters can, optionally, be enclosed with underscores.
  1793. * These are ignored by the injector when the reference name is resolved.
  1794. *
  1795. * For example, the parameter `_myService_` would be resolved as the reference `myService`.
  1796. * Since it is available in the function body as _myService_, we can then assign it to a variable
  1797. * defined in an outer scope.
  1798. *
  1799. * ```
  1800. * // Defined out reference variable outside
  1801. * var myService;
  1802. *
  1803. * // Wrap the parameter in underscores
  1804. * beforeEach( inject( function(_myService_){
  1805. * myService = _myService_;
  1806. * }));
  1807. *
  1808. * // Use myService in a series of tests.
  1809. * it('makes use of myService', function() {
  1810. * myService.doStuff();
  1811. * });
  1812. *
  1813. * ```
  1814. *
  1815. * See also {@link angular.mock.module angular.mock.module}
  1816. *
  1817. * ## Example
  1818. * Example of what a typical jasmine tests looks like with the inject method.
  1819. * <pre>
  1820. *
  1821. * angular.module('myApplicationModule', [])
  1822. * .value('mode', 'app')
  1823. * .value('version', 'v1.0.1');
  1824. *
  1825. *
  1826. * describe('MyApp', function() {
  1827. *
  1828. * // You need to load modules that you want to test,
  1829. * // it loads only the "ng" module by default.
  1830. * beforeEach(module('myApplicationModule'));
  1831. *
  1832. *
  1833. * // inject() is used to inject arguments of all given functions
  1834. * it('should provide a version', inject(function(mode, version) {
  1835. * expect(version).toEqual('v1.0.1');
  1836. * expect(mode).toEqual('app');
  1837. * }));
  1838. *
  1839. *
  1840. * // The inject and module method can also be used inside of the it or beforeEach
  1841. * it('should override a version and test the new version is injected', function() {
  1842. * // module() takes functions or strings (module aliases)
  1843. * module(function($provide) {
  1844. * $provide.value('version', 'overridden'); // override version here
  1845. * });
  1846. *
  1847. * inject(function(version) {
  1848. * expect(version).toEqual('overridden');
  1849. * });
  1850. * });
  1851. * });
  1852. *
  1853. * </pre>
  1854. *
  1855. * @param {...Function} fns any number of functions which will be injected using the injector.
  1856. */
  1857. var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {
  1858. this.message = e.message;
  1859. this.name = e.name;
  1860. if (e.line) this.line = e.line;
  1861. if (e.sourceId) this.sourceId = e.sourceId;
  1862. if (e.stack && errorForStack)
  1863. this.stack = e.stack + '\n' + errorForStack.stack;
  1864. if (e.stackArray) this.stackArray = e.stackArray;
  1865. };
  1866. ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;
  1867. window.inject = angular.mock.inject = function() {
  1868. var blockFns = Array.prototype.slice.call(arguments, 0);
  1869. var errorForStack = new Error('Declaration Location');
  1870. return isSpecRunning() ? workFn.call(currentSpec) : workFn;
  1871. /////////////////////
  1872. function workFn() {
  1873. var modules = currentSpec.$modules || [];
  1874. modules.unshift('ngMock');
  1875. modules.unshift('ng');
  1876. var injector = currentSpec.$injector;
  1877. if (!injector) {
  1878. injector = currentSpec.$injector = angular.injector(modules);
  1879. }
  1880. for(var i = 0, ii = blockFns.length; i < ii; i++) {
  1881. try {
  1882. /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
  1883. injector.invoke(blockFns[i] || angular.noop, this);
  1884. /* jshint +W040 */
  1885. } catch (e) {
  1886. if (e.stack && errorForStack) {
  1887. throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
  1888. }
  1889. throw e;
  1890. } finally {
  1891. errorForStack = null;
  1892. }
  1893. }
  1894. }
  1895. };
  1896. }
  1897. })(window, window.angular);