AnyEvent-WebDriver
view release on metacpan or search on metacpan
WebDriver.pm view on Meta::CPAN
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_
or Carp::croak "$AUTOLOAD: no such method";
my $func_ = \&$name_;
*$name = sub {
$func_->(@_, my $cv = AE::cv);
my ($status, $res) = $cv->recv;
if ($status ne "200") {
my $msg;
if (exists $res->{error}) {
$msg = "AyEvent::WebDriver: $res->{error}: $res->{message}";
$msg .= "\n$res->{stacktrace}caught at" if length $res->{stacktrace};
} else {
$msg = "AnyEvent::WebDriver: http status $status (wrong endpoint?), caught";
}
Carp::croak $msg;
}
( run in 1.438 second using v1.01-cache-2.11-cpan-df04353d9ac )