15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/example_3/example_3.js:
--------------------------------------------------------------------------------
1 |
2 | angular.module('User', ['firebaseResource']).
3 | factory('User', function ($rootScope, firebaseResource) {
4 | var User = firebaseResource(
5 | {
6 | path: 'users',
7 | hasMany: ['Post']
8 | }
9 | );
10 | return User;
11 | });
12 |
13 | angular.module('Post', ['firebaseResource']).
14 | factory('Post', function ($rootScope, firebaseResource) {
15 | var Post = firebaseResource(
16 | {
17 | path: 'posts',
18 | belongsTo: true,
19 | perPage: 3
20 | }
21 | );
22 | return Post;
23 | });
24 |
25 |
26 | angular.module('MainCtrl', ['User', 'Post']).
27 | controller('MainCtrl', function($rootScope, $scope, User, Post) {
28 |
29 | $scope.user = new User({name: 'Test User'});
30 | $scope.user.save()
31 | $scope.current_page = 0;
32 |
33 | /*
34 | * Pagination is a way to limit the number of objects coming back
35 | * from Firebase for a given query. It is not intended to only show
36 | * a certain number of objects in a given view; that will still need
37 | * to be handled separatley. So whenever a new page is requested via
38 | * the query() method, those objects are added to the full list of
39 | * objects. For now, pagination is in reverse order, so the most
40 | * recently created objects come back with page 1.
41 | */
42 |
43 | for (var i=0;i<10;i++) {
44 | var post = $scope.user.posts().new({content: 'test post ' + i});
45 | post.save().then(function() {
46 | Post.clearAll(); // clearing all cached objects so that pagination works for this demo
47 | });
48 | }
49 |
50 | $scope.nextPage = function() {
51 | $scope.current_page++;
52 | $scope.user.posts().query({page: $scope.current_page});
53 | }
54 |
55 |
56 | })
57 |
58 |
--------------------------------------------------------------------------------
/examples/example_3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
374 | * $log.log('Some Error');
375 | * var first = $log.error.logs.unshift();
376 | *
377 | */
378 | $log.error.logs = [];
379 | };
380 |
381 | /**
382 | * @ngdoc method
383 | * @name ngMock.$log#assertEmpty
384 | * @methodOf ngMock.$log
385 | *
386 | * @description
387 | * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
388 | */
389 | $log.assertEmpty = function() {
390 | var errors = [];
391 | angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
392 | angular.forEach($log[logLevel].logs, function(log) {
393 | angular.forEach(log, function (logItem) {
394 | errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
395 | });
396 | });
397 | });
398 | 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:");
401 | errors.push('');
402 | throw new Error(errors.join('\n---------\n'));
403 | }
404 | };
405 |
406 | $log.reset();
407 | return $log;
408 | };
409 | };
410 |
411 |
412 | (function() {
413 | 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 |
415 | function jsonStringToDate(string){
416 | var match;
417 | if (match = string.match(R_ISO8061_STR)) {
418 | var date = new Date(0),
419 | tzHour = 0,
420 | tzMin = 0;
421 | if (match[9]) {
422 | tzHour = int(match[9] + match[10]);
423 | tzMin = int(match[9] + match[11]);
424 | }
425 | 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));
427 | return date;
428 | }
429 | return string;
430 | }
431 |
432 | function int(str) {
433 | return parseInt(str, 10);
434 | }
435 |
436 | function padNumber(num, digits, trim) {
437 | var neg = '';
438 | if (num < 0) {
439 | neg = '-';
440 | num = -num;
441 | }
442 | num = '' + num;
443 | while(num.length < digits) num = '0' + num;
444 | if (trim)
445 | num = num.substr(num.length - digits);
446 | return neg + num;
447 | }
448 |
449 |
450 | /**
451 | * @ngdoc object
452 | * @name angular.mock.TzDate
453 | * @description
454 | *
455 | * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
456 | *
457 | * Mock of the Date type which has its timezone specified via constructor arg.
458 | *
459 | * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
460 | * offset, so that we can test code that depends on local timezone settings without dependency on
461 | * the time zone settings of the machine where the code is running.
462 | *
463 | * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
464 | * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
465 | *
466 | * @example
467 | * !!!! WARNING !!!!!
468 | * This is not a complete Date object so only methods that were implemented can be called safely.
469 | * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
470 | *
471 | * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
472 | * incomplete we might be missing some non-standard methods. This can result in errors like:
473 | * "Date.prototype.foo called on incompatible Object".
474 | *
475 | *
484 | *
485 | */
486 | angular.mock.TzDate = function (offset, timestamp) {
487 | var self = new Date(0);
488 | if (angular.isString(timestamp)) {
489 | var tsStr = timestamp;
490 |
491 | self.origDate = jsonStringToDate(timestamp);
492 |
493 | timestamp = self.origDate.getTime();
494 | if (isNaN(timestamp))
495 | throw {
496 | name: "Illegal Argument",
497 | message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
498 | };
499 | } else {
500 | self.origDate = new Date(timestamp);
501 | }
502 |
503 | var localOffset = new Date(timestamp).getTimezoneOffset();
504 | self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
505 | self.date = new Date(timestamp + self.offsetDiff);
506 |
507 | self.getTime = function() {
508 | return self.date.getTime() - self.offsetDiff;
509 | };
510 |
511 | self.toLocaleDateString = function() {
512 | return self.date.toLocaleDateString();
513 | };
514 |
515 | self.getFullYear = function() {
516 | return self.date.getFullYear();
517 | };
518 |
519 | self.getMonth = function() {
520 | return self.date.getMonth();
521 | };
522 |
523 | self.getDate = function() {
524 | return self.date.getDate();
525 | };
526 |
527 | self.getHours = function() {
528 | return self.date.getHours();
529 | };
530 |
531 | self.getMinutes = function() {
532 | return self.date.getMinutes();
533 | };
534 |
535 | self.getSeconds = function() {
536 | return self.date.getSeconds();
537 | };
538 |
539 | self.getTimezoneOffset = function() {
540 | return offset * 60;
541 | };
542 |
543 | self.getUTCFullYear = function() {
544 | return self.origDate.getUTCFullYear();
545 | };
546 |
547 | self.getUTCMonth = function() {
548 | return self.origDate.getUTCMonth();
549 | };
550 |
551 | self.getUTCDate = function() {
552 | return self.origDate.getUTCDate();
553 | };
554 |
555 | self.getUTCHours = function() {
556 | return self.origDate.getUTCHours();
557 | };
558 |
559 | self.getUTCMinutes = function() {
560 | return self.origDate.getUTCMinutes();
561 | };
562 |
563 | self.getUTCSeconds = function() {
564 | return self.origDate.getUTCSeconds();
565 | };
566 |
567 | self.getUTCMilliseconds = function() {
568 | return self.origDate.getUTCMilliseconds();
569 | };
570 |
571 | self.getDay = function() {
572 | return self.date.getDay();
573 | };
574 |
575 | // provide this method only on browsers that already have it
576 | if (self.toISOString) {
577 | self.toISOString = function() {
578 | return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
579 | padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
580 | padNumber(self.origDate.getUTCDate(), 2) + 'T' +
581 | padNumber(self.origDate.getUTCHours(), 2) + ':' +
582 | padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
583 | padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
584 | padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
585 | }
586 | }
587 |
588 | //hide all methods not implemented in this mock that the Date prototype exposes
589 | var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
590 | 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
591 | 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
592 | 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
593 | 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
594 | 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
595 |
596 | angular.forEach(unimplementedMethods, function(methodName) {
597 | self[methodName] = function() {
598 | throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
599 | };
600 | });
601 |
602 | return self;
603 | };
604 |
605 | //make "tzDateInstance instanceof Date" return true
606 | angular.mock.TzDate.prototype = Date.prototype;
607 | })();
608 |
609 |
610 | /**
611 | * @ngdoc function
612 | * @name angular.mock.dump
613 | * @description
614 | *
615 | * *NOTE*: this is not an injectable instance, just a globally available function.
616 | *
617 | * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
618 | *
619 | * This method is also available on window, where it can be used to display objects on debug console.
620 | *
621 | * @param {*} object - any object to turn into string.
622 | * @return {string} a serialized string of the argument
623 | */
624 | angular.mock.dump = function(object) {
625 | return serialize(object);
626 |
627 | function serialize(object) {
628 | var out;
629 |
630 | if (angular.isElement(object)) {
631 | object = angular.element(object);
632 | out = angular.element('');
633 | angular.forEach(object, function(element) {
634 | out.append(angular.element(element).clone());
635 | });
636 | out = out.html();
637 | } else if (angular.isArray(object)) {
638 | out = [];
639 | angular.forEach(object, function(o) {
640 | out.push(serialize(o));
641 | });
642 | out = '[ ' + out.join(', ') + ' ]';
643 | } else if (angular.isObject(object)) {
644 | if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
645 | out = serializeScope(object);
646 | } else if (object instanceof Error) {
647 | out = object.stack || ('' + object.name + ': ' + object.message);
648 | } else {
649 | out = angular.toJson(object, true);
650 | }
651 | } else {
652 | out = String(object);
653 | }
654 |
655 | return out;
656 | }
657 |
658 | function serializeScope(scope, offset) {
659 | offset = offset || ' ';
660 | var log = [offset + 'Scope(' + scope.$id + '): {'];
661 | for ( var key in scope ) {
662 | if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
663 | log.push(' ' + key + ': ' + angular.toJson(scope[key]));
664 | }
665 | }
666 | var child = scope.$$childHead;
667 | while(child) {
668 | log.push(serializeScope(child, offset + ' '));
669 | child = child.$$nextSibling;
670 | }
671 | log.push('}');
672 | return log.join('\n' + offset);
673 | }
674 | };
675 |
676 | /**
677 | * @ngdoc object
678 | * @name ngMock.$httpBackend
679 | * @description
680 | * Fake HTTP backend implementation suitable for unit testing applications that use the
681 | * {@link ng.$http $http service}.
682 | *
683 | * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
684 | * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
685 | *
686 | * During unit testing, we want our unit tests to run quickly and have no external dependencies so
687 | * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
688 | * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
689 | * to verify whether a certain request has been sent or not, or alternatively just let the
690 | * application make requests, respond with pre-trained responses and assert that the end result is
691 | * what we expect it to be.
692 | *
693 | * This mock implementation can be used to respond with static or dynamic responses via the
694 | * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
695 | *
696 | * When an Angular application needs some data from a server, it calls the $http service, which
697 | * sends the request to a real server using $httpBackend service. With dependency injection, it is
698 | * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
699 | * the requests and respond with some testing data without sending a request to real server.
700 | *
701 | * There are two ways to specify what test data should be returned as http responses by the mock
702 | * backend when the code under test makes http requests:
703 | *
704 | * - `$httpBackend.expect` - specifies a request expectation
705 | * - `$httpBackend.when` - specifies a backend definition
706 | *
707 | *
708 | * # Request Expectations vs Backend Definitions
709 | *
710 | * Request expectations provide a way to make assertions about requests made by the application and
711 | * to define responses for those requests. The test will fail if the expected requests are not made
712 | * or they are made in the wrong order.
713 | *
714 | * Backend definitions allow you to define a fake backend for your application which doesn't assert
715 | * if a particular request was made or not, it just returns a trained response if a request is made.
716 | * The test will pass whether or not the request gets made during testing.
717 | *
718 | *
719 | *
720 | *
Request expectations
Backend definitions
721 | *
722 | *
Syntax
723 | *
.expect(...).respond(...)
724 | *
.when(...).respond(...)
725 | *
726 | *
727 | *
Typical usage
728 | *
strict unit tests
729 | *
loose (black-box) unit testing
730 | *
731 | *
732 | *
Fulfills multiple requests
733 | *
NO
734 | *
YES
735 | *
736 | *
737 | *
Order of requests matters
738 | *
YES
739 | *
NO
740 | *
741 | *
742 | *
Request required
743 | *
YES
744 | *
NO
745 | *
746 | *
747 | *
Response required
748 | *
optional (see below)
749 | *
YES
750 | *
751 | *
752 | *
753 | * In cases where both backend definitions and request expectations are specified during unit
754 | * testing, the request expectations are evaluated first.
755 | *
756 | * If a request expectation has no response specified, the algorithm will search your backend
757 | * definitions for an appropriate response.
758 | *
759 | * If a request didn't match any expectation or if the expectation doesn't have the response
760 | * defined, the backend definitions are evaluated in sequential order to see if any of them match
761 | * the request. The response from the first matched definition is returned.
762 | *
763 | *
764 | * # Flushing HTTP requests
765 | *
766 | * The $httpBackend used in production, always responds to requests with responses asynchronously.
767 | * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are
768 | * hard to write, follow and maintain. At the same time the testing mock, can't respond
769 | * synchronously because that would change the execution of the code under test. For this reason the
770 | * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
771 | * requests and thus preserving the async api of the backend, while allowing the test to execute
772 | * synchronously.
773 | *
774 | *
775 | * # Unit testing with mock $httpBackend
776 | *
777 | *
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 | }
793 |
794 | // testing controller
795 | var $httpBackend;
796 |
797 | beforeEach(inject(function($injector) {
798 | $httpBackend = $injector.get('$httpBackend');
799 |
800 | // backend definition common for all tests
801 | $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
802 | }));
803 |
804 |
805 | afterEach(function() {
806 | $httpBackend.verifyNoOutstandingExpectation();
807 | $httpBackend.verifyNoOutstandingRequest();
808 | });
809 |
810 |
811 | it('should fetch authentication token', function() {
812 | $httpBackend.expectGET('/auth.py');
813 | var controller = scope.$new(MyController);
814 | $httpBackend.flush();
815 | });
816 |
817 |
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 |
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 | });
832 |
833 |
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, '');
840 |
841 | var controller = scope.$new(MyController);
842 | controller.saveMessage('whatever');
843 | $httpBackend.flush();
844 | });
845 |
846 | */
847 | angular.mock.$HttpBackendProvider = function() {
848 | this.$get = [createHttpBackendMock];
849 | };
850 |
851 | /**
852 | * General factory function for $httpBackend mock.
853 | * Returns instance for unit testing (when no arguments specified):
854 | * - passing through is disabled
855 | * - auto flushing is disabled
856 | *
857 | * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
858 | * - passing through (delegating request to real backend) is enabled
859 | * - auto flushing is enabled
860 | *
861 | * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
862 | * @param {Object=} $browser Auto-flushing enabled if specified
863 | * @return {Object} Instance of $httpBackend mock
864 | */
865 | function createHttpBackendMock($delegate, $browser) {
866 | var definitions = [],
867 | expectations = [],
868 | responses = [],
869 | responsesPush = angular.bind(responses, responses.push);
870 |
871 | function createResponse(status, data, headers) {
872 | if (angular.isFunction(status)) return status;
873 |
874 | return function() {
875 | return angular.isNumber(status)
876 | ? [status, data, headers]
877 | : [200, status, data];
878 | };
879 | }
880 |
881 | // TODO(vojta): change params to: method, url, data, headers, callback
882 | function $httpBackend(method, url, data, callback, headers) {
883 | var xhr = new MockXhr(),
884 | expectation = expectations[0],
885 | wasExpected = false;
886 |
887 | function prettyPrint(data) {
888 | return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
889 | ? data
890 | : angular.toJson(data);
891 | }
892 |
893 | if (expectation && expectation.match(method, url)) {
894 | if (!expectation.matchData(data))
895 | throw Error('Expected ' + expectation + ' with different data\n' +
896 | 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
897 |
898 | if (!expectation.matchHeaders(headers))
899 | throw Error('Expected ' + expectation + ' with different headers\n' +
900 | 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
901 | prettyPrint(headers));
902 |
903 | expectations.shift();
904 |
905 | 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 | });
911 | return;
912 | }
913 | wasExpected = true;
914 | }
915 |
916 | var i = -1, definition;
917 | while ((definition = definitions[++i])) {
918 | if (definition.match(method, url, data, headers || {})) {
919 | if (definition.response) {
920 | // 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 | });
926 | } else if (definition.passThrough) {
927 | $delegate(method, url, data, callback, headers);
928 | } else throw Error('No response defined !');
929 | return;
930 | }
931 | }
932 | throw wasExpected ?
933 | Error('No response defined !') :
934 | Error('Unexpected request: ' + method + ' ' + url + '\n' +
935 | (expectation ? 'Expected ' + expectation : 'No more request expected'));
936 | }
937 |
938 | /**
939 | * @ngdoc method
940 | * @name ngMock.$httpBackend#when
941 | * @methodOf ngMock.$httpBackend
942 | * @description
943 | * Creates a new backend definition.
944 | *
945 | * @param {string} method HTTP method.
946 | * @param {string|RegExp} url HTTP url.
947 | * @param {(string|RegExp)=} data HTTP request body.
948 | * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
949 | * 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
951 | * request is handled.
952 | *
953 | * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
954 | * – The respond method takes a set of static data to be returned or a function that can return
955 | * an array containing response status (number), response data (string) and response headers
956 | * (Object).
957 | */
958 | $httpBackend.when = function(method, url, data, headers) {
959 | var definition = new MockHttpExpectation(method, url, data, headers),
960 | chain = {
961 | respond: function(status, data, headers) {
962 | definition.response = createResponse(status, data, headers);
963 | }
964 | };
965 |
966 | if ($browser) {
967 | chain.passThrough = function() {
968 | definition.passThrough = true;
969 | };
970 | }
971 |
972 | definitions.push(definition);
973 | return chain;
974 | };
975 |
976 | /**
977 | * @ngdoc method
978 | * @name ngMock.$httpBackend#whenGET
979 | * @methodOf ngMock.$httpBackend
980 | * @description
981 | * Creates a new backend definition for GET requests. For more info see `when()`.
982 | *
983 | * @param {string|RegExp} url HTTP url.
984 | * @param {(Object|function(Object))=} headers HTTP headers.
985 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
986 | * request is handled.
987 | */
988 |
989 | /**
990 | * @ngdoc method
991 | * @name ngMock.$httpBackend#whenHEAD
992 | * @methodOf ngMock.$httpBackend
993 | * @description
994 | * Creates a new backend definition for HEAD requests. For more info see `when()`.
995 | *
996 | * @param {string|RegExp} url HTTP url.
997 | * @param {(Object|function(Object))=} headers HTTP headers.
998 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
999 | * request is handled.
1000 | */
1001 |
1002 | /**
1003 | * @ngdoc method
1004 | * @name ngMock.$httpBackend#whenDELETE
1005 | * @methodOf ngMock.$httpBackend
1006 | * @description
1007 | * Creates a new backend definition for DELETE requests. For more info see `when()`.
1008 | *
1009 | * @param {string|RegExp} url HTTP url.
1010 | * @param {(Object|function(Object))=} headers HTTP headers.
1011 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1012 | * request is handled.
1013 | */
1014 |
1015 | /**
1016 | * @ngdoc method
1017 | * @name ngMock.$httpBackend#whenPOST
1018 | * @methodOf ngMock.$httpBackend
1019 | * @description
1020 | * Creates a new backend definition for POST requests. For more info see `when()`.
1021 | *
1022 | * @param {string|RegExp} url HTTP url.
1023 | * @param {(string|RegExp)=} data HTTP request body.
1024 | * @param {(Object|function(Object))=} headers HTTP headers.
1025 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1026 | * request is handled.
1027 | */
1028 |
1029 | /**
1030 | * @ngdoc method
1031 | * @name ngMock.$httpBackend#whenPUT
1032 | * @methodOf ngMock.$httpBackend
1033 | * @description
1034 | * Creates a new backend definition for PUT requests. For more info see `when()`.
1035 | *
1036 | * @param {string|RegExp} url HTTP url.
1037 | * @param {(string|RegExp)=} data HTTP request body.
1038 | * @param {(Object|function(Object))=} headers HTTP headers.
1039 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1040 | * request is handled.
1041 | */
1042 |
1043 | /**
1044 | * @ngdoc method
1045 | * @name ngMock.$httpBackend#whenJSONP
1046 | * @methodOf ngMock.$httpBackend
1047 | * @description
1048 | * Creates a new backend definition for JSONP requests. For more info see `when()`.
1049 | *
1050 | * @param {string|RegExp} url HTTP url.
1051 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1052 | * request is handled.
1053 | */
1054 | createShortMethods('when');
1055 |
1056 |
1057 | /**
1058 | * @ngdoc method
1059 | * @name ngMock.$httpBackend#expect
1060 | * @methodOf ngMock.$httpBackend
1061 | * @description
1062 | * Creates a new request expectation.
1063 | *
1064 | * @param {string} method HTTP method.
1065 | * @param {string|RegExp} url HTTP url.
1066 | * @param {(string|RegExp)=} data HTTP request body.
1067 | * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1068 | * object and returns true if the headers match the current expectation.
1069 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1070 | * request is handled.
1071 | *
1072 | * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
1073 | * – The respond method takes a set of static data to be returned or a function that can return
1074 | * an array containing response status (number), response data (string) and response headers
1075 | * (Object).
1076 | */
1077 | $httpBackend.expect = function(method, url, data, headers) {
1078 | var expectation = new MockHttpExpectation(method, url, data, headers);
1079 | expectations.push(expectation);
1080 | return {
1081 | respond: function(status, data, headers) {
1082 | expectation.response = createResponse(status, data, headers);
1083 | }
1084 | };
1085 | };
1086 |
1087 |
1088 | /**
1089 | * @ngdoc method
1090 | * @name ngMock.$httpBackend#expectGET
1091 | * @methodOf ngMock.$httpBackend
1092 | * @description
1093 | * Creates a new request expectation for GET requests. For more info see `expect()`.
1094 | *
1095 | * @param {string|RegExp} url HTTP url.
1096 | * @param {Object=} headers HTTP headers.
1097 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1098 | * request is handled. See #expect for more info.
1099 | */
1100 |
1101 | /**
1102 | * @ngdoc method
1103 | * @name ngMock.$httpBackend#expectHEAD
1104 | * @methodOf ngMock.$httpBackend
1105 | * @description
1106 | * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1107 | *
1108 | * @param {string|RegExp} url HTTP url.
1109 | * @param {Object=} headers HTTP headers.
1110 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1111 | * request is handled.
1112 | */
1113 |
1114 | /**
1115 | * @ngdoc method
1116 | * @name ngMock.$httpBackend#expectDELETE
1117 | * @methodOf ngMock.$httpBackend
1118 | * @description
1119 | * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1120 | *
1121 | * @param {string|RegExp} url HTTP url.
1122 | * @param {Object=} headers HTTP headers.
1123 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1124 | * request is handled.
1125 | */
1126 |
1127 | /**
1128 | * @ngdoc method
1129 | * @name ngMock.$httpBackend#expectPOST
1130 | * @methodOf ngMock.$httpBackend
1131 | * @description
1132 | * Creates a new request expectation for POST requests. For more info see `expect()`.
1133 | *
1134 | * @param {string|RegExp} url HTTP url.
1135 | * @param {(string|RegExp)=} data HTTP request body.
1136 | * @param {Object=} headers HTTP headers.
1137 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1138 | * request is handled.
1139 | */
1140 |
1141 | /**
1142 | * @ngdoc method
1143 | * @name ngMock.$httpBackend#expectPUT
1144 | * @methodOf ngMock.$httpBackend
1145 | * @description
1146 | * Creates a new request expectation for PUT requests. For more info see `expect()`.
1147 | *
1148 | * @param {string|RegExp} url HTTP url.
1149 | * @param {(string|RegExp)=} data HTTP request body.
1150 | * @param {Object=} headers HTTP headers.
1151 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1152 | * request is handled.
1153 | */
1154 |
1155 | /**
1156 | * @ngdoc method
1157 | * @name ngMock.$httpBackend#expectPATCH
1158 | * @methodOf ngMock.$httpBackend
1159 | * @description
1160 | * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1161 | *
1162 | * @param {string|RegExp} url HTTP url.
1163 | * @param {(string|RegExp)=} data HTTP request body.
1164 | * @param {Object=} headers HTTP headers.
1165 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1166 | * request is handled.
1167 | */
1168 |
1169 | /**
1170 | * @ngdoc method
1171 | * @name ngMock.$httpBackend#expectJSONP
1172 | * @methodOf ngMock.$httpBackend
1173 | * @description
1174 | * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1175 | *
1176 | * @param {string|RegExp} url HTTP url.
1177 | * @returns {requestHandler} Returns an object with `respond` method that control how a matched
1178 | * request is handled.
1179 | */
1180 | createShortMethods('expect');
1181 |
1182 |
1183 | /**
1184 | * @ngdoc method
1185 | * @name ngMock.$httpBackend#flush
1186 | * @methodOf ngMock.$httpBackend
1187 | * @description
1188 | * Flushes all pending requests using the trained responses.
1189 | *
1190 | * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
1191 | * all pending requests will be flushed. If there are no pending requests when the flush method
1192 | * is called an exception is thrown (as this typically a sign of programming error).
1193 | */
1194 | $httpBackend.flush = function(count) {
1195 | if (!responses.length) throw Error('No pending request to flush !');
1196 |
1197 | if (angular.isDefined(count)) {
1198 | while (count--) {
1199 | if (!responses.length) throw Error('No more pending request to flush !');
1200 | responses.shift()();
1201 | }
1202 | } else {
1203 | while (responses.length) {
1204 | responses.shift()();
1205 | }
1206 | }
1207 | $httpBackend.verifyNoOutstandingExpectation();
1208 | };
1209 |
1210 |
1211 | /**
1212 | * @ngdoc method
1213 | * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
1214 | * @methodOf ngMock.$httpBackend
1215 | * @description
1216 | * Verifies that all of the requests defined via the `expect` api were made. If any of the
1217 | * requests were not made, verifyNoOutstandingExpectation throws an exception.
1218 | *
1219 | * Typically, you would call this method following each test case that asserts requests using an
1220 | * "afterEach" clause.
1221 | *
1222 | *