From b083a96812ad97d64d81f8f8ce0b87dad8f00608 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Thu, 3 Jul 2014 10:16:16 -0400 Subject: [PATCH 1/2] feat(mocks): change MockHttpBackend to define the assertion on flush. Add new methods (`flushGET`, `flushPOST`, etc) to the `MockHttpBackend` class to allow defining assertions on flush. These methods add a new expectation and then flush all the pending requests until they find the one matching the expectation. BREAKING CHANGE: Unexpected requests are detected only when `flush` is called. Before: backend("GET", /some"); //throws here if `/some` has not been defined After: backend("GET", /some"); //no problem, just records the request backend.flush(); //throws here Closes #900 --- lib/mock/http_backend.dart | 388 ++++++++++++++++++++++--------- test/core_dom/http_spec.dart | 13 +- test/mock/http_backend_spec.dart | 73 ++++-- 3 files changed, 336 insertions(+), 138 deletions(-) diff --git a/lib/mock/http_backend.dart b/lib/mock/http_backend.dart index 2d472ccd8..47662f949 100644 --- a/lib/mock/http_backend.dart +++ b/lib/mock/http_backend.dart @@ -75,37 +75,37 @@ class MockHttpExpectation { MockHttpExpectation(this.method, this.url, [this.data, this.headers, withCredentials]) : this.withCredentials = withCredentials == true; - 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; - } + bool match(req) => + matchMethodAndUrl(req) && matchData(req) && matchHeaders(req) && matchWithCredentials(req); + + bool matchMethodAndUrl(req) => + method == req.method && matchUrl(req); - bool matchUrl(u) { + bool matchUrl(req) { if (url == null) return true; - if (url is RegExp) return url.hasMatch(u); - return url == u; + return _matchUrl(url, req.url); } - bool matchHeaders(h) { + bool matchHeaders(req) { if (headers == null) return true; - if (headers is Function) return headers(h); - return "$headers" == "$h"; + if (headers is Function) return headers(req.headers); + return "$headers" == "${req.headers}"; } - bool matchData(d) { + bool matchData(req) { if (data == null) return true; - if (d == null) return false; - if (data is File) return data == d; - assert(d is String); - if (data is RegExp) return data.hasMatch(d); - return JSON.encode(data) == JSON.encode(d); + if (req.data == null) return false; + if (data is File) return data == req.data; + assert(req.data is String); + if (data is RegExp) return data.hasMatch(req.data); + return JSON.encode(data) == JSON.encode(req.data); } - bool matchWithCredentials(withCredentials) => this.withCredentials == withCredentials; + bool matchWithCredentials(req) { + if (withCredentials == null) return true; + if (req.withCredentials == null) return true; + return withCredentials == req.withCredentials; + } String toString() => "$method $url"; } @@ -117,13 +117,32 @@ class _Chain { respond([x,y,z]) => _respondFn(x,y,z); } + +/** + * An internal class used by [MockHttpBackend]. + */ +class RecordedRequest { + final String method; + final url, callback, data, headers, timeout; + final bool withCredentials; + + RecordedRequest({this.method, this.url, this.callback, this.data, + this.headers, this.timeout, this.withCredentials}); + + bool matchMethodAndUrl(method, url) => + this.method == method && _matchUrl(url, this.url); +} + +bool _matchUrl(expected, actual) => + (expected is RegExp) ? expected.hasMatch(actual) : expected == actual; + /** * A mock implementation of [HttpBackend], used in tests. */ class MockHttpBackend implements HttpBackend { var definitions = [], expectations = [], - responses = []; + requests = []; /** * This function is called from [Http] and designed to mimic the Dart APIs. @@ -164,81 +183,16 @@ 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, callback, {data, headers, timeout, withCredentials: false}) { - var xhr = new _MockXhr(), - expectation = expectations.isEmpty ? null : expectations[0], - wasExpected = false; - - var prettyPrint = (data) { - return (data is String || data is Function || data is RegExp) - ? data - : JSON.encode(data); - }; - - var wrapResponse = (wrapped) { - var handleResponse = () { - var response = wrapped.response(method, url, data, headers); - xhr.respHeaders = response[2]; - utils.relaxFnApply(callback, [response[0], response[1], - xhr.getAllResponseHeaders()]); - }; - - var handleTimeout = () { - for (var i = 0; i < responses.length; i++) { - if (identical(responses[i], handleResponse)) { - responses.removeAt(i); - callback(-1, null, ''); - break; - } - } - }; - - if (timeout != null) timeout.then(handleTimeout); - return handleResponse; - }; - - if (expectation != null && expectation.match(method, url)) { - if (!expectation.matchData(data)) - throw ['Expected $expectation with different data\n' + - 'EXPECTED: ${prettyPrint(expectation.data)}\nGOT: $data']; - - if (!expectation.matchHeaders(headers)) - throw ['Expected $expectation with different headers\n' - '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) { - responses.add(wrapResponse(expectation)); - return; - } - wasExpected = true; - } - - for (var definition in definitions) { - 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)); - } else throw ['No response defined !']; - return; - } - } - throw wasExpected ? - ['No response defined !'] : - ['Unexpected request: $method $url\n' + (expectation != null ? - 'Expected $expectation' : - 'No more requests expected')]; + requests.add(new RecordedRequest( + method: method, + url: url, + callback: callback, + data: data, + headers: headers, + timeout: timeout, + withCredentials: withCredentials + )); } /** @@ -475,19 +429,6 @@ class MockHttpBackend implements HttpBackend { _Chain expectPATCH(url, [data, headers, withCredentials = false]) => expect('PATCH', url, data, headers, withCredentials); - /** - * @ngdoc method - * @name ngMock.httpBackend#expectHEAD - * @methodOf ngMock.httpBackend - * @description - * Creates a new request expectation for HEAD requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - /** * @ngdoc method * @name ngMock.httpBackend#flush @@ -500,21 +441,147 @@ class MockHttpBackend implements HttpBackend { * is called an exception is thrown (as this typically a sign of programming error). */ void flush([count]) { - if (responses.isEmpty) throw ['No pending request to flush !']; + if (requests.isEmpty) throw ['No pending request to flush !']; if (count != null) { while (count-- > 0) { - if (responses.isEmpty) throw ['No more pending request to flush !']; - responses.removeAt(0)(); + if (requests.isEmpty) throw ['No more pending request to flush !']; + _processRequest(requests.removeAt(0)); } } else { - while (!responses.isEmpty) { - responses.removeAt(0)(); + while (!requests.isEmpty) { + _processRequest(requests.removeAt(0)); } } verifyNoOutstandingExpectation(); } + /** + * Creates a new expectation and flushes all pending requests until the one matching the expectation. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers or function that + * receives http header object and returns true if the headers match the + * current definition. + * @returns {requestHandler} Returns an object with `respond` method that + * control how a matched request is handled. + * + * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + _Chain flushExpected(String method, url, [data, headers, withCredentials = false]) { + var expectation = new MockHttpExpectation(method, url, data, headers, withCredentials); + expectations.add(expectation); + + flushUntilMethodAndUrlMatch () { + while (requests.isNotEmpty) { + final r = requests.removeAt(0); + _processRequest(r); + if (r.matchMethodAndUrl(method, url)) return; + } + throw ['No more pending requests matching $method $url']; + } + + return new _Chain(respond: (status, data, headers) { + expectation.response = _createResponse(status, data, headers); + flushUntilMethodAndUrlMatch(); + }); + } + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushGET + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for GET requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushGET(url, [headers, withCredentials = false]) => + flushExpected("GET", url, null, headers, withCredentials); + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushPOST + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for POST requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushPOST(url, [data, headers, withCredentials = false]) => + flushExpected("POST", url, data, headers, withCredentials); + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushPUT + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for PUT requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushPUT(url, [data, headers, withCredentials = false]) => + flushExpected("PUT", url, data, headers, withCredentials); + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushPATCH + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for PATCH requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushPATCH(url, [data, headers, withCredentials = false]) => + flushExpected("PATCH", url, data, headers, withCredentials); + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushDELETE + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for DELETE requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushDELETE(url, [headers, withCredentials = false]) => + flushExpected("DELETE", url, null, headers, withCredentials); + + /** + * @ngdoc method + * @name ngMock.httpBackend#flushJSONP + * @methodOf ngMock.httpBackend + * @description + * Creates a new request expectation for JSONP requests. For more info see `flushExpected()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + _Chain flushJSONP(url, [headers, withCredentials = false]) => + flushExpected("JSONP", url, null, headers, withCredentials); + /** * @ngdoc method @@ -553,7 +620,7 @@ class MockHttpBackend implements HttpBackend { * */ void verifyNoOutstandingRequest() { - if (!responses.isEmpty) throw ['Unflushed requests: ${responses.length}']; + if (!requests.isEmpty) throw ['Unflushed requests: ${requests.length}']; } @@ -568,7 +635,96 @@ class MockHttpBackend implements HttpBackend { */ void resetExpectations() { expectations.length = 0; - responses.length = 0; + requests.length = 0; + } + + + void _processRequest(RecordedRequest req) { + prettyPrint(data) { + return (data is String || data is Function || data is RegExp) + ? data + : JSON.encode(data); + } + + handleResponse(expectation) { + final xhr = new _MockXhr(); + final response = expectation.response(req.method, req.url, req.data, req.headers); + + final status = response[0]; + final data = response[1]; + xhr.respHeaders = response[2]; + + utils.relaxFnApply(req.callback, [status, data, xhr.getAllResponseHeaders()]); + } + + handleResponseAndTimeout(expectation) { + if (req.timeout != null) { + req.timeout.then(() => req.callback(-1, null, '')); + } else { + handleResponse(expectation); + } + } + + checkExpectation(expectation) { + if (!expectation.matchData(req)) { + throw ['Expected $expectation with different data\n' + 'EXPECTED: ${prettyPrint(expectation.data)}\nGOT: ${req.data}']; + } + + if (!expectation.matchHeaders(req)) { + throw ['Expected $expectation with different headers\n' + 'EXPECTED: ${prettyPrint(expectation.headers)}\n' + 'GOT: ${prettyPrint(req.headers)}']; + } + + if (!expectation.matchWithCredentials(req)) { + throw ['Expected $expectation with different withCredentials\n' + 'EXPECTED: ${prettyPrint(expectation.withCredentials)}\n' + 'GOT: ${prettyPrint(req.withCredentials)}']; + } + } + + hasResponse(d) => d != null && d.response != null; + + executeFirstExpectation(e, d) { + checkExpectation(e); + expectations.remove(e); + + if (hasResponse(e)) { + handleResponseAndTimeout(e); + } else if (hasResponse(d)) { + handleResponseAndTimeout(d); + } else { + throw ['No response defined !']; + } + } + + executeMatchingDefinition(e, d) { + if (hasResponse(d)) { + handleResponseAndTimeout(d); + } else if (d != null) { + throw ['No response defined !'];; + } else if (e != null) { + throw ['Unexpected request: ${req.method} ${req.url}\nExpected $e']; + } else { + throw ['Unexpected request: ${req.method} ${req.url}\nNo more requests expected']; + } + } + + firstExpectation() => + expectations.isEmpty ? null : expectations.first; + + matchingDefinition() => + definitions.firstWhere((d) => d.match(req), orElse: () => null); + + final e = firstExpectation(); + final d = matchingDefinition(); + + if (e != null && e.matchMethodAndUrl(req)) { + executeFirstExpectation(e, d); + } else { + executeMatchingDefinition(e, d); + } } } diff --git a/test/core_dom/http_spec.dart b/test/core_dom/http_spec.dart index edcf2222b..89a7aa86e 100644 --- a/test/core_dom/http_spec.dart +++ b/test/core_dom/http_spec.dart @@ -70,16 +70,14 @@ void main() { it('should do basic request', async(() { - backend.expect('GET', '/url').respond(''); http(url: '/url', method: 'GET'); - flush(); + backend.flushGET('/url').respond(''); })); it('should pass data if specified', async(() { - backend.expect('POST', '/url', 'some-data').respond(''); http(url: '/url', method: 'POST', data: 'some-data'); - flush(); + backend.flushPOST('/url', 'some-data').respond(''); })); @@ -89,13 +87,15 @@ void main() { // we don't care about the data field. backend.expect('POST', '/url', 'null').respond(''); + expect(() { http(url: '/url', method: 'POST'); + backend.flush(); }).toThrow('with different data'); // satisfy the expectation for our afterEach's assert. http(url: '/url', method: 'POST', data: 'null'); - flush(); + backend.flush(); })); describe('backend', () { @@ -975,8 +975,9 @@ void main() { 'synchronous', async(() { backend.expect('POST', '/url', '').respond(''); http(url: '/url', method: 'POST', data: ''); + expect(interceptorCalled).toBe(true); - expect(backend.responses.isEmpty).toBe(false); // request made immediately + expect(backend.requests.isEmpty).toBe(false); // request made immediately flush(); })); }); diff --git a/test/mock/http_backend_spec.dart b/test/mock/http_backend_spec.dart index e8842f2b3..01df2982d 100644 --- a/test/mock/http_backend_spec.dart +++ b/test/mock/http_backend_spec.dart @@ -80,6 +80,7 @@ void main() { hb.when('GET', '/url1').respond(200, 'content'); expect(() { hb('GET', '/xxx', noop); + hb.flush(); }).toThrow('Unexpected request: GET /xxx\nNo more requests expected'); }); @@ -226,11 +227,10 @@ void main() { describe('expect()', () { it('should require specified order', () { - hb.expect('GET', '/url1').respond(200, ''); - hb.expect('GET', '/url2').respond(200, ''); - expect(() { hb('GET', '/url2', noop, headers: {}); + + hb.flushExpected('GET', '/url1').respond(200, ''); }).toThrow('Unexpected request: GET /url2\nExpected GET /url1'); }); @@ -256,6 +256,7 @@ void main() { expect(() { hb('GET', '/match', noop, headers: {}); + hb.flush(); }).toThrow('Expected GET /match with different headers\n' + 'EXPECTED: {"Content-Type":"application/json"}\nGOT: {}'); }); @@ -267,6 +268,7 @@ void main() { expect(() { hb('GET', '/match', noop, data: 'different'); + hb.flush(); }).toThrow('Expected GET /match with different data\n' + 'EXPECTED: some-data\nGOT: different'); }); @@ -318,7 +320,7 @@ void main() { hb.when('GET').respond(200, ''); hb('GET', '/url', callback); - expect(() {hb.flush(2);}).toThrow('No more pending request to flush !'); + expect(() {hb.flush(2); }).toThrow('No more pending request to flush !'); expect(callback).toHaveBeenCalledOnce(); }); @@ -352,6 +354,7 @@ void main() { }); hb('GET', '/url1', callback, timeout: new _Chain(then: then)); + hb.flush(); expect(canceler is Function).toBe(true); canceler(); // simulate promise resolution @@ -366,6 +369,7 @@ void main() { hb.when('GET', '/test'); expect(() { hb('GET', '/test', callback); + hb.flush(); }).toThrow('No response defined !'); }); @@ -374,10 +378,10 @@ void main() { hb.expect('GET', '/url'); expect(() { hb('GET', '/url', callback); + hb.flush(); }).toThrow('No response defined !'); }); - it('should respond undefined when JSONP method', () { hb.when('JSONP', '/url1').respond(200); hb.expect('JSONP', '/url2').respond(200); @@ -395,9 +399,11 @@ void main() { hb.expect('POST', '/u3').respond(201, '', {}); hb('POST', '/u1', noop, data: 'ddd', headers: {}); + expect(() {hb.flush(1); }).toThrow(); - expect(() {hb.verifyNoOutstandingExpectation();}). - toThrow('Unsatisfied requests: GET /u2, POST /u3'); + expect(() { + hb.verifyNoOutstandingExpectation(); + }).toThrow('Unsatisfied requests: GET /u2, POST /u3'); }); @@ -415,6 +421,7 @@ void main() { hb('GET', '/u2', noop); hb('POST', '/u3', noop); + hb.flush(); expect(() {hb.verifyNoOutstandingExpectation();}).not.toThrow(); }); @@ -501,24 +508,57 @@ void main() { }); + describe("flushExpected()", () { + it("flushes all the requests until a matching one is found", () { + hb.when("GET", '/first').respond("OK"); + + hb("GET", '/first', callback); + hb("GET", '/second', callback); + hb("GET", '/third', callback); + + hb.flushExpected("GET", "/second").respond("OK"); + + expect(hb.requests.length).toEqual(1); + expect(hb.requests.first.url).toEqual("/third"); + }); + }); + + + describe('flush shortcuts', () { + [[(x, r) => hb.flushGET(x).respond(r), 'GET'], + [(x, r) => hb.flushPOST(x).respond(r), 'POST'], + [(x, r) => hb.flushPUT(x).respond(r), 'PUT'], + [(x, r) => hb.flushPATCH(x).respond(r), 'PATCH'], + [(x, r) => hb.flushDELETE(x).respond(r), 'DELETE'], + [(x, r) => hb.flushJSONP(x).respond(r), 'JSONP'] + ].forEach((step) { + var shortcut = step[0], method = step[1]; + it('should provide $shortcut shortcut method', () { + hb(method, '/foo', callback); + shortcut('/foo', 'bar'); + expect(callback).toHaveBeenCalledOnceWith(200, 'bar', ''); + }); + }); + }); + describe('MockHttpExpectation', () { it('should accept url as regexp', () { var exp = new MockHttpExpectation('GET', new RegExp('^\/x')); - expect(exp.match('GET', '/x')).toBe(true); - expect(exp.match('GET', '/xxx/x')).toBe(true); - expect(exp.match('GET', 'x')).toBe(false); - expect(exp.match('GET', 'a/x')).toBe(false); + expect(exp.match(new RecordedRequest(method: 'GET', url: '/x'))).toBe(true); + expect(exp.match(new RecordedRequest(method: 'GET', url: '/xxx/x'))).toBe(true); + expect(exp.match(new RecordedRequest(method: 'GET', url: 'x'))).toBe(false); + expect(exp.match(new RecordedRequest(method: 'GET', url: 'a/x'))).toBe(false); }); it('should accept data as regexp', () { var exp = new MockHttpExpectation('POST', '/url', new RegExp('\{.*?\}')); - expect(exp.match('POST', '/url', '{"a": "aa"}')).toBe(true); - expect(exp.match('POST', '/url', '{"one": "two"}')).toBe(true); - expect(exp.match('POST', '/url', '{"one"')).toBe(false); + expect(exp.match(new RecordedRequest(method: 'POST', url: '/url', data: '{"a": "aa"}'))).toBe(true); + expect(exp.match(new RecordedRequest(method: 'POST', url: '/url', data: '{"one": "two"}'))).toBe(true); + expect(exp.match(new RecordedRequest(method: 'POST', url: '/url', data: '{"one"'))).toBe(false); }); @@ -527,8 +567,9 @@ void main() { return h['Content-Type'] == 'application/json'; }); - expect(exp.matchHeaders({})).toBe(false); - expect(exp.matchHeaders({'Content-Type': 'application/json', 'X-Another': 'true'})).toBe(true); + expect(exp.matchHeaders(new RecordedRequest(headers: {}))).toBe(false); + expect(exp.matchHeaders(new RecordedRequest( + headers: {'Content-Type': 'application/json', 'X-Another': 'true'}))).toBe(true); }); }); }); From 2bbc18345ead6e701cd353109774070a798e46b0 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Mon, 7 Jul 2014 10:43:43 -0400 Subject: [PATCH 2/2] refactor(tests): change tests to use flushGET instead of expectGET --- test/core/templateurl_spec.dart | 74 ++++++++++----------------- test/core_dom/view_cache_spec.dart | 6 +-- test/core_dom/web_platform_spec.dart | 73 ++++++++++---------------- test/directive/ng_base_css_spec.dart | 51 +++++++----------- test/playback/playback_http_spec.dart | 8 +-- 5 files changed, 74 insertions(+), 138 deletions(-) diff --git a/test/core/templateurl_spec.dart b/test/core/templateurl_spec.dart index fca4105fa..21d4ee984 100644 --- a/test/core/templateurl_spec.dart +++ b/test/core/templateurl_spec.dart @@ -98,16 +98,15 @@ _run({resolveUrls, staticMode}) { Injector injector, VmTurnZone zone, MockHttpBackend backend, DirectiveMap directives) { - backend - ..whenGET('PREFIX:${prefix}simple.html').respond('
Simple!
') - ..whenGET('PREFIX:${prefix}simple.css').respond('.hello{}'); - var element = e('
ignore
'); zone.run(() { compile([element], directives)(rootScope, null, [element]); }); - backend.flush(); + backend + ..flushGET('PREFIX:${prefix}simple.css').respond('.hello{}') + ..flushGET('PREFIX:${prefix}simple.html').respond('
Simple!
'); + microLeap(); expect(element).toHaveText('.hello{}Simple!'); @@ -131,13 +130,10 @@ _run({resolveUrls, staticMode}) { it('should replace element with template from url', async( (Http http, Compiler compile, Scope rootScope, Logger log, Injector injector, MockHttpBackend backend, DirectiveMap directives) { - backend.expectGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = es('
ignore
'); compile(element, directives)(rootScope, null, element); - microLeap(); - backend.flush(); + backend.flushGET('${prefix}simple.html').respond(200, '
Simple!
'); microLeap(); expect(element[0]).toHaveText('Simple!'); @@ -149,8 +145,6 @@ _run({resolveUrls, staticMode}) { it('should load template from URL once', async( (Http http, Compiler compile, Scope rootScope, Logger log, Injector injector, MockHttpBackend backend, DirectiveMap directives) { - backend.whenGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = es( '
' 'ignore' @@ -158,8 +152,7 @@ _run({resolveUrls, staticMode}) { '
'); compile(element, directives)(rootScope, null, element); - microLeap(); - backend.flush(); + backend.flushGET('${prefix}simple.html').respond(200, '
Simple!
'); microLeap(); expect(element.first).toHaveText('Simple!Simple!'); @@ -172,15 +165,13 @@ _run({resolveUrls, staticMode}) { it('should load a CSS file into a style', async( (Http http, Compiler compile, Scope rootScope, Logger log, Injector injector, MockHttpBackend backend, DirectiveMap directives) { - backend - ..expectGET('${prefix}simple.css').respond(200, '.hello{}') - ..expectGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = e('
ignore
'); compile([element], directives)(rootScope, null, [element]); - microLeap(); - backend.flush(); + backend + ..flushGET('${prefix}simple.css').respond(200, '.hello{}') + ..flushGET('${prefix}simple.html').respond(200, '
Simple!
'); + microLeap(); expect(element).toHaveText('.hello{}Simple!'); @@ -196,12 +187,11 @@ _run({resolveUrls, staticMode}) { (Http http, Compiler compile, Scope rootScope, Injector injector, MockHttpBackend backend, DirectiveMap directives) { var element = es('
ignore
'); - backend.expectGET('${prefix}simple.css').respond(200, '.hello{}'); compile(element, directives)(rootScope, null, element); + backend.flushGET('${prefix}simple.css').respond(200, '.hello{}'); microLeap(); - backend.flush(); - microLeap(); + expect(element[0]).toHaveText('.hello{}inline!'); })); @@ -209,12 +199,11 @@ _run({resolveUrls, staticMode}) { (Http http, Compiler compile, Scope rootScope, Injector injector, MockHttpBackend backend, DirectiveMap directives) { var element = es('
ignore
'); - backend.expectGET('${prefix}simple.css').respond(500, 'some error'); compile(element, directives)(rootScope, null, element); + backend.flushGET('${prefix}simple.css').respond(500, 'some error'); microLeap(); - backend.flush(); - microLeap(); + expect(element.first).toHaveText( '/*\n' 'HTTP 500: some error\n' @@ -226,28 +215,25 @@ _run({resolveUrls, staticMode}) { (Http http, Compiler compile, Scope rootScope, Injector injector, MockHttpBackend backend, DirectiveMap directives) { var element = es('
ignore
'); - backend.expectGET('${prefix}simple.css').respond(200, '.hello{}'); compile(element, directives)(rootScope, null, element); + backend.flushGET('${prefix}simple.css').respond(200, '.hello{}'); microLeap(); - backend.flush(); - microLeap(); + expect(element[0]).toHaveText('.hello{}'); })); it('should load the CSS before the template is loaded', async( (Http http, Compiler compile, Scope rootScope, Injector injector, MockHttpBackend backend, DirectiveMap directives) { - backend - ..expectGET('${prefix}simple.css').respond(200, '.hello{}') - ..expectGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = es('ignore'); compile(element, directives)(rootScope, null, element); + backend + ..flushGET('${prefix}simple.css').respond(200, '.hello{}') + ..flushGET('${prefix}simple.html').respond(200, '
Simple!
'); microLeap(); - backend.flush(); - microLeap(); + expect(element.first).toHaveText('.hello{}Simple!'); })); }); @@ -262,16 +248,13 @@ _run({resolveUrls, staticMode}) { it('should load multiple CSS files into a style', async( (Http http, Compiler compile, Scope rootScope, Logger log, Injector injector, MockHttpBackend backend, DirectiveMap directives) { - backend - ..expectGET('${prefix}simple.css').respond(200, '.hello{}') - ..expectGET('${prefix}another.css').respond(200, '.world{}') - ..expectGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = e('
ignore
'); compile([element], directives)(rootScope, null, [element]); - microLeap(); - backend.flush(); + backend + ..flushGET('${prefix}simple.css').respond(200, '.hello{}') + ..flushGET('${prefix}another.css').respond(200, '.world{}') + ..flushGET('${prefix}simple.html').respond(200, '
Simple!
'); microLeap(); expect(element).toHaveText('.hello{}.world{}Simple!'); @@ -295,15 +278,12 @@ _run({resolveUrls, staticMode}) { it('should load css from the style cache for the second component', async( (Http http, Compiler compile, MockHttpBackend backend, RootScope rootScope, DirectiveMap directives, Injector injector) { - backend - ..expectGET('${prefix}simple.css').respond(200, '.hello{}') - ..expectGET('${prefix}simple.html').respond(200, '
Simple!
'); - var element = e('
ignore
'); compile([element], directives)(rootScope, null, [element]); - microLeap(); - backend.flush(); + backend + ..flushGET('${prefix}simple.css').respond(200, '.hello{}') + ..flushGET('${prefix}simple.html').respond(200, '
Simple!
'); microLeap(); expect(element.children[0].shadowRoot).toHaveHtml( diff --git a/test/core_dom/view_cache_spec.dart b/test/core_dom/view_cache_spec.dart index a812be408..6ab731692 100644 --- a/test/core_dom/view_cache_spec.dart +++ b/test/core_dom/view_cache_spec.dart @@ -20,14 +20,10 @@ main() { expect(cache.fromHtml(HTML, directives)).toBe(firstFactory); - // Also for fromUrl - backend.whenGET('template.url').respond(200, HTML); - var httpFactory; cache.fromUrl('template.url', directives, Uri.base).then((f) => httpFactory = f); - microLeap(); - backend.flush(); + backend.flushGET('template.url').respond(200, HTML); microLeap(); expect(httpFactory).toBe(firstFactory); diff --git a/test/core_dom/web_platform_spec.dart b/test/core_dom/web_platform_spec.dart index 178b8a439..95b550165 100644 --- a/test/core_dom/web_platform_spec.dart +++ b/test/core_dom/web_platform_spec.dart @@ -19,19 +19,14 @@ main() { it('should scope styles to shadow dom across browsers.', async((TestBed _, MockHttpBackend backend, WebPlatform platform) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, 'span { background-color: red; ' - '}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); - Element element = e('ignore' ''); _.compile(element); - microLeap(); - backend.flush(); - microLeap(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, 'span {background-color: red;}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); try { document.body.append(element); @@ -58,37 +53,27 @@ main() { it('should not crash with an attribute selector; but wont work either..', async((TestBed _, MockHttpBackend backend, WebPlatform platform) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, 'span { background-color: red; ' - '}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); - Element element = e('ignore' ''); _.compile(element); - microLeap(); - backend.flush(); - microLeap(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, 'span{background-color: red}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); })); it('should scope :host styles to the primary element.', async((TestBed _, MockHttpBackend backend, WebPlatform platform) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, ':host {' - 'background-color: red; }') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); - Element element = e('ignore' ''); _.compile(element); - microLeap(); - backend.flush(); - microLeap(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/style.css').respond(200, ':host {background-color: red; }') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/core_dom/template.html').respond(200, 'foo'); try { document.body.append(element); @@ -109,21 +94,17 @@ main() { xit('should scope ::content rules to component content.', async((TestBed _, MockHttpBackend backend, WebPlatform platform) { - backend - ..expectGET('style.css').respond(200, - "polyfill-next-selector { content: ':host span:not([:host])'; }" - "::content span { background-color: red; }") - ..expectGET('template.html').respond(200, - ''); - Element element = e('RED' ''); _.compile(element); - microLeap(); - backend.flush(); - microLeap(); + backend + ..flushGET('style.css').respond(200, + "polyfill-next-selector { content: ':host span:not([:host])'; }" + "::content span { background-color: red; }") + ..flushGET('template.html').respond(200, + ''); try { document.body.append(element); @@ -147,25 +128,23 @@ main() { xit('should style into child shadow dom with ::shadow.', async((TestBed _, MockHttpBackend backend, WebPlatform platform) { - backend - ..expectGET('outer-style.css').respond(200, 'my-inner::shadow .foo {' - 'background-color: red; }') - ..expectGET('outer-html.html').respond(200, - 'foo'); - - Element element = e(''); _.compile(element); - microLeap(); + backend - ..flush() - ..expectGET('inner-style.css').respond(200, '/* no style */') - ..expectGET('inner-html.html').respond(200, - ''); + ..flushGET('outer-style.css').respond(200, + 'my-inner::shadow .foo {background-color: red; }') + ..flushGET('outer-html.html').respond(200, + 'foo'); + microLeap(); - backend.flush(); + + backend + ..flushGET('inner-style.css').respond(200, '/* no style */') + ..flushGET('inner-html.html').respond(200, + ''); try { document.body.append(element); diff --git a/test/directive/ng_base_css_spec.dart b/test/directive/ng_base_css_spec.dart index e35e04233..0ba79f75a 100644 --- a/test/directive/ng_base_css_spec.dart +++ b/test/directive/ng_base_css_spec.dart @@ -24,16 +24,13 @@ main() => describe('NgBaseCss', () { }); it('should load css urls from ng-base-css', async((TestBed _, MockHttpBackend backend) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') - ..expectGET('base.css').respond(200, '.base{}'); - var element = e('
ignore
'); _.compile(element); - microLeap(); - backend.flush(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') + ..flushGET('base.css').respond(200, '.base{}'); microLeap(); expect(element.children[0].shadowRoot).toHaveHtml( @@ -42,16 +39,13 @@ main() => describe('NgBaseCss', () { })); it('ng-base-css should overwrite parent ng-base-csses', async((TestBed _, MockHttpBackend backend) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') - ..expectGET('base.css').respond(200, '.base{}'); - var element = e('
ignore
'); _.compile(element); - microLeap(); - backend.flush(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') + ..flushGET('base.css').respond(200, '.base{}'); microLeap(); expect(element.children[0].children[0].shadowRoot).toHaveHtml( @@ -60,15 +54,12 @@ main() => describe('NgBaseCss', () { })); it('should respect useNgBaseCss', async((TestBed _, MockHttpBackend backend) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
'); - var element = e('
ignore
'); _.compile(element); - microLeap(); - backend.flush(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
'); microLeap(); expect(element.children[0].shadowRoot).toHaveHtml( @@ -82,16 +73,13 @@ main() => describe('NgBaseCss', () { }); it('ng-base-css should be available from the injector', async((TestBed _, MockHttpBackend backend) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') - ..expectGET('injected.css').respond(200, '.injected{}'); - var element = e('
ignore
'); _.compile(element); - microLeap(); - backend.flush(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
') + ..flushGET('injected.css').respond(200, '.injected{}'); microLeap(); expect(element.children[0].shadowRoot).toHaveHtml( @@ -100,15 +88,12 @@ main() => describe('NgBaseCss', () { })); it('should respect useNgBaseCss', async((TestBed _, MockHttpBackend backend) { - backend - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') - ..expectGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
'); - var element = e('
ignore
'); _.compile(element); - microLeap(); - backend.flush(); + backend + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.css').respond(200, '.simple{}') + ..flushGET('${TEST_SERVER_BASE_PREFIX}test/directive/simple.html').respond(200, '
Simple!
'); microLeap(); expect(element.children[0].shadowRoot).toHaveHtml( diff --git a/test/playback/playback_http_spec.dart b/test/playback/playback_http_spec.dart index 8cf7c7647..e2abc8d5c 100644 --- a/test/playback/playback_http_spec.dart +++ b/test/playback/playback_http_spec.dart @@ -27,25 +27,21 @@ void main() { it('should record a request', async((Http http) { - backend.expectGET('request').respond(200, 'response'); - var responseData; http(method: 'GET', url: 'request').then((HttpResponse r) { responseData = r.data; }); + backend.flushGET('request').respond(200, 'response'); microLeap(); - backend.flush(); backend - .expectPOST('/record', + .flushPOST('/record', r'{"key":"{\"url\":\"request\",\"method\":\"GET\",\"requestHeaders\":' r'{\"Accept\":\"application/json, text/plain, */*\",\"X-XSRF-TOKEN\":\"secret\"},\"data\":null}",' r'"data":"{\"status\":200,\"headers\":\"\",\"data\":\"response\"}"}') .respond(200); - microLeap(); - backend.flush(); microLeap(); expect(responseData).toEqual('response');