ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.3
Committed: Tue Aug 28 23:33:10 2018 UTC (5 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-0_1
Changes since 1.2: +38 -27 lines
Log Message:
0.1

File Contents

# Content
1 NAME
2 AnyEvent::WebDriver - control browsers using the W3C WebDriver protocol
3
4 SYNOPSIS
5 # start geckodriver or any other w3c-compatible webdriver via the shell
6 $ geckdriver -b myfirefox/firefox --log trace --port 4444
7
8 # then use it
9 use AnyEvent::WebDriver;
10
11 # create a new webdriver object
12 my $wd = new AnyEvent::WebDriver;
13
14 # create a new session with default capabilities.
15 $wd->new_session ({});
16
17 $wd->navigate_to ("https://duckduckgo.com/html");
18 my $searchbox = $wd->find_element ("css selector" => 'input[type="text"]');
19
20 $wd->element_send_keys ($searchbox => "free software");
21 $wd->element_click ($wd->find_element ("css selector" => 'input[type="submit"]'));
22
23 sleep 10;
24
25 DESCRIPTION
26 This module aims to implement the W3C WebDriver specification which is
27 the standardised equivalent to the Selenium WebDriver API., which in
28 turn aims at remotely controlling web browsers such as Firefox or
29 Chromium.
30
31 At the time of this writing, it was only available as a draft document,
32 so changes will be expected. Also, only geckodriver did implement it, or
33 at least, most of it.
34
35 To make most of this module, or, in fact, to make any reasonable use of
36 this module, you would need to refer tot he W3C WebDriver document,
37 which can be found here <https://w3c.github.io/webdriver/>:
38
39 https://w3c.github.io/webdriver/
40
41 CREATING WEBDRIVER OBJECTS
42 new AnyEvent::WebDriver key => value...
43 Create a new WebDriver object. Example for a remote WebDriver
44 connection (the only type supported at the moment):
45
46 my $wd = new AnyEvent::WebDriver host => "localhost", port => 4444;
47
48 Supported keys are:
49
50 endpoint => $string
51 For remote connections, the endpoint to connect to (defaults to
52 "http://localhost:4444").
53
54 proxy => $proxyspec
55 The proxy to use (same as the "proxy" argument used by
56 AnyEvent::HTTP). The default is "undef", which disables proxies.
57 To use the system-provided proxy (e.g. "http_proxy" environment
58 variable), specify a value of "default".
59
60 autodelete => $boolean
61 If true (the default), then automatically execute
62 "delete_session" when the WebDriver object is destroyed with an
63 active session. IF set to a false value, then the session will
64 continue to exist.
65
66 timeout => $seconds
67 The HTTP timeout, in (fractional) seconds (default: 300, but
68 this will likely drastically reduce). This timeout is reset on
69 any activity, so it is not an overall request timeout. Also,
70 individual requests might extend this timeout if they are known
71 to take longer.
72
73 SIMPLIFIED API
74 This section documents the simplified API, which is really just a very
75 thin wrapper around the WebDriver protocol commands. They all block
76 (using AnyEvent condvars) the caller until the result is available, so
77 must not be called from an event loop callback - see "EVENT BASED API"
78 for an alternative.
79
80 The method names are pretty much taken directly from the W3C WebDriver
81 specification, e.g. the request documented in the "Get All Cookies"
82 section is implemented via the "get_all_cookies" method.
83
84 The order is the same as in the WebDriver draft at the time of this
85 writing, and only minimal massaging is done to request parameters and
86 results.
87
88 SESSIONS
89 $wd->new_session ({ key => value... })
90 Try to connect to the WebDriver and initialize a new session with a
91 "new session" command, passing the given key-value pairs as value
92 (e.g. "capabilities").
93
94 No session-dependent methods must be called before this function
95 returns successfully, and only one session can be created per
96 WebDriver object.
97
98 On success, "$wd->{sid}" is set to the session ID, and
99 "$wd->{capabilities}" is set to the returned capabilities.
100
101 my $wd = new AnyEvent::Selenium endpoint => "http://localhost:4545";
102
103 $wd->new_session ({
104 capabilities => {
105 pageLoadStrategy => "normal",
106 }.
107 });
108
109 $wd->delete_session
110 Deletes the session - the WebDriver object must not be used after
111 this call.
112
113 $timeouts = $wd->get_timeouts
114 Get the current timeouts, e.g.:
115
116 my $timeouts = $wd->get_timeouts;
117 => { implicit => 0, pageLoad => 300000, script => 30000 }
118
119 $wd->set_timeouts ($timeouts)
120 Sets one or more timeouts, e.g.:
121
122 $wd->set_timeouts ({ script => 60000 });
123
124 NAVIGATION
125 $wd->navigate_to ($url)
126 Navigates to the specified URL.
127
128 $url = $wd->get_current_url
129 Queries the current page URL as set by "navigate_to".
130
131 $wd->back
132 The equivalent of pressing "back" in the browser.
133
134 $wd->forward
135 The equivalent of pressing "forward" in the browser.
136
137 $wd->refresh
138 The equivalent of pressing "refresh" in the browser.
139
140 $title = $wd->get_title
141 Returns the current document title.
142
143 COMMAND CONTEXTS
144 $handle = $wd->get_window_handle
145 Returns the current window handle.
146
147 $wd->close_window
148 Closes the current browsing context.
149
150 $wd->switch_to_window ($handle)
151 Changes the current browsing context to the given window.
152
153 $handles = $wd->get_window_handles
154 Return the current window handles as an array-ref of handle IDs.
155
156 $handles = $wd->switch_to_frame ($frame)
157 Switch to the given frame identified by $frame, which must be either
158 "undef" to go back to the top-level browsing context, an integer to
159 select the nth subframe, or an element object (as e.g. returned by
160 the "element_object" method.
161
162 $handles = $wd->switch_to_parent_frame
163 Switch to the parent frame.
164
165 $rect = $wd->get_window_rect
166 Return the current window rect, e.g.:
167
168 $rect = $wd->get_window_rect
169 => { height => 1040, width => 540, x => 0, y => 0 }
170
171 $wd->set_window_rect ($rect)
172 Sets the window rect.
173
174 $wd->maximize_window
175 $wd->minimize_window
176 $wd->fullscreen_window
177 Changes the window size by either maximising, minimising or making
178 it fullscreen. In my experience, this will timeout if no window
179 manager is running.
180
181 ELEMENT RETRIEVAL
182 $element_id = $wd->find_element ($location_strategy, $selector)
183 Finds the first element specified by the given selector and returns
184 its web element ID (the strong, not the object from the protocol).
185 Raises an error when no element was found.
186
187 $element = $wd->find_element ("css selector" => "body a");
188 $element = $wd->find_element ("link text" => "Click Here For Porn");
189 $element = $wd->find_element ("partial link text" => "orn");
190 $element = $wd->find_element ("tag name" => "input");
191 $element = $wd->find_element ("xpath" => '//input[@type="text"]');
192 => e.g. "decddca8-5986-4e1d-8c93-efe952505a5f"
193
194 $element_ids = $wd->find_elements ($location_strategy, $selector)
195 As above, but returns an arrayref of all found element IDs.
196
197 $element_id = $wd->find_element_from_element ($element_id,
198 $location_strategy, $selector)
199 Like "find_element", but looks only inside the specified $element.
200
201 $element_ids = $wd->find_elements_from_element ($element_id,
202 $location_strategy, $selector)
203 Like "find_elements", but looks only inside the specified $element.
204
205 my $head = $wd->find_element ("tag name" => "head");
206 my $links = $wd->find_elements_from_element ($head, "tag name", "link");
207
208 $element_id = $wd->get_active_element
209 Returns the active element.
210
211 ELEMENT STATE
212 $bool = $wd->is_element_selected
213 Returns whether the given input or option element is selected or
214 not.
215
216 $string = $wd->get_element_attribute ($element_id, $name)
217 Returns the value of the given attribute.
218
219 $string = $wd->get_element_property ($element_id, $name)
220 Returns the value of the given property.
221
222 $string = $wd->get_element_css_value ($element_id, $name)
223 Returns the value of the given CSS value.
224
225 $string = $wd->get_element_text ($element_id)
226 Returns the (rendered) text content of the given element.
227
228 $string = $wd->get_element_tag_name ($element_id)
229 Returns the tag of the given element.
230
231 $rect = $wd->get_element_rect ($element_id)
232 Returns the element rect(angle) of the given element.
233
234 $bool = $wd->is_element_enabled
235 Returns whether the element is enabled or not.
236
237 ELEMENT INTERACTION
238 $wd->element_click ($element_id)
239 Clicks the given element.
240
241 $wd->element_clear ($element_id)
242 Clear the contents of the given element.
243
244 $wd->element_send_keys ($element_id, $text)
245 Sends the given text as key events to the given element.
246
247 DOCUMENT HANDLING
248 $source = $wd->get_page_source
249 Returns the (HTML/XML) page source of the current document.
250
251 $results = $wd->execute_script ($javascript, $args)
252 Synchronously execute the given script with given arguments and
253 return its results ($args can be "undef" if no arguments are
254 wanted/needed).
255
256 $ten = $wd->execute_script ("return arguments[0]+arguments[1]", [3, 7]);
257
258 $results = $wd->execute_async_script ($javascript, $args)
259 Similar to "execute_script", but doesn't wait for script to return,
260 but instead waits for the script to call its last argument, which is
261 added to $args automatically.
262
263 $twenty = $wd->execute_async_script ("arguments[0](20)", undef);
264
265 COOKIES
266 $cookies = $wd->get_all_cookies
267 Returns all cookies, as an arrayref of hashrefs.
268
269 # google surely sets a lot of cookies without my consent
270 $wd->navigate_to ("http://google.com");
271 use Data::Dump;
272 ddx $wd->get_all_cookies;
273
274 $cookie = $wd->get_named_cookie ($name)
275 Returns a single cookie as a hashref.
276
277 $wd->add_cookie ($cookie)
278 Adds the given cookie hashref.
279
280 $wd->delete_cookie ($name)
281 Delete the named cookie.
282
283 $wd->delete_all_cookies
284 Delete all cookies.
285
286 ACTIONS
287 $wd->perform_actions ($actions)
288 Perform the given actions (an arrayref of action specifications
289 simulating user activity). For further details, read the spec.
290
291 An example to get you started:
292
293 $wd->navigate_to ("https://duckduckgo.com/html");
294 $wd->set_timeouts ({ implicit => 10000 });
295 my $input = $wd->find_element ("css selector", 'input[type="text"]');
296 $wd->perform_actions ([
297 {
298 id => "myfatfinger",
299 type => "pointer",
300 pointerType => "touch",
301 actions => [
302 { type => "pointerMove", duration => 100, origin => $wd->element_object ($input), x => 40, y => 5 },
303 { type => "pointerDown", button => 1 },
304 { type => "pause", duration => 40 },
305 { type => "pointerUp", button => 1 },
306 ],
307 },
308 {
309 id => "mykeyboard",
310 type => "key",
311 actions => [
312 { type => "pause" },
313 { type => "pause" },
314 { type => "pause" },
315 { type => "pause" },
316 { type => "keyDown", value => "a" },
317 { type => "pause", duration => 100 },
318 { type => "keyUp", value => "a" },
319 { type => "pause", duration => 100 },
320 { type => "keyDown", value => "b" },
321 { type => "pause", duration => 100 },
322 { type => "keyUp", value => "b" },
323 { type => "pause", duration => 2000 },
324 { type => "keyDown", value => "\x{E007}" }, # enter
325 { type => "pause", duration => 100 },
326 { type => "keyUp", value => "\x{E007}" }, # enter
327 { type => "pause", duration => 5000 },
328 ],
329 },
330 ]);
331
332 $wd->release_actions
333 Release all keys and pointer buttons currently depressed.
334
335 USER PROMPTS
336 $wd->dismiss_alert
337 Dismiss a simple dialog, if present.
338
339 $wd->accept_alert
340 Accept a simple dialog, if present.
341
342 $text = $wd->get_alert_text
343 Returns the text of any simple dialog.
344
345 $text = $wd->send_alert_text
346 Fills in the user prompt with the given text.
347
348 SCREEN CAPTURE
349 $wd->take_screenshot
350 Create a screenshot, returning it as a PNG image in a "data:" URL.
351
352 $wd->take_element_screenshot ($element_id)
353 Accept a simple dialog, if present.
354
355 HELPER METHODS
356 $object = AnyEvent::WebDriver->element_object ($element_id)
357 $object = $wd->element_object ($element_id)
358 Encoding element IDs in data structures is done by representing them
359 as an object with a special key and the element ID as value. This
360 helper method does this for you.
361
362 EVENT BASED API
363 This module wouldn't be a good AnyEvent citizen if it didn't have a true
364 event-based API.
365
366 In fact, the simplified API, as documented above, is emulated via the
367 event-based API and an "AUTOLOAD" function that automatically provides
368 blocking wrappers around the callback-based API.
369
370 Every method documented in the "SIMPLIFIED API" section has an
371 equivalent event-based method that is formed by appending a underscore
372 ("_") to the method name, and appending a callback to the argument list
373 (mnemonic: the underscore indicates the "the action is not yet finished"
374 after the call returns).
375
376 For example, instead of a blocking calls to "new_session", "navigate_to"
377 and "back", you can make a callback-based ones:
378
379 my $cv = AE::cv;
380
381 $wd->new_session ({}, sub {
382 my ($status, $value) = @_,
383
384 die "error $value->{error}" if $status ne "200";
385
386 $wd->navigate_to_ ("http://www.nethype.de", sub {
387
388 $wd->back_ (sub {
389 print "all done\n";
390 $cv->send;
391 });
392
393 });
394 });
395
396 $cv->recv;
397
398 While the blocking methods "croak" on errors, the callback-based ones
399 all pass two values to the callback, $status and $res, where $status is
400 the HTTP status code (200 for successful requests, typically 4xx or 5xx
401 for errors), and $res is the value of the "value" key in the JSON
402 response object.
403
404 Other than that, the underscore variants and the blocking variants are
405 identical.
406
407 LOW LEVEL API
408 All the simplified API methods are very thin wrappers around WebDriver
409 commands of the same name. They are all implemented in terms of the
410 low-level methods ("req", "get", "post" and "delete"), which exists in
411 blocking and callback-based variants ("req_", "get_", "post_" and
412 "delete_").
413
414 Examples are after the function descriptions.
415
416 $wd->req_ ($method, $uri, $body, $cb->($status, $value))
417 $value = $wd->req ($method, $uri, $body)
418 Appends the $uri to the "endpoint/session/{sessionid}/" URL and
419 makes a HTTP $method request ("GET", "POST" etc.). "POST" requests
420 can provide a UTF-8-encoded JSON text as HTTP request body, or the
421 empty string to indicate no body is used.
422
423 For the callback version, the callback gets passed the HTTP status
424 code (200 for every successful request), and the value of the
425 "value" key in the JSON response object as second argument.
426
427 $wd->get_ ($uri, $cb->($status, $value))
428 $value = $wd->get ($uri)
429 Simply a call to "req_" with $method set to "GET" and an empty body.
430
431 $wd->post_ ($uri, $data, $cb->($status, $value))
432 $value = $wd->post ($uri, $data)
433 Simply a call to "req_" with $method set to "POST" - if $body is
434 "undef", then an empty object is send, otherwise, $data must be a
435 valid request object, which gets encoded into JSON for you.
436
437 $wd->delete_ ($uri, $cb->($status, $value))
438 $value = $wd->delete ($uri)
439 Simply a call to "req_" with $method set to "DELETE" and an empty
440 body.
441
442 Example: implement "get_all_cookies", which is a simple "GET" request
443 without any parameters:
444
445 $cookies = $wd->get ("cookie");
446
447 Example: implement "execute_script", which needs some parameters:
448
449 $results = $wd->post ("execute/sync" => { script => "$javascript", args => [] });
450
451 Example: call "find_elements" to find all "IMG" elements, stripping the
452 returned element objects to only return the element ID strings:
453
454 my $elems = $wd->post (elements => { using => "css selector", value => "img" });
455
456 # yes, the W3C found an interesting way around the typelessness of JSON
457 $_ = $_->{"element-6066-11e4-a52e-4f735466cecf"}
458 for @$elems;
459
460 HISTORY
461 This module was unintentionally created (it started inside some quickly
462 hacked-together script) simply because I couldn't get the existing
463 "Selenium::Remote::Driver" module to work, ever, despite multiple
464 attempts over the years and trying to report multiple bugs, which have
465 been completely ignored. It's also not event-based, so, yeah...
466
467 AUTHOR
468 Marc Lehmann <schmorp@schmorp.de>
469 http://anyevent.schmorp.de
470