AnyEvent-WebDriver

 view release on metacpan or  search on metacpan

WebDriver.pm  view on Meta::CPAN

   $wd->element_click ($wd->find_element (css => 'input[type="submit"]'));

   # session gets autodeleted by default, so wait a bit
   sleep 10;

   # this is an example of an action sequence
   $wd->actions
      ->move ($wd->find_element (...), 40, 5)
      ->click
      ->type ("some text")
      ->key ("{Enter}")
      ->perform;

=head1 DESCRIPTION

This module aims to implement the L<W3C
WebDriver|https://www.w3.org/TR/webdriver1/> specification which is the
standardised equivalent to the Selenium WebDriver API, which in turn aims
at remotely controlling web browsers such as Firefox or Chromium.

One of the design goals of this module was to stay very close to the
language and words used in the WebDriver specification itself, so to make
most of this module, or, in fact, to make any reasonable use of this
module, you would need to refer to the W3C WebDriver recommendation, which
can be found L<here|https://www.w3.org/TR/webdriver1/>:

   https://www.w3.org/TR/webdriver1/

Mozilla's C<geckodriver> has had webdriver support for a long time, while
C<chromedriver> only has basic and mostly undocumented webdriver support
as of release 77.

In Debian GNU/Linux, you can install the chromedriver for chromium
via the C<chromium-driver> package. Unfortunately, there is no
(working) package for geckodriver, but you can download it from
L<github|https://github.com/mozilla/geckodriver/releases>.

=head2 CONVENTIONS

Unless otherwise stated, all delays and time differences in this module
are represented as an integer number of milliseconds, which is perhaps
surprising to users of my other modules but is what the WebDriver spec
uses.

=cut

package AnyEvent::WebDriver;

use common::sense;

use Carp ();
use AnyEvent ();
use AnyEvent::HTTP ();

our $VERSION = '1.2';

our $WEB_ELEMENT_IDENTIFIER = "element-6066-11e4-a52e-4f735466cecf";
our $WEB_WINDOW_IDENTIFIER  =  "window-fcc6-11e5-b4f8-330a88ab9d7f";
our $WEB_FRAME_IDENTIFIER   =   "frame-075b-4da1-b6ba-e579c2d3230a";

my $json = eval { require JSON::XS; JSON::XS:: } || do { require JSON::PP; JSON::PP:: };
$json = $json->new->utf8;

$json->boolean_values (0, 1)
   if $json->can ("boolean_values");

sub _decode_base64 {
   require MIME::Base64;

   MIME::Base64::decode_base64 (shift)
}

sub req_ {
   my ($self, $method, $ep, $body, $cb) = @_;

   AnyEvent::HTTP::http_request $method => "$self->{_ep}$ep",
      body => $body,
      $self->{persistent} ? (persistent => 1) : (),
      $self->{proxy} eq "default" ? () : (proxy => $self->{proxy}),
      timeout => $self->{timeout},
      headers => { "content-type" => "application/json; charset=utf-8", "cache-control" => "no-cache" },
      sub {
         my ($res, $hdr) = @_;

         $res = eval { $json->decode ($res) };
         $hdr->{Status} = 500 unless exists $res->{value};

         $cb->($hdr->{Status}, $res->{value});
      }
   ;
}

sub get_ {
   my ($self, $ep, $cb) = @_;

   $self->req_ (GET => $ep, undef, $cb)
}

sub post_ {
   my ($self, $ep, $data, $cb) = @_;

   $self->req_ (POST => $ep, $json->encode ($data || {}), $cb)
}

sub delete_ {
   my ($self, $ep, $cb) = @_;

   $self->req_ (DELETE => $ep, "", $cb)
}

sub AUTOLOAD {
   our $AUTOLOAD;

   $_[0]->isa (__PACKAGE__)
      or Carp::croak "$AUTOLOAD: no such function";

   (my $name = $AUTOLOAD) =~ s/^.*://;

   my $name_ = "$name\_";

   defined &$name_



( run in 1.097 second using v1.01-cache-2.11-cpan-39bf76dae61 )