ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-WebDriver/README
Revision: 1.10
Committed: Sat Mar 28 17:06:20 2020 UTC (4 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-1_2, HEAD
Changes since 1.9: +58 -18 lines
Log Message:
1.2

File Contents

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