OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library webdriver; | 5 library webdriver; |
6 | 6 |
7 import 'dart:json'; | 7 import 'dart:json' as json; |
8 import 'dart:uri'; | 8 import 'dart:uri'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:math'; | |
11 | 10 |
12 part 'src/base64decoder.dart'; | 11 part 'src/base64decoder.dart'; |
13 | 12 |
14 /** | 13 /** |
15 * WebDriver bindings for Dart. | 14 * WebDriver bindings for Dart. |
16 * | 15 * |
17 * These bindings are based on the WebDriver JSON wire protocol spec | 16 * These bindings are based on the WebDriver JSON wire protocol spec |
18 * (http://code.google.com/p/selenium/wiki/JsonWireProtocol). Not | 17 * (http://code.google.com/p/selenium/wiki/JsonWireProtocol). Not |
19 * all of these commands are implemented yet by WebDriver itself. | 18 * all of these commands are implemented yet by WebDriver itself. |
20 * Nontheless this is a complete implementation of the spec as the | 19 * Nontheless this is a complete implementation of the spec as the |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 * http://localhost:4444/wd/hub. | 199 * http://localhost:4444/wd/hub. |
201 */ | 200 */ |
202 WebDriverBase.fromUrl([this._url = 'http://localhost:4444/wd/hub']) { | 201 WebDriverBase.fromUrl([this._url = 'http://localhost:4444/wd/hub']) { |
203 // Break out the URL components. | 202 // Break out the URL components. |
204 var re = new RegExp('[^:/]+://([^/]+)(/.*)'); | 203 var re = new RegExp('[^:/]+://([^/]+)(/.*)'); |
205 var matches = re.firstMatch(_url); | 204 var matches = re.firstMatch(_url); |
206 _host = matches[1]; | 205 _host = matches[1]; |
207 _path = matches[2]; | 206 _path = matches[2]; |
208 var idx = _host.indexOf(':'); | 207 var idx = _host.indexOf(':'); |
209 if (idx >= 0) { | 208 if (idx >= 0) { |
210 _port = parseInt(_host.substring(idx+1)); | 209 _port = int.parse(_host.substring(idx+1)); |
211 _host = _host.substring(0, idx); | 210 _host = _host.substring(0, idx); |
212 } else { | 211 } else { |
213 _port = 80; | 212 _port = 80; |
214 } | 213 } |
215 } | 214 } |
216 | 215 |
217 WebDriverBase([ | 216 WebDriverBase([ |
218 this._host = 'localhost', | 217 this._host = 'localhost', |
219 this._port = 4444, | 218 this._port = 4444, |
220 this._path = '/wd/hub']) { | 219 this._path = '/wd/hub']) { |
(...skipping 13 matching lines...) Expand all Loading... |
234 var results = null; | 233 var results = null; |
235 var message = null; | 234 var message = null; |
236 if (successCodes == null) { | 235 if (successCodes == null) { |
237 successCodes = [ 200, 204 ]; | 236 successCodes = [ 200, 204 ]; |
238 } | 237 } |
239 try { | 238 try { |
240 if (params != null && params is List && http_method != 'POST') { | 239 if (params != null && params is List && http_method != 'POST') { |
241 throw new Exception( | 240 throw new Exception( |
242 'The http method called for ${command} is ${http_method} but it has ' | 241 'The http method called for ${command} is ${http_method} but it has ' |
243 'to be POST if you want to pass the JSON params ' | 242 'to be POST if you want to pass the JSON params ' |
244 '${JSON.stringify(params)}'); | 243 '${json.stringify(params)}'); |
245 } | 244 } |
246 | 245 |
247 var path = command; | 246 var path = command; |
248 if (params != null && (params is num || params is String)) { | 247 if (params != null && (params is num || params is String)) { |
249 path = '$path/$params'; | 248 path = '$path/$params'; |
250 } | 249 } |
251 | 250 |
252 var client = new HttpClient(); | 251 var client = new HttpClient(); |
253 var connection = client.open(http_method, _host, _port, path); | 252 var connection = client.open(http_method, _host, _port, path); |
254 | 253 |
255 connection.onRequest = (r) { | 254 connection.onRequest = (r) { |
256 r.headers.add(HttpHeaders.ACCEPT, "application/json"); | 255 r.headers.add(HttpHeaders.ACCEPT, "application/json"); |
257 r.headers.add( | 256 r.headers.add( |
258 HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8'); | 257 HttpHeaders.CONTENT_TYPE, 'application/json;charset=UTF-8'); |
259 OutputStream s = r.outputStream; | 258 OutputStream s = r.outputStream; |
260 if (params != null && params is Map) { | 259 if (params != null && params is Map) { |
261 s.writeString(JSON.stringify(params)); | 260 s.writeString(json.stringify(params)); |
262 } | 261 } |
263 s.close(); | 262 s.close(); |
264 }; | 263 }; |
265 connection.onError = (e) { | 264 connection.onError = (e) { |
266 if (completer != null) { | 265 if (completer != null) { |
267 completer.completeException(new WebDriverError(-1, e)); | 266 completer.completeException(new WebDriverError(-1, e)); |
268 completer = null; | 267 completer = null; |
269 } | 268 } |
270 }; | 269 }; |
271 connection.followRedirects = false; | 270 connection.followRedirects = false; |
272 connection.onResponse = (r) { | 271 connection.onResponse = (r) { |
273 StringInputStream s = new StringInputStream(r.inputStream); | 272 StringInputStream s = new StringInputStream(r.inputStream); |
274 StringBuffer sbuf = new StringBuffer(); | 273 StringBuffer sbuf = new StringBuffer(); |
275 s.onData = () { | 274 s.onData = () { |
276 var data = s.read(); | 275 var data = s.read(); |
277 if (data != null) { | 276 if (data != null) { |
278 sbuf.add(data); | 277 sbuf.add(data); |
279 } | 278 } |
280 }; | 279 }; |
281 s.onClosed = () { | 280 s.onClosed = () { |
282 var value = null; | 281 var value = null; |
283 results = sbuf.toString().trim(); | 282 results = sbuf.toString().trim(); |
284 // For some reason we get a bunch of NULs on the end | 283 // For some reason we get a bunch of NULs on the end |
285 // of the text and the JSON parser blows up on these, so | 284 // of the text and the json.parse blows up on these, so |
286 // strip them. We have to do this the hard way as | 285 // strip them. We have to do this the hard way as |
287 // replaceAll('\0', '') does not work. | 286 // replaceAll('\0', '') does not work. |
288 // These NULs can be seen in the TCP packet, so it is not | 287 // These NULs can be seen in the TCP packet, so it is not |
289 // an issue with character encoding; it seems to be a bug | 288 // an issue with character encoding; it seems to be a bug |
290 // in WebDriver stack. | 289 // in WebDriver stack. |
291 for (var i = results.length; --i >= 0;) { | 290 for (var i = results.length; --i >= 0;) { |
292 var code = results.charCodeAt(i); | 291 var code = results.charCodeAt(i); |
293 if (code != 0) { | 292 if (code != 0) { |
294 results = results.substring(0, i+1); | 293 results = results.substring(0, i+1); |
295 break; | 294 break; |
296 } | 295 } |
297 } | 296 } |
298 if (successCodes.indexOf(r.statusCode) < 0) { | 297 if (successCodes.indexOf(r.statusCode) < 0) { |
299 throw 'Unexpected response ${r.statusCode}'; | 298 throw 'Unexpected response ${r.statusCode}'; |
300 } | 299 } |
301 if (status == 0 && results.length > 0) { | 300 if (status == 0 && results.length > 0) { |
302 // 4xx responses send plain text; others send JSON. | 301 // 4xx responses send plain text; others send JSON. |
303 if (r.statusCode < 400) { | 302 if (r.statusCode < 400) { |
304 results = JSON.parse(results); | 303 results = json.parse(results); |
305 status = results['status']; | 304 status = results['status']; |
306 } | 305 } |
307 if (results is Map && (results as Map).containsKey('value')) { | 306 if (results is Map && (results as Map).containsKey('value')) { |
308 value = results['value']; | 307 value = results['value']; |
309 } | 308 } |
310 if (value is Map && value.containsKey('message')) { | 309 if (value is Map && value.containsKey('message')) { |
311 message = value['message']; | 310 message = value['message']; |
312 } | 311 } |
313 } | 312 } |
314 if (status == 0) { | 313 if (status == 0) { |
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 * Get the log for a given log type. Log buffer is reset after each request. | 1356 * Get the log for a given log type. Log buffer is reset after each request. |
1358 * Each log entry is a [Map] with these fields: | 1357 * Each log entry is a [Map] with these fields: |
1359 * | 1358 * |
1360 * 'timestamp' (int) - The timestamp of the entry. | 1359 * 'timestamp' (int) - The timestamp of the entry. |
1361 * 'level' (String) - The log level of the entry, for example, "INFO". | 1360 * 'level' (String) - The log level of the entry, for example, "INFO". |
1362 * 'message' (String) - The log message. | 1361 * 'message' (String) - The log message. |
1363 */ | 1362 */ |
1364 Future<List<Map>> getLogs(String type) => | 1363 Future<List<Map>> getLogs(String type) => |
1365 _post('log', params: { 'type': type }); | 1364 _post('log', params: { 'type': type }); |
1366 } | 1365 } |
OLD | NEW |