ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.6
Committed: Fri Aug 31 02:44:31 2018 UTC (5 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-0_9
Changes since 1.5: +44 -18 lines
Log Message:
0.9

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