ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.1
Committed: Tue Aug 28 22:55:57 2018 UTC (5 years, 9 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

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