From 94601604b870b4dcc53a93a5d170afa297d8d85a Mon Sep 17 00:00:00 2001 From: Marko Vuksanovic Date: Fri, 9 May 2014 21:20:22 +1000 Subject: [PATCH 1/2] feat(Http): Http service can make cross-site requests (get, post, put, etc.) which use credentials (such as cookies or authorization headers). Closes #945 --- lib/core_dom/http.dart | 60 +++++++++++++++++++++--------------- test/core_dom/http_spec.dart | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 25 deletions(-) diff --git a/lib/core_dom/http.dart b/lib/core_dom/http.dart index 72c9e7875..40b98437d 100644 --- a/lib/core_dom/http.dart +++ b/lib/core_dom/http.dart @@ -410,6 +410,8 @@ class Http { * - headers: Map of strings or functions which return strings representing * HTTP headers to send to the server. If the return value of a function * is null, the header will not be sent. + * - withCredentials: True if cross-site requests should use credentials such as cookies or + * authorization headers; false otherwise. If not specified, defaults to false. * - xsrfHeaderName: TBI * - xsrfCookieName: TBI * - interceptors: Either a [HttpInterceptor] or a [HttpInterceptors] @@ -422,6 +424,7 @@ class Http { data, Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, @@ -481,7 +484,8 @@ class Http { var result = _backend.request(url, method: method, requestHeaders: config.headers, - sendData: config.data).then((dom.HttpRequest value) { + sendData: config.data, + withCredentials: withCredentials).then((dom.HttpRequest value) { // TODO: Uncomment after apps migrate off of this class. // assert(value.status >= 200 && value.status < 300); @@ -535,15 +539,16 @@ class Http { String data, Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'GET', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'GET', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Shortcut method for DELETE requests. See [call] for a complete description @@ -553,15 +558,16 @@ class Http { String data, Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'DELETE', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'DELETE', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Shortcut method for HEAD requests. See [call] for a complete description @@ -571,15 +577,16 @@ class Http { String data, Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'HEAD', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'HEAD', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Shortcut method for PUT requests. See [call] for a complete description @@ -588,15 +595,16 @@ class Http { async.Future put(String url, String data, { Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'PUT', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'PUT', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Shortcut method for POST requests. See [call] for a complete description @@ -605,15 +613,16 @@ class Http { async.Future post(String url, String data, { Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'POST', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'POST', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Shortcut method for JSONP requests. See [call] for a complete description @@ -623,15 +632,16 @@ class Http { String data, Map params, Map headers, + bool withCredentials: false, xsrfHeaderName, xsrfCookieName, interceptors, cache, timeout - }) => call(method: 'JSONP', url: url, data: data, params: params, - headers: headers, xsrfHeaderName: xsrfHeaderName, - xsrfCookieName: xsrfCookieName, interceptors: interceptors, - cache: cache, timeout: timeout); + }) => call(method: 'JSONP', url: url, data: data, params: params, headers: headers, + withCredentials: withCredentials, xsrfHeaderName: xsrfHeaderName, + xsrfCookieName: xsrfCookieName, interceptors: interceptors, cache: cache, + timeout: timeout); /** * Parse raw headers into key-value object diff --git a/test/core_dom/http_spec.dart b/test/core_dom/http_spec.dart index b15f7a856..888d4fdba 100644 --- a/test/core_dom/http_spec.dart +++ b/test/core_dom/http_spec.dart @@ -98,6 +98,23 @@ void main() { flush(); })); + describe('backend', () { + beforeEachModule((Module module) { + FakeBackend fakeBackend = new FakeBackend(); + module.bind(HttpBackend, toFactory: (i) => fakeBackend); + module.bind(FakeBackend, toFactory: (i) => i.get(HttpBackend)); + }); + + it('should pass on withCredentials to backend and use GET as default method', + async((FakeBackend backend) { + http(url: '/url', method: 'GET', withCredentials: true); + microLeap(); + expect(backend.url).toEqual('/url'); + expect(backend.method).toEqual('GET'); + expect(backend.withCredentials).toBeTruthy(); + })); + }); + describe('params', () { it('should do basic request with params and encode', async(() { @@ -1356,3 +1373,40 @@ class FakeFile implements File { Blob slice([int start, int end, String contentType]) => null; int get lastModified => new DateTime.now().millisecondsSinceEpoch; } + +class FakeBackend extends Mock implements HttpBackend { + + String url; + String method; + bool withCredentials; + String responseType; + String mimeType; + Map requestHeaders; + dynamic sendData; + + Future request(String url, { + String method, + bool withCredentials, + String responseType, + String mimeType, + Map requestHeaders, + sendData, + void onProgress(ProgressEvent e)}) { + this.url = url; + this.method = method; + this.withCredentials = withCredentials; + this.responseType = responseType; + this.mimeType = mimeType; + this.requestHeaders = requestHeaders; + this.sendData = sendData; + HttpRequest request = new HttpRequest(); + return new Future.value(new HttpRequest()); + } +} + +class FakeHttpRequest extends Mock implements HttpRequest { + FakeHttpRequest() { + when(callsTo('get status')).thenReturn(200); + when(callsTo('get responseText')).thenReturn('Fake Request'); + } +} From 92706b5b825f055ffa0bf9fab8a794dea67a7586 Mon Sep 17 00:00:00 2001 From: Marko Vuksanovic Date: Sun, 18 May 2014 01:24:16 +1000 Subject: [PATCH 2/2] feat(MockHttpBackend): Add support for withCredentials. MockHttpBackend takes one more parameter, withCredentials. This is used to mimic withCredentials parameter from real HttpRequest. --- lib/mock/http_backend.dart | 52 +++++++++------ test/core_dom/http_spec.dart | 51 +-------------- test/mock/http_backend_spec.dart | 107 ++++++++++++++++++------------- 3 files changed, 98 insertions(+), 112 deletions(-) diff --git a/lib/mock/http_backend.dart b/lib/mock/http_backend.dart index 59f60719c..a5e4ad6ce 100644 --- a/lib/mock/http_backend.dart +++ b/lib/mock/http_backend.dart @@ -64,20 +64,23 @@ class _MockXhr { * An internal class used by [MockHttpBackend]. */ class MockHttpExpectation { - final method; - final url; + final String method; + final String url; final data; final headers; + final bool withCredentials; var response; - MockHttpExpectation(this.method, this.url, [this.data, this.headers]); + MockHttpExpectation(this.method, this.url, [this.data, this.headers, withCredentials]) : + this.withCredentials = withCredentials == true; - bool match(method, url, [data, headers]) { + bool match(method, url, [data, headers, withCredentials]) { if (method != method) return false; if (!matchUrl(url)) return false; if (data != null && !matchData(data)) return false; if (headers != null && !matchHeaders(headers)) return false; + if (withCredentials != null && !matchWithCredentials(withCredentials)) return false; return true; } @@ -102,6 +105,8 @@ class MockHttpExpectation { return JSON.encode(data) == JSON.encode(d); } + bool matchWithCredentials(withCredentials) => this.withCredentials == withCredentials; + String toString() => "$method $url"; } @@ -124,7 +129,7 @@ class MockHttpBackend implements HttpBackend { * This function is called from [Http] and designed to mimic the Dart APIs. */ dart_async.Future request(String url, - {String method, bool withCredentials, String responseType, + {String method, bool withCredentials: false, String responseType, String mimeType, Map requestHeaders, sendData, void onProgress(ProgressEvent e)}) { dart_async.Completer c = new dart_async.Completer(); @@ -136,7 +141,7 @@ class MockHttpBackend implements HttpBackend { new MockHttpRequest(status, data, headers))); } }; - call(method == null ? 'GET' : method, url, sendData, callback, + call(method == null ? 'GET' : method, url, sendData, withCredentials, callback, requestHeaders); return c.future; } @@ -163,7 +168,7 @@ class MockHttpBackend implements HttpBackend { * A callback oriented API. This function takes a callback with * will be called with (status, data, headers) */ - void call(method, [url, data, callback, headers, timeout]) { + void call(method, [url, data, withCredentials, callback, headers, timeout]) { var xhr = new _MockXhr(), expectation = expectations.isEmpty ? null : expectations[0], wasExpected = false; @@ -206,6 +211,11 @@ class MockHttpBackend implements HttpBackend { 'EXPECTED: ${prettyPrint(expectation.headers)}\n' 'GOT: ${prettyPrint(headers)}']; + if (!expectation.matchWithCredentials(withCredentials)) + throw ['Expected $expectation with different withCredentials\n' + 'EXPECTED: ${prettyPrint(expectation.withCredentials)}\n' + 'GOT: ${prettyPrint(withCredentials)}']; + expectations.removeAt(0); if (expectation.response != null) { @@ -216,7 +226,7 @@ class MockHttpBackend implements HttpBackend { } for (var definition in definitions) { - if (definition.match(method, url, data, headers != null ? headers : {})) { + if (definition.match(method, url, data, headers != null ? headers : {}, withCredentials)) { if (definition.response != null) { // if $browser specified, we do auto flush all requests responses.add(wrapResponse(definition)); @@ -248,8 +258,8 @@ class MockHttpBackend implements HttpBackend { * an array containing response status (number), response data (string) and response headers * (Object). */ - _Chain when(method, [url, data, headers]) { - var definition = new MockHttpExpectation(method, url, data, headers), + _Chain when(method, [url, data, headers, withCredentials = false]) { + var definition = new MockHttpExpectation(method, url, data, headers, withCredentials), chain = new _Chain(respond: (status, data, headers) { definition.response = _createResponse(status, data, headers); }); @@ -364,8 +374,8 @@ class MockHttpBackend implements HttpBackend { * an array containing response status (number), response data (string) and response headers * (Object). */ - _Chain expect(method, [url, data, headers]) { - var expectation = new MockHttpExpectation(method, url, data, headers); + _Chain expect(method, [url, data, headers, withCredentials = false]) { + var expectation = new MockHttpExpectation(method, url, data, headers, withCredentials); expectations.add(expectation); return new _Chain(respond: (status, data, headers) { expectation.response = _createResponse(status, data, headers); @@ -385,7 +395,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. See #expect for more info. */ - _Chain expectGET(url, [headers]) => expect('GET', url, null, headers); + _Chain expectGET(url, [headers, withCredentials = false]) => expect('GET', url, null, headers, + withCredentials); /** * @ngdoc method @@ -399,7 +410,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. */ - _Chain expectDELETE(url, [headers]) => expect('DELETE', url, null, headers); + _Chain expectDELETE(url, [headers, withCredentials = false]) => expect('DELETE', url, null, + headers, withCredentials); /** * @ngdoc method @@ -412,7 +424,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. */ - _Chain expectJSONP(url, [headers]) => expect('JSONP', url, null, headers); + _Chain expectJSONP(url, [headers, withCredentials = false]) => expect('JSONP', url, null, headers, + withCredentials); /** * @ngdoc method @@ -427,7 +440,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. */ - _Chain expectPUT(url, [data, headers]) => expect('PUT', url, data, headers); + _Chain expectPUT(url, [data, headers, withCredentials = false]) => expect('PUT', url, data, + headers, withCredentials); /** * @ngdoc method @@ -442,7 +456,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. */ - _Chain expectPOST(url, [data, headers]) => expect('POST', url, data, headers); + _Chain expectPOST(url, [data, headers, withCredentials = false]) => expect('POST', url, data, + headers, withCredentials); /** * @ngdoc method @@ -457,7 +472,8 @@ class MockHttpBackend implements HttpBackend { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. */ - _Chain expectPATCH(url, [data, headers]) => expect('PATCH', url, data, headers); + _Chain expectPATCH(url, [data, headers, withCredentials = false]) => expect('PATCH', url, data, + headers, withCredentials); /** * @ngdoc method diff --git a/test/core_dom/http_spec.dart b/test/core_dom/http_spec.dart index 888d4fdba..e31d75565 100644 --- a/test/core_dom/http_spec.dart +++ b/test/core_dom/http_spec.dart @@ -99,19 +99,11 @@ void main() { })); describe('backend', () { - beforeEachModule((Module module) { - FakeBackend fakeBackend = new FakeBackend(); - module.bind(HttpBackend, toFactory: (i) => fakeBackend); - module.bind(FakeBackend, toFactory: (i) => i.get(HttpBackend)); - }); - it('should pass on withCredentials to backend and use GET as default method', - async((FakeBackend backend) { + async(() { + backend.expect('GET', '/url', null, null, true).respond(''); http(url: '/url', method: 'GET', withCredentials: true); - microLeap(); - expect(backend.url).toEqual('/url'); - expect(backend.method).toEqual('GET'); - expect(backend.withCredentials).toBeTruthy(); + flush(); })); }); @@ -1373,40 +1365,3 @@ class FakeFile implements File { Blob slice([int start, int end, String contentType]) => null; int get lastModified => new DateTime.now().millisecondsSinceEpoch; } - -class FakeBackend extends Mock implements HttpBackend { - - String url; - String method; - bool withCredentials; - String responseType; - String mimeType; - Map requestHeaders; - dynamic sendData; - - Future request(String url, { - String method, - bool withCredentials, - String responseType, - String mimeType, - Map requestHeaders, - sendData, - void onProgress(ProgressEvent e)}) { - this.url = url; - this.method = method; - this.withCredentials = withCredentials; - this.responseType = responseType; - this.mimeType = mimeType; - this.requestHeaders = requestHeaders; - this.sendData = sendData; - HttpRequest request = new HttpRequest(); - return new Future.value(new HttpRequest()); - } -} - -class FakeHttpRequest extends Mock implements HttpRequest { - FakeHttpRequest() { - when(callsTo('get status')).thenReturn(200); - when(callsTo('get responseText')).thenReturn('Fake Request'); - } -} diff --git a/test/mock/http_backend_spec.dart b/test/mock/http_backend_spec.dart index d9bdfc601..06ce9a327 100644 --- a/test/mock/http_backend_spec.dart +++ b/test/mock/http_backend_spec.dart @@ -36,7 +36,22 @@ void main() { expect(response).toBe('content'); }); - hb('GET', '/url1', null, callback); + hb('GET', '/url1', null, false, callback); + expect(callback).not.toHaveBeenCalled(); + hb.flush(); + expect(callback).toHaveBeenCalledOnce(); + }); + + it('should match when with credentials is set', () { + hb.when('GET', '/url1').respond(200, 'content', {}); + hb.when('GET', '/url1', null, null, true).respond(201, 'another', {}); + + callback.andCallFake((status, response, _) { + expect(status).toBe(201); + expect(response).toBe('another'); + }); + + hb('GET', '/url1', null, true, callback); expect(callback).not.toHaveBeenCalled(); hb.flush(); expect(callback).toHaveBeenCalledOnce(); @@ -53,8 +68,8 @@ void main() { logger(response); }); - hb('GET', '/url1', null, callback); - hb('GET', '/url2', null, callback); + hb('GET', '/url1', null, false, callback); + hb('GET', '/url2', null, false, callback); hb.flush(); expect(logger).toEqual(['["abc"]', '{"key":"value"}']); }); @@ -87,17 +102,17 @@ void main() { hb.when('GET', '/url', null, {'X': 'val2'}).respond(202, 'content2'); hb.when('GET', '/url').respond(203, 'content3'); - hb('GET', '/url', null, (status, response, _) { + hb('GET', '/url', null, false, (status, response, _) { expect(status).toBe(203); expect(response).toBe('content3'); }); - hb('GET', '/url', null, (status, response, _) { + hb('GET', '/url', null, false, (status, response, _) { expect(status).toBe(201); expect(response).toBe('content1'); }, {'X': 'val1'}); - hb('GET', '/url', null, (status, response, _) { + hb('GET', '/url', null, false, (status, response, _) { expect(status).toBe(202); expect(response).toBe('content2'); }, {'X': 'val2'}); @@ -111,12 +126,12 @@ void main() { hb.when('GET', '/a/b', '{a: true}').respond(201, 'content1'); hb.when('GET', '/a/b').respond(202, 'content2'); - hb('GET', '/a/b', '{a: true}', (status, response) { + hb('GET', '/a/b', '{a: true}', false, (status, response) { expect(status).toBe(201); expect(response).toBe('content1'); }); - hb('GET', '/a/b', '{}', (status, response) { + hb('GET', '/a/b', '{}', false, (status, response) { expect(status).toBe(202); expect(response).toBe('content2'); }); @@ -132,9 +147,9 @@ void main() { expect(response).toBe('c'); }); - hb('GET', '/some', null, callback, {}); - hb('GET', '/another', null, callback, {'X-Fake': 'Header'}); - hb('GET', '/third', 'some-data', callback, {}); + hb('GET', '/some', null, false, callback, {}); + hb('GET', '/another', null, false, callback, {'X-Fake': 'Header'}); + hb('GET', '/third', 'some-data',false ,callback, {}); hb.flush(); expect(callback).toHaveBeenCalled(); @@ -145,8 +160,8 @@ void main() { hb.when('GET', '/url1').respond(200, 'first'); hb.when('GET', '/url2').respond(201, 'second'); - hb('GET', '/url2', null, callback); - hb('GET', '/url1', null, callback); + hb('GET', '/url2', null, false, callback); + hb('GET', '/url1', null, false, callback); hb.flush(); @@ -159,7 +174,7 @@ void main() { describe('respond()', () { it('should take values', () { hb.expect('GET', '/url1').respond(200, 'first', {'header': 'val'}); - hb('GET', '/url1', null, callback); + hb('GET', '/url1', null, false, callback); hb.flush(); expect(callback).toHaveBeenCalledOnceWith(200, 'first', "header: val"); @@ -170,7 +185,7 @@ void main() { return [301, m + u + ';' + d + ';a=' + h['a'], {'Connection': 'keep-alive'}]; }); - hb('GET', '/some', 'data', callback, {'a': 'b'}); + hb('GET', '/some', 'data', false, callback, {'a': 'b'}); hb.flush(); expect(callback).toHaveBeenCalledOnceWith(301, 'GET/some;data;a=b', 'Connection: keep-alive'); @@ -184,8 +199,8 @@ void main() { hb.expect('GET', '/url1').respond('some-data'); hb.expect('GET', '/url2').respond('some-data', {'X-Header': 'true'}); - hb('GET', '/url1', null, callback); - hb('GET', '/url2', null, callback); + hb('GET', '/url1', null, false, callback); + hb('GET', '/url2', null, false, callback); hb.flush(); expect(callback).toHaveBeenCalled(); expect(callback.callCount).toBe(2); @@ -196,8 +211,8 @@ void main() { hb.expect('GET', '/url1').respond(200, 'first'); hb.expect('GET', '/url2').respond('second'); - hb('GET', '/url1', null, callback); - hb('GET', '/url2', null, callback); + hb('GET', '/url1', null, false, callback); + hb('GET', '/url2', null, false, callback); hb.flush(); @@ -214,7 +229,7 @@ void main() { hb.expect('GET', '/url2').respond(200, ''); expect(() { - hb('GET', '/url2', null, noop, {}); + hb('GET', '/url2', null, false, noop, {}); }).toThrow('Unexpected request: GET /url2\nExpected GET /url1'); }); @@ -228,7 +243,7 @@ void main() { hb.when('GET', '/url').respond(200, 'when'); hb.expect('GET', '/url').respond(299, 'expect'); - hb('GET', '/url', null, callback, null); + hb('GET', '/url', null, false, callback, null); hb.flush(); expect(callback).toHaveBeenCalledOnce(); }); @@ -239,7 +254,7 @@ void main() { hb.expect('GET', '/match', null, {'Content-Type': 'application/json'}).respond(200, '', {}); expect(() { - hb('GET', '/match', null, noop, {}); + hb('GET', '/match', null, false, noop, {}); }).toThrow('Expected GET /match with different headers\n' + 'EXPECTED: {"Content-Type":"application/json"}\nGOT: {}'); }); @@ -250,7 +265,7 @@ void main() { hb.expect('GET', '/match', 'some-data').respond(200, '', {}); expect(() { - hb('GET', '/match', 'different', noop, null); + hb('GET', '/match', 'different', false, noop, null); }).toThrow('Expected GET /match with different data\n' + 'EXPECTED: some-data\nGOT: different'); }); @@ -264,7 +279,7 @@ void main() { hb.when('GET', '/some').respond(201, 'data'); hb.expect('GET', '/some'); - hb('GET', '/some', null, callback); + hb('GET', '/some', null, false, callback); hb.flush(); expect(callback).toHaveBeenCalled(); @@ -277,8 +292,8 @@ void main() { it('flush() should flush requests fired during callbacks', () { hb.when('GET', '/some').respond(200, ''); hb.when('GET', '/other').respond(200, ''); - hb('GET', '/some', null, (_, __) { - hb('GET', '/other', null, callback); + hb('GET', '/some', null, false, (_, __) { + hb('GET', '/other', null, false, callback); }); hb.flush(); @@ -288,9 +303,9 @@ void main() { it('should flush given number of pending requests', () { hb.when('GET').respond(200, ''); - hb('GET', '/some', null, callback); - hb('GET', '/some', null, callback); - hb('GET', '/some', null, callback); + hb('GET', '/some', null, false, callback); + hb('GET', '/some', null, false, callback); + hb('GET', '/some', null, false, callback); hb.flush(2); expect(callback).toHaveBeenCalled(); @@ -300,7 +315,7 @@ void main() { it('should throw exception when flushing more requests than pending', () { hb.when('GET').respond(200, ''); - hb('GET', '/url', null, callback); + hb('GET', '/url', null, false, callback); expect(() {hb.flush(2);}).toThrow('No more pending request to flush !'); expect(callback).toHaveBeenCalledOnce(); @@ -311,7 +326,7 @@ void main() { expect(() {hb.flush();}).toThrow('No pending request to flush !'); hb.when('GET').respond(200, ''); - hb('GET', '/some', null, callback); + hb('GET', '/some', null, false, callback); hb.flush(); expect(() {hb.flush();}).toThrow('No pending request to flush !'); @@ -322,7 +337,7 @@ void main() { hb.expect('GET', '/url1').respond(); hb.expect('GET', '/url2').respond(); - hb('GET', '/url1', null, noop); + hb('GET', '/url1', null, false, noop); expect(() {hb.flush();}).toThrow('Unsatisfied requests: GET /url2'); }); }); @@ -335,7 +350,7 @@ void main() { canceler = fn; }); - hb('GET', '/url1', null, callback, null, new _Chain(then: then)); + hb('GET', '/url1', null, false, callback, null, new _Chain(then: then)); expect(canceler is Function).toBe(true); canceler(); // simulate promise resolution @@ -349,7 +364,7 @@ void main() { it('should throw an exception if no response defined', () { hb.when('GET', '/test'); expect(() { - hb('GET', '/test', null, callback); + hb('GET', '/test', null, false, callback); }).toThrow('No response defined !'); }); @@ -357,7 +372,7 @@ void main() { it('should throw an exception if no response for exception and no definition', () { hb.expect('GET', '/url'); expect(() { - hb('GET', '/url', null, callback); + hb('GET', '/url', null, false, callback); }).toThrow('No response defined !'); }); @@ -366,8 +381,8 @@ void main() { hb.when('JSONP', '/url1').respond(200); hb.expect('JSONP', '/url2').respond(200); - expect(hb('JSONP', '/url1')).toBeNull(); - expect(hb('JSONP', '/url2')).toBeNull(); + expect(hb('JSONP', '/url1', null, false)).toBeNull(); + expect(hb('JSONP', '/url2', null, false)).toBeNull(); }); @@ -378,7 +393,7 @@ void main() { hb.expect('GET', '/u2').respond(200, '', {}); hb.expect('POST', '/u3').respond(201, '', {}); - hb('POST', '/u1', 'ddd', noop, {}); + hb('POST', '/u1', 'ddd', false, noop, {}); expect(() {hb.verifyNoOutstandingExpectation();}). toThrow('Unsatisfied requests: GET /u2, POST /u3'); @@ -397,8 +412,8 @@ void main() { hb.expect('POST', '/u3').respond(201, '', {}); hb.when('DELETE', '/some').respond(200, ''); - hb('GET', '/u2'); - hb('POST', '/u3'); + hb('GET', '/u2', null, false); + hb('POST', '/u3', null, false); expect(() {hb.verifyNoOutstandingExpectation();}).not.toThrow(); }); @@ -408,7 +423,7 @@ void main() { it('should throw exception if not all requests were flushed', () { hb.when('GET').respond(200); - hb('GET', '/some', null, noop, {}); + hb('GET', '/some', null, false, noop, {}); expect(() { hb.verifyNoOutstandingRequest(); @@ -432,11 +447,11 @@ void main() { var cancelledClb = guinness.createSpy('cancelled'); hb.expect('GET', '/url').respond(200, ''); - hb('GET', '/url', null, cancelledClb); + hb('GET', '/url', null, false, cancelledClb); hb.resetExpectations(); hb.expect('GET', '/url').respond(300, ''); - hb('GET', '/url', null, callback, {}); + hb('GET', '/url', null, false, callback, {}); hb.flush(); expect(callback).toHaveBeenCalledOnce(); @@ -448,10 +463,10 @@ void main() { var cancelledClb = guinness.createSpy('cancelled'); hb.when('GET', '/url').respond(200, 'success'); - hb('GET', '/url', null, cancelledClb); + hb('GET', '/url', null, false, cancelledClb); hb.resetExpectations(); - hb('GET', '/url', null, callback, {}); + hb('GET', '/url', null, false, callback, {}); hb.flush(); expect(callback).toHaveBeenCalledOnce(); @@ -477,7 +492,7 @@ void main() { var shortcut = step[0], method = step[1]; it('should provide $shortcut shortcut method', () { shortcut('/foo').respond('bar'); - hb(method, '/foo', undefined, callback); + hb(method, '/foo', undefined, false, callback); hb.flush(); expect(callback).toHaveBeenCalledOnceWith(200, 'bar', ''); });