| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library XHRTask2Test; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:convert'; | |
| 9 import 'dart:html'; | |
| 10 import 'dart:typed_data'; | |
| 11 import 'package:unittest/html_individual_config.dart'; | |
| 12 import 'package:unittest/unittest.dart'; | |
| 13 | |
| 14 class MockProgressEvent implements ProgressEvent { | |
| 15 final target; | |
| 16 MockProgressEvent(this.target); | |
| 17 | |
| 18 noSuchMethod(Invocation invocation) { | |
| 19 throw "missing function in MockProgressEvent"; | |
| 20 } | |
| 21 } | |
| 22 | |
| 23 class MockHttpRequestTask implements Future<HttpRequest> { | |
| 24 final Completer completer = new Completer<HttpRequest>(); | |
| 25 final HttpRequestTaskSpecification spec; | |
| 26 final Zone zone; | |
| 27 | |
| 28 MockHttpRequestTask(this.spec, this.zone); | |
| 29 | |
| 30 void trigger(response) { | |
| 31 var xhr = new MockHttpRequest(spec, response); | |
| 32 var arg; | |
| 33 if (spec.url == "NonExistingFile") { | |
| 34 arg = new MockProgressEvent(xhr); | |
| 35 } else { | |
| 36 arg = xhr; | |
| 37 } | |
| 38 zone.runTask(run, this, arg); | |
| 39 } | |
| 40 | |
| 41 then(onData, {onError}) => completer.future.then(onData, onError: onError); | |
| 42 catchError(f, {test}) => completer.future.catchError(f, test: test); | |
| 43 whenComplete(f) => completer.future.whenComplete(f); | |
| 44 asStream() => completer.future.asStream(); | |
| 45 timeout(timeLimit, {onTimeout}) => | |
| 46 completer.future.timeout(timeLimit, onTimeout: onTimeout); | |
| 47 | |
| 48 static create(HttpRequestTaskSpecification spec, Zone zone) { | |
| 49 return new MockHttpRequestTask(spec, zone); | |
| 50 } | |
| 51 | |
| 52 static run(MockHttpRequestTask task, value) { | |
| 53 if (value is HttpRequest) { | |
| 54 task.completer.complete(value); | |
| 55 } else { | |
| 56 task.completer.completeError(value); | |
| 57 } | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 class MockHttpRequest implements HttpRequest { | |
| 62 final HttpRequestTaskSpecification spec; | |
| 63 final response; | |
| 64 | |
| 65 MockHttpRequest(this.spec, this.response); | |
| 66 | |
| 67 noSuchMethod(Invocation invocation) { | |
| 68 print("isGetter: ${invocation.isGetter}"); | |
| 69 print("isMethod: ${invocation.isMethod}"); | |
| 70 print("memberName: ${invocation.memberName}"); | |
| 71 } | |
| 72 | |
| 73 int get status => spec.url == "NonExistingFile" ? 404 : 200; | |
| 74 | |
| 75 get readyState => HttpRequest.DONE; | |
| 76 get responseText => "$response"; | |
| 77 | |
| 78 Map get responseHeaders => {'content-type': 'text/plain; charset=utf-8',}; | |
| 79 } | |
| 80 | |
| 81 main() { | |
| 82 useHtmlIndividualConfiguration(); | |
| 83 unittestConfiguration.timeout = const Duration(milliseconds: 800); | |
| 84 | |
| 85 var urlExpando = new Expando(); | |
| 86 | |
| 87 var url = 'some/url.html'; | |
| 88 | |
| 89 Function buildCreateTaskHandler(List log, List tasks) { | |
| 90 Object createTaskHandler(Zone self, ZoneDelegate parent, Zone zone, | |
| 91 TaskCreate create, TaskSpecification spec) { | |
| 92 if (spec is HttpRequestTaskSpecification) { | |
| 93 var url = spec.url; | |
| 94 var method = spec.method; | |
| 95 var withCredentials = spec.withCredentials; | |
| 96 var responseType = spec.responseType; | |
| 97 var mimeType = spec.mimeType; | |
| 98 var data = spec.sendData; | |
| 99 | |
| 100 log.add("request $url"); | |
| 101 var dataLog = data is List<int> ? "binary ${data.length}" : "$data"; | |
| 102 log.add(" method: $method withCredentials: $withCredentials " | |
| 103 "responseType: $responseType mimeType: $mimeType data: $dataLog"); | |
| 104 var task = parent.createTask(zone, MockHttpRequestTask.create, spec); | |
| 105 urlExpando[task] = url; | |
| 106 tasks.add(task); | |
| 107 return task; | |
| 108 } | |
| 109 if (spec is EventSubscriptionSpecification) { | |
| 110 EventSubscriptionSpecification eventSpec = spec; | |
| 111 if (eventSpec.target is HttpRequest) { | |
| 112 HttpRequest target = eventSpec.target; | |
| 113 log.add("event listener on http-request ${eventSpec.eventType}"); | |
| 114 if (eventSpec.eventType == "readystatechange") { | |
| 115 var oldOnData = eventSpec.onData; | |
| 116 spec = eventSpec.replace(onData: (event) { | |
| 117 oldOnData(event); | |
| 118 if (target.readyState == HttpRequest.DONE) { | |
| 119 log.add("unknown request done"); | |
| 120 } | |
| 121 }); | |
| 122 } | |
| 123 } | |
| 124 } | |
| 125 return parent.createTask(zone, create, spec); | |
| 126 } | |
| 127 | |
| 128 return createTaskHandler; | |
| 129 } | |
| 130 | |
| 131 Function buildRunTaskHandler(List log, List tasks) { | |
| 132 void runTaskHandler(Zone self, ZoneDelegate parent, Zone zone, TaskRun run, | |
| 133 Object task, Object arg) { | |
| 134 if (tasks.contains(task)) { | |
| 135 var url = urlExpando[task]; | |
| 136 if (arg is Error || arg is Exception) { | |
| 137 log.add("failed $url"); | |
| 138 } else { | |
| 139 if (arg is ProgressEvent) { | |
| 140 log.add("success $url with progress-event"); | |
| 141 } else if (arg is HttpRequest) { | |
| 142 log.add("success $url with http-request"); | |
| 143 } else { | |
| 144 log.add("success $url (unknown arg)"); | |
| 145 } | |
| 146 } | |
| 147 } | |
| 148 parent.runTask(zone, run, task, arg); | |
| 149 } | |
| 150 | |
| 151 return runTaskHandler; | |
| 152 } | |
| 153 | |
| 154 Future<List> runMocked(response, fun) async { | |
| 155 var log = []; | |
| 156 var tasks = []; | |
| 157 var future = runZoned(fun, | |
| 158 zoneSpecification: new ZoneSpecification( | |
| 159 createTask: buildCreateTaskHandler(log, tasks), | |
| 160 runTask: buildRunTaskHandler(log, tasks))); | |
| 161 // Wait a full cycle to make sure things settle. | |
| 162 await new Future(() {}); | |
| 163 var beforeTriggerLog = log.toList(); | |
| 164 log.clear(); | |
| 165 expect(tasks.length, 1); | |
| 166 tasks.single.trigger(response); | |
| 167 await future; | |
| 168 return [beforeTriggerLog, log]; | |
| 169 } | |
| 170 | |
| 171 void validate200Response(xhr) { | |
| 172 expect(xhr.status, equals(200)); | |
| 173 var data = JSON.decode(xhr.responseText); | |
| 174 expect(data, contains('feed')); | |
| 175 expect(data['feed'], contains('entry')); | |
| 176 expect(data, isMap); | |
| 177 } | |
| 178 | |
| 179 void validate404(xhr) { | |
| 180 expect(xhr.status, equals(404)); | |
| 181 // We cannot say much about xhr.responseText, most HTTP servers will | |
| 182 // include an HTML page explaining the error to a human. | |
| 183 String responseText = xhr.responseText; | |
| 184 expect(responseText, isNotNull); | |
| 185 } | |
| 186 | |
| 187 group('xhr', () { | |
| 188 test('XHR.request No file', () async { | |
| 189 var log = await runMocked("404", () { | |
| 190 var completer = new Completer(); | |
| 191 HttpRequest.request('NonExistingFile').then((_) { | |
| 192 fail('Request should not have succeeded.'); | |
| 193 }, onError: expectAsync((error) { | |
| 194 var xhr = error.target; | |
| 195 expect(xhr.readyState, equals(HttpRequest.DONE)); | |
| 196 validate404(xhr); | |
| 197 completer.complete('done'); | |
| 198 })); | |
| 199 return completer.future; | |
| 200 }); | |
| 201 expect( | |
| 202 log, | |
| 203 equals([ | |
| 204 [ | |
| 205 'request NonExistingFile', | |
| 206 ' method: null withCredentials: null responseType: null ' | |
| 207 'mimeType: null data: null', | |
| 208 ], | |
| 209 ['success NonExistingFile with progress-event'] | |
| 210 ])); | |
| 211 }); | |
| 212 | |
| 213 test('XHR.request file', () async { | |
| 214 var log = await runMocked('{"feed": {"entry": 499}}', () { | |
| 215 var completer = new Completer(); | |
| 216 HttpRequest.request(url).then(expectAsync((xhr) { | |
| 217 expect(xhr.readyState, equals(HttpRequest.DONE)); | |
| 218 validate200Response(xhr); | |
| 219 completer.complete('done'); | |
| 220 })); | |
| 221 return completer.future; | |
| 222 }); | |
| 223 expect( | |
| 224 log, | |
| 225 equals([ | |
| 226 [ | |
| 227 'request $url', | |
| 228 ' method: null withCredentials: null responseType: null ' | |
| 229 'mimeType: null data: null' | |
| 230 ], | |
| 231 ['success $url with http-request'] | |
| 232 ])); | |
| 233 }); | |
| 234 | |
| 235 test('XHR.getString file', () async { | |
| 236 var log = await runMocked("foo", () { | |
| 237 return HttpRequest.getString(url).then(expectAsync((str) {})); | |
| 238 }); | |
| 239 expect( | |
| 240 log, | |
| 241 equals([ | |
| 242 [ | |
| 243 'request $url', | |
| 244 ' method: null withCredentials: null responseType: null ' | |
| 245 'mimeType: null data: null' | |
| 246 ], | |
| 247 ['success $url with http-request'] | |
| 248 ])); | |
| 249 }); | |
| 250 | |
| 251 test('XHR.request responseType arraybuffer', () async { | |
| 252 if (Platform.supportsTypedData) { | |
| 253 var data = new Uint8List(128); | |
| 254 var log = await runMocked(data.buffer, () { | |
| 255 return HttpRequest.request(url, | |
| 256 responseType: 'arraybuffer', | |
| 257 requestHeaders: { | |
| 258 'Content-Type': 'text/xml' | |
| 259 }).then(expectAsync((xhr) { | |
| 260 expect(xhr.status, equals(200)); | |
| 261 var byteBuffer = xhr.response; | |
| 262 expect(byteBuffer, new isInstanceOf<ByteBuffer>()); | |
| 263 expect(byteBuffer, isNotNull); | |
| 264 })); | |
| 265 }); | |
| 266 expect( | |
| 267 log, | |
| 268 equals([ | |
| 269 [ | |
| 270 'request $url', | |
| 271 ' method: null withCredentials: null responseType: arraybuffer' | |
| 272 ' mimeType: null data: null' | |
| 273 ], | |
| 274 ['success $url with http-request'] | |
| 275 ])); | |
| 276 } | |
| 277 ; | |
| 278 }); | |
| 279 }); | |
| 280 } | |
| OLD | NEW |