ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.8
Committed: Fri Sep 20 20:15:58 2019 UTC (4 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-1_0
Changes since 1.7: +42 -26 lines
Log Message:
1.0

File Contents

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