ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.7
Committed: Tue Sep 4 01:21:21 2018 UTC (5 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-0_91
Changes since 1.6: +48 -32 lines
Log Message:
0.91

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 root 1.7 my $searchbox = $wd->find_element (css => 'input[type="text"]');
19 root 1.1
20     $wd->element_send_keys ($searchbox => "free software");
21 root 1.7 $wd->element_click ($wd->find_element (css => 'input[type="submit"]'));
22 root 1.1
23 root 1.7 # session gets autodeleted by default, so wait a bit
24 root 1.1 sleep 10;
25    
26 root 1.7 # this is an example of an action sequence
27     $wd->actions
28     ->move ($wd->find_element (...), 40, 5)
29     ->click
30     ->type ("some text")
31     ->key ("{Enter}")
32     ->perform;
33    
34 root 1.1 DESCRIPTION
35 root 1.7 WARNING: BEFORE VERSION 1.0, API CHANGES ARE LIKELY.
36 root 1.5
37 root 1.1 This module aims to implement the W3C WebDriver specification which is
38     the standardised equivalent to the Selenium WebDriver API., which in
39     turn aims at remotely controlling web browsers such as Firefox or
40     Chromium.
41    
42 root 1.6 At the time of this writing, it was so brand new that I could only get
43 root 1.7 "geckodriver" (for Firefox) to work, but that is expected to be fixed
44 root 1.4 very soon indeed.
45 root 1.1
46 root 1.7 One of the design goals of this module was to stay very close to the
47     language and words used in the WebDriver specification itself, so to
48     make most of this module, or, in fact, to make any reasonable use of
49 root 1.4 this module, you would need to refer to the W3C WebDriver
50     recommendation, which can be found here
51     <https://www.w3.org/TR/webdriver1/>:
52 root 1.1
53 root 1.4 https://www.w3.org/TR/webdriver1/
54 root 1.1
55 root 1.4 CONVENTIONS
56     Unless otherwise stated, all delays and time differences in this module
57     are represented as an integer number of milliseconds.
58    
59     WEBDRIVER OBJECTS
60 root 1.1 new AnyEvent::WebDriver key => value...
61 root 1.3 Create a new WebDriver object. Example for a remote WebDriver
62 root 1.1 connection (the only type supported at the moment):
63    
64     my $wd = new AnyEvent::WebDriver host => "localhost", port => 4444;
65    
66     Supported keys are:
67    
68     endpoint => $string
69     For remote connections, the endpoint to connect to (defaults to
70     "http://localhost:4444").
71    
72     proxy => $proxyspec
73     The proxy to use (same as the "proxy" argument used by
74     AnyEvent::HTTP). The default is "undef", which disables proxies.
75     To use the system-provided proxy (e.g. "http_proxy" environment
76     variable), specify a value of "default".
77    
78     autodelete => $boolean
79     If true (the default), then automatically execute
80     "delete_session" when the WebDriver object is destroyed with an
81     active session. IF set to a false value, then the session will
82     continue to exist.
83    
84 root 1.3 timeout => $seconds
85     The HTTP timeout, in (fractional) seconds (default: 300, but
86     this will likely drastically reduce). This timeout is reset on
87     any activity, so it is not an overall request timeout. Also,
88     individual requests might extend this timeout if they are known
89     to take longer.
90    
91 root 1.6 persistent => 1 | "undef"
92     If true (the default) then persistent connections will be used
93     for all requests, which assumes you have a reasonably stable
94     connection (such as to "localhost" :) and that the WebDriver has
95     a persistent timeout much higher than what AnyEvent::HTTP uses.
96    
97     You can force connections to be closed for non-idempotent
98     requests by setting this to "undef".
99    
100 root 1.4 $al = $wd->actions
101     Creates an action list associated with this WebDriver. See ACTION
102     LISTS, below, for full details.
103    
104 root 1.5 $sessionstring = $wd->save_session
105     Save the current session in a string so it can be restored load with
106     "load_session". Note that only the session data itself is stored
107     (currently the session id and capabilities), not the endpoint
108     information itself.
109    
110     The main use of this function is in conjunction with disabled
111     "autodelete", to save a session to e.g., and restore it later. It
112 root 1.6 could presumably used for other applications, such as using the same
113     session from multiple processes and so on.
114 root 1.5
115     $wd->load_session ($sessionstring)
116     $wd->set_session ($sessionid, $capabilities)
117     Starts using the given session, as identified by $sessionid.
118     $capabilities should be the original session capabilities, although
119     the current version of this module does not make any use of it.
120    
121     The $sessionid is stored in "$wd->{sid}" (and could be fetched form
122     there for later use), while the capabilities are stored in
123     "$wd->{capabilities}".
124    
125 root 1.1 SIMPLIFIED API
126     This section documents the simplified API, which is really just a very
127     thin wrapper around the WebDriver protocol commands. They all block
128     (using AnyEvent condvars) the caller until the result is available, so
129     must not be called from an event loop callback - see "EVENT BASED API"
130     for an alternative.
131    
132 root 1.3 The method names are pretty much taken directly from the W3C WebDriver
133 root 1.1 specification, e.g. the request documented in the "Get All Cookies"
134     section is implemented via the "get_all_cookies" method.
135    
136 root 1.3 The order is the same as in the WebDriver draft at the time of this
137 root 1.1 writing, and only minimal massaging is done to request parameters and
138     results.
139    
140     SESSIONS
141     $wd->new_session ({ key => value... })
142 root 1.3 Try to connect to the WebDriver and initialize a new session with a
143     "new session" command, passing the given key-value pairs as value
144     (e.g. "capabilities").
145 root 1.1
146     No session-dependent methods must be called before this function
147 root 1.3 returns successfully, and only one session can be created per
148     WebDriver object.
149 root 1.1
150 root 1.3 On success, "$wd->{sid}" is set to the session ID, and
151 root 1.1 "$wd->{capabilities}" is set to the returned capabilities.
152    
153 root 1.6 Simple example of creating a WebDriver object and a new session:
154 root 1.5
155 root 1.3 my $wd = new AnyEvent::Selenium endpoint => "http://localhost:4545";
156 root 1.5 $wd->new_session ({});
157    
158     Real-world example with capability negotiation:
159 root 1.1
160     $wd->new_session ({
161     capabilities => {
162 root 1.5 alwaysMatch => {
163     pageLoadStrategy => "eager",
164     unhandledPromptBehavior => "dismiss",
165     # proxy => { proxyType => "manual", httpProxy => "1.2.3.4:56", sslProxy => "1.2.3.4:56" },
166     },
167     firstMatch => [
168     {
169     browserName => "firefox",
170     "moz:firefoxOptions" => {
171     binary => "firefox/firefox",
172     args => ["-devtools"],
173     prefs => {
174     "dom.webnotifications.enabled" => \0,
175 root 1.6 "dom.push.enabled" => \0,
176 root 1.5 "dom.disable_beforeunload" => \1,
177     "browser.link.open_newwindow" => 3,
178     "browser.link.open_newwindow.restrictions" => 0,
179     "dom.popup_allowed_events" => "",
180     "dom.disable_open_during_load" => \1,
181     },
182     },
183     },
184     {
185     # generic fallback
186     },
187     ],
188    
189     },
190 root 1.1 });
191    
192 root 1.5 Firefox-specific capability documentation can be found on MDN
193     <https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities
194     >, Chrome-specific capability documentation might be found here
195     <http://chromedriver.chromium.org/capabilities>, but the latest
196     release at the time of this writing has effectively no WebDriver
197     support at all, and canary releases are not freely downloadable.
198    
199     If you have URLs for Safari/IE/Edge etc. capabilities, feel free to
200     tell me about them.
201    
202 root 1.1 $wd->delete_session
203     Deletes the session - the WebDriver object must not be used after
204     this call.
205    
206     $timeouts = $wd->get_timeouts
207     Get the current timeouts, e.g.:
208    
209     my $timeouts = $wd->get_timeouts;
210 root 1.3 => { implicit => 0, pageLoad => 300000, script => 30000 }
211 root 1.1
212     $wd->set_timeouts ($timeouts)
213     Sets one or more timeouts, e.g.:
214    
215     $wd->set_timeouts ({ script => 60000 });
216    
217     NAVIGATION
218     $wd->navigate_to ($url)
219     Navigates to the specified URL.
220    
221     $url = $wd->get_current_url
222 root 1.3 Queries the current page URL as set by "navigate_to".
223 root 1.1
224     $wd->back
225     The equivalent of pressing "back" in the browser.
226    
227     $wd->forward
228     The equivalent of pressing "forward" in the browser.
229    
230     $wd->refresh
231     The equivalent of pressing "refresh" in the browser.
232    
233     $title = $wd->get_title
234     Returns the current document title.
235    
236     COMMAND CONTEXTS
237     $handle = $wd->get_window_handle
238     Returns the current window handle.
239    
240     $wd->close_window
241     Closes the current browsing context.
242    
243     $wd->switch_to_window ($handle)
244     Changes the current browsing context to the given window.
245    
246     $handles = $wd->get_window_handles
247     Return the current window handles as an array-ref of handle IDs.
248    
249     $handles = $wd->switch_to_frame ($frame)
250 root 1.3 Switch to the given frame identified by $frame, which must be either
251     "undef" to go back to the top-level browsing context, an integer to
252 root 1.4 select the nth subframe, or an element object.
253 root 1.1
254     $handles = $wd->switch_to_parent_frame
255     Switch to the parent frame.
256    
257     $rect = $wd->get_window_rect
258 root 1.6 Return the current window rect(angle), e.g.:
259 root 1.1
260     $rect = $wd->get_window_rect
261 root 1.3 => { height => 1040, width => 540, x => 0, y => 0 }
262 root 1.1
263     $wd->set_window_rect ($rect)
264 root 1.7 Sets the window rect(angle), e.g.:
265    
266     $wd->set_window_rect ({ width => 780, height => 560 });
267     $wd->set_window_rect ({ x => 0, y => 0, width => 780, height => 560 });
268 root 1.1
269     $wd->maximize_window
270     $wd->minimize_window
271     $wd->fullscreen_window
272 root 1.3 Changes the window size by either maximising, minimising or making
273     it fullscreen. In my experience, this will timeout if no window
274 root 1.1 manager is running.
275    
276     ELEMENT RETRIEVAL
277 root 1.5 To reduce typing and memory strain, the element finding functions accept
278     some shorter and hopefully easier to remember aliases for the standard
279     locator strategy values, as follows:
280    
281     Alias Locator Strategy
282     css css selector
283     link link text
284     substr partial link text
285     tag tag name
286    
287     $element = $wd->find_element ($locator_strategy, $selector)
288 root 1.1 Finds the first element specified by the given selector and returns
289 root 1.4 its element object. Raises an error when no element was found.
290 root 1.1
291 root 1.6 Examples showing all standard locator strategies:
292    
293 root 1.1 $element = $wd->find_element ("css selector" => "body a");
294     $element = $wd->find_element ("link text" => "Click Here For Porn");
295     $element = $wd->find_element ("partial link text" => "orn");
296     $element = $wd->find_element ("tag name" => "input");
297     $element = $wd->find_element ("xpath" => '//input[@type="text"]');
298 root 1.4 => e.g. { "element-6066-11e4-a52e-4f735466cecf" => "decddca8-5986-4e1d-8c93-efe952505a5f" }
299 root 1.1
300 root 1.6 Same examples using aliases provided by this module:
301    
302     $element = $wd->find_element (css => "body a");
303     $element = $wd->find_element (link => "Click Here For Porn");
304     $element = $wd->find_element (substr => "orn");
305     $element = $wd->find_element (tag => "input");
306    
307 root 1.5 $elements = $wd->find_elements ($locator_strategy, $selector)
308 root 1.4 As above, but returns an arrayref of all found element objects.
309 root 1.1
310 root 1.5 $element = $wd->find_element_from_element ($element, $locator_strategy,
311 root 1.4 $selector)
312 root 1.1 Like "find_element", but looks only inside the specified $element.
313    
314 root 1.4 $elements = $wd->find_elements_from_element ($element,
315 root 1.5 $locator_strategy, $selector)
316 root 1.1 Like "find_elements", but looks only inside the specified $element.
317    
318     my $head = $wd->find_element ("tag name" => "head");
319     my $links = $wd->find_elements_from_element ($head, "tag name", "link");
320    
321 root 1.4 $element = $wd->get_active_element
322 root 1.1 Returns the active element.
323    
324     ELEMENT STATE
325     $bool = $wd->is_element_selected
326     Returns whether the given input or option element is selected or
327     not.
328    
329 root 1.4 $string = $wd->get_element_attribute ($element, $name)
330 root 1.1 Returns the value of the given attribute.
331    
332 root 1.4 $string = $wd->get_element_property ($element, $name)
333 root 1.1 Returns the value of the given property.
334    
335 root 1.4 $string = $wd->get_element_css_value ($element, $name)
336 root 1.3 Returns the value of the given CSS value.
337 root 1.1
338 root 1.4 $string = $wd->get_element_text ($element)
339 root 1.1 Returns the (rendered) text content of the given element.
340    
341 root 1.4 $string = $wd->get_element_tag_name ($element)
342 root 1.1 Returns the tag of the given element.
343    
344 root 1.4 $rect = $wd->get_element_rect ($element)
345 root 1.3 Returns the element rect(angle) of the given element.
346 root 1.1
347     $bool = $wd->is_element_enabled
348     Returns whether the element is enabled or not.
349    
350     ELEMENT INTERACTION
351 root 1.4 $wd->element_click ($element)
352 root 1.1 Clicks the given element.
353    
354 root 1.4 $wd->element_clear ($element)
355 root 1.1 Clear the contents of the given element.
356    
357 root 1.4 $wd->element_send_keys ($element, $text)
358 root 1.7 Sends the given text as key events to the given element. Key input
359     state can be cleared by embedding "\x{e000}" in $text. Presumably,
360     you can embed modifiers using their unicode codepoints, but the
361     specification is less than clear to mein this area.
362 root 1.1
363     DOCUMENT HANDLING
364     $source = $wd->get_page_source
365     Returns the (HTML/XML) page source of the current document.
366    
367     $results = $wd->execute_script ($javascript, $args)
368     Synchronously execute the given script with given arguments and
369     return its results ($args can be "undef" if no arguments are
370     wanted/needed).
371    
372     $ten = $wd->execute_script ("return arguments[0]+arguments[1]", [3, 7]);
373    
374     $results = $wd->execute_async_script ($javascript, $args)
375     Similar to "execute_script", but doesn't wait for script to return,
376     but instead waits for the script to call its last argument, which is
377     added to $args automatically.
378    
379     $twenty = $wd->execute_async_script ("arguments[0](20)", undef);
380    
381     COOKIES
382     $cookies = $wd->get_all_cookies
383     Returns all cookies, as an arrayref of hashrefs.
384    
385     # google surely sets a lot of cookies without my consent
386     $wd->navigate_to ("http://google.com");
387     use Data::Dump;
388     ddx $wd->get_all_cookies;
389    
390     $cookie = $wd->get_named_cookie ($name)
391     Returns a single cookie as a hashref.
392    
393     $wd->add_cookie ($cookie)
394     Adds the given cookie hashref.
395    
396     $wd->delete_cookie ($name)
397     Delete the named cookie.
398    
399     $wd->delete_all_cookies
400     Delete all cookies.
401    
402     ACTIONS
403     $wd->perform_actions ($actions)
404     Perform the given actions (an arrayref of action specifications
405 root 1.4 simulating user activity, or an "AnyEvent::WebDriver::Actions"
406     object). For further details, read the spec or the section "ACTION
407     LISTS", below.
408    
409     An example to get you started (see the next example for a mostly
410     equivalent example using the "AnyEvent::WebDriver::Actions" helper
411     API):
412 root 1.1
413     $wd->navigate_to ("https://duckduckgo.com/html");
414     my $input = $wd->find_element ("css selector", 'input[type="text"]');
415     $wd->perform_actions ([
416     {
417     id => "myfatfinger",
418     type => "pointer",
419     pointerType => "touch",
420     actions => [
421 root 1.4 { type => "pointerMove", duration => 100, origin => $input, x => 40, y => 5 },
422 root 1.7 { type => "pointerDown", button => 0 },
423 root 1.1 { type => "pause", duration => 40 },
424 root 1.7 { type => "pointerUp", button => 0 },
425 root 1.1 ],
426     },
427     {
428     id => "mykeyboard",
429     type => "key",
430     actions => [
431     { type => "pause" },
432     { type => "pause" },
433     { type => "pause" },
434     { type => "pause" },
435     { type => "keyDown", value => "a" },
436     { type => "pause", duration => 100 },
437     { type => "keyUp", value => "a" },
438     { type => "pause", duration => 100 },
439     { type => "keyDown", value => "b" },
440     { type => "pause", duration => 100 },
441     { type => "keyUp", value => "b" },
442     { type => "pause", duration => 2000 },
443     { type => "keyDown", value => "\x{E007}" }, # enter
444     { type => "pause", duration => 100 },
445     { type => "keyUp", value => "\x{E007}" }, # enter
446     { type => "pause", duration => 5000 },
447     ],
448     },
449     ]);
450    
451 root 1.4 And here is essentially the same (except for fewer pauses) example
452 root 1.7 as above, using the much simpler "AnyEvent::WebDriver::Actions" API:
453 root 1.4
454     $wd->navigate_to ("https://duckduckgo.com/html");
455     my $input = $wd->find_element ("css selector", 'input[type="text"]');
456     $wd->actions
457     ->move ($input, 40, 5, "touch1")
458 root 1.6 ->click
459     ->key ("a")
460     ->key ("b")
461 root 1.7 ->pause (2000) # so you can watch leisurely
462     ->key ("{Enter}")
463     ->pause (5000) # so you can see the result
464 root 1.4 ->perform;
465    
466 root 1.1 $wd->release_actions
467     Release all keys and pointer buttons currently depressed.
468    
469     USER PROMPTS
470     $wd->dismiss_alert
471     Dismiss a simple dialog, if present.
472    
473     $wd->accept_alert
474     Accept a simple dialog, if present.
475    
476     $text = $wd->get_alert_text
477     Returns the text of any simple dialog.
478    
479     $text = $wd->send_alert_text
480     Fills in the user prompt with the given text.
481    
482     SCREEN CAPTURE
483     $wd->take_screenshot
484 root 1.3 Create a screenshot, returning it as a PNG image in a "data:" URL.
485 root 1.1
486 root 1.4 $wd->take_element_screenshot ($element)
487 root 1.1 Accept a simple dialog, if present.
488    
489 root 1.4 ACTION LISTS
490     Action lists can be quite complicated. Or at least it took a while for
491     me to twist my head around them. Basically, an action list consists of a
492     number of sources representing devices (such as a finger, a mouse, a pen
493     or a keyboard) and a list of actions for each source.
494    
495     An action can be a key press, a pointer move or a pause (time delay).
496    
497 root 1.7 While you can provide these action lists manually, it is (hopefully)
498     less cumbersome to use the API described in this section to create them.
499 root 1.4
500     The basic process of creating and performing actions is to create a new
501     action list, adding action sources, followed by adding actions. Finally
502     you would "perform" those actions on the WebDriver.
503    
504     Most methods here are designed to chain, i.e. they return the web
505     actions object, to simplify multiple calls.
506    
507 root 1.7 Also, while actions from different sources can happen "at the same time"
508     in the WebDriver protocol, this class ensures that actions will execute
509     in the order specified.
510    
511 root 1.4 For example, to simulate a mouse click to an input element, followed by
512     entering some text and pressing enter, you can use this:
513    
514     $wd->actions
515 root 1.7 ->click (0, 100)
516 root 1.4 ->type ("some text")
517 root 1.5 ->key ("{Enter}")
518 root 1.4 ->perform;
519    
520     By default, keyboard and mouse input sources are provided. You can
521     create your own sources and use them when adding events. The above
522     example could be more verbosely written like this:
523    
524     $wd->actions
525 root 1.6 ->source ("mouse", "pointer", pointerType => "mouse")
526     ->source ("kbd", "key")
527 root 1.7 ->click (0, 100, "mouse")
528 root 1.6 ->type ("some text", "kbd")
529     ->key ("{Enter}", "kbd")
530 root 1.4 ->perform;
531    
532 root 1.6 When you specify the event source explicitly it will switch the current
533 root 1.4 "focus" for this class of device (all keyboards are in one class, all
534     pointer-like devices such as mice/fingers/pens are in one class), so you
535     don't have to specify the source for subsequent actions.
536    
537     When you use the sources "keyboard", "mouse", "touch1".."touch3", "pen"
538     without defining them, then a suitable default source will be created
539     for them.
540    
541     $al = new AnyEvent::WebDriver::Actions
542     Create a new empty action list object. More often you would use the
543 root 1.5 "$wd->action_list" method to create one that is already associated
544 root 1.4 with a given web driver.
545    
546     $al = $al->source ($id, $type, key => value...)
547 root 1.6 The first time you call this with a given ID, this defines the event
548 root 1.4 source using the extra parameters. Subsequent calls merely switch
549     the current source for its event class.
550    
551     It's not an error to define built-in sources (such as "keyboard" or
552     "touch1") differently then the defaults.
553    
554     Example: define a new touch device called "fatfinger".
555    
556     $al->source (fatfinger => "pointer", pointerType => "touch");
557    
558 root 1.6 Example: define a new touch device called "fatfinger".
559 root 1.4
560     $al->source (fatfinger => "pointer", pointerType => "touch");
561    
562 root 1.6 Example: switch default keyboard source to "kbd1", assuming it is of
563     "key" class.
564    
565     $al->source ("kbd1");
566    
567 root 1.4 $al = $al->pause ($duration)
568     Creates a pause with the given duration. Makes sure that time
569     progresses in any case, even when $duration is 0.
570    
571     $al = $al->pointer_down ($button, $source)
572     $al = $al->pointer_up ($button, $source)
573 root 1.7 Press or release the given button. $button defaults to 0.
574 root 1.4
575     $al = $al->click ($button, $source)
576     Convenience function that creates a button press and release action
577 root 1.7 without any delay between them. $button defaults to 0.
578 root 1.4
579     $al = $al->doubleclick ($button, $source)
580     Convenience function that creates two button press and release
581     action pairs in a row, with no unnecessary delay between them.
582 root 1.7 $button defaults to 0.
583 root 1.4
584     $al = $al->move ($button, $origin, $x, $y, $duration, $source)
585     Moves a pointer to the given position, relative to origin (either
586     "viewport", "pointer" or an element object.
587    
588 root 1.7 $al = $al->cancel ($source)
589     Executes a pointer cancel action.
590    
591 root 1.4 $al = $al->keyDown ($key, $source)
592     $al = $al->keyUp ($key, $source)
593     Press or release the given key.
594    
595 root 1.5 $al = $al->key ($key, $source)
596     Peess and release the given key, without unnecessary delay.
597    
598     A special syntax, "{keyname}" can be used for special keys - all the
599     special key names from section 17.4.2
600     <https://www.w3.org/TR/webdriver1/#keyboard-actions> of the
601     WebDriver recommendation can be used.
602    
603     Example: press and release "a".
604    
605     $al->key ("a");
606    
607     Example: press and release the "Enter" key:
608    
609     $al->key ("\x{e007}");
610    
611     Example: press and release the "enter" key using the special key
612     name syntax:
613    
614     $al->key ("{Enter}");
615    
616     $al = $al->type ($string, $source)
617     Convenience method to simulate a series of key press and release
618 root 1.7 events for the keys in $string, one pair per extended unicode
619     grapheme cluster. There is no syntax for special keys, everything
620     will be typed "as-is" if possible.
621 root 1.5
622 root 1.4 $al->perform ($wd)
623 root 1.6 Finalises and compiles the list, if not done yet, and calls
624 root 1.4 "$wd->perform" with it.
625    
626     If $wd is undef, and the action list was created using the
627     "$wd->actions" method, then perform it against that WebDriver
628     object.
629    
630     There is no underscore variant - call the "perform_actions_" method
631     with the action object instead.
632    
633     $al->perform_release ($wd)
634     Exactly like "perform", but additionally call "release_actions"
635     afterwards.
636    
637     ($actions, $duration) = $al->compile
638     Finalises and compiles the list, if not done yet, and returns an
639     actions object suitable for calls to "$wd->perform_actions". When
640     called in list context, additionally returns the total duration of
641     the action list.
642    
643     Since building large action lists can take nontrivial amounts of
644     time, it can make sense to build an action list only once and then
645     perform it multiple times.
646    
647     Actions must not be added after compiling a list.
648 root 1.1
649     EVENT BASED API
650     This module wouldn't be a good AnyEvent citizen if it didn't have a true
651     event-based API.
652    
653     In fact, the simplified API, as documented above, is emulated via the
654     event-based API and an "AUTOLOAD" function that automatically provides
655     blocking wrappers around the callback-based API.
656    
657     Every method documented in the "SIMPLIFIED API" section has an
658     equivalent event-based method that is formed by appending a underscore
659     ("_") to the method name, and appending a callback to the argument list
660     (mnemonic: the underscore indicates the "the action is not yet finished"
661     after the call returns).
662    
663     For example, instead of a blocking calls to "new_session", "navigate_to"
664     and "back", you can make a callback-based ones:
665    
666     my $cv = AE::cv;
667    
668     $wd->new_session ({}, sub {
669     my ($status, $value) = @_,
670    
671     die "error $value->{error}" if $status ne "200";
672    
673     $wd->navigate_to_ ("http://www.nethype.de", sub {
674    
675     $wd->back_ (sub {
676     print "all done\n";
677     $cv->send;
678     });
679    
680     });
681     });
682    
683     $cv->recv;
684    
685     While the blocking methods "croak" on errors, the callback-based ones
686     all pass two values to the callback, $status and $res, where $status is
687 root 1.3 the HTTP status code (200 for successful requests, typically 4xx or 5xx
688 root 1.1 for errors), and $res is the value of the "value" key in the JSON
689     response object.
690    
691     Other than that, the underscore variants and the blocking variants are
692     identical.
693    
694     LOW LEVEL API
695 root 1.3 All the simplified API methods are very thin wrappers around WebDriver
696     commands of the same name. They are all implemented in terms of the
697 root 1.7 low-level methods ("req", "get", "post" and "delete"), which exist in
698 root 1.1 blocking and callback-based variants ("req_", "get_", "post_" and
699     "delete_").
700    
701     Examples are after the function descriptions.
702    
703     $wd->req_ ($method, $uri, $body, $cb->($status, $value))
704     $value = $wd->req ($method, $uri, $body)
705     Appends the $uri to the "endpoint/session/{sessionid}/" URL and
706     makes a HTTP $method request ("GET", "POST" etc.). "POST" requests
707     can provide a UTF-8-encoded JSON text as HTTP request body, or the
708     empty string to indicate no body is used.
709    
710     For the callback version, the callback gets passed the HTTP status
711     code (200 for every successful request), and the value of the
712     "value" key in the JSON response object as second argument.
713    
714     $wd->get_ ($uri, $cb->($status, $value))
715     $value = $wd->get ($uri)
716     Simply a call to "req_" with $method set to "GET" and an empty body.
717    
718     $wd->post_ ($uri, $data, $cb->($status, $value))
719     $value = $wd->post ($uri, $data)
720     Simply a call to "req_" with $method set to "POST" - if $body is
721     "undef", then an empty object is send, otherwise, $data must be a
722     valid request object, which gets encoded into JSON for you.
723    
724     $wd->delete_ ($uri, $cb->($status, $value))
725     $value = $wd->delete ($uri)
726     Simply a call to "req_" with $method set to "DELETE" and an empty
727     body.
728    
729     Example: implement "get_all_cookies", which is a simple "GET" request
730     without any parameters:
731    
732     $cookies = $wd->get ("cookie");
733    
734     Example: implement "execute_script", which needs some parameters:
735    
736     $results = $wd->post ("execute/sync" => { script => "$javascript", args => [] });
737    
738 root 1.4 Example: call "find_elements" to find all "IMG" elements:
739 root 1.1
740 root 1.4 $elems = $wd->post (elements => { using => "css selector", value => "img" });
741 root 1.1
742     HISTORY
743 root 1.2 This module was unintentionally created (it started inside some quickly
744     hacked-together script) simply because I couldn't get the existing
745 root 1.1 "Selenium::Remote::Driver" module to work, ever, despite multiple
746     attempts over the years and trying to report multiple bugs, which have
747     been completely ignored. It's also not event-based, so, yeah...
748    
749     AUTHOR
750     Marc Lehmann <schmorp@schmorp.de>
751     http://anyevent.schmorp.de
752