Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 7551b89

Browse files
fix(ngMock/$httpBackend): fail if a url is provided but is undefined
While the `url` parameter is optional for `$httpBackend.when`, `$httpBackend.expect` and related shortcut methods, it should not have the value of `undefined` if it has been provided. This change ensures that an error is thrown in those cases. Closes #8442 Closes #8462 Closes #10934 Closes #12777 BREAKING CHANGE It is no longer valid to explicitly pass `undefined` as the `url` argument to any of the `$httpBackend.when...()` and `$httpBackend.expect...()` methods. While this argument is optional, it must have a defined value if it is provided. Previously passing an explicit `undefined` value was ignored but this lead to invalid tests passing unexpectedly.
1 parent f467dc3 commit 7551b89

File tree

2 files changed

+137
-23
lines changed

2 files changed

+137
-23
lines changed

src/ngMock/angular-mocks.js

+46-23
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
14231423
* Creates a new backend definition.
14241424
*
14251425
* @param {string} method HTTP method.
1426-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1426+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
14271427
* and returns true if the url matches the current definition.
14281428
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
14291429
* data string and returns true if the data is as expected.
@@ -1445,6 +1445,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
14451445
* the `requestHandler` object for possible overrides.
14461446
*/
14471447
$httpBackend.when = function(method, url, data, headers, keys) {
1448+
1449+
assertArgDefined(arguments, 1, 'url');
1450+
14481451
var definition = new MockHttpExpectation(method, url, data, headers, keys),
14491452
chain = {
14501453
respond: function(status, data, headers, statusText) {
@@ -1472,7 +1475,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
14721475
* @description
14731476
* Creates a new backend definition for GET requests. For more info see `when()`.
14741477
*
1475-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1478+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
14761479
* and returns true if the url matches the current definition.
14771480
* @param {(Object|function(Object))=} headers HTTP headers.
14781481
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1487,7 +1490,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
14871490
* @description
14881491
* Creates a new backend definition for HEAD requests. For more info see `when()`.
14891492
*
1490-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1493+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
14911494
* and returns true if the url matches the current definition.
14921495
* @param {(Object|function(Object))=} headers HTTP headers.
14931496
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1502,7 +1505,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
15021505
* @description
15031506
* Creates a new backend definition for DELETE requests. For more info see `when()`.
15041507
*
1505-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1508+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
15061509
* and returns true if the url matches the current definition.
15071510
* @param {(Object|function(Object))=} headers HTTP headers.
15081511
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1517,7 +1520,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
15171520
* @description
15181521
* Creates a new backend definition for POST requests. For more info see `when()`.
15191522
*
1520-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1523+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
15211524
* and returns true if the url matches the current definition.
15221525
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
15231526
* data string and returns true if the data is as expected.
@@ -1534,7 +1537,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
15341537
* @description
15351538
* Creates a new backend definition for PUT requests. For more info see `when()`.
15361539
*
1537-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1540+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
15381541
* and returns true if the url matches the current definition.
15391542
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
15401543
* data string and returns true if the data is as expected.
@@ -1551,7 +1554,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
15511554
* @description
15521555
* Creates a new backend definition for JSONP requests. For more info see `when()`.
15531556
*
1554-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1557+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
15551558
* and returns true if the url matches the current definition.
15561559
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
15571560
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
@@ -1614,7 +1617,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
16141617
* Creates a new request expectation.
16151618
*
16161619
* @param {string} method HTTP method.
1617-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1620+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
16181621
* and returns true if the url matches the current definition.
16191622
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
16201623
* receives data string and returns true if the data is as expected, or Object if request body
@@ -1637,6 +1640,9 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
16371640
* the `requestHandler` object for possible overrides.
16381641
*/
16391642
$httpBackend.expect = function(method, url, data, headers, keys) {
1643+
1644+
assertArgDefined(arguments, 1, 'url');
1645+
16401646
var expectation = new MockHttpExpectation(method, url, data, headers, keys),
16411647
chain = {
16421648
respond: function(status, data, headers, statusText) {
@@ -1655,7 +1661,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
16551661
* @description
16561662
* Creates a new request expectation for GET requests. For more info see `expect()`.
16571663
*
1658-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1664+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
16591665
* and returns true if the url matches the current definition.
16601666
* @param {Object=} headers HTTP headers.
16611667
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1670,7 +1676,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
16701676
* @description
16711677
* Creates a new request expectation for HEAD requests. For more info see `expect()`.
16721678
*
1673-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1679+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
16741680
* and returns true if the url matches the current definition.
16751681
* @param {Object=} headers HTTP headers.
16761682
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1685,7 +1691,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
16851691
* @description
16861692
* Creates a new request expectation for DELETE requests. For more info see `expect()`.
16871693
*
1688-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1694+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
16891695
* and returns true if the url matches the current definition.
16901696
* @param {Object=} headers HTTP headers.
16911697
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
@@ -1700,7 +1706,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
17001706
* @description
17011707
* Creates a new request expectation for POST requests. For more info see `expect()`.
17021708
*
1703-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1709+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
17041710
* and returns true if the url matches the current definition.
17051711
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
17061712
* receives data string and returns true if the data is as expected, or Object if request body
@@ -1718,7 +1724,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
17181724
* @description
17191725
* Creates a new request expectation for PUT requests. For more info see `expect()`.
17201726
*
1721-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1727+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
17221728
* and returns true if the url matches the current definition.
17231729
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
17241730
* receives data string and returns true if the data is as expected, or Object if request body
@@ -1736,7 +1742,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
17361742
* @description
17371743
* Creates a new request expectation for PATCH requests. For more info see `expect()`.
17381744
*
1739-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1745+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
17401746
* and returns true if the url matches the current definition.
17411747
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
17421748
* receives data string and returns true if the data is as expected, or Object if request body
@@ -1754,7 +1760,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
17541760
* @description
17551761
* Creates a new request expectation for JSONP requests. For more info see `expect()`.
17561762
*
1757-
* @param {string|RegExp|function(string)} url HTTP url or function that receives an url
1763+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives an url
17581764
* and returns true if the url matches the current definition.
17591765
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described above.
17601766
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
@@ -1870,18 +1876,35 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
18701876
function createShortMethods(prefix) {
18711877
angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
18721878
$httpBackend[prefix + method] = function(url, headers, keys) {
1879+
assertArgDefined(arguments, 0, 'url');
1880+
1881+
// Change url to `null` if `undefined` to stop it throwing an exception further down
1882+
if (angular.isUndefined(url)) url = null;
1883+
18731884
return $httpBackend[prefix](method, url, undefined, headers, keys);
18741885
};
18751886
});
18761887

18771888
angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
18781889
$httpBackend[prefix + method] = function(url, data, headers, keys) {
1890+
assertArgDefined(arguments, 0, 'url');
1891+
1892+
// Change url to `null` if `undefined` to stop it throwing an exception further down
1893+
if (angular.isUndefined(url)) url = null;
1894+
18791895
return $httpBackend[prefix](method, url, data, headers, keys);
18801896
};
18811897
});
18821898
}
18831899
}
18841900

1901+
function assertArgDefined(args, index, name) {
1902+
if (args.length > index && angular.isUndefined(args[index])) {
1903+
throw new Error("Undefined argument `" + name + "`; the argument is provided but not defined");
1904+
}
1905+
}
1906+
1907+
18851908
function MockHttpExpectation(method, url, data, headers, keys) {
18861909

18871910
function getUrlParams(u) {
@@ -2462,7 +2485,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
24622485
* Creates a new backend definition.
24632486
*
24642487
* @param {string} method HTTP method.
2465-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2488+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
24662489
* and returns true if the url matches the current definition.
24672490
* @param {(string|RegExp)=} data HTTP request body.
24682491
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
@@ -2494,7 +2517,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
24942517
* @description
24952518
* Creates a new backend definition for GET requests. For more info see `when()`.
24962519
*
2497-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2520+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
24982521
* and returns true if the url matches the current definition.
24992522
* @param {(Object|function(Object))=} headers HTTP headers.
25002523
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
@@ -2511,7 +2534,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25112534
* @description
25122535
* Creates a new backend definition for HEAD requests. For more info see `when()`.
25132536
*
2514-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2537+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
25152538
* and returns true if the url matches the current definition.
25162539
* @param {(Object|function(Object))=} headers HTTP headers.
25172540
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
@@ -2528,7 +2551,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25282551
* @description
25292552
* Creates a new backend definition for DELETE requests. For more info see `when()`.
25302553
*
2531-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2554+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
25322555
* and returns true if the url matches the current definition.
25332556
* @param {(Object|function(Object))=} headers HTTP headers.
25342557
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
@@ -2545,7 +2568,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25452568
* @description
25462569
* Creates a new backend definition for POST requests. For more info see `when()`.
25472570
*
2548-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2571+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
25492572
* and returns true if the url matches the current definition.
25502573
* @param {(string|RegExp)=} data HTTP request body.
25512574
* @param {(Object|function(Object))=} headers HTTP headers.
@@ -2563,7 +2586,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25632586
* @description
25642587
* Creates a new backend definition for PUT requests. For more info see `when()`.
25652588
*
2566-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2589+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
25672590
* and returns true if the url matches the current definition.
25682591
* @param {(string|RegExp)=} data HTTP request body.
25692592
* @param {(Object|function(Object))=} headers HTTP headers.
@@ -2581,7 +2604,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25812604
* @description
25822605
* Creates a new backend definition for PATCH requests. For more info see `when()`.
25832606
*
2584-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2607+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
25852608
* and returns true if the url matches the current definition.
25862609
* @param {(string|RegExp)=} data HTTP request body.
25872610
* @param {(Object|function(Object))=} headers HTTP headers.
@@ -2599,7 +2622,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
25992622
* @description
26002623
* Creates a new backend definition for JSONP requests. For more info see `when()`.
26012624
*
2602-
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2625+
* @param {string|RegExp|function(string)=} url HTTP url or function that receives a url
26032626
* and returns true if the url matches the current definition.
26042627
* @param {(Array)=} keys Array of keys to assign to regex matches in request url described on
26052628
* {@link ngMock.$httpBackend $httpBackend mock}.

test/ngMock/angular-mocksSpec.js

+91
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,97 @@ describe('ngMock', function() {
11731173
});
11741174

11751175

1176+
it('should not error if the url is not provided', function() {
1177+
expect(function() {
1178+
hb.when('GET');
1179+
1180+
hb.whenGET();
1181+
hb.whenPOST();
1182+
hb.whenPUT();
1183+
hb.whenPATCH();
1184+
hb.whenDELETE();
1185+
hb.whenHEAD();
1186+
1187+
hb.expect('GET');
1188+
1189+
hb.expectGET();
1190+
hb.expectPOST();
1191+
hb.expectPUT();
1192+
hb.expectPATCH();
1193+
hb.expectDELETE();
1194+
hb.expectHEAD();
1195+
}).not.toThrow();
1196+
});
1197+
1198+
1199+
it('should error if the url is undefined', function() {
1200+
expect(function() {
1201+
hb.when('GET', undefined);
1202+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1203+
1204+
expect(function() {
1205+
hb.whenGET(undefined);
1206+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1207+
1208+
expect(function() {
1209+
hb.whenDELETE(undefined);
1210+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1211+
1212+
expect(function() {
1213+
hb.whenJSONP(undefined);
1214+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1215+
1216+
expect(function() {
1217+
hb.whenHEAD(undefined);
1218+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1219+
1220+
expect(function() {
1221+
hb.whenPATCH(undefined);
1222+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1223+
1224+
expect(function() {
1225+
hb.whenPOST(undefined);
1226+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1227+
1228+
expect(function() {
1229+
hb.whenPUT(undefined);
1230+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1231+
1232+
1233+
expect(function() {
1234+
hb.expect('GET', undefined);
1235+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1236+
1237+
expect(function() {
1238+
hb.expectGET(undefined);
1239+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1240+
1241+
expect(function() {
1242+
hb.expectDELETE(undefined);
1243+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1244+
1245+
expect(function() {
1246+
hb.expectJSONP(undefined);
1247+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1248+
1249+
expect(function() {
1250+
hb.expectHEAD(undefined);
1251+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1252+
1253+
expect(function() {
1254+
hb.expectPATCH(undefined);
1255+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1256+
1257+
expect(function() {
1258+
hb.expectPOST(undefined);
1259+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1260+
1261+
expect(function() {
1262+
hb.expectPUT(undefined);
1263+
}).toThrowError('Undefined argument `url`; the argument is provided but not defined');
1264+
});
1265+
1266+
11761267
it('should preserve the order of requests', function() {
11771268
hb.when('GET', '/url1').respond(200, 'first');
11781269
hb.when('GET', '/url2').respond(201, 'second');

0 commit comments

Comments
 (0)