فهرست منبع

mass tidy to lessen urge to submit useless patches by users

George S. Baugh 6 سال پیش
والد
کامیت
974ab4ed5b

+ 39 - 34
lib/Selenium/ActionChains.pm

@@ -10,79 +10,78 @@ use Moo;
 
 =cut
 
-has 'driver' => (
-    is => 'ro',
-);
+has 'driver' => ( is => 'ro', );
 
 has 'actions' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub { [] },
     clearer => 1,
 );
 
 sub perform {
     my $self = shift;
-    foreach my $action (@{$self->actions}) {
+    foreach my $action ( @{ $self->actions } ) {
         $action->();
     }
 }
 
 sub click {
-    my $self = shift;
+    my $self    = shift;
     my $element = shift;
     if ($element) {
-       $self->move_to_element($element);
+        $self->move_to_element($element);
     }
+
     # left click
-    push @{$self->actions}, sub { $self->driver->click('LEFT') };
+    push @{ $self->actions }, sub { $self->driver->click('LEFT') };
     $self;
 }
 
 sub click_and_hold {
-    my $self = shift;
+    my $self    = shift;
     my $element = shift;
     if ($element) {
-       $self->move_to_element($element);
+        $self->move_to_element($element);
     }
-    push @{$self->actions}, sub { $self->driver->button_down };
+    push @{ $self->actions }, sub { $self->driver->button_down };
     $self;
 }
 
 sub context_click {
-    my $self = shift;
+    my $self    = shift;
     my $element = shift;
     if ($element) {
-       $self->move_to_element($element);
+        $self->move_to_element($element);
     }
+
     # right click
-    push @{$self->actions}, sub { $self->driver->click('RIGHT') };
+    push @{ $self->actions }, sub { $self->driver->click('RIGHT') };
     $self;
 }
 
-
 sub double_click {
-    my $self = shift;
+    my $self    = shift;
     my $element = shift;
     if ($element) {
-       $self->move_to_element($element);
+        $self->move_to_element($element);
     }
-    push @{$self->actions}, sub { $self->driver->double_click };
+    push @{ $self->actions }, sub { $self->driver->double_click };
     $self;
 }
 
 sub release {
-    my $self = shift;
+    my $self    = shift;
     my $element = shift;
     if ($element) {
-       $self->move_to_element($element);
+        $self->move_to_element($element);
     }
-    push @{$self->actions}, sub { $self->driver->button_up };
+    push @{ $self->actions }, sub { $self->driver->button_up };
     $self;
 }
 
 sub drag_and_drop {
     my $self = shift;
-    my ($source,$target) = @_;
+    my ( $source, $target ) = @_;
     $self->click_and_hold($source);
     $self->release($target);
     $self;
@@ -90,9 +89,9 @@ sub drag_and_drop {
 
 sub drag_and_drop_by_offset {
     my $self = shift;
-    my ($source,$xoffset,$yoffset) = @_;
+    my ( $source, $xoffset, $yoffset ) = @_;
     $self->click_and_hold($source);
-    $self->move_by_offset($xoffset,$yoffset);
+    $self->move_by_offset( $xoffset, $yoffset );
     $self->release($source);
     $self;
 }
@@ -118,42 +117,48 @@ sub move_to_element_with_offset {
     my $self = shift;
     my ( $element, $xoffset, $yoffset ) = @_;
     push @{ $self->actions }, sub {
-        $self->driver->move_to( element => $element, xoffset => $xoffset,
-            yoffset => $yoffset );
+        $self->driver->move_to(
+            element => $element,
+            xoffset => $xoffset,
+            yoffset => $yoffset
+        );
     };
     $self;
 }
 
 sub key_down {
     my $self = shift;
-    my ($value ,$element) = @_;
-    if (defined($element)) {
+    my ( $value, $element ) = @_;
+    if ( defined($element) ) {
         $self->click($element);
     }
-    push @{ $self->actions }, sub { $self->driver->send_keys_to_active_element(@$value) };
+    push @{ $self->actions },
+      sub { $self->driver->send_keys_to_active_element(@$value) };
     $self;
 }
 
 sub key_up {
     my $self = shift;
-    my ($value ,$element) = @_;
-    if (defined($element)) {
+    my ( $value, $element ) = @_;
+    if ( defined($element) ) {
         $self->click($element);
     }
-    push @{ $self->actions }, sub { $self->driver->send_keys_to_active_element(@$value) };
+    push @{ $self->actions },
+      sub { $self->driver->send_keys_to_active_element(@$value) };
     $self;
 }
 
 sub send_keys {
     my $self = shift;
     my $keys = shift;
-    push @{ $self->actions} , sub { $self->driver->get_active_element->send_keys($keys) };
+    push @{ $self->actions },
+      sub { $self->driver->get_active_element->send_keys($keys) };
     $self;
 }
 
 sub send_keys_to_element {
     my $self = shift;
-    my ($element,$keys) = @_;
+    my ( $element, $keys ) = @_;
     push @{ $self->actions }, sub { $element->send_keys($keys) };
     $self;
 }

+ 80 - 63
lib/Selenium/CanStartBinary.pm

@@ -5,7 +5,8 @@ use warnings;
 
 # ABSTRACT: Teach a WebDriver how to start its own binary aka no JRE!
 use File::Spec;
-use Selenium::CanStartBinary::ProbePort qw/find_open_port_above find_open_port probe_port/;
+use Selenium::CanStartBinary::ProbePort
+  qw/find_open_port_above find_open_port probe_port/;
 use Selenium::Firefox::Binary qw/setup_firefox_binary_env/;
 use Selenium::Waiter qw/wait_until/;
 use Moo::Role;
@@ -95,11 +96,11 @@ C<127.0.0.1:4444>.
 =cut
 
 has '_real_binary' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 
-        if ($self->_is_old_ff) {
+        if ( $self->_is_old_ff ) {
             return $self->firefox_binary;
         }
         else {
@@ -109,7 +110,7 @@ has '_real_binary' => (
 );
 
 has '_is_old_ff' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 
@@ -118,20 +119,20 @@ has '_is_old_ff' => (
 );
 
 has '+port' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 
-        if ($self->_real_binary) {
-            if ($self->fixed_ports) {
-                return find_open_port($self->binary_port);
+        if ( $self->_real_binary ) {
+            if ( $self->fixed_ports ) {
+                return find_open_port( $self->binary_port );
             }
             else {
-                return find_open_port_above($self->binary_port);
+                return find_open_port_above( $self->binary_port );
             }
         }
         else {
-            return 4444
+            return 4444;
         }
     }
 );
@@ -156,7 +157,7 @@ assigned, or no port will be assigned at all.
 =cut
 
 has 'fixed_ports' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 0 }
 );
 
@@ -176,25 +177,25 @@ To specify multiple arguments, just include them all in the string.
 =cut
 
 has custom_args => (
-    is => 'lazy',
+    is        => 'lazy',
     predicate => 1,
-    default => sub { '' }
+    default   => sub { '' }
 );
 
 has 'marionette_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 
-        if ($self->_is_old_ff) {
+        if ( $self->_is_old_ff ) {
             return 0;
         }
         else {
-            if ($self->fixed_ports) {
-                return find_open_port($self->marionette_binary_port);
+            if ( $self->fixed_ports ) {
+                return find_open_port( $self->marionette_binary_port );
             }
             else {
-                return find_open_port_above($self->marionette_binary_port);
+                return find_open_port_above( $self->marionette_binary_port );
             }
         }
     }
@@ -222,7 +223,7 @@ section of a L<Selenium::Waiter/wait_until> subroutine call.
 =cut
 
 has startup_timeout => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 10 }
 );
 
@@ -241,14 +242,14 @@ class should attempt normal L<Selenium::Remote::Driver> behavior.
 =cut
 
 has 'binary_mode' => (
-    is => 'lazy',
-    init_arg => undef,
-    builder => 1,
+    is        => 'lazy',
+    init_arg  => undef,
+    builder   => 1,
     predicate => 1
 );
 
 has 'try_binary' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 0 },
     trigger => sub {
         my ($self) = @_;
@@ -265,11 +266,12 @@ up, we know what the window title is that we're going to C<taskkill>.
 =cut
 
 has 'window_title' => (
-    is => 'lazy',
+    is       => 'lazy',
     init_arg => undef,
-    builder => sub {
+    builder  => sub {
         my ($self) = @_;
-        my (undef, undef, $file) = File::Spec->splitpath( $self->_real_binary );
+        my ( undef, undef, $file ) =
+          File::Spec->splitpath( $self->_real_binary );
         my $port = $self->port;
 
         return $file . ':' . $port;
@@ -288,9 +290,9 @@ was run to start the webdriver server.
 =cut
 
 has '_command' => (
-    is => 'lazy',
+    is       => 'lazy',
     init_arg => undef,
-    builder => sub {
+    builder  => sub {
         my ($self) = @_;
         return $self->_construct_command;
     }
@@ -304,7 +306,7 @@ Setting this will redirect it to the provided file.
 =cut
 
 has 'logfile' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub {
         return '/nul' if IS_WIN;
         return '/dev/null';
@@ -312,6 +314,7 @@ has 'logfile' => (
 );
 
 sub BUILDARGS {
+
     # There's a bit of finagling to do to since we can't ensure the
     # attribute instantiation order. To decide whether we're going into
     # binary mode, we need the remote_server_addr and port. But, they're
@@ -328,7 +331,7 @@ sub BUILDARGS {
     # binary mode or not.
     my ( undef, %args ) = @_;
 
-    if ( ! exists $args{remote_server_addr} && ! exists $args{port} ) {
+    if ( !exists $args{remote_server_addr} && !exists $args{port} ) {
         $args{try_binary} = 1;
 
         # Windows may throw a fit about invalid pointers if we try to
@@ -336,11 +339,11 @@ sub BUILDARGS {
         $args{remote_server_addr} = '127.0.0.1';
     }
     else {
-        $args{try_binary} = 0;
+        $args{try_binary}  = 0;
         $args{binary_mode} = 0;
     }
 
-    return { %args };
+    return {%args};
 }
 
 sub _build_binary_mode {
@@ -352,49 +355,54 @@ sub _build_binary_mode {
     # Either the user asked for 4444, or we couldn't find an open port
     my $port = $self->port + 0;
     return if $port == 4444;
-    if( $self->fixed_ports && $port == 0 ){
-        die 'port ' . $self->binary_port . ' is not free and have requested fixed ports';
+    if ( $self->fixed_ports && $port == 0 ) {
+        die 'port '
+          . $self->binary_port
+          . ' is not free and have requested fixed ports';
     }
 
     $self->_handle_firefox_setup($port);
 
-    system($self->_command);
+    system( $self->_command );
 
-    my $success = wait_until { probe_port($port) } timeout => $self->startup_timeout;
+    my $success =
+      wait_until { probe_port($port) } timeout => $self->startup_timeout;
     if ($success) {
         return 1;
     }
     else {
-        die 'Unable to connect to the ' . $self->_real_binary . ' binary on port ' . $port;
+        die 'Unable to connect to the '
+          . $self->_real_binary
+          . ' binary on port '
+          . $port;
     }
 }
 
 sub _handle_firefox_setup {
-    my ($self, $port) = @_;
+    my ( $self, $port ) = @_;
 
     # This is a no-op for other browsers
     return unless $self->isa('Selenium::Firefox');
 
-    my $user_profile = $self->has_firefox_profile
+    my $user_profile =
+        $self->has_firefox_profile
       ? $self->firefox_profile
       : 0;
 
-    my $profile = setup_firefox_binary_env(
-        $port,
-        $self->marionette_port,
-        $user_profile
-    );
+    my $profile =
+      setup_firefox_binary_env( $port, $self->marionette_port, $user_profile );
+
+    if ( $self->_is_old_ff ) {
 
-    if ($self->_is_old_ff) {
         # For non-geckodriver/non-marionette, we want to get rid of
         # the profile so that we don't accidentally zip it and encode
         # it down the line while Firefox is trying to read from it.
         $self->clear_firefox_profile if $self->has_firefox_profile;
     }
     else {
-        # For geckodriver/marionette, we keep the enhanced profile around because
-        # we need to send it to geckodriver as a zipped b64-encoded
-        # directory.
+       # For geckodriver/marionette, we keep the enhanced profile around because
+       # we need to send it to geckodriver as a zipped b64-encoded
+       # directory.
         $self->firefox_profile($profile);
     }
 }
@@ -406,11 +414,12 @@ sub shutdown_binary {
         $self->quit();
     }
 
-    if ($self->has_binary_mode && $self->binary_mode) {
+    if ( $self->has_binary_mode && $self->binary_mode ) {
+
         # Tell the binary itself to shutdown
         my $port = $self->port;
-        my $ua = $self->ua;
-        $ua->get('http://127.0.0.1:' . $port . '/wd/hub/shutdown');
+        my $ua   = $self->ua;
+        $ua->get( 'http://127.0.0.1:' . $port . '/wd/hub/shutdown' );
 
         # Close the orphaned command windows on windows
         $self->shutdown_windows_binary;
@@ -423,11 +432,14 @@ sub shutdown_unix_binary {
     my ($self) = @_;
     if (!IS_WIN) {
         my $cmd = "lsof -t -i :".$self->port();
-        my ( $pid ) = grep { $_ && $_ ne $$ } split /\s+/, scalar `$cmd`;
+        my ( $pid ) = grep { $_ && $_ ne $$ } split( /\s+/, scalar `$cmd` );
         if ($pid) {
-            print "Killing Driver PID $pid listening on port ".$self->port."...\n";
+            print "Killing Driver PID $pid listening on port "
+              . $self->port . "...\n";
             eval { kill 'KILL', $pid };
-            warn "Could not kill driver process! you may have to clean up manually." if $@;
+            warn
+"Could not kill driver process! you may have to clean up manually."
+              if $@;
         }
     }
 }
@@ -436,7 +448,8 @@ sub shutdown_windows_binary {
     my ($self) = @_;
 
     if (IS_WIN) {
-        if ($self->_is_old_ff) {
+        if ( $self->_is_old_ff ) {
+
             # FIXME: Blech, handle a race condition that kills the
             # driver before it's finished cleaning up its sessions. In
             # particular, when the perl process ends, it wants to
@@ -445,17 +458,20 @@ sub shutdown_windows_binary {
             # it will have a lock on the temp profile directory, and
             # perl will get upset. This "solution" is _very_ bad.
             sleep(2);
+
             # Firefox doesn't have a Driver/Session architecture - the
             # only thing running is Firefox itself, so there's no
             # other task to kill.
             return;
         }
-        system('taskkill /FI "WINDOWTITLE eq ' . $self->window_title . '" > nul 2>&1');
+        system( 'taskkill /FI "WINDOWTITLE eq '
+              . $self->window_title
+              . '" > nul 2>&1' );
     }
 }
 
 sub DEMOLISH {
-    my ($self, $in_gd) = @_;
+    my ( $self, $in_gd ) = @_;
 
     # if we're in global destruction, all bets are off.
     return if $in_gd;
@@ -471,13 +487,13 @@ sub _construct_command {
 
     # The different binaries take different arguments for proper setup
     $executable .= $self->_binary_args;
-    if ($self->has_custom_args) {
+    if ( $self->has_custom_args ) {
         $executable .= ' ' . $self->custom_args;
     }
 
     # Handle Windows vs Unix discrepancies for invoking shell commands
-    my ($prefix, $suffix) = ($self->_cmd_prefix, $self->_cmd_suffix);
-    return join(' ', ($prefix, $executable, $suffix) );
+    my ( $prefix, $suffix ) = ( $self->_cmd_prefix, $self->_cmd_suffix );
+    return join( ' ', ( $prefix, $executable, $suffix ) );
 }
 
 sub _cmd_prefix {
@@ -487,7 +503,8 @@ sub _cmd_prefix {
     if (IS_WIN) {
         $prefix = 'start "' . $self->window_title . '"';
 
-        if ($self->_is_old_ff) {
+        if ( $self->_is_old_ff ) {
+
             # For older versions of Firefox that run without
             # marionette, the command we're running actually starts up
             # the browser itself, so we don't want to minimize it.
@@ -505,8 +522,8 @@ sub _cmd_prefix {
 
 sub _cmd_suffix {
     my ($self) = @_;
-    return " > ".$self->logfile." 2>&1 " if IS_WIN;
-    return " > ".$self->logfile." 2>&1 &";
+    return " > " . $self->logfile . " 2>&1 " if IS_WIN;
+    return " > " . $self->logfile . " 2>&1 &";
 }
 
 =head1 SEE ALSO

+ 7 - 5
lib/Selenium/CanStartBinary/FindBinary.pm

@@ -10,7 +10,7 @@ use IO::Socket::INET;
 use Selenium::Firefox::Binary qw/firefox_path/;
 
 require Exporter;
-our @ISA = qw/Exporter/;
+our @ISA       = qw/Exporter/;
 our @EXPORT_OK = qw/coerce_simple_binary coerce_firefox_binary/;
 
 use constant IS_WIN => $^O eq 'MSWin32';
@@ -49,15 +49,17 @@ sub _validate_manual_binary {
     my $abs_executable = eval {
         my $path = abs_path($executable);
         die unless -e $path;
-        $path
+        $path;
     };
 
-    if ( $abs_executable ) {
+    if ($abs_executable) {
         if ( -x $abs_executable || IS_WIN ) {
             return $abs_executable;
         }
         else {
-            die 'The binary at ' . $executable . ' is not executable. Choose the correct file or chmod +x it as needed.';
+            die 'The binary at '
+              . $executable
+              . ' is not executable. Choose the correct file or chmod +x it as needed.';
         }
     }
 }
@@ -66,7 +68,7 @@ sub _naive_find_binary {
     my ($executable) = @_;
 
     my $naive_binary = which($executable);
-    if (defined $naive_binary) {
+    if ( defined $naive_binary ) {
         return $naive_binary;
     }
     else {

+ 2 - 2
lib/Selenium/CanStartBinary/ProbePort.pm

@@ -9,7 +9,7 @@ use IO::Socket::INET;
 use Selenium::Waiter qw/wait_until/;
 
 require Exporter;
-our @ISA = qw/Exporter/;
+our @ISA       = qw/Exporter/;
 our @EXPORT_OK = qw/find_open_port_above find_open_port probe_port/;
 
 =for Pod::Coverage *EVERYTHING*
@@ -44,6 +44,6 @@ sub probe_port {
     return IO::Socket::INET->new(
         PeerAddr => '127.0.0.1',
         PeerPort => $port,
-        Timeout => 3
+        Timeout  => 3
     );
 }

+ 6 - 6
lib/Selenium/Chrome.pm

@@ -38,7 +38,7 @@ check the C<binary_mode> attr after instantiation.
 =cut
 
 has '+browser_name' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'chrome' }
 );
 
@@ -50,9 +50,9 @@ anything, we'll try to find it on our own via L<File::Which/which>.
 =cut
 
 has 'binary' => (
-    is => 'lazy',
-    coerce => \&coerce_simple_binary,
-    default => sub { 'chromedriver' },
+    is        => 'lazy',
+    coerce    => \&coerce_simple_binary,
+    default   => sub { 'chromedriver' },
     predicate => 1
 );
 
@@ -71,12 +71,12 @@ actual port turned out to be.
 =cut
 
 has 'binary_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 9515 }
 );
 
 has '_binary_args' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 

+ 6 - 6
lib/Selenium/Edge.pm

@@ -38,7 +38,7 @@ check the C<binary_mode> attr after instantiation.
 =cut
 
 has '+browser_name' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'MicrosoftEdge' }
 );
 
@@ -50,9 +50,9 @@ anything, we'll try to find it on our own via L<File::Which/which>.
 =cut
 
 has 'binary' => (
-    is => 'lazy',
-    coerce => \&coerce_simple_binary,
-    default => sub { 'MicrosoftWebDriver.exe' },
+    is        => 'lazy',
+    coerce    => \&coerce_simple_binary,
+    default   => sub { 'MicrosoftWebDriver.exe' },
     predicate => 1
 );
 
@@ -71,12 +71,12 @@ actual port turned out to be.
 =cut
 
 has 'binary_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 17556 }
 );
 
 has '_binary_args' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 

+ 23 - 18
lib/Selenium/Firefox.pm

@@ -7,7 +7,8 @@ use warnings;
 use Moo;
 use Carp;
 use Selenium::Firefox::Binary qw/firefox_path/;
-use Selenium::CanStartBinary::FindBinary qw/coerce_simple_binary coerce_firefox_binary/;
+use Selenium::CanStartBinary::FindBinary
+  qw/coerce_simple_binary coerce_firefox_binary/;
 extends 'Selenium::Remote::Driver';
 
 =head1 SYNOPSIS
@@ -94,7 +95,7 @@ Firefox.
 =cut
 
 has '+browser_name' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'firefox' }
 );
 
@@ -114,9 +115,9 @@ older FF browsers do not use the separate driver binary startup.
 =cut
 
 has 'binary' => (
-    is => 'lazy',
-    coerce => \&coerce_simple_binary,
-    default => sub { 'geckodriver' },
+    is        => 'lazy',
+    coerce    => \&coerce_simple_binary,
+    default   => sub { 'geckodriver' },
     predicate => 1
 );
 
@@ -135,7 +136,7 @@ actual port turned out to be.
 =cut
 
 has 'binary_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 9090 }
 );
 
@@ -154,14 +155,18 @@ result some options may be overwritten or ignored.
 =cut
 
 has '_binary_args' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 
         if ( $self->marionette_enabled ) {
-            my $args = ' --port ' . $self->port
-              . ' --marionette-port ' . $self->marionette_binary_port
-              . ' --binary "' . $self->firefox_binary . '"';
+            my $args =
+                ' --port '
+              . $self->port
+              . ' --marionette-port '
+              . $self->marionette_binary_port
+              . ' --binary "'
+              . $self->firefox_binary . '"';
 
             return $args;
         }
@@ -172,11 +177,11 @@ has '_binary_args' => (
 );
 
 has '+wd_context_prefix' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub {
         my ($self) = @_;
 
-        if ($self->marionette_enabled) {
+        if ( $self->marionette_enabled ) {
             return '';
         }
         else {
@@ -206,7 +211,7 @@ not do anything useful.
 =cut
 
 has 'marionette_binary_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 2828 }
 );
 
@@ -224,7 +229,7 @@ start Firefox 47 or older, you must pass C<< marionette_enabled => 0 >>.
 =cut
 
 has 'marionette_enabled' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => 1
 );
 
@@ -247,14 +252,14 @@ directly start up.
 =cut
 
 has 'firefox_binary' => (
-    is => 'lazy',
-    coerce => \&coerce_firefox_binary,
+    is        => 'lazy',
+    coerce    => \&coerce_firefox_binary,
     predicate => 1,
-    builder => 'firefox_path'
+    builder   => 'firefox_path'
 );
 
 has '_execute_script_suffix' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => 'Gecko'
 );
 

+ 26 - 20
lib/Selenium/Firefox/Binary.pm

@@ -8,10 +8,11 @@ use File::Which qw/which/;
 use Selenium::Firefox::Profile;
 
 require Exporter;
-our @ISA = qw/Exporter/;
+our @ISA       = qw/Exporter/;
 our @EXPORT_OK = qw/firefox_path setup_firefox_binary_env/;
 
 sub _firefox_windows_path {
+
     # TODO: make this slightly less dumb
     my @program_files = (
         $ENV{PROGRAMFILES} // 'C:\Program Files',
@@ -24,15 +25,17 @@ sub _firefox_windows_path {
     }
 
     # Fall back to a completely naive strategy
-    warn q/We couldn't find a viable firefox.EXE; you may want to specify it via the binary attribute./;
+    warn
+q/We couldn't find a viable firefox.EXE; you may want to specify it via the binary attribute./;
     return which('firefox');
 }
 
 sub _firefox_darwin_path {
-    my $default_firefox = '/Applications/Firefox.app/Contents/MacOS/firefox-bin';
+    my $default_firefox =
+      '/Applications/Firefox.app/Contents/MacOS/firefox-bin';
 
-    if (-e $default_firefox && -x $default_firefox) {
-        return $default_firefox
+    if ( -e $default_firefox && -x $default_firefox ) {
+        return $default_firefox;
     }
     else {
         return which('firefox-bin');
@@ -40,6 +43,7 @@ sub _firefox_darwin_path {
 }
 
 sub _firefox_unix_path {
+
     # TODO: maybe which('firefox3'), which('firefox2') ?
     return which('firefox') || '/usr/bin/firefox';
 }
@@ -54,17 +58,17 @@ Return the path to the firefox binary on your system.
 
 sub firefox_path {
     my $path;
-    if ($^O eq 'MSWin32') {
-        $path =_firefox_windows_path();
+    if ( $^O eq 'MSWin32' ) {
+        $path = _firefox_windows_path();
     }
-    elsif ($^O eq 'darwin') {
+    elsif ( $^O eq 'darwin' ) {
         $path = _firefox_darwin_path();
     }
     else {
         $path = _firefox_unix_path;
     }
 
-    if (not -x $path) {
+    if ( not -x $path ) {
         die $path . ' is not an executable file.';
     }
 
@@ -80,21 +84,23 @@ Sets various environment variables to make firefox work correctly with webDriver
 # We want the profile to persist to the end of the session, not just
 # the end of this function.
 my $profile;
+
 sub setup_firefox_binary_env {
-    my ($port, $marionette_port, $caller_profile) = @_;
+    my ( $port, $marionette_port, $caller_profile ) = @_;
 
     $profile = $caller_profile || Selenium::Firefox::Profile->new;
-    $profile->add_webdriver($port, $marionette_port);
+    $profile->add_webdriver( $port, $marionette_port );
     $profile->add_marionette($marionette_port);
 
     # For non-geckodriver/marionette startup, we instruct Firefox to
     # use the profile by specifying the appropriate environment
     # variables for it to hook onto.
-    if (! $marionette_port) {
+    if ( !$marionette_port ) {
         $ENV{'XRE_PROFILE_PATH'} = $profile->_layout_on_disk;
-        $ENV{'MOZ_NO_REMOTE'} = '1'; # able to launch multiple instances
-        $ENV{'MOZ_CRASHREPORTER_DISABLE'} = '1'; # disable breakpad
-        $ENV{'NO_EM_RESTART'} = '1'; # prevent the binary from detaching from the console.log
+        $ENV{'MOZ_NO_REMOTE'} = '1';    # able to launch multiple instances
+        $ENV{'MOZ_CRASHREPORTER_DISABLE'} = '1';    # disable breakpad
+        $ENV{'NO_EM_RESTART'} =
+          '1';    # prevent the binary from detaching from the console.log
     }
     else {
         # In case the user created an old Firefox, which would've set
@@ -104,11 +110,11 @@ sub setup_firefox_binary_env {
         # load it in the new geckodriver Firefox, which would cause an
         # extension compatibility check
         my @env_vars = qw/
-                             XRE_PROFILE_PATH
-                             MOZ_NO_REMOTE
-                             MOZ_CRASHREPORTER_DISABLE
-                             NO_EM_RESTART
-                         /;
+          XRE_PROFILE_PATH
+          MOZ_NO_REMOTE
+          MOZ_CRASHREPORTER_DISABLE
+          NO_EM_RESTART
+          /;
 
         foreach (@env_vars) {
             delete $ENV{$_};

+ 52 - 42
lib/Selenium/Firefox/Profile.pm

@@ -75,9 +75,9 @@ sub new {
     # constructor
     my $self = {
         profile_dir => $profile_dir,
-        user_prefs => {},
-        extensions => []
-      };
+        user_prefs  => {},
+        extensions  => []
+    };
     bless $self, $class or die "Can't bless $class: $!";
 
     return $self;
@@ -103,17 +103,18 @@ either use JSON::true/JSON::false, or see C<set_boolean_preference()>.
 =cut
 
 sub set_preference {
-    my ($self, %prefs) = @_;
+    my ( $self, %prefs ) = @_;
 
-    foreach (keys %prefs) {
-        my $value = $prefs{$_};
+    foreach ( keys %prefs ) {
+        my $value       = $prefs{$_};
         my $clean_value = '';
 
         if ( JSON::is_bool($value) ) {
-            $self->set_boolean_preference($_, $value );
+            $self->set_boolean_preference( $_, $value );
             next;
         }
-        elsif ($value =~ /^(['"]).*\1$/ or looks_like_number($value)) {
+        elsif ( $value =~ /^(['"]).*\1$/ or looks_like_number($value) ) {
+
             # plain integers: 0, 1, 32768, or integers wrapped in strings:
             # "0", "1", "20140204". in either case, there's nothing for us
             # to do.
@@ -144,9 +145,9 @@ preferences, use C<set_preference()>.
 =cut
 
 sub set_boolean_preference {
-    my ($self, %prefs) = @_;
+    my ( $self, %prefs ) = @_;
 
-    foreach (keys %prefs) {
+    foreach ( keys %prefs ) {
         my $value = $prefs{$_};
 
         $self->{user_prefs}->{$_} = $value ? 'true' : 'false';
@@ -168,7 +169,7 @@ accordingly.
 =cut
 
 sub get_preference {
-    my ($self, $pref) = @_;
+    my ( $self, $pref ) = @_;
 
     return $self->{user_prefs}->{$pref};
 }
@@ -184,13 +185,14 @@ directories.
 =cut
 
 sub add_extension {
-    my ($self, $xpi) = @_;
+    my ( $self, $xpi ) = @_;
 
     croak 'File not found: ' . $xpi unless -e $xpi;
     my $xpi_abs_path = abs_path($xpi);
-    croak '$xpi_abs_path: extensions must be in .xpi format' unless $xpi_abs_path =~ /\.xpi$/;
+    croak '$xpi_abs_path: extensions must be in .xpi format'
+      unless $xpi_abs_path =~ /\.xpi$/;
 
-    push (@{$self->{extensions}}, $xpi_abs_path);
+    push( @{ $self->{extensions} }, $xpi_abs_path );
 }
 
 =head2 add_webdriver
@@ -201,22 +203,24 @@ for a new geckodriver session.
 =cut
 
 sub add_webdriver {
-    my ($self, $port, $is_marionette) = @_;
+    my ( $self, $port, $is_marionette ) = @_;
 
-    my $prefs = $self->_load_prefs;
+    my $prefs              = $self->_load_prefs;
     my $current_user_prefs = $self->{user_prefs};
 
     $self->set_preference(
         %{ $prefs->{mutable} },
+
         # having the user prefs here allows them to overwrite the
         # mutable loaded prefs
-        %{ $current_user_prefs },
+        %{$current_user_prefs},
+
         # but the frozen ones cannot be overwritten
         %{ $prefs->{frozen} },
         'webdriver_firefox_port' => $port
     );
 
-    if (! $is_marionette) {
+    if ( !$is_marionette ) {
         $self->_add_webdriver_xpi;
     }
 
@@ -224,21 +228,22 @@ sub add_webdriver {
 }
 
 sub _load_prefs {
+
     # The appropriate webdriver preferences are stored in an adjacent
     # JSON file; it's useful things like disabling default browser
     # checks and setting an empty single page as the start up tab
     # configuration. Unfortunately, these change with each version of
     # webdriver.
 
-    my $this_dir = dirname(abs_path(__FILE__));
+    my $this_dir               = dirname( abs_path(__FILE__) );
     my $default_prefs_filename = $this_dir . '/webdriver_prefs.json';
 
     my $json;
     {
         local $/;
-        open (my $fh, '<', $default_prefs_filename);
+        open( my $fh, '<', $default_prefs_filename );
         $json = <$fh>;
-        close ($fh);
+        close($fh);
     }
 
     my $prefs = decode_json($json);
@@ -259,7 +264,7 @@ introduction of C<geckodriver>.
 sub _add_webdriver_xpi {
     my ($self) = @_;
 
-    my $this_dir = dirname(abs_path(__FILE__));
+    my $this_dir            = dirname( abs_path(__FILE__) );
     my $webdriver_extension = $this_dir . '/webdriver.xpi';
 
     $self->add_extension($webdriver_extension);
@@ -273,9 +278,9 @@ current Firefox profile.
 =cut
 
 sub add_marionette {
-    my ($self, $port) = @_;
+    my ( $self, $port ) = @_;
     return if !$port;
-    $self->set_preference('marionette.defaultPrefs.port', $port);
+    $self->set_preference( 'marionette.defaultPrefs.port', $port );
 }
 
 sub _encode {
@@ -289,13 +294,13 @@ sub _encode {
     $zip->addTree( $self->{profile_dir} );
 
     my $string = "";
-    open (my $fh, ">", \$string);
+    open( my $fh, ">", \$string );
     binmode($fh);
     unless ( $zip->writeToFileHandle($fh) == AZ_OK ) {
         die 'write error';
     }
 
-    return encode_base64($string, '');
+    return encode_base64( $string, '' );
 }
 
 sub _layout_on_disk {
@@ -311,56 +316,61 @@ sub _write_preferences {
     my $self = shift;
 
     my $userjs = $self->{profile_dir} . "/user.js";
-    open (my $fh, ">>", $userjs)
-        or die "Cannot open $userjs for writing preferences: $!";
+    open( my $fh, ">>", $userjs )
+      or die "Cannot open $userjs for writing preferences: $!";
 
-    foreach (keys %{$self->{user_prefs}}) {
-        print $fh 'user_pref("' . $_ . '", ' . $self->get_preference($_) . ');' . "\n";
+    foreach ( keys %{ $self->{user_prefs} } ) {
+        print $fh 'user_pref("'
+          . $_ . '", '
+          . $self->get_preference($_) . ');' . "\n";
     }
-    close ($fh);
+    close($fh);
 }
 
 sub _install_extensions {
-    my $self = shift;
+    my $self          = shift;
     my $extension_dir = $self->{profile_dir} . "/extensions/";
     mkdir $extension_dir unless -d $extension_dir;
 
     # TODO: handle extensions that need to be unpacked
-    foreach my $xpi (@{$self->{extensions}}) {
+    foreach my $xpi ( @{ $self->{extensions} } ) {
+
         # For Firefox to recognize the extension, we have to put the
         # .xpi in the /extensions/ folder and change the filename to
         # its id, which is found in the install.rdf in the root of the
         # zip.
 
         my $rdf_string = $self->_extract_install_rdf($xpi);
-        my $rdf = XMLin($rdf_string);
-        my $name = $rdf->{Description}->{'em:id'};
+        my $rdf        = XMLin($rdf_string);
+        my $name       = $rdf->{Description}->{'em:id'};
 
         my $xpi_dest = $extension_dir . $name . ".xpi";
-        copy($xpi, $xpi_dest)
-            or croak "Error copying $_ to $xpi_dest : $!";
+        copy( $xpi, $xpi_dest )
+          or croak "Error copying $_ to $xpi_dest : $!";
     }
 }
 
 sub _extract_install_rdf {
-    my ($self, $xpi) = @_;
+    my ( $self, $xpi ) = @_;
 
     my $unzipped = IO::Uncompress::Unzip->new($xpi)
       or die "Cannot unzip $xpi: $UnzipError";
 
     my $install_rdf = '';
-    while ($unzipped->nextStream) {
+    while ( $unzipped->nextStream ) {
         my $filename = $unzipped->getHeaderInfo->{Name};
-        if ($filename eq 'install.rdf') {
+        if ( $filename eq 'install.rdf' ) {
             my $buffer;
-            while ((my $status = $unzipped->read($buffer)) > 0) {
+            while ( ( my $status = $unzipped->read($buffer) ) > 0 ) {
                 $install_rdf .= $buffer;
             }
             return $install_rdf;
         }
     }
 
-    croak 'Invalid Firefox extension: could not find install.rdf in the .XPI at: ' . $xpi
+    croak
+      'Invalid Firefox extension: could not find install.rdf in the .XPI at: '
+      . $xpi;
 }
 
 1;

+ 2 - 2
lib/Selenium/InternetExplorer.pm

@@ -16,12 +16,12 @@ extends 'Selenium::Remote::Driver';
 =cut
 
 has '+browser_name' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'internet_explorer' }
 );
 
 has '+platform' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'WINDOWS' }
 );
 

+ 6 - 6
lib/Selenium/PhantomJS.pm

@@ -51,7 +51,7 @@ L<Github|https://github.com/gempesaw/Selenium-Remote-Driver>; thanks!
 =cut
 
 has '+browser_name' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'phantomjs' }
 );
 
@@ -63,9 +63,9 @@ anything, we'll try to find it on our own via L<File::Which/which>.
 =cut
 
 has 'binary' => (
-    is => 'lazy',
-    coerce => \&coerce_simple_binary,
-    default => sub { 'phantomjs' },
+    is        => 'lazy',
+    coerce    => \&coerce_simple_binary,
+    default   => sub { 'phantomjs' },
     predicate => 1
 );
 
@@ -84,12 +84,12 @@ actual port turned out to be.
 =cut
 
 has 'binary_port' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 8910 }
 );
 
 has '_binary_args' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my ($self) = @_;
 

+ 52 - 51
lib/Selenium/Remote/Commands.pm

@@ -51,13 +51,13 @@ has '_cmds' => (
                 'no_content_success' => 1
             },
             'setAsyncScriptTimeout' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/timeouts/async_script',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/timeouts/async_script',
                 'no_content_success' => 1
             },
             'setImplicitWaitTimeout' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/timeouts/implicit_wait',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/timeouts/implicit_wait',
                 'no_content_success' => 1
             },
             'quit' => {
@@ -76,28 +76,28 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'getWindowSize' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/window/:windowHandle/size',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/window/:windowHandle/size',
                 'no_content_success' => 0
             },
             'getWindowPosition' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/window/:windowHandle/position',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/window/:windowHandle/position',
                 'no_content_success' => 0
             },
             'maximizeWindow' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/window/:windowHandle/maximize',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/window/:windowHandle/maximize',
                 'no_content_success' => 1
             },
             'setWindowSize' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/window/:windowHandle/size',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/window/:windowHandle/size',
                 'no_content_success' => 1
             },
             'setWindowPosition' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/window/:windowHandle/position',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/window/:windowHandle/position',
                 'no_content_success' => 1
             },
             'getCurrentUrl' => {
@@ -141,8 +141,8 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'availableEngines' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/ime/available_engines',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/ime/available_engines',
                 'no_content_success' => 0
             },
             'switchToFrame' => {
@@ -206,13 +206,13 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'findChildElement' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/element/:id/element',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/element/:id/element',
                 'no_content_success' => 0
             },
             'findChildElements' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/element/:id/elements',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/element/:id/elements',
                 'no_content_success' => 0
             },
             'clickElement' => {
@@ -241,13 +241,13 @@ has '_cmds' => (
                 'no_content_success' => 1
             },
             'isElementSelected' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/selected',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/selected',
                 'no_content_success' => 0
             },
             'setElementSelected' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/element/:id/selected',
+                'method' => 'POST',
+                'url'    => 'session/:sessionId/element/:id/selected',
                 'no_content_success' => 0
             },
             'toggleElement' => {
@@ -256,18 +256,18 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'isElementEnabled' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/enabled',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/enabled',
                 'no_content_success' => 0
             },
             'getElementLocation' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/location',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/location',
                 'no_content_success' => 0
             },
             'getElementLocationInView' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/location_in_view',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/location_in_view',
                 'no_content_success' => 0
             },
             'getElementTagName' => {
@@ -281,18 +281,18 @@ has '_cmds' => (
                 'no_content_success' => 1
             },
             'getElementAttribute' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/attribute/:name',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/attribute/:name',
                 'no_content_success' => 0
             },
             'elementEquals' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/equals/:other',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/equals/:other',
                 'no_content_success' => 0
             },
             'isElementDisplayed' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/displayed',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/displayed',
                 'no_content_success' => 0
             },
             'close' => {
@@ -311,8 +311,8 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'getElementValueOfCssProperty' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/element/:id/css/:propertyName',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/element/:id/css/:propertyName',
                 'no_content_success' => 0
             },
             'mouseMoveToLocation' => {
@@ -366,18 +366,18 @@ has '_cmds' => (
                 'no_content_success' => 0
             },
             'getLocalStorageItem' => {
-                'method'             => 'GET',
-                'url'                => '/session/:sessionId/local_storage/key/:key',
+                'method' => 'GET',
+                'url'    => '/session/:sessionId/local_storage/key/:key',
                 'no_content_success' => 0
             },
             'deleteLocalStorageItem' => {
-                'method'             => 'DELETE',
-                'url'                => '/session/:sessionId/local_storage/key/:key',
+                'method' => 'DELETE',
+                'url'    => '/session/:sessionId/local_storage/key/:key',
                 'no_content_success' => 1
             },
             'cacheStatus' => {
-                'method'             => 'GET',
-                'url'                => 'session/:sessionId/application_cache/status',
+                'method' => 'GET',
+                'url'    => 'session/:sessionId/application_cache/status',
                 'no_content_success' => 0
             },
             'setGeolocation' => {
@@ -385,7 +385,7 @@ has '_cmds' => (
                 'url'                => 'session/:sessionId/location',
                 'no_content_success' => 1
             },
-            'getGeolocation'   => {
+            'getGeolocation' => {
                 'method'             => 'GET',
                 'url'                => 'session/:sessionId/location',
                 'no_content_success' => 0
@@ -395,7 +395,7 @@ has '_cmds' => (
                 'url'                => 'session/:sessionId/log',
                 'no_content_success' => 0
             },
-            'getLogTypes'   => {
+            'getLogTypes' => {
                 'method'             => 'GET',
                 'url'                => 'session/:sessionId/log/types',
                 'no_content_success' => 0
@@ -405,11 +405,12 @@ has '_cmds' => (
                 'url'                => 'session/:sessionId/orientation',
                 'no_content_success' => 1
             },
-            'getOrientation'   => {
+            'getOrientation' => {
                 'method'             => 'GET',
                 'url'                => 'session/:sessionId/orientation',
                 'no_content_success' => 0
             },
+
             # firefox extension
             'setContext' => {
                 'method'             => 'POST',
@@ -473,7 +474,7 @@ sub get_params {
     #Allow fall-back in the event the command passed doesn't exist
     return unless $self->get_cmds()->{$command};
 
-    my $url     = $self->get_url($command);
+    my $url = $self->get_url($command);
 
     # Do the var substitutions.
     $url =~ s/:sessionId/$args->{'session_id'}/;
@@ -483,15 +484,15 @@ sub get_params {
     $url =~ s/:other/$args->{'other'}/;
     $url =~ s/:windowHandle/$args->{'window_handle'}/;
 
-    $data->{'method'} = $self->get_method($command);
+    $data->{'method'}             = $self->get_method($command);
     $data->{'no_content_success'} = $self->get_no_content_success($command);
-    $data->{'url'}    = $url;
+    $data->{'url'}                = $url;
 
     return $data;
 }
 
 sub parse_response {
-    my ($self,$res,$resp) = @_;
+    my ( $self, $res, $resp ) = @_;
     if ( ref($resp) eq 'HASH' ) {
         if ( $resp->{cmd_status} && $resp->{cmd_status} eq 'OK' ) {
             return $resp->{cmd_return};

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 298 - 207
lib/Selenium/Remote/Driver.pm


+ 1 - 1
lib/Selenium/Remote/Driver/CanSetWebdriverContext.pm

@@ -23,7 +23,7 @@ internal-facing concern.
 =cut
 
 has 'wd_context_prefix' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { '/wd/hub' }
 );
 

+ 22 - 16
lib/Selenium/Remote/ErrorHandler.pm

@@ -17,42 +17,42 @@ has STATUS_CODE => (
             7 => {
                 'code' => 'NO_SUCH_ELEMENT',
                 'msg' =>
-                  'An element could not be located on the page using the given search parameters.',
+'An element could not be located on the page using the given search parameters.',
             },
             8 => {
                 'code' => 'NO_SUCH_FRAME',
                 'msg' =>
-                  'A request to switch to a frame could not be satisfied because the frame could not be found.',
+'A request to switch to a frame could not be satisfied because the frame could not be found.',
             },
             9 => {
                 'code' => 'UNKNOWN_COMMAND',
                 'msg' =>
-                  'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.',
+'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.',
             },
             10 => {
                 'code' => 'STALE_ELEMENT_REFERENCE',
                 'msg' =>
-                  'An element command failed because the referenced element is no longer attached to the DOM.',
+'An element command failed because the referenced element is no longer attached to the DOM.',
             },
             11 => {
                 'code' => 'ELEMENT_NOT_VISIBLE',
                 'msg' =>
-                  'An element command could not be completed because the element is not visible on the page.',
+'An element command could not be completed because the element is not visible on the page.',
             },
             12 => {
                 'code' => 'INVALID_ELEMENT_STATE',
                 'msg' =>
-                  'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).',
+'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).',
             },
             13 => {
                 'code' => 'UNKNOWN_ERROR',
                 'msg' =>
-                  'An unknown server-side error occurred while processing the command.',
+'An unknown server-side error occurred while processing the command.',
             },
             15 => {
                 'code' => 'ELEMENT_IS_NOT_SELECTABLE',
                 'msg' =>
-                  'An attempt was made to select an element that cannot be selected.',
+'An attempt was made to select an element that cannot be selected.',
             },
             19 => {
                 'code' => 'XPATH_LOOKUP_ERROR',
@@ -67,12 +67,12 @@ has STATUS_CODE => (
             23 => {
                 'code' => 'NO_SUCH_WINDOW',
                 'msg' =>
-                  'A request to switch to a different window could not be satisfied because the window could not be found.',
+'A request to switch to a different window could not be satisfied because the window could not be found.',
             },
             24 => {
                 'code' => 'INVALID_COOKIE_DOMAIN',
                 'msg' =>
-                  'An illegal attempt was made to set a cookie under a different domain than the current page.',
+'An illegal attempt was made to set a cookie under a different domain than the current page.',
             },
             25 => {
                 'code' => 'UNABLE_TO_SET_COOKIE',
@@ -86,7 +86,7 @@ has STATUS_CODE => (
             27 => {
                 'code' => 'NO_ALERT_OPEN_ERROR',
                 'msg' =>
-                  'An attempt was made to operate on a modal dialog when one was not open.',
+'An attempt was made to operate on a modal dialog when one was not open.',
             },
             28 => {
                 'code' => 'SCRIPT_TIMEOUT',
@@ -96,7 +96,7 @@ has STATUS_CODE => (
             29 => {
                 'code' => 'INVALID_ELEMENT_COORDINATES',
                 'msg' =>
-                  'The coordinates provided to an interactions operation are invalid.',
+'The coordinates provided to an interactions operation are invalid.',
             },
             30 => {
                 'code' => 'IME_NOT_AVAILABLE',
@@ -126,7 +126,8 @@ You could additionally alter the STATUS_CODE parameter of this module to add ext
 =cut
 
 sub process_error {
-    my ($self, $resp) = @_;
+    my ( $self, $resp ) = @_;
+
     # TODO: Handle screen if it sent back with the response. Either we could
     # let the end user handle it or we can save it an image file at a temp
     # location & return the path.
@@ -136,10 +137,15 @@ sub process_error {
     $resp->{status} = 13 unless $resp->{status};
 
     my $ret;
+
     #XXX capitalization is inconsistent among geckodriver versions
-    $ret->{'stackTrace'} = $resp->{'value'}->{'stacktrace'} // $resp->{'value'}->{'stackTrace'};
-    $ret->{'error'}      = $is_stacktrace ? $resp->{value}->{error} : $self->STATUS_CODE->{$resp->{'status'}};
-    $ret->{'message'}    = $resp->{'value'}->{'message'};
+    $ret->{'stackTrace'} = $resp->{'value'}->{'stacktrace'}
+      // $resp->{'value'}->{'stackTrace'};
+    $ret->{'error'} =
+        $is_stacktrace
+      ? $resp->{value}->{error}
+      : $self->STATUS_CODE->{ $resp->{'status'} };
+    $ret->{'message'} = $resp->{'value'}->{'message'};
 
     return $ret;
 }

+ 4 - 4
lib/Selenium/Remote/Finders.pm

@@ -20,20 +20,20 @@ for the specific finder functions.
 =cut
 
 sub _build_find_by {
-    my ($self, $by) = @_;
+    my ( $self, $by ) = @_;
 
     return sub {
-        my ($driver, $locator) = @_;
+        my ( $driver, $locator ) = @_;
         my $strategy = $by;
 
         return try {
-            return $driver->find_element($locator, $strategy);
+            return $driver->find_element( $locator, $strategy );
         }
         catch {
             carp $_;
             return 0;
         };
-    }
+      }
 }
 
 1;

+ 13 - 11
lib/Selenium/Remote/Mock/Commands.pm

@@ -15,24 +15,26 @@ extends 'Selenium::Remote::Commands';
 # override get_params so we do not rewrite the parameters
 
 sub get_params {
-    my $self = shift;
-    my $args = shift;
-    my $data = {};
+    my $self    = shift;
+    my $args    = shift;
+    my $data    = {};
     my $command = delete $args->{command};
-    $data->{'url'} = $self->get_url($command);
-    $data->{'method'} = $self->get_method($command);
+    $data->{'url'}                = $self->get_url($command);
+    $data->{'method'}             = $self->get_method($command);
     $data->{'no_content_success'} = $self->get_no_content_success($command);
-    $data->{'url_params'}  = $args;
+    $data->{'url_params'}         = $args;
     return $data;
 }
 
 sub get_method_name_from_parameters {
-    my $self = shift;
-    my $params = shift;
+    my $self        = shift;
+    my $params      = shift;
     my $method_name = '';
-    my $cmds = $self->get_cmds();
-    foreach my $cmd (keys %{$cmds}) {
-        if (($cmds->{$cmd}->{method} eq $params->{method}) && ($cmds->{$cmd}->{url} eq $params->{url})) {
+    my $cmds        = $self->get_cmds();
+    foreach my $cmd ( keys %{$cmds} ) {
+        if (   ( $cmds->{$cmd}->{method} eq $params->{method} )
+            && ( $cmds->{$cmd}->{url} eq $params->{url} ) )
+        {
             $method_name = $cmd;
             last;
         }

+ 43 - 44
lib/Selenium/Remote/Mock/RemoteConnection.pm

@@ -15,48 +15,43 @@ use Data::Dumper;
 extends 'Selenium::Remote::RemoteConnection';
 
 has 'spec' => (
-    is       => 'ro',
-    default => sub {{}},
+    is      => 'ro',
+    default => sub { {} },
 );
 
-has 'mock_cmds' => (
-    is => 'ro',
-);
+has 'mock_cmds' => ( is => 'ro', );
 
 has 'fake_session_id' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub {
         my $id = join '',
-        map +( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' )[ rand( 10 + 26 * 2 ) ], 1 .. 50;
+          map +( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' )[ rand( 10 + 26 * 2 ) ],
+          1 .. 50;
         return $id;
     },
 );
 
 has 'record' => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 0 }
 );
 
-has 'replay' => (
-    is => 'ro',
-);
+has 'replay' => ( is => 'ro', );
 
-has 'replay_file' => (
-    is => 'ro',
-);
+has 'replay_file' => ( is => 'ro', );
 
 has 'session_store' => (
-    is => 'rw',
+    is      => 'rw',
     default => sub { {} }
 );
 
 has 'session_id' => (
-    is => 'rw',
+    is      => 'rw',
     default => sub { undef },
 );
 
 has 'remote_server_addr' => (
-    is => 'lazy',
+    is      => 'lazy',
     default => sub { 'localhost' }
 );
 
@@ -66,12 +61,15 @@ has 'remote_server_addr' => (
 
 sub BUILD {
     my $self = shift;
-    croak 'Cannot define replay and record attributes at the same time' if (($self->replay) && ($self->record));
-    croak 'replay_file attribute needs to be defined' if (($self->replay) && !($self->replay_file));
-    croak 'replay attribute needs to be defined' if (!($self->replay) && ($self->replay_file));
+    croak 'Cannot define replay and record attributes at the same time'
+      if ( ( $self->replay ) && ( $self->record ) );
+    croak 'replay_file attribute needs to be defined'
+      if ( ( $self->replay ) && !( $self->replay_file ) );
+    croak 'replay attribute needs to be defined'
+      if ( !( $self->replay ) && ( $self->replay_file ) );
     $self->port('4444');
-    if ($self->replay) {
-        $self->load_session_store($self->replay_file);
+    if ( $self->replay ) {
+        $self->load_session_store( $self->replay_file );
     }
 }
 
@@ -82,8 +80,9 @@ sub check_status {
 sub load_session_store {
     my $self = shift;
     my $file = shift;
-    croak "'$file' is not a valid file" unless (-f $file);
-    open (my $fh, '<', $file) or croak  "Opening '$file' failed";
+    croak "'$file' is not a valid file" unless ( -f $file );
+    open( my $fh, '<', $file ) or croak "Opening '$file' failed";
+
     # here we use a fake session id since we have no way of figuring out
     # which session is good or not
     local $/ = undef;
@@ -91,24 +90,24 @@ sub load_session_store {
     my $json = JSON->new;
     $json->allow_blessed;
     my $decoded_json = $json->allow_nonref(1)->utf8(1)->decode(<$fh>);
-    close ($fh);
+    close($fh);
     $self->session_store($decoded_json);
 }
 
 sub dump_session_store {
     my $self = shift;
     my ($file) = @_;
-    open (my $fh, '>', $file) or croak "Opening '$file' failed";
+    open( my $fh, '>', $file ) or croak "Opening '$file' failed";
     my $session_store = $self->session_store;
-    my $dump = {};
-    foreach my $path (keys %{$session_store}) {
+    my $dump          = {};
+    foreach my $path ( keys %{$session_store} ) {
         $dump->{$path} = $session_store->{$path};
     }
     my $json = JSON->new;
     $json->allow_blessed;
     my $json_session = $json->allow_nonref->utf8->pretty->encode($dump);
     print $fh $json_session;
-    close ($fh);
+    close($fh);
 }
 
 sub request {
@@ -120,6 +119,7 @@ sub request {
     my $content            = '';
     my $json               = JSON->new;
     $json->allow_blessed;
+
     if ($params) {
         $content = $json->allow_nonref->utf8->canonical(1)->encode($params);
     }
@@ -129,21 +129,20 @@ sub request {
 
     if ( $self->record ) {
         my $response = $self->SUPER::request( $resource, $params, 1 );
-        push @{$self->session_store->{"$method $url $content"}},$response->as_string;
+        push @{ $self->session_store->{"$method $url $content"} },
+          $response->as_string;
         return $self->_process_response( $response, $no_content_success );
     }
     if ( $self->replay ) {
         my $resp;
-        my $arr_of_resps = $self->session_store->{"$method $url $content"} // [];
+        my $arr_of_resps = $self->session_store->{"$method $url $content"}
+          // [];
         if ( scalar(@$arr_of_resps) ) {
             $resp = shift @$arr_of_resps;
             $resp = HTTP::Response->parse($resp);
         }
         else {
-            $resp = HTTP::Response->new(
-                '501',
-                "Failed to find a response"
-            );
+            $resp = HTTP::Response->new( '501', "Failed to find a response" );
         }
         return $self->_process_response( $resp, $no_content_success );
     }
@@ -154,15 +153,15 @@ sub request {
     my $ret = { cmd_status => 'OK', cmd_return => 1 };
     if ( defined( $spec->{$cmd} ) ) {
         my $return_sub = $spec->{$cmd};
-            my $mock_return = $return_sub->( $url_params, $params );
-            if ( ref($mock_return) eq 'HASH' ) {
-                $ret->{cmd_status} = $mock_return->{status};
-                $ret->{cmd_return} = $mock_return->{return};
-                $ret->{cmd_error}  = $mock_return->{error} // '';
-            }
-            else {
-                $ret = $mock_return;
-            }
+        my $mock_return = $return_sub->( $url_params, $params );
+        if ( ref($mock_return) eq 'HASH' ) {
+            $ret->{cmd_status} = $mock_return->{status};
+            $ret->{cmd_return} = $mock_return->{return};
+            $ret->{cmd_error}  = $mock_return->{error} // '';
+        }
+        else {
+            $ret = $mock_return;
+        }
         $ret->{session_id} = $self->fake_session_id if ( ref($ret) eq 'HASH' );
     }
     else {

+ 71 - 59
lib/Selenium/Remote/RemoteConnection.pm

@@ -16,26 +16,22 @@ use Data::Dumper;
 use Selenium::Remote::ErrorHandler;
 use Scalar::Util qw{looks_like_number};
 
-has 'remote_server_addr' => (
-    is => 'rw',
-);
+has 'remote_server_addr' => ( is => 'rw', );
 
-has 'port' => (
-    is => 'rw',
-);
+has 'port' => ( is => 'rw', );
 
 has 'debug' => (
-    is => 'rw',
+    is      => 'rw',
     default => sub { 0 }
 );
 
 has 'ua' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub { return LWP::UserAgent->new; }
 );
 
 has 'error_handler' => (
-    is => 'lazy',
+    is      => 'lazy',
     builder => sub { return Selenium::Remote::ErrorHandler->new; }
 );
 
@@ -86,19 +82,21 @@ sub check_status {
     my $status;
 
     try {
-        $status = $self->request({method => 'GET', url => 'status'});
+        $status = $self->request( { method => 'GET', url => 'status' } );
     }
     catch {
-        croak "Could not connect to SeleniumWebDriver: $_" ;
+        croak "Could not connect to SeleniumWebDriver: $_";
     };
 
-    if($status->{cmd_status} ne 'OK') {
+    if ( $status->{cmd_status} ne 'OK' ) {
+
         # Could be grid, see if we can talk to it
         $status = undef;
-        $status = $self->request({method => 'GET', url => 'grid/api/hub/status'});
+        $status =
+          $self->request( { method => 'GET', url => 'grid/api/hub/status' } );
     }
 
-    unless ($status->{cmd_status} eq 'OK') {
+    unless ( $status->{cmd_status} eq 'OK' ) {
         croak "Selenium server did not return proper status";
     }
 }
@@ -110,47 +108,41 @@ Make a request of the Selenium server.  Mostly useful for debugging things going
 =cut
 
 sub request {
-    my ($self,$resource,$params,$dont_process_response) = @_;
-    my $method =        $resource->{method};
-    my $url =        $resource->{url};
-    my $no_content_success =        $resource->{no_content_success} // 0;
+    my ( $self, $resource, $params, $dont_process_response ) = @_;
+    my $method             = $resource->{method};
+    my $url                = $resource->{url};
+    my $no_content_success = $resource->{no_content_success} // 0;
 
     my $content = '';
     my $fullurl = '';
 
     # Construct full url.
-    if ($url =~ m/^http/g) {
+    if ( $url =~ m/^http/g ) {
         $fullurl = $url;
     }
-    elsif ($url =~ m/^\//) {
+    elsif ( $url =~ m/^\// ) {
+
         # This is used when we get a 302 Redirect with a Location header.
         $fullurl =
-           "http://"
-          . $self->remote_server_addr . ":"
-          . $self->port
-          . $url;
+          "http://" . $self->remote_server_addr . ":" . $self->port . $url;
     }
-    elsif ($url =~ m/grid/g) {
+    elsif ( $url =~ m/grid/g ) {
         $fullurl =
-            "http://"
-          . $self->remote_server_addr . ":"
-          . $self->port
-          . "/$url";
+          "http://" . $self->remote_server_addr . ":" . $self->port . "/$url";
     }
     else {
         $fullurl =
             "http://"
           . $self->remote_server_addr . ":"
           . $self->port
-          . $self->wd_context_prefix
-          . "/$url";
+          . $self->wd_context_prefix . "/$url";
     }
 
-    if ((defined $params) && $params ne '') {
+    if ( ( defined $params ) && $params ne '' ) {
 
         #WebDriver 3 shims
-        if ($resource->{payload}) {
-            foreach my $key (keys(%{$resource->{payload}})) {
+        if ( $resource->{payload} ) {
+            foreach my $key ( keys( %{ $resource->{payload} } ) ) {
                 $params->{$key} = $resource->{payload}->{$key};
             }
         }
@@ -164,22 +156,22 @@ sub request {
 
     # HTTP request
     my $header =
-      HTTP::Headers->new(Content_Type => 'application/json; charset=utf-8');
-    $header->header('Accept' => 'application/json');
-    my $request = HTTP::Request->new($method, $fullurl, $header, $content);
+      HTTP::Headers->new( Content_Type => 'application/json; charset=utf-8' );
+    $header->header( 'Accept' => 'application/json' );
+    my $request = HTTP::Request->new( $method, $fullurl, $header, $content );
     my $response = $self->ua->request($request);
     if ($dont_process_response) {
         return $response;
     }
-    return $self->_process_response($response, $no_content_success);
+    return $self->_process_response( $response, $no_content_success );
 }
 
 sub _process_response {
-    my ($self, $response, $no_content_success) = @_;
-    my $data; # server response 'value' that'll be returned to the user
+    my ( $self, $response, $no_content_success ) = @_;
+    my $data;    # server response 'value' that'll be returned to the user
     my $json = JSON->new;
 
-    if ($response->is_redirect) {
+    if ( $response->is_redirect ) {
         my $redirect = {
             method => 'GET',
             url    => $response->header('location')
@@ -188,38 +180,52 @@ sub _process_response {
     }
     else {
         my $decoded_json = undef;
-        print "RES: ".$response->decoded_content."\n\n" if $self->debug;
+        print "RES: " . $response->decoded_content . "\n\n" if $self->debug;
 
-        if (($response->message ne 'No Content') && ($response->content ne '')) {
-            if ($response->content_type !~ m/json/i) {
+        if (   ( $response->message ne 'No Content' )
+            && ( $response->content ne '' ) )
+        {
+            if ( $response->content_type !~ m/json/i ) {
                 $data->{'cmd_status'} = 'NOTOK';
-                $data->{'cmd_return'}->{message} = 'Server returned error message '.$response->content.' instead of data';
+                $data->{'cmd_return'}->{message} =
+                    'Server returned error message '
+                  . $response->content
+                  . ' instead of data';
                 return $data;
             }
-            $decoded_json = $json->allow_nonref(1)->utf8(1)->decode($response->content);
+            $decoded_json =
+              $json->allow_nonref(1)->utf8(1)->decode( $response->content );
             $data->{'sessionId'} = $decoded_json->{'sessionId'};
         }
 
-        if ($response->is_error) {
+        if ( $response->is_error ) {
             $data->{'cmd_status'} = 'NOTOK';
-            if (defined $decoded_json) {
-                $data->{'cmd_return'} = $self->error_handler->process_error($decoded_json);
+            if ( defined $decoded_json ) {
+                $data->{'cmd_return'} =
+                  $self->error_handler->process_error($decoded_json);
             }
             else {
-                $data->{'cmd_return'} = 'Server returned error code '.$response->code.' and no data';
+                $data->{'cmd_return'} =
+                    'Server returned error code '
+                  . $response->code
+                  . ' and no data';
             }
             return $data;
         }
-        elsif ($response->is_success) {
+        elsif ( $response->is_success ) {
             $data->{'cmd_status'} = 'OK';
-            if (defined $decoded_json) {
+            if ( defined $decoded_json ) {
 
                 #XXX MS edge doesn't follow spec here either
-                if (looks_like_number($decoded_json->{status}) && $decoded_json->{status} > 0 && $decoded_json->{value}{message}) {
+                if (   looks_like_number( $decoded_json->{status} )
+                    && $decoded_json->{status} > 0
+                    && $decoded_json->{value}{message} )
+                {
                     $data->{cmd_status} = 'NOT OK';
                     $data->{cmd_return} = $decoded_json->{value};
                     return $data;
                 }
+
                 #XXX shockingly, neither does InternetExplorerDriver
                 if ( ref $decoded_json eq 'HASH' && $decoded_json->{error} ) {
                     $data->{cmd_status} = 'NOT OK';
@@ -228,31 +234,37 @@ sub _process_response {
                 }
 
                 if ($no_content_success) {
-                    $data->{'cmd_return'} = 1
+                    $data->{'cmd_return'} = 1;
                 }
                 else {
                     $data->{'cmd_return'} = $decoded_json->{'value'};
-                    if (ref($data->{cmd_return}) eq 'HASH'
-                        && exists $data->{cmd_return}->{sessionId}) {
+                    if ( ref( $data->{cmd_return} ) eq 'HASH'
+                        && exists $data->{cmd_return}->{sessionId} )
+                    {
                         $data->{sessionId} = $data->{cmd_return}->{sessionId};
                     }
                 }
             }
             else {
-                $data->{'cmd_return'} = 'Server returned status code '.$response->code.' but no data';
+                $data->{'cmd_return'} =
+                    'Server returned status code '
+                  . $response->code
+                  . ' but no data';
             }
             return $data;
         }
         else {
             # No idea what the server is telling me, must be high
             $data->{'cmd_status'} = 'NOTOK';
-            $data->{'cmd_return'} = 'Server returned status code '.$response->code.' which I don\'t understand';
+            $data->{'cmd_return'} =
+                'Server returned status code '
+              . $response->code
+              . ' which I don\'t understand';
             return $data;
         }
     }
 }
 
-
 1;
 
 __END__

+ 68 - 54
lib/Selenium/Remote/Spec.pm

@@ -90,15 +90,17 @@ our $spec_parsed;
 
 sub get_spec {
     return $spec_parsed if $spec_parsed;
-    my @split = split(/\n/,$spec);
+    my @split = split( /\n/, $spec );
     foreach my $line (@split) {
         next unless $line;
-        my ($method,$uri,$nc_success,$key,@description) =  split(/ +/,$line);
+        my ( $method, $uri, $nc_success, $key, @description ) =
+          split( / +/, $line );
         $spec_parsed->{$key} = {
-           method             => $method,
-           url                => $uri,
-           no_content_success => int($nc_success), #XXX this *should* always be 0, but specs lie
-           description        => join(' ',@description),
+            method             => $method,
+            url                => $uri,
+            no_content_success => int($nc_success)
+            ,    #XXX this *should* always be 0, but specs lie
+            description => join( ' ', @description ),
         };
     }
     return $spec_parsed;
@@ -130,29 +132,23 @@ New Stuff:
 =cut
 
 has '_caps' => (
-    is     => 'lazy',
-    reader => 'get_caps',
+    is      => 'lazy',
+    reader  => 'get_caps',
     builder => sub {
         return [
-            'browserName',
-            'acceptInsecureCerts',
-            'browserVersion',
-            'platformName',
-            'proxy',
-            'pageLoadStrategy',
-            'setWindowRect',
-            'timeouts',
-            'unhandledPromptBehavior',
-            'moz:firefoxOptions',
+            'browserName',             'acceptInsecureCerts',
+            'browserVersion',          'platformName',
+            'proxy',                   'pageLoadStrategy',
+            'setWindowRect',           'timeouts',
+            'unhandledPromptBehavior', 'moz:firefoxOptions',
             'chromeOptions',
         ];
     }
 );
 
-
 has '_caps_map' => (
-    is     => 'lazy',
-    reader => 'get_caps_map',
+    is      => 'lazy',
+    reader  => 'get_caps_map',
     builder => sub {
         return {
             browserName    => 'browserName',
@@ -171,11 +167,12 @@ sub get_params {
     }
 
     #Allow fall-back in the event the command passed doesn't exist
-    return unless $self->get_cmds()->{$args->{command}};
+    return unless $self->get_cmds()->{ $args->{command} };
 
-    my $url     = $self->get_url($args->{command});
+    my $url = $self->get_url( $args->{command} );
 
     my $data = {};
+
     # Do the var substitutions.
     $url =~ s/:sessionId/$args->{'session_id'}/;
     $url =~ s/:id/$args->{'id'}/;
@@ -184,53 +181,68 @@ sub get_params {
     $url =~ s/:other/$args->{'other'}/;
     $url =~ s/:windowHandle/$args->{'window_handle'}/;
 
-    $data->{'method'} = $self->get_method($args->{command});
-    $data->{'no_content_success'} = $self->get_no_content_success($args->{command});
-    $data->{'url'}    = $url;
+    $data->{'method'} = $self->get_method( $args->{command} );
+    $data->{'no_content_success'} =
+      $self->get_no_content_success( $args->{command} );
+    $data->{'url'} = $url;
 
     #URL & data polyfills for the way selenium2 used to do things, etc
     $data->{payload} = {};
-    if ($args->{type} ) {
-        $data->{payload}->{pageLoad} = $args->{ms} if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'page load';
-        $data->{payload}->{script}   = $args->{ms} if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'script';
-        $data->{payload}->{implicit} = $args->{ms} if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'implicit';
+    if ( $args->{type} ) {
+        $data->{payload}->{pageLoad} = $args->{ms}
+          if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'page load';
+        $data->{payload}->{script} = $args->{ms}
+          if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'script';
+        $data->{payload}->{implicit} = $args->{ms}
+          if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'implicit';
     }
 
-    #finder polyfills
-    #orig: class, class_name, css, id, link, link_text, partial_link_text, tag_name, name, xpath
-    #new:  "css selector", "link text", "partial link text", "tag name", "xpath"
-    #map: class, class_name, id, name, link = 'css selector'
-    if ($args->{using} && $args->{value}) {
-        $data->{payload}->{using} = 'css selector'            if grep {$args->{using} eq $_ } ('id', 'class name', 'name');
-        $data->{payload}->{value} = "[id='$args->{value}']"   if $args->{using} eq 'id';
-        $data->{payload}->{value} = ".$args->{value}"         if $args->{using} eq 'class name';
-        $data->{payload}->{value} = "[name='$args->{value}']" if $args->{using} eq 'name';
+#finder polyfills
+#orig: class, class_name, css, id, link, link_text, partial_link_text, tag_name, name, xpath
+#new:  "css selector", "link text", "partial link text", "tag name", "xpath"
+#map: class, class_name, id, name, link = 'css selector'
+    if ( $args->{using} && $args->{value} ) {
+        $data->{payload}->{using} = 'css selector'
+          if grep { $args->{using} eq $_ } ( 'id', 'class name', 'name' );
+        $data->{payload}->{value} = "[id='$args->{value}']"
+          if $args->{using} eq 'id';
+        $data->{payload}->{value} = ".$args->{value}"
+          if $args->{using} eq 'class name';
+        $data->{payload}->{value} = "[name='$args->{value}']"
+          if $args->{using} eq 'name';
     }
-    if ($data->{url} =~ s/timeouts\/async_script$/timeouts/g) {
+    if ( $data->{url} =~ s/timeouts\/async_script$/timeouts/g ) {
         $data->{payload}->{script} = $args->{ms};
-        $data->{payload}->{type}   = 'script'; #XXX chrome doesn't follow the spec
+        $data->{payload}->{type} = 'script'; #XXX chrome doesn't follow the spec
     }
-    if ( $data->{url} =~ s/timeouts\/implicit_wait$/timeouts/g) {
+    if ( $data->{url} =~ s/timeouts\/implicit_wait$/timeouts/g ) {
         $data->{payload}->{implicit} = $args->{ms};
-        $data->{payload}->{type}     = 'implicit'; #XXX chrome doesn't follow the spec
+        $data->{payload}->{type} =
+          'implicit';                        #XXX chrome doesn't follow the spec
     }
-    $data->{payload}->{value}    = $args->{text}          if $args->{text} && $args->{command} ne 'sendKeysToElement';
-    $data->{payload}->{handle}   = $args->{window_handle} if grep { $args->{command} eq $_ } qw{fullscreenWindow minimizeWindow maximizeWindow};
+    $data->{payload}->{value} = $args->{text}
+      if $args->{text} && $args->{command} ne 'sendKeysToElement';
+    $data->{payload}->{handle} = $args->{window_handle}
+      if grep { $args->{command} eq $_ }
+      qw{fullscreenWindow minimizeWindow maximizeWindow};
     return $data;
 }
 
 sub parse_response {
-    my ($self,undef,$resp) = @_;
+    my ( $self, undef, $resp ) = @_;
 
     if ( ref($resp) eq 'HASH' ) {
         if ( $resp->{cmd_status} && $resp->{cmd_status} eq 'OK' ) {
             return $resp->{cmd_return};
         }
         my $msg = "Error while executing command";
-        if (ref $resp->{cmd_return} eq 'HASH' ) {
-            $msg .= ": $resp->{cmd_return}{error}"   if $resp->{cmd_return}{error};
-            $msg .= ": $resp->{cmd_return}{message}" if $resp->{cmd_return}{message};
-        } else {
+        if ( ref $resp->{cmd_return} eq 'HASH' ) {
+            $msg .= ": $resp->{cmd_return}{error}"
+              if $resp->{cmd_return}{error};
+            $msg .= ": $resp->{cmd_return}{message}"
+              if $resp->{cmd_return}{message};
+        }
+        else {
             $msg .= ": $resp->{cmd_return}";
         }
         croak $msg;
@@ -245,11 +257,13 @@ sub get_spec_differences {
     my $v2_spec = Selenium::Remote::Commands->new()->get_cmds();
     my $v3_spec = Selenium::Remote::Spec->new()->get_cmds();
 
-    foreach my $key (keys(%$v2_spec)) {
-        print "v2 $key NOT present in v3 spec!!!\n" unless any { $_ eq $key } keys(%$v3_spec);
+    foreach my $key ( keys(%$v2_spec) ) {
+        print "v2 $key NOT present in v3 spec!!!\n"
+          unless any { $_ eq $key } keys(%$v3_spec);
     }
-    foreach my $key (keys(%$v3_spec)) {
-        print "v3 $key NOT present in v2 spec!!!\n" unless any { $_ eq $key } keys(%$v2_spec);
+    foreach my $key ( keys(%$v3_spec) ) {
+        print "v3 $key NOT present in v2 spec!!!\n"
+          unless any { $_ eq $key } keys(%$v2_spec);
     }
 }
 

+ 57 - 57
lib/Selenium/Remote/WDKeys.pm

@@ -15,63 +15,63 @@ use base 'Exporter';
 
 # http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value
 use constant KEYS => {
-    'null'   => "\N{U+E000}",
-    'cancel'     => "\N{U+E001}",
-    'help'   => "\N{U+E002}",
-    'backspace'  => "\N{U+E003}",
-    'tab'    => "\N{U+E004}",
-    'clear'  => "\N{U+E005}",
-    'return'     => "\N{U+E006}",
-    'enter'  => "\N{U+E007}",
-    'shift'  => "\N{U+E008}",
-    'control'    => "\N{U+E009}",
-    'alt'    => "\N{U+E00A}",
-    'pause'  => "\N{U+E00B}",
-    'escape'     => "\N{U+E00C}",
-    'space'  => "\N{U+E00D}",
-    'page_up'    => "\N{U+E00E}",
-    'page_down'  => "\N{U+E00f}",
-    'end'    => "\N{U+E010}",
-    'home'   => "\N{U+E011}",
-    'left_arrow' => "\N{U+E012}",
-    'up_arrow'   => "\N{U+E013}",
-    'right_arrow'=> "\N{U+E014}",
-    'down_arrow' => "\N{U+E015}",
-    'insert'     => "\N{U+E016}",
-    'delete'     => "\N{U+E017}",
-    'semicolon'  => "\N{U+E018}",
-    'equals'     => "\N{U+E019}",
-    'numpad_0'   => "\N{U+E01A}",
-    'numpad_1'   => "\N{U+E01B}",
-    'numpad_2'   => "\N{U+E01C}",
-    'numpad_3'   => "\N{U+E01D}",
-    'numpad_4'   => "\N{U+E01E}",
-    'numpad_5'   => "\N{U+E01f}",
-    'numpad_6'   => "\N{U+E020}",
-    'numpad_7'   => "\N{U+E021}",
-    'numpad_8'   => "\N{U+E022}",
-    'numpad_9'   => "\N{U+E023}",
-    'multiply'   => "\N{U+E024}",
-    'add'        => "\N{U+E025}",
-    'separator'  => "\N{U+E026}",
-    'subtract'   => "\N{U+E027}",
-    'decimal'    => "\N{U+E028}",
-    'divide'     => "\N{U+E029}",
-    'f1'     => "\N{U+E031}",
-    'f2'     => "\N{U+E032}",
-    'f3'     => "\N{U+E033}",
-    'f4'     => "\N{U+E034}",
-    'f5'     => "\N{U+E035}",
-    'f6'     => "\N{U+E036}",
-    'f7'     => "\N{U+E037}",
-    'f8'     => "\N{U+E038}",
-    'f9'     => "\N{U+E039}",
-    'f10'    => "\N{U+E03A}",
-    'f11'    => "\N{U+E03B}",
-    'f12'    => "\N{U+E03C}",
-    'command_meta'  => "\N{U+E03D}",
-    'ZenkakuHankaku' => "\N{U+E040}", #Asian language keys, maybe altGr too?
-    #There are other code points for say, left versus right meta/shift/alt etc, but I don't seriously believe anyone uses that level of sophistication on the web yet.
+    'null'           => "\N{U+E000}",
+    'cancel'         => "\N{U+E001}",
+    'help'           => "\N{U+E002}",
+    'backspace'      => "\N{U+E003}",
+    'tab'            => "\N{U+E004}",
+    'clear'          => "\N{U+E005}",
+    'return'         => "\N{U+E006}",
+    'enter'          => "\N{U+E007}",
+    'shift'          => "\N{U+E008}",
+    'control'        => "\N{U+E009}",
+    'alt'            => "\N{U+E00A}",
+    'pause'          => "\N{U+E00B}",
+    'escape'         => "\N{U+E00C}",
+    'space'          => "\N{U+E00D}",
+    'page_up'        => "\N{U+E00E}",
+    'page_down'      => "\N{U+E00f}",
+    'end'            => "\N{U+E010}",
+    'home'           => "\N{U+E011}",
+    'left_arrow'     => "\N{U+E012}",
+    'up_arrow'       => "\N{U+E013}",
+    'right_arrow'    => "\N{U+E014}",
+    'down_arrow'     => "\N{U+E015}",
+    'insert'         => "\N{U+E016}",
+    'delete'         => "\N{U+E017}",
+    'semicolon'      => "\N{U+E018}",
+    'equals'         => "\N{U+E019}",
+    'numpad_0'       => "\N{U+E01A}",
+    'numpad_1'       => "\N{U+E01B}",
+    'numpad_2'       => "\N{U+E01C}",
+    'numpad_3'       => "\N{U+E01D}",
+    'numpad_4'       => "\N{U+E01E}",
+    'numpad_5'       => "\N{U+E01f}",
+    'numpad_6'       => "\N{U+E020}",
+    'numpad_7'       => "\N{U+E021}",
+    'numpad_8'       => "\N{U+E022}",
+    'numpad_9'       => "\N{U+E023}",
+    'multiply'       => "\N{U+E024}",
+    'add'            => "\N{U+E025}",
+    'separator'      => "\N{U+E026}",
+    'subtract'       => "\N{U+E027}",
+    'decimal'        => "\N{U+E028}",
+    'divide'         => "\N{U+E029}",
+    'f1'             => "\N{U+E031}",
+    'f2'             => "\N{U+E032}",
+    'f3'             => "\N{U+E033}",
+    'f4'             => "\N{U+E034}",
+    'f5'             => "\N{U+E035}",
+    'f6'             => "\N{U+E036}",
+    'f7'             => "\N{U+E037}",
+    'f8'             => "\N{U+E038}",
+    'f9'             => "\N{U+E039}",
+    'f10'            => "\N{U+E03A}",
+    'f11'            => "\N{U+E03B}",
+    'f12'            => "\N{U+E03C}",
+    'command_meta'   => "\N{U+E03D}",
+    'ZenkakuHankaku' => "\N{U+E040}",    #Asian language keys, maybe altGr too?
+      #There are other code points for say, left versus right meta/shift/alt etc, but I don't seriously believe anyone uses that level of sophistication on the web yet.
 };
 
 our @EXPORT = ('KEYS');

+ 101 - 44
lib/Selenium/Remote/WebElement.pm

@@ -75,18 +75,20 @@ exact behavior.
 =cut
 
 has 'id' => (
-    is => 'ro',
+    is       => 'ro',
     required => 1,
-    coerce => sub {
+    coerce   => sub {
         my ($value) = @_;
-        if (ref($value) eq 'HASH') {
-            if (exists $value->{ELEMENT}) {
+        if ( ref($value) eq 'HASH' ) {
+            if ( exists $value->{ELEMENT} ) {
+
                 # The JSONWireProtocol web element object looks like
                 #
                 #     { "ELEMENT": $INTEGER_ID }
                 return $value->{ELEMENT};
             }
-            elsif (exists $value->{'element-6066-11e4-a52e-4f735466cecf'}) {
+            elsif ( exists $value->{'element-6066-11e4-a52e-4f735466cecf'} ) {
+
                 # but the WebDriver spec web element uses a magic
                 # string. See the spec for more information:
                 #
@@ -94,7 +96,8 @@ has 'id' => (
                 return $value->{'element-6066-11e4-a52e-4f735466cecf'};
             }
             else {
-                croak 'When passing in an object to the WebElement id attribute, it must have at least one of the ELEMENT or element-6066-11e4-a52e-4f735466cecf keys.';
+                croak
+'When passing in an object to the WebElement id attribute, it must have at least one of the ELEMENT or element-6066-11e4-a52e-4f735466cecf keys.';
             }
         }
         else {
@@ -104,9 +107,9 @@ has 'id' => (
 );
 
 has 'driver' => (
-    is => 'ro',
+    is       => 'ro',
     required => 1,
-    handles => [qw(_execute_command)],
+    handles  => [qw(_execute_command)],
 );
 
 =head1 FUNCTIONS
@@ -160,11 +163,22 @@ sub click {
 
 sub submit {
     my ($self) = @_;
-    if ($self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge})) {
-        if ($self->get_tag_name() ne 'form') {
-            return $self->driver->execute_script("return arguments[0].form.submit();",{'element-6066-11e4-a52e-4f735466cecf'=> $self->{id}} );
-        } else {
-            return $self->driver->execute_script("return arguments[0].submit();",{'element-6066-11e4-a52e-4f735466cecf'=> $self->{id}} );
+    if (
+        $self->driver->{is_wd3}
+        && !(
+            grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}
+        )
+      )
+    {
+        if ( $self->get_tag_name() ne 'form' ) {
+            return $self->driver->execute_script(
+                "return arguments[0].form.submit();",
+                { 'element-6066-11e4-a52e-4f735466cecf' => $self->{id} } );
+        }
+        else {
+            return $self->driver->execute_script(
+                "return arguments[0].submit();",
+                { 'element-6066-11e4-a52e-4f735466cecf' => $self->{id} } );
         }
     }
     my $res = { 'command' => 'submitElement', 'id' => $self->id };
@@ -206,10 +220,10 @@ sub send_keys {
     # corresponding value must be ('h', 'e', 'l', 'l', 'o' ). This
     # format conforms with the Spec AND works with the Selenium
     # standalone server.
-    my $strings = join('', map { $_."" } @strings);
+    my $strings = join( '', map { $_ . "" } @strings );
     my $params = {
-        'value' => [ split('', $strings) ],
-        text => $strings,
+        'value' => [ split( '', $strings ) ],
+        text    => $strings,
     };
     return $self->_execute_command( $res, $params );
 }
@@ -231,7 +245,10 @@ sub send_keys {
 sub is_selected {
     my ($self) = @_;
 
-    return $self->get_property('checked') if $self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge});
+    return $self->get_property('checked')
+      if $self->driver->{is_wd3}
+      && !( grep { $self->driver->browser_name eq $_ }
+        qw{chrome MicrosoftEdge} );
     my $res = { 'command' => 'isElementSelected', 'id' => $self->id };
     return $self->_execute_command($res);
 }
@@ -249,7 +266,7 @@ sub is_selected {
 
 sub set_selected {
     my ($self) = @_;
-    if ($self->driver->{is_wd3}) {
+    if ( $self->driver->{is_wd3} ) {
         return if $self->is_selected();
         return $self->click();
     }
@@ -273,9 +290,12 @@ sub set_selected {
 
 sub toggle {
     my ($self) = @_;
-    if ($self->driver->{is_wd3}) {
+    if ( $self->driver->{is_wd3} ) {
         return $self->click() unless $self->is_selected();
-        return $self->driver->execute_script(qq/ if (arguments[0].checked) { arguments[0].checked = 0 }; return arguments[0].checked; /, {'element-6066-11e4-a52e-4f735466cecf'=> $self->{id}});
+        return $self->driver->execute_script(
+qq/ if (arguments[0].checked) { arguments[0].checked = 0 }; return arguments[0].checked; /,
+            { 'element-6066-11e4-a52e-4f735466cecf' => $self->{id} }
+        );
     }
     my $res = { 'command' => 'toggleElement', 'id' => $self->id };
     return $self->_execute_command($res);
@@ -296,7 +316,13 @@ sub toggle {
 
 sub is_enabled {
     my ($self) = @_;
-    if ($self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge})) {
+    if (
+        $self->driver->{is_wd3}
+        && !(
+            grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}
+        )
+      )
+    {
         return 1 if $self->get_tag_name() ne 'input';
         return $self->get_property('disabled') ? 0 : 1;
     }
@@ -325,7 +351,13 @@ sub is_enabled {
 
 sub get_element_location {
     my ($self) = @_;
-    if ($self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge})) {
+    if (
+        $self->driver->{is_wd3}
+        && !(
+            grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}
+        )
+      )
+    {
         my $data = $self->get_element_rect();
         delete $data->{height};
         delete $data->{width};
@@ -356,7 +388,13 @@ sub get_element_location {
 
 sub get_size {
     my ($self) = @_;
-    if ($self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge})) {
+    if (
+        $self->driver->{is_wd3}
+        && !(
+            grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}
+        )
+      )
+    {
         my $data = $self->get_element_rect();
         delete $data->{x};
         delete $data->{y};
@@ -366,7 +404,6 @@ sub get_size {
     return $self->_execute_command($res);
 }
 
-
 =head2 get_element_rect
 
 Get the element's size AND location in a hash.
@@ -407,15 +444,20 @@ sub get_element_rect {
 
 sub get_element_location_in_view {
     my ($self) = @_;
+
     #XXX chrome is dopey here
-    return $self->driver->execute_script(qq{
+    return $self->driver->execute_script(
+        qq{
         if (typeof(arguments[0]) !== 'undefined' && arguments[0].nodeType === Node.ELEMENT_NODE) {
             arguments[0].scrollIntoView();
             var pos = arguments[0].getBoundingClientRect();
             return {y:pos.top,x:pos.left};
         }
         return {};
-    }, {'element-6066-11e4-a52e-4f735466cecf'=> $self->{id}} ) if $self->driver->{is_wd3} && grep { $self->driver->browser_name eq $_ } ('firefox','internet explorer');
+    }, { 'element-6066-11e4-a52e-4f735466cecf' => $self->{id} }
+      )
+      if $self->driver->{is_wd3} && grep { $self->driver->browser_name eq $_ }
+      ( 'firefox', 'internet explorer' );
     my $res = { 'command' => 'getElementLocationInView', 'id' => $self->id };
     return $self->_execute_command($res);
 }
@@ -492,7 +534,11 @@ sub get_attribute {
     #Handle global JSONWire emulation flag
     $no_i_really_mean_it = 1 unless $self->{driver}->{emulate_jsonwire};
 
-    return $self->get_property($attr_name) if $self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}) && !$no_i_really_mean_it;
+    return $self->get_property($attr_name)
+      if $self->driver->{is_wd3}
+      && !( grep { $self->driver->browser_name eq $_ }
+        qw{chrome MicrosoftEdge} )
+      && !$no_i_really_mean_it;
 
     my $res = {
         'command' => 'getElementAttribute',
@@ -513,13 +559,16 @@ Only available on WebDriver 3 enabled servers.
 =cut
 
 sub get_property {
-    my ($self,$prop) = @_;
-    return $self->get_attribute($prop) if $self->driver->{is_wd3} && (grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge});
-    my $res = { 'command' => 'getElementProperty', id => $self->id, name => $prop };
+    my ( $self, $prop ) = @_;
+    return $self->get_attribute($prop)
+      if $self->driver->{is_wd3}
+      && ( grep { $self->driver->browser_name eq $_ }
+        qw{chrome MicrosoftEdge} );
+    my $res =
+      { 'command' => 'getElementProperty', id => $self->id, name => $prop };
     return $self->_execute_command($res);
 }
 
-
 =head2 get_value
 
  Description:
@@ -560,10 +609,18 @@ sub get_value {
 
 sub is_displayed {
     my ($self) = @_;
-    if ($self->driver->{is_wd3} && !(grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge})) {
-        return 0 if $self->get_tag_name() eq 'input' && $self->get_property('type') eq 'hidden'; #hidden type inputs
+    if (
+        $self->driver->{is_wd3}
+        && !(
+            grep { $self->driver->browser_name eq $_ } qw{chrome MicrosoftEdge}
+        )
+      )
+    {
+        return 0
+          if $self->get_tag_name() eq 'input'
+          && $self->get_property('type') eq 'hidden';    #hidden type inputs
         return 0 unless $self->_is_in_viewport();
-        return int($self->get_css_attribute('display') ne 'none');
+        return int( $self->get_css_attribute('display') ne 'none' );
     }
     my $res = { 'command' => 'isElementDisplayed', 'id' => $self->id };
     return $self->_execute_command($res);
@@ -571,7 +628,8 @@ sub is_displayed {
 
 sub _is_in_viewport {
     my ($self) = @_;
-    return $self->driver->execute_script(qq{
+    return $self->driver->execute_script(
+        qq{
         var rect = arguments[0].getBoundingClientRect();
         return (
             rect.top >= 0 &&
@@ -579,7 +637,8 @@ sub _is_in_viewport {
             rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
             rect.right <= (window.innerWidth || document.documentElement.clientWidth)
         );
-    },{'element-6066-11e4-a52e-4f735466cecf'=> $self->{id}});
+    }, { 'element-6066-11e4-a52e-4f735466cecf' => $self->{id} }
+    );
 }
 
 =head2 is_hidden
@@ -597,7 +656,7 @@ sub _is_in_viewport {
 
 sub is_hidden {
     my ($self) = @_;
-    return ! $self->is_displayed();
+    return !$self->is_displayed();
 }
 
 =head2 drag
@@ -613,10 +672,10 @@ Provide element you wish to drag to as argument.
 =cut
 
 sub drag {
-    my ($self,$target) = @_;
+    my ( $self, $target ) = @_;
     require Selenium::ActionChains;
     my $chain = Selenium::ActionChains->new( driver => $self->driver );
-    return $chain->drag_and_drop($self,$target)->perform();
+    return $chain->drag_and_drop( $self, $target )->perform();
 }
 
 =head2 get_text
@@ -714,11 +773,11 @@ To conveniently write the screenshot to a file, see L</capture_screenshot>.
 =cut
 
 sub screenshot {
-    my ($self, $scroll) = @_;
+    my ( $self, $scroll ) = @_;
     $scroll //= 1;
     my $res = { 'command' => 'elementScreenshot', id => $self->id };
-    my $input = {scroll => int($scroll) };
-    return $self->_execute_command($res, $input);
+    my $input = { scroll => int($scroll) };
+    return $self->_execute_command( $res, $input );
 }
 
 =head2 capture_screenshot
@@ -752,6 +811,4 @@ sub capture_screenshot {
     return 1;
 }
 
-
-
 1;

+ 9 - 9
lib/Selenium/Waiter.pm

@@ -6,7 +6,7 @@ use warnings;
 # ABSTRACT: Provides a utility wait_until function
 use Try::Tiny;
 require Exporter;
-our @ISA = qw/Exporter/;
+our @ISA    = qw/Exporter/;
 our @EXPORT = qw/wait_until/;
 
 =head1 SYNOPSIS
@@ -77,21 +77,21 @@ iterations.
 
 sub wait_until (&%) {
     my $assert = shift;
-    my $args = {
-        timeout => 30,
+    my $args   = {
+        timeout  => 30,
         interval => 1,
-        debug => 0,
+        debug    => 0,
         @_
     };
 
-    my $start = time;
+    my $start               = time;
     my $timeout_not_elapsed = sub {
         my $elapsed = time - $start;
         return $elapsed < $args->{timeout};
     };
 
     my $exception = '';
-    while ($timeout_not_elapsed->()) {
+    while ( $timeout_not_elapsed->() ) {
         my $assert_ret;
         my $try_ret = try {
             $assert_ret = $assert->();
@@ -103,8 +103,8 @@ sub wait_until (&%) {
             return '';
         }
         finally {
-            if (! $assert_ret) {
-                sleep($args->{interval});
+            if ( !$assert_ret ) {
+                sleep( $args->{interval} );
             }
         };
 
@@ -112,7 +112,7 @@ sub wait_until (&%) {
     }
 
     # No need to repeat ourselves if we're already debugging.
-    warn $exception if $exception && ! $args->{debug};
+    warn $exception if $exception && !$args->{debug};
     return '';
 }
 

+ 1 - 1
lib/Test/Selenium/Chrome.pm

@@ -5,7 +5,7 @@ extends 'Selenium::Chrome', 'Test::Selenium::Remote::Driver';
 
 has 'webelement_class' => (
     is      => 'rw',
-    default => sub {'Test::Selenium::Remote::WebElement'},
+    default => sub { 'Test::Selenium::Remote::WebElement' },
 );
 
 1;

+ 1 - 1
lib/Test/Selenium/Edge.pm

@@ -5,7 +5,7 @@ extends 'Selenium::Edge', 'Test::Selenium::Remote::Driver';
 
 has 'webelement_class' => (
     is      => 'rw',
-    default => sub {'Test::Selenium::Remote::WebElement'},
+    default => sub { 'Test::Selenium::Remote::WebElement' },
 );
 
 1;

+ 1 - 1
lib/Test/Selenium/Firefox.pm

@@ -5,7 +5,7 @@ extends 'Selenium::Firefox', 'Test::Selenium::Remote::Driver';
 
 has 'webelement_class' => (
     is      => 'rw',
-    default => sub {'Test::Selenium::Remote::WebElement'},
+    default => sub { 'Test::Selenium::Remote::WebElement' },
 );
 
 1;

+ 1 - 1
lib/Test/Selenium/InternetExplorer.pm

@@ -5,7 +5,7 @@ extends 'Selenium::InternetExplorer', 'Test::Selenium::Remote::Driver';
 
 has 'webelement_class' => (
     is      => 'rw',
-    default => sub {'Test::Selenium::Remote::WebElement'},
+    default => sub { 'Test::Selenium::Remote::WebElement' },
 );
 
 1;

+ 1 - 1
lib/Test/Selenium/PhantomJS.pm

@@ -5,7 +5,7 @@ extends 'Selenium::PhantomJS', 'Test::Selenium::Remote::Driver';
 
 has 'webelement_class' => (
     is      => 'rw',
-    default => sub {'Test::Selenium::Remote::WebElement'},
+    default => sub { 'Test::Selenium::Remote::WebElement' },
 );
 
 1;

+ 48 - 50
lib/Test/Selenium/Remote/Driver.pm

@@ -16,27 +16,32 @@ has func_list => (
     is      => 'lazy',
     builder => sub {
         return [
-            'alert_text_is',     'alert_text_isnt', 'alert_text_like',
-            'alert_text_unlike', 'current_window_handle_is',
-            'current_window_handle_isnt',   'current_window_handle_like',
-            'current_window_handle_unlike', 'window_handles_is',
-            'window_handles_isnt',          'window_handles_like',
-            'window_handles_unlike', 'window_size_is', 'window_size_isnt',
-            'window_size_like', 'window_size_unlike', 'window_position_is',
-            'window_position_isnt', 'window_position_like',
-            'window_position_unlike', 'current_url_is',     'current_url_isnt',
-            'current_url_like',       'current_url_unlike', 'title_is',
-            'title_isnt', 'title_like', 'title_unlike', 'active_element_is',
-            'active_element_isnt',   'active_element_like',
-            'active_element_unlike', 'send_keys_to_active_element_ok',
-            'send_keys_to_alert_ok', 'send_keys_to_prompt_ok',
-            'send_modifier_ok', 'accept_alert_ok', 'dismiss_alert_ok',
-            'get_ok', 'go_back_ok', 'go_forward_ok', 'add_cookie_ok',
-            'get_page_source_ok', 'find_element_ok', 'find_elements_ok',
-            'find_child_element_ok', 'find_child_elements_ok',
-            'find_no_element_ok',
-            'compare_elements_ok', 'click_ok', 'double_click_ok',
-            'body_like',
+            'alert_text_is',                  'alert_text_isnt',
+            'alert_text_like',                'alert_text_unlike',
+            'current_window_handle_is',       'current_window_handle_isnt',
+            'current_window_handle_like',     'current_window_handle_unlike',
+            'window_handles_is',              'window_handles_isnt',
+            'window_handles_like',            'window_handles_unlike',
+            'window_size_is',                 'window_size_isnt',
+            'window_size_like',               'window_size_unlike',
+            'window_position_is',             'window_position_isnt',
+            'window_position_like',           'window_position_unlike',
+            'current_url_is',                 'current_url_isnt',
+            'current_url_like',               'current_url_unlike',
+            'title_is',                       'title_isnt',
+            'title_like',                     'title_unlike',
+            'active_element_is',              'active_element_isnt',
+            'active_element_like',            'active_element_unlike',
+            'send_keys_to_active_element_ok', 'send_keys_to_alert_ok',
+            'send_keys_to_prompt_ok',         'send_modifier_ok',
+            'accept_alert_ok',                'dismiss_alert_ok',
+            'get_ok',                         'go_back_ok',
+            'go_forward_ok',                  'add_cookie_ok',
+            'get_page_source_ok',             'find_element_ok',
+            'find_elements_ok',               'find_child_element_ok',
+            'find_child_elements_ok',         'find_no_element_ok',
+            'compare_elements_ok',            'click_ok',
+            'double_click_ok',                'body_like',
         ];
     },
 );
@@ -73,7 +78,8 @@ sub BUILD {
         unless ( defined( __PACKAGE__->can($method_name) ) ) {
             my $sub = $self->_build_sub($method_name);
             Sub::Install::install_sub(
-                {   code => $sub,
+                {
+                    code => $sub,
                     into => __PACKAGE__,
                     as   => $method_name
                 }
@@ -139,9 +145,7 @@ Enable/disable debugging output, or view the status of verbosity.
 
 =cut
 
-has verbose => (
-    is => 'rw',
-);
+has verbose => ( is => 'rw', );
 
 =head2 server_is_running( $host, $port )
 
@@ -154,8 +158,8 @@ determine the server to check.
 =cut
 
 sub server_is_running {
-    my $host          = $ENV{TWD_HOST} || shift || 'localhost';
-    my $port          = $ENV{TWD_PORT} || shift || 4444;
+    my $host = $ENV{TWD_HOST} || shift || 'localhost';
+    my $port = $ENV{TWD_PORT} || shift || 4444;
 
     return ( $host, $port )
       if IO::Socket::INET->new(
@@ -343,9 +347,7 @@ sub _find_element_with_action {
         $desc .= "'" . join( " ", ( $params // '' ) ) . "'";
     }
     my $element;
-    eval {
-        $element = $self->find_element( $locator, $locator_strategy );
-    };
+    eval { $element = $self->find_element( $locator, $locator_strategy ); };
     if ($@) {
         print "# Error: $@\n";
         return 0;
@@ -449,7 +451,6 @@ sub is_element_enabled_ok {
     return $self->_find_element_with_action( $method, @_ );
 }
 
-
 =head2 $twd->find_element_ok($search_target [,$finder, $desc ]);
 
    $twd->find_element_ok( $search_target [,$finder, $desc ] );
@@ -495,7 +496,7 @@ sub content_like {
         $desc = qq{Content is like "$regex"} if ( not defined $desc );
         $ret = like_string( $content, $regex, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $regex");
+            $self->error_handler->( $self, "Failed to find $regex" );
         }
         return $ret;
     }
@@ -504,7 +505,7 @@ sub content_like {
             $desc = qq{Content is like "$re"} if ( not defined $desc );
             $ret = like_string( $content, $re, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $re");
+                $self->error_handler->( $self, "Failed to find $re" );
             }
         }
     }
@@ -537,7 +538,7 @@ sub content_unlike {
         $desc = qq{Content is unlike "$regex"} if ( not defined $desc );
         $ret = unlike_string( $content, $regex, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $regex");
+            $self->error_handler->( $self, "Failed to find $regex" );
         }
     }
     elsif ( ref $regex eq 'ARRAY' ) {
@@ -545,13 +546,12 @@ sub content_unlike {
             $desc = qq{Content is unlike "$re"} if ( not defined $desc );
             $ret = unlike_string( $content, $re, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $re");
+                $self->error_handler->( $self, "Failed to find $re" );
             }
         }
     }
 }
 
-
 =head2 $twd->body_text_like( $regex [, $desc ] )
 
    $twd->body_text_like( $regex [, $desc ] )
@@ -582,7 +582,7 @@ sub body_text_like {
         $desc = qq{Text is like "$regex"} if ( not defined $desc );
         $ret = like_string( $text, $regex, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $regex");
+            $self->error_handler->( $self, "Failed to find $regex" );
         }
         return $ret;
     }
@@ -591,7 +591,7 @@ sub body_text_like {
             $desc = qq{Text is like "$re"} if ( not defined $desc );
             $ret = like_string( $text, $re, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $re");
+                $self->error_handler->( $self, "Failed to find $re" );
             }
         }
     }
@@ -628,7 +628,7 @@ sub body_text_unlike {
         $desc = qq{Text is unlike "$regex"} if ( not defined $desc );
         $ret = unlike_string( $text, $regex, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $regex");
+            $self->error_handler->( $self, "Failed to find $regex" );
         }
         return $ret;
 
@@ -638,7 +638,7 @@ sub body_text_unlike {
             $desc = qq{Text is unlike "$re"} if ( not defined $desc );
             $ret = unlike_string( $text, $re, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $re");
+                $self->error_handler->( $self, "Failed to find $re" );
             }
         }
     }
@@ -674,7 +674,7 @@ sub content_contains {
         $desc = qq{Content contains "$str"} if ( not defined $desc );
         $ret = contains_string( $content, $str, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $str");
+            $self->error_handler->( $self, "Failed to find $str" );
         }
         return $ret;
     }
@@ -684,7 +684,7 @@ sub content_contains {
             $ret = contains_string( $content, $s, $desc );
 
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $s");
+                $self->error_handler->( $self, "Failed to find $s" );
             }
         }
     }
@@ -718,7 +718,7 @@ sub content_lacks {
         $desc = qq{Content lacks "$str"} if ( not defined $desc );
         $ret = lacks_string( $content, $str, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $str");
+            $self->error_handler->( $self, "Failed to find $str" );
         }
         return $ret;
     }
@@ -727,13 +727,12 @@ sub content_lacks {
             $desc = qq{Content lacks "$s"} if ( not defined $desc );
             $ret = lacks_string( $content, $s, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $s");
+                $self->error_handler->( $self, "Failed to find $s" );
             }
         }
     }
 }
 
-
 =head2 $twd->body_text_contains( $str [, $desc ] )
 
    $twd->body_text_contains( $str [, $desc ] )
@@ -764,7 +763,7 @@ sub body_text_contains {
         $desc = qq{Text contains "$str"} if ( not defined $desc );
         $ret = contains_string( $text, $str, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $str");
+            $self->error_handler->( $self, "Failed to find $str" );
         }
         return $ret;
     }
@@ -773,7 +772,7 @@ sub body_text_contains {
             $desc = qq{Text contains "$s"} if ( not defined $desc );
             $ret = contains_string( $text, $s, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $s");
+                $self->error_handler->( $self, "Failed to find $s" );
             }
         }
     }
@@ -810,7 +809,7 @@ sub body_text_lacks {
         $desc = qq{Text lacks "$str"} if ( not defined $desc );
         $ret = lacks_string( $text, $str, $desc );
         if ( !$ret && $self->has_error_handler ) {
-            $self->error_handler->($self,"Failed to find $str");
+            $self->error_handler->( $self, "Failed to find $str" );
         }
         return $ret;
     }
@@ -819,13 +818,12 @@ sub body_text_lacks {
             $desc = qq{Text lacks "$s"} if ( not defined $desc );
             $ret = lacks_string( $text, $s, $desc );
             if ( !$ret && $self->has_error_handler ) {
-                $self->error_handler->($self,"Failed to find $s");
+                $self->error_handler->( $self, "Failed to find $s" );
             }
         }
     }
 }
 
-
 1;
 
 __END__

+ 27 - 26
lib/Test/Selenium/Remote/Role/DoesTesting.pm

@@ -1,4 +1,5 @@
 package Test::Selenium::Remote::Role::DoesTesting;
+
 # ABSTRACT: Role to cope with everything that is related to testing (could
 # be reused in both testing classes)
 
@@ -17,14 +18,13 @@ has _builder => (
     handles => [qw/is_eq isnt_eq like unlike ok croak/],
 );
 
-
 # get back the key value from an already coerced finder (default finder)
 
 sub _get_finder_key {
-    my $self = shift;
+    my $self         = shift;
     my $finder_value = shift;
-    foreach my $k (keys %{$self->FINDERS}) {
-        return $k if ($self->FINDERS->{$k} eq $finder_value);
+    foreach my $k ( keys %{ $self->FINDERS } ) {
+        return $k if ( $self->FINDERS->{$k} eq $finder_value );
     }
     return;
 }
@@ -54,34 +54,38 @@ sub _check_method {
 # a bit hacked so that find_no_element_ok can also be processed
 
 sub _check_ok {
-    my $self   = shift;
-    my $method = shift;
+    my $self        = shift;
+    my $method      = shift;
     my $real_method = '';
-    my @args   = @_;
-    my ($rv, $num_of_args, @r_args);
+    my @args        = @_;
+    my ( $rv, $num_of_args, @r_args );
     try {
         $num_of_args = $self->has_args($method);
         @r_args = splice( @args, 0, $num_of_args );
-        if ($method =~ m/^find(_no|_child)?_element/) {
+        if ( $method =~ m/^find(_no|_child)?_element/ ) {
+
             # case find_element_ok was called with no arguments
-            if (scalar(@r_args) - $num_of_args == 1) {
-                push @r_args, $self->_get_finder_key($self->default_finder);
+            if ( scalar(@r_args) - $num_of_args == 1 ) {
+                push @r_args, $self->_get_finder_key( $self->default_finder );
             }
             else {
-                if (scalar(@r_args) == $num_of_args) {
+                if ( scalar(@r_args) == $num_of_args ) {
+
                     # case find_element was called with no finder but
                     # a test description
-                    my $finder = $r_args[$num_of_args - 1];
-                    my @FINDERS = keys (%{$self->FINDERS});
-                    unless ( any { $finder eq $_ } @FINDERS) {
-                        $r_args[$num_of_args - 1] = $self->_get_finder_key($self->default_finder);
+                    my $finder  = $r_args[ $num_of_args - 1 ];
+                    my @FINDERS = keys( %{ $self->FINDERS } );
+                    unless ( any { $finder eq $_ } @FINDERS ) {
+                        $r_args[ $num_of_args - 1 ] =
+                          $self->_get_finder_key( $self->default_finder );
                         push @args, $finder;
                     }
                 }
             }
         }
+
         # quick hack to fit 'find_no_element' into check_ok logic
-        if ($method eq 'find_no_element') {
+        if ( $method eq 'find_no_element' ) {
             $real_method = $method;
 
             # If we use `find_element` and find nothing, the error
@@ -91,7 +95,7 @@ sub _check_ok {
             # https://github.com/gempesaw/Selenium-Remote-Driver/issues/253
             $method = 'find_elements';
             my $elements = $self->$method(@r_args);
-            if (scalar(@$elements)) {
+            if ( scalar(@$elements) ) {
                 $rv = $elements->[0];
             }
             else {
@@ -112,23 +116,21 @@ sub _check_ok {
         }
     };
 
-
     my $default_test_name = $method;
-    $default_test_name .= "'" . join("' ", @r_args) . "'"
-        if $num_of_args > 0;
+    $default_test_name .= "'" . join( "' ", @r_args ) . "'"
+      if $num_of_args > 0;
 
     my $test_name = pop @args // $default_test_name;
 
     # case when find_no_element found an element, we should croak
-    if ($real_method eq 'find_no_element') {
-        if (blessed($rv) && $rv->isa('Selenium::Remote::WebElement')) {
+    if ( $real_method eq 'find_no_element' ) {
+        if ( blessed($rv) && $rv->isa('Selenium::Remote::WebElement') ) {
             $self->croak($test_name);
         }
     }
-    return $self->ok( $rv, $test_name);
+    return $self->ok( $rv, $test_name );
 }
 
-
 # build the subs with the correct arg set
 
 sub _build_sub {
@@ -171,7 +173,6 @@ sub _build_sub {
 
 1;
 
-
 =head1 NAME
 
 Selenium::Remote::Role::DoesTesting - Role implementing the common logic used for testing

+ 11 - 11
lib/Test/Selenium/Remote/WebElement.pm

@@ -1,4 +1,5 @@
 package Test::Selenium::Remote::WebElement;
+
 # ABSTRACT: A sub-class of L<Selenium::Remote::WebElement>, with several test-specific method additions.
 
 use Moo;
@@ -15,14 +16,14 @@ has func_list => (
     is      => 'lazy',
     builder => sub {
         return [
-            'clear_ok',     'click_ok',
-            'send_keys_ok', 'is_displayed_ok',
-            'is_enabled_ok', 'is_selected_ok', 'submit_ok',
-            'text_is',          'text_isnt',      'text_like',  'text_unlike',
-            'attribute_is',     'attribute_isnt', 'attribute_like',
-            'attribute_unlike', 'value_is',       'value_isnt', 'value_like',
-            'value_unlike', 'tag_name_is', 'tag_name_isnt', 'tag_name_like',
-            'tag_name_unlike'
+            'clear_ok',        'click_ok',       'send_keys_ok',
+            'is_displayed_ok', 'is_enabled_ok',  'is_selected_ok',
+            'submit_ok',       'text_is',        'text_isnt',
+            'text_like',       'text_unlike',    'attribute_is',
+            'attribute_isnt',  'attribute_like', 'attribute_unlike',
+            'value_is',        'value_isnt',     'value_like',
+            'value_unlike',    'tag_name_is',    'tag_name_isnt',
+            'tag_name_like',   'tag_name_unlike'
         ];
     }
 );
@@ -41,7 +42,6 @@ sub has_args {
     return ( $hash_fun_args->{$fun_name} // 0 );
 }
 
-
 # install the test methods into the class namespace
 
 sub BUILD {
@@ -50,7 +50,8 @@ sub BUILD {
         unless ( defined( __PACKAGE__->can($method_name) ) ) {
             my $sub = $self->_build_sub($method_name);
             Sub::Install::install_sub(
-                {   code => $sub,
+                {
+                    code => $sub,
                     into => __PACKAGE__,
                     as   => $method_name
                 }
@@ -59,7 +60,6 @@ sub BUILD {
     }
 }
 
-
 1;
 
 __END__

+ 23 - 23
t/lib/TestHarness.pm

@@ -37,7 +37,7 @@ C<01-driver.t>.
 =cut
 
 has calling_file => (
-    is => 'ro',
+    is       => 'ro',
     init_arg => 'this_file',
     required => 1
 );
@@ -53,11 +53,12 @@ equal to 1.
 =cut
 
 has record => (
-    is => 'ro',
+    is        => 'ro',
     init_args => undef,
-    default => sub {
-        if (defined $ENV{WD_MOCKING_RECORD}
-              && $ENV{WD_MOCKING_RECORD} == 1) {
+    default   => sub {
+        if ( defined $ENV{WD_MOCKING_RECORD}
+            && $ENV{WD_MOCKING_RECORD} == 1 )
+        {
             return 1;
         }
         else {
@@ -67,13 +68,13 @@ has record => (
 );
 
 has base_caps => (
-    is => 'rw',
-    lazy => 1,
+    is      => 'rw',
+    lazy    => 1,
     default => sub {
         my ($self) = @_;
         my $args = {
             browser_name => 'firefox',
-            remote_conn => $self->mock_remote_conn
+            remote_conn  => $self->mock_remote_conn
         };
 
         return $args;
@@ -81,14 +82,12 @@ has base_caps => (
 );
 
 has mock_remote_conn => (
-    is => 'ro',
-    lazy => 1,
+    is      => 'ro',
+    lazy    => 1,
     builder => sub {
         my ($self) = @_;
-        if ($self->record) {
-            return Selenium::Remote::Mock::RemoteConnection->new(
-                record => 1
-            );
+        if ( $self->record ) {
+            return Selenium::Remote::Mock::RemoteConnection->new( record => 1 );
         }
         else {
             return Selenium::Remote::Mock::RemoteConnection->new(
@@ -100,8 +99,8 @@ has mock_remote_conn => (
 );
 
 has mock_file => (
-    is => 'ro',
-    lazy => 1,
+    is      => 'ro',
+    lazy    => 1,
     builder => sub {
         my ($self) = @_;
 
@@ -110,15 +109,16 @@ has mock_file => (
         # to the folder that the *.t files live in - that is, `t`.
         my $mock_folder = $FindBin::Bin . '/mock-recordings/';
 
-        my $test_name = lc($self->calling_file);
+        my $test_name = lc( $self->calling_file );
         $test_name =~ s/\.t$//;
 
         my $mock_file = $mock_folder . $test_name . '-mock.json';
 
         # If we're replaying, we need a mock to read from. Otherwise,
         # we can't do anything
-        if (not $self->record) {
-            plan skip_all => "Mocking of tests is not been enabled for this platform"
+        if ( not $self->record ) {
+            plan skip_all =>
+              "Mocking of tests is not been enabled for this platform"
               unless -e $mock_file;
         }
 
@@ -127,7 +127,7 @@ has mock_file => (
 );
 
 has website => (
-    is => 'ro',
+    is      => 'ro',
     default => sub {
         my ($self) = @_;
         my $port = 63636;
@@ -137,14 +137,14 @@ has website => (
 );
 
 has domain => (
-    is => 'ro',
+    is      => 'ro',
     default => sub { 'localhost' }
 );
 
 sub DEMOLISH {
     my ($self) = @_;
-    if ($self->record) {
-        $self->mock_remote_conn->dump_session_store($self->mock_file);
+    if ( $self->record ) {
+        $self->mock_remote_conn->dump_session_store( $self->mock_file );
     }
 }
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است