Ver código fonte

Merge pull request #164 from gempesaw/mock-driver-experiment

Mock driver experiment - curious to see how this merges automatically, as I had to resolve a couple errors when I was doing it manually.
Daniel Gempesaw 11 anos atrás
pai
commit
926c652a5e
34 arquivos alterados com 949 adições e 700 exclusões
  1. 2 1
      Changes
  2. 4 5
      cpanfile
  3. 2 5
      dist.ini
  4. 0 5
      lib/Selenium/Remote/Commands.pm
  5. 32 40
      lib/Selenium/Remote/Driver.pm
  6. 47 0
      lib/Selenium/Remote/Mock/Commands.pm
  7. 324 0
      lib/Selenium/Remote/Mock/RemoteConnection.pm
  8. 13 6
      lib/Selenium/Remote/RemoteConnection.pm
  9. 1 0
      lib/Test/Selenium/Remote/Driver.pm
  10. 55 39
      t/01-driver.t
  11. 10 22
      t/02-webelement.t
  12. 16 5
      t/10-switch-to-window.t
  13. 17 27
      t/Firefox-Profile.t
  14. 12 5
      t/Test-Selenium-Remote-Driver-google.t
  15. 24 118
      t/Test-Selenium-Remote-Driver.t
  16. 45 272
      t/Test-Selenium-Remote-WebElement.t
  17. 32 36
      t/bin/record.pl
  18. 0 114
      t/lib/MockSeleniumWebDriver.pm
  19. 130 0
      t/lib/TestHarness.pm
  20. 0 0
      t/mock-recordings/01-driver-mock-MSWin32.json
  21. 0 0
      t/mock-recordings/01-driver-mock-darwin.json
  22. 0 0
      t/mock-recordings/01-driver-mock-linux.json
  23. 0 0
      t/mock-recordings/02-webelement-mock-MSWin32.json
  24. 0 0
      t/mock-recordings/02-webelement-mock-darwin.json
  25. 0 0
      t/mock-recordings/02-webelement-mock-linux.json
  26. 41 0
      t/mock-recordings/10-switch-to-window-mock-MSWin32.json
  27. 41 0
      t/mock-recordings/10-switch-to-window-mock-darwin.json
  28. 41 0
      t/mock-recordings/10-switch-to-window-mock-linux.json
  29. 0 0
      t/mock-recordings/firefox-profile-mock-MSWin32.json
  30. 0 0
      t/mock-recordings/firefox-profile-mock-darwin.json
  31. 0 0
      t/mock-recordings/firefox-profile-mock-linux.json
  32. 20 0
      t/mock-recordings/test-selenium-remote-driver-google-mock-MSWin32.json
  33. 20 0
      t/mock-recordings/test-selenium-remote-driver-google-mock-darwin.json
  34. 20 0
      t/mock-recordings/test-selenium-remote-driver-google-mock-linux.json

+ 2 - 1
Changes

@@ -1,6 +1,6 @@
 Revision history for Selenium-Remote-Driver
 
-0.2150 10-10-2014
+0.2151 10-10-2014
         [NEW FEATURES]
         - Improved error messaging for Saucelabs non-json cases
         - Improved error messaging for incorrectly configured chromedrivers
@@ -9,6 +9,7 @@ Revision history for Selenium-Remote-Driver
         - Specify minimum compatible version of Moo dep
         - Make Driver.pm more easily subclassed ( ea68e06, 63e78e3 )
         - Get TravisCI passing again
+        - Roll & use our own mocking classes #164
 
         [BREAKING]
         - get|set_speed subs are no-ops and will be removed in the upcoming release

+ 4 - 5
cpanfile

@@ -8,6 +8,7 @@ requires "File::Copy" => "0";
 requires "File::Temp" => "0";
 requires "HTTP::Headers" => "0";
 requires "HTTP::Request" => "0";
+requires "HTTP::Response" => "0";
 requires "IO::Compress::Zip" => "0";
 requires "IO::Socket" => "0";
 requires "JSON" => "0";
@@ -31,19 +32,17 @@ requires "warnings" => "0";
 on 'test' => sub {
   requires "File::Basename" => "0";
   requires "File::stat" => "0";
+  requires "FindBin" => "0";
   requires "IO::Socket::INET" => "0";
-  requires "LWP::Protocol::PSGI" => "0.04";
   requires "LWP::Simple" => "0";
   requires "Test::Exception" => "0";
   requires "Test::LWP::UserAgent" => "0";
-  requires "Test::MockObject" => "0";
-  requires "Test::MockObject::Extends" => "0";
   requires "Test::More" => "0";
-  requires "Test::Tester" => "0";
+  requires "lib" => "0";
 };
 
 on 'configure' => sub {
-  requires "ExtUtils::MakeMaker" => "6.30";
+  requires "ExtUtils::MakeMaker" => "0";
 };
 
 on 'develop' => sub {

+ 2 - 5
dist.ini

@@ -1,5 +1,5 @@
 name = Selenium-Remote-Driver
-version = 0.2150
+version = 0.2151
 author = Aditya Ivaturi <ivaturi@gmail.com>
 author = Daniel Gempesaw <gempesaw@gmail.com>
 author = Luke Closs <cpan@5thplane.com>
@@ -27,6 +27,7 @@ release_message = v%v - Build results of %h (on %b)
 [GatherDir]
 include_dotfiles = 1
 exclude_filename = cpanfile
+exclude_match = \.swp$
 
 [MakeMaker]
 [ManifestSkip]
@@ -70,10 +71,6 @@ copy = cpanfile
 perl = 5.010
 Moo = 1.005
 
-[Prereqs / TestRequires]
-; unfortunately this doesn't coerce 0.04, it just sets the minimum.
-LWP::Protocol::PSGI = 0.04
-
 [MetaResources]
 bugtracker.web = https://github.com/gempesaw/Selenium-Remote-Driver/issues
 repository.type = git

+ 0 - 5
lib/Selenium/Remote/Commands.pm

@@ -279,11 +279,6 @@ has '_cmds' => (
                 'url'                => 'session/:sessionId/window',
                 'no_content_success' => 1
             },
-            'dragElement' => {
-                'method'             => 'POST',
-                'url'                => 'session/:sessionId/element/:id/drag',
-                'no_content_success' => 1
-            },
             'getElementSize' => {
                 'method'             => 'GET',
                 'url'                => 'session/:sessionId/element/:id/size',

+ 32 - 40
lib/Selenium/Remote/Driver.pm

@@ -312,12 +312,12 @@ has 'session_id' => (
 has 'remote_conn' => (
     is      => 'lazy',
     builder => sub {
-        my $self = shift;
-        return Selenium::Remote::RemoteConnection->new(
-            remote_server_addr => $self->remote_server_addr,
-            port               => $self->port,
-            ua                 => $self->ua
-        );
+            my $self = shift;
+            return Selenium::Remote::RemoteConnection->new(
+                remote_server_addr => $self->remote_server_addr,
+                port               => $self->port,
+                ua                 => $self->ua
+            );
     },
 );
 
@@ -328,7 +328,9 @@ has 'ua' => (
 
 has 'commands' => (
     is      => 'lazy',
-    builder => sub { return Selenium::Remote::Commands->new; },
+    builder => sub {
+        return Selenium::Remote::Commands->new;
+    },
 );
 
 has 'auto_close' => (
@@ -415,32 +417,23 @@ has 'inner_window_size' => (
 
 );
 
-has 'testing' => (
-    is => 'rw',
-    default => sub { 0 },
-);
-
 sub BUILD {
     my $self = shift;
 
-    # disable server connection when testing attribute is on
-    unless ($self->testing) {
-
-        if ($self->has_desired_capabilities) {
-            $self->new_desired_session( $self->desired_capabilities );
-        }
-        else {
-            # Connect to remote server & establish a new session
-            $self->new_session( $self->extra_capabilities );
-        }
+    if ($self->has_desired_capabilities) {
+        $self->new_desired_session( $self->desired_capabilities );
+    }
+    else {
+        # Connect to remote server & establish a new session
+        $self->new_session( $self->extra_capabilities );
+    }
 
-        if ( !( defined $self->session_id ) ) {
-            croak "Could not establish a session with the remote server\n";
-        }
-        elsif ($self->has_inner_window_size) {
-            my $size = $self->inner_window_size;
-            $self->set_inner_window_size(@$size);
-        }
+    if ( !( defined $self->session_id ) ) {
+        croak "Could not establish a session with the remote server\n";
+    }
+    elsif ($self->has_inner_window_size) {
+        my $size = $self->inner_window_size;
+        $self->set_inner_window_size(@$size);
     }
 }
 
@@ -470,12 +463,7 @@ sub _execute_command {
 
     if ($resource) {
         $params = {} unless $params;
-        my $resp = $self->remote_conn->request(
-            $resource->{method},
-            $resource->{url},
-            $resource->{no_content_success},
-            $params
-        );
+        my $resp = $self->remote_conn->request( $resource, $params);
         if ( ref($resp) eq 'HASH' ) {
             if ( $resp->{cmd_status} && $resp->{cmd_status} eq 'OK' ) {
                 return $resp->{cmd_return};
@@ -544,13 +532,17 @@ sub new_desired_session {
 
 sub _request_new_session {
     my ( $self, $args ) = @_;
-
+    $self->remote_conn->check_status();
     # command => 'newSession' to fool the tests of commands implemented
     # TODO: rewrite the testing better, this is so fragile.
-    my $resp = $self->remote_conn->request(
-        $self->commands->get_method('newSession'),
-        $self->commands->get_url('newSession'),
-        $self->commands->get_no_content_success('newSession'),
+    my $resource_new_session = {
+        method => $self->commands->get_method('newSession'),
+        url => $self->commands->get_url('newSession'),
+        no_content_success => $self->commands->get_no_content_success('newSession'),
+    };
+    my $rc = $self->remote_conn;
+    my $resp = $rc->request(
+        $resource_new_session,
         $args,
     );
     if ( ( defined $resp->{'sessionId'} ) && $resp->{'sessionId'} ne '' ) {

+ 47 - 0
lib/Selenium/Remote/Mock/Commands.pm

@@ -0,0 +1,47 @@
+package Selenium::Remote::Mock::Commands;
+
+# ABSTRACT: utility class to mock Selenium::Remote::Commands
+#
+use Moo;
+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 $command = delete $args->{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;
+    return $data;
+}
+
+sub get_method_name_from_parameters {
+    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})) {
+            $method_name = $cmd;
+            last;
+        }
+    }
+    return $method_name;
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 DESCRIPTION
+
+Utility class to be for testing purposes, with L<Selenium::Remote::Mock::RemoteConnection> only.
+
+=cut

+ 324 - 0
lib/Selenium/Remote/Mock/RemoteConnection.pm

@@ -0,0 +1,324 @@
+package Selenium::Remote::Mock::RemoteConnection;
+
+# ABSTRACT: utility class to mock the responses from Selenium server
+
+use Moo;
+use JSON;
+use Carp;
+use Try::Tiny;
+use HTTP::Response;
+use Data::Dumper;
+
+extends 'Selenium::Remote::RemoteConnection';
+
+has 'spec' => (
+    is       => 'ro',
+    default => sub {{}},
+);
+
+has 'mock_cmds' => (
+    is => 'ro',
+);
+
+has 'fake_session_id' => (
+    is => 'lazy',
+    builder => sub {
+        my $id = join '',
+        map +( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' )[ rand( 10 + 26 * 2 ) ], 1 .. 50;
+        return $id;
+    },
+);
+
+has 'record' => (
+    is => 'ro',
+    default => sub { 0 }
+);
+
+has 'replay' => (
+    is => 'ro',
+);
+
+has 'replay_file' => (
+    is => 'ro',
+);
+
+has 'session_store' => (
+    is => 'rw',
+    default => sub { {} }
+);
+
+has 'session_id' => (
+    is => 'rw',
+    default => sub { undef },
+);
+
+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));
+    $self->remote_server_addr('localhost');
+    $self->port('4444');
+    if ($self->replay) {
+        $self->load_session_store($self->replay_file);
+    }
+}
+
+sub check_status {
+    return;
+}
+
+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";
+    # here we use a fake session id since we have no way of figuring out
+    # which session is good or not
+    local $/ = undef;
+
+    my $json = JSON->new;
+    $json->allow_blessed;
+    my $decoded_json = $json->allow_nonref(1)->utf8(1)->decode(<$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";
+    my $session_store = $self->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);
+}
+
+sub request {
+    my $self = shift;
+    my ( $resource, $params ) = @_;
+    my $method             = $resource->{method};
+    my $url                = $resource->{url};
+    my $no_content_success = $resource->{no_content_success} // 0;
+    my $content            = '';
+    my $json               = JSON->new;
+    $json->allow_blessed;
+    if ($params) {
+        $content = $json->allow_nonref->utf8->canonical(1)->encode($params);
+    }
+    my $url_params = $resource->{url_params};
+    if ( $self->record ) {
+        my $response = $self->SUPER::request( $resource, $params, 1 );
+        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"} // [];
+        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"
+            );
+        }
+        return $self->_process_response( $resp, $no_content_success );
+    }
+    my $mock_cmds = $self->mock_cmds;
+    my $spec      = $self->spec;
+    my $cmd       = $mock_cmds->get_method_name_from_parameters(
+        { method => $method, url => $url } );
+    my $ret = { cmd_status => 'OK', cmd_return => 1 };
+    if ( defined( $spec->{$cmd} ) ) {
+        my $return_sub = $spec->{$cmd};
+        if ($no_content_success) {
+            $ret->{cmd_return} = 1;
+        }
+        else {
+            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 {
+        $ret->{sessionId} = $self->fake_session_id;
+    }
+    return $ret;
+}
+
+1;
+__END__
+
+=pod
+
+=head1 DESCRIPTION
+
+Selenium::Remote::Mock::RemoteConnection is a class to act as a short-circuit or a pass through to the connection to a Selenium Server.
+Using this class in place of L<Selenium::Remote::RemoteConnection> allows to:
+
+=over
+
+=item *
+record interactions with the Selenium Server into a JSON file
+
+=item *
+replay recorded interactions from a JSON file to mock answers from the Selenium Server
+
+=item *
+mock responses to specific functions
+
+=back
+
+=head1 SYNOPSIS
+
+=head2 Record interactions
+
+    #!perl
+    use strict;
+    use warnings;
+    use Selenium::Remote::Driver;
+    use Selenium::Remote::Mock::RemoteConnection;
+
+    # create a new Mock object to record the interactions with Selenium
+    # Server
+    my $mock_connection = Selenium::Remote::Mock::RemoteConnection->new( record => 1 );
+
+    # the Mock object is passed to the driver in place of what would be
+    # a regular Selenium::Remote::RemoteConnection object
+    my $driver = Selenium::Remote::Driver->new( remote_conn => $mock_connection );
+
+    # always store the session id, as it will become undef once
+    # $driver->quit is called
+    my $session_id = $driver->session_id;
+
+    # do all the selenium things and quit
+    $driver->get('http://www.google.com');
+    $driver->get('http://www.wikipedia.com');
+    $driver->quit;
+
+    # dump the session to a file
+    $mock_connection->dump_session_store( 'my_record.json' );
+
+
+This code, above doing some basic Selenium interactions, will end up generating a JSON file containing all the requests and their responses for your Selenium session.
+The JSON file looks like this :
+
+    {
+        "HTTP_REQUEST URL {request_parameters}":[ARRAY_OF_RESPONSES]
+        ...
+    }
+
+The reason why we store array of responses is that the exact same request can be made more than once during a session, so we have to store every response to the same requests.
+
+=head2 Replay interactions
+
+    #!perl
+    use strict;
+    use warnings;
+    use Test::More;
+    use Test::Selenium::Remote::Driver;
+    use Selenium::Remote::Mock::RemoteConnection;
+    my $mock_connection_2 =
+      Selenium::Remote::Mock::RemoteConnection->new( replay => 1,
+        replay_file => 'my_record.json' );
+    # javascript + version parameters added or else it will not work
+    my $driver =
+      Test::Selenium::Remote::Driver->new( remote_conn => $mock_connection_2, javascript => 1, version => '' );
+    $driver->get_ok('http://www.google.com');
+    $driver->get_ok('http://www.wikipedia.com');
+    $driver->quit;
+    done_testing;
+
+Using the file generated with the recording snippet from the section before, we are able to mock the responses.
+
+Note that there is one small limitation (that I hope to remove in future versions), is that a record generated with L<Selenium::Remote::Driver> is not directly useable with L<Test::Selenium::Remote::Driver>.
+This is mainly because the way the two instances are created are a bit different, which leads to different requests made, for creating a session for instance.
+For now, what works for sure is recording and replaying from the same class.
+
+=head2 Mock responses
+
+
+    #!perl
+    use Test::More;
+    use Test::Selenium::Remote::Driver;
+    use Selenium::Remote::WebElement;
+    use Selenium::Remote::Mock::Commands;
+    use Selenium::Remote::Mock::RemoteConnection;
+
+    my $spec = {
+        findElement => sub {
+            my (undef,$searched_item) = @_;
+            return { status => 'OK', return => { ELEMENT => '123456' } }
+              if ( $searched_item->{value} eq 'q' );
+            return { status => 'NOK', return => 0, error => 'element not found' };
+        },
+        getPageSource => sub { return 'this output matches regex'},
+    };
+    my $mock_commands = Selenium::Remote::Mock::Commands->new;
+
+    my $successful_driver =
+      Test::Selenium::Remote::Driver->new(
+        remote_conn => Selenium::Remote::Mock::RemoteConnection->new( spec => $spec, mock_cmds => $mock_commands ),
+        commands => $mock_commands,
+    );
+    $successful_driver->find_element_ok('q','find_element_ok works');
+    dies_ok { $successful_driver->find_element_ok('notq') } 'find_element_ok dies if element not found';
+    $successful_driver->find_no_element_ok('notq','find_no_element_ok works');
+    $successful_driver->content_like( qr/matches/, 'content_like works');
+    $successful_driver->content_unlike( qr/nomatch/, 'content_unlike works');
+
+    done_testing();
+
+Mocking responses by hand requires a more advanced knowledge of the underlying implementation of L<Selenium::Remote::Driver>.
+What we mock here is the processed response that will be returned by L<Selenium::Remote::RemoteConnection> to '_execute_command' call.
+To accomplish this we need :
+
+=over
+
+=item *
+a spec: a HASHREF which keys are the name of the methods we want to mock. Note that those keys should also be valid keys from the _cmds attribute in L<Selenium::Remote::Command>.
+The value of each key is a sub which will be given two parameters:
+
+=over
+
+=item *
+$url_params : the values that should have been replaced in the URL
+For instance, on the example above, it would have been:
+    { session_id => 'some_session_id'}
+
+=item *
+$params : the original parameters of the request.
+On the example above it would have been:
+    { value => 'q', using => 'xpath'}
+
+
+=back
+
+The sub used as a value in the spec is not expected to return anything, so you have to craft very carefully what you return so that it will produce the expected result.
+
+=item *
+a mock_cmd: a L<Selenium::Remote::Mock::Commands> object. This is used mainly to hijack the normal commands so that placeholders do not get replaced in the URLs.
+
+=back
+
+=head1 BUGS
+
+This code is really early alpha, so its API might change. Use with caution !
+
+=cut

+ 13 - 6
lib/Selenium/Remote/RemoteConnection.pm

@@ -36,11 +36,13 @@ has 'error_handler' => (
     builder => sub { return Selenium::Remote::ErrorHandler->new; }
 );
 
-sub BUILD {
+
+
+sub check_status {
     my $self = shift;
     my $status;
     try {
-        $status = $self->request('GET','status');
+        $status = $self->request({method => 'GET', url => 'status'});
     }
     catch {
         croak "Could not connect to SeleniumWebDriver: $_" ;
@@ -49,7 +51,7 @@ sub BUILD {
     if($status->{cmd_status} ne 'OK') {
         # Could be grid, see if we can talk to it
         $status = undef;
-        $status = $self->request('GET', 'grid/api/hub/status');
+        $status = $self->request({method => 'GET', url => 'grid/api/hub/status'});
     }
 
     unless ($status->{cmd_status} eq 'OK') {
@@ -58,10 +60,13 @@ sub BUILD {
 }
 
 
+
 # This request method is tailored for Selenium RC server
 sub request {
-    my ($self, $method, $url, $no_content_success, $params) = @_;
-    $no_content_success = $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 = '';
@@ -99,7 +104,9 @@ sub request {
     $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);
 }
 

+ 1 - 0
lib/Test/Selenium/Remote/Driver.pm

@@ -1,4 +1,5 @@
 package Test::Selenium::Remote::Driver;
+
 # ABSTRACT: Useful testing subclass for Selenium::Remote::Driver
 
 use Moo;

+ 55 - 39
t/01-driver.t

@@ -2,38 +2,27 @@ use strict;
 use warnings;
 
 use JSON;
-use Net::Ping;
-use HTTP::Headers;
 use Test::More;
-use LWP::Protocol::PSGI;
+use LWP::UserAgent;
 use Test::LWP::UserAgent;
+use IO::Socket::INET;
 use Selenium::Remote::Driver;
-
-BEGIN {
-    if (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1)) {
-        use t::lib::MockSeleniumWebDriver;
-        my $p = Net::Ping->new("tcp", 2);
-        $p->port_number(4444);
-        unless ($p->ping('localhost')) {
-            plan skip_all => "Selenium server is not running on localhost:4444";
-            exit;
-        }
-        warn "\n\nRecording...\n\n";
-    }
-}
-
-my $record = (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1))?1:0;
-my $os  = $^O;
-if ($os =~ m/(aix|freebsd|openbsd|sunos|solaris)/) {
-    $os = 'linux';
-}
-my $mock_file = "01-driver-mock-$os.json";
-if (!$record && !(-e "t/mock-recordings/$mock_file")) {
+use Selenium::Remote::Mock::Commands;
+use Selenium::Remote::Mock::RemoteConnection;
+
+use FindBin;
+use lib $FindBin::Bin . '/lib';
+use TestHarness;
+
+my $harness = TestHarness->new(
+    this_file => $FindBin::Script
+);
+my %selenium_args = %{ $harness->base_caps };
+unless ($harness->mocks_exist_for_platform) {
     plan skip_all => "Mocking of tests is not been enabled for this platform";
 }
-t::lib::MockSeleniumWebDriver::register($record,"t/mock-recordings/$mock_file");
 
-my $driver = Selenium::Remote::Driver->new(browser_name => 'firefox');
+my $driver = Selenium::Remote::Driver->new(%selenium_args);
 my $website = 'http://localhost:63636';
 my $ret;
 
@@ -337,9 +326,10 @@ PAUSE: {
 }
 
 AUTO_CLOSE: {
+    my %stay_open_selenium_args = %selenium_args;
+    $stay_open_selenium_args{auto_close} = 0;
     my $stayOpen = Selenium::Remote::Driver->new(
-        browser_name => 'firefox',
-        auto_close => 0
+        %stay_open_selenium_args
     );
 
     $stayOpen->DESTROY();
@@ -355,10 +345,12 @@ AUTO_CLOSE: {
 }
 
 INNER_WINDOW_SIZE: {
-    my $normal = Selenium::Remote::Driver->new->get_window_size;
-
+    my %normal_selenium_args = %selenium_args;
+    my $normal = Selenium::Remote::Driver->new(%normal_selenium_args)->get_window_size;
+    my %resized_selenium_args = %selenium_args;
+    $resized_selenium_args{inner_window_size} = [ 640,480];
     my $resized = Selenium::Remote::Driver->new(
-        inner_window_size => [ 640, 480 ]
+        %resized_selenium_args
     )->get_window_size;
 
     ok($normal->{height} != $resized->{height}, 'inner window size: height is immediately changed');
@@ -399,12 +391,19 @@ BASE_URL: {
         url      => 'http://blog.example.com/foo',
         expected => 'http://blog.example.com/foo',
     });
-
+    my $mock_commands = Selenium::Remote::Mock::Commands->new;
     for my $test (@tests) {
         my $base_url_driver = MySeleniumRemoteDriver->new(
             browser_name => 'firefox',
             base_url     => $test->{base_url},
-            testing      => 1,
+            remote_conn => Selenium::Remote::Mock::RemoteConnection->new(
+                spec => {
+                    get =>
+                      sub { my ( undef, $params ) = @_; return $params->{url} }
+                },
+                mock_cmds => $mock_commands
+              ),
+            commands => $mock_commands,
         );
         my $got = $base_url_driver->get($test->{url});
         is $got, $test->{expected}, "base_url + $test->{url}";
@@ -416,17 +415,14 @@ USER_AGENT: {
     ok($ua =~ /Firefox/, 'we can get a user agent');
 }
 
-QUIT: {
-    $ret = $driver->quit();
-    ok((not defined $driver->{'session_id'}), 'Killed the remote session');
-}
-
 STORAGE: {
     my $chrome;
+    my %selenium_chrome_args = ( browser_name => 'chrome');
+    $selenium_chrome_args{remote_conn} = $selenium_args{remote_conn};
 
   SKIP: {
         eval {
-            $chrome = Selenium::Remote::Driver->new(browser_name => 'chrome');
+            $chrome = Selenium::Remote::Driver->new(%selenium_chrome_args);
             $chrome->get($website);
         };
 
@@ -446,6 +442,26 @@ STORAGE: {
     }
 }
 
+QUIT: {
+    $ret = $driver->quit();
+    ok((not defined $driver->{'session_id'}), 'Killed the remote session');
+}
 
+NO_SERVER_ERROR_MESSAGE: {
+    my $unused_port = do {
+        my $l = IO::Socket::INET->new(
+            Listen    => 5,
+            LocalHost => '127.0.0.1',
+            LocalPort => 0,
+            Proto     => 'tcp',
+            ReuseAddr => 1,
+        ) or die $!;
+        $l->sockport;
+    };
+    eval {
+        my $sel = Selenium::Remote::Driver->new(port => $unused_port);
+    };
+    unlike($@, qr/Use of uninitialized value/, "Error message for no server at host/port combination is helpful");
+}
 
 done_testing;

+ 10 - 22
t/02-webelement.t

@@ -2,34 +2,22 @@ use strict;
 use warnings;
 
 use Test::More;
-use Net::Ping;
 use Selenium::Remote::Driver;
+use Selenium::Remote::Mock::RemoteConnection;
 
-BEGIN {
-    if (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1)) {
-        use t::lib::MockSeleniumWebDriver;
-        my $p = Net::Ping->new("tcp", 2);
-        $p->port_number(4444);
-        unless ($p->ping('localhost')) {
-            plan skip_all => "Selenium server is not running on localhost:4444";
-            exit;
-        }
-        warn "\n\nRecording...\n\n";
-    }
-}
+use FindBin;
+use lib $FindBin::Bin . '/lib';
+use TestHarness;
 
-my $record = (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1))?1:0;
-my $os  = $^O;
-if ($os =~ m/(aix|freebsd|openbsd|sunos|solaris)/) {
-    $os = 'linux';
-}
-my $mock_file = "02-webelement-mock-$os.json";
-if (!$record && !(-e "t/mock-recordings/$mock_file")) {
+my $harness = TestHarness->new(
+    this_file => $FindBin::Script
+);
+my %selenium_args = %{ $harness->base_caps };
+unless ($harness->mocks_exist_for_platform) {
     plan skip_all => "Mocking of tests is not been enabled for this platform";
 }
-t::lib::MockSeleniumWebDriver::register($record,"t/mock-recordings/$mock_file");
 
-my $driver = new Selenium::Remote::Driver(browser_name => 'firefox');
+my $driver = Selenium::Remote::Driver->new(%selenium_args);
 my $website = 'http://localhost:63636';
 $driver->get("$website/formPage.html");
 my $ret;

+ 16 - 5
t/10-switch-to-window.t

@@ -4,16 +4,28 @@ use 5.010;
 
 use Test::More;
 use Test::Selenium::Remote::Driver;
+use Selenium::Remote::Mock::RemoteConnection;
 
-if (not Test::Selenium::Remote::Driver->server_is_running()) {
-    plan skip_all => 'The Selenium server must be running for this test';
+use FindBin;
+use lib $FindBin::Bin . '/lib';
+use TestHarness;
+
+my $harness = TestHarness->new(
+    this_file => $FindBin::Script
+);
+my %selenium_args = (
+    default_finder => 'css',
+    javascript     => 1,
+    %{ $harness->base_caps }
+);
+unless ($harness->mocks_exist_for_platform) {
+    plan skip_all => "Mocking of tests is not been enabled for this platform";
 }
 
 plan tests => 9;
 
 my $s = Test::Selenium::Remote::Driver->new(
-    default_finder => 'css',
-    javascript     => 1,
+    %selenium_args
 );
 
 my $perl_title = 'The Perl Programming Language - www.perl.org';
@@ -48,4 +60,3 @@ $s->title_is($cpan_title);
 
 $s->switch_to_window('perlorg');
 $s->title_is($perl_title);
-

+ 17 - 27
t/Firefox-Profile.t

@@ -1,4 +1,4 @@
-#! /usr/bin/perl
+#!/usr/bin/perl
 
 use strict;
 use warnings;
@@ -10,31 +10,20 @@ use MIME::Base64 qw/decode_base64/;
 use Archive::Extract;
 use File::Temp;
 use JSON;
+use Selenium::Remote::Mock::RemoteConnection;
 use Selenium::Remote::Driver::Firefox::Profile;
 
-BEGIN {
-    if (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1)) {
-        use t::lib::MockSeleniumWebDriver;
-        my $p = Net::Ping->new("tcp", 2);
-        $p->port_number(4444);
-        unless ($p->ping('localhost')) {
-            plan skip_all => "Selenium server is not running on localhost:4444";
-            exit;
-        }
-        warn "\n\nRecording...\n\n";
-    }
-}
+use FindBin;
+use lib $FindBin::Bin . '/lib';
+use TestHarness;
 
-my $record = (defined $ENV{'WD_MOCKING_RECORD'} && ($ENV{'WD_MOCKING_RECORD'}==1))?1:0;
-my $os  = $^O;
-if ($os =~ m/(aix|freebsd|openbsd|sunos|solaris)/) {
-    $os = 'linux';
-}
-my $mock_file = "firefox-profile-mock-$os.json";
-if (!$record && !(-e "t/mock-recordings/$mock_file")) {
+my $harness = TestHarness->new(
+    this_file => $FindBin::Script
+);
+my %selenium_args = %{ $harness->base_caps };
+unless ($harness->mocks_exist_for_platform) {
     plan skip_all => "Mocking of tests is not been enabled for this platform";
 }
-t::lib::MockSeleniumWebDriver::register($record,"t/mock-recordings/$mock_file");
 
 CUSTOM_EXTENSION_LOADED: {
     my $profile = Selenium::Remote::Driver::Firefox::Profile->new;
@@ -45,7 +34,7 @@ CUSTOM_EXTENSION_LOADED: {
     # Set this to true to re-encode the profile. This should not need
     # to happen often.
     my $create_new_profile = 0;
-    if ($record && $create_new_profile) {
+    if ($create_new_profile) {
         $profile->set_preference(
             'browser.startup.homepage' => $website
         );
@@ -73,10 +62,9 @@ CUSTOM_EXTENSION_LOADED: {
         $encoded = do {local $/ = undef; <$fh>};
         close ($fh);
     }
-
-    my $driver = Selenium::Remote::Driver->new(extra_capabilities => {
-        firefox_profile => $encoded
-    });
+    my %driver_args = %selenium_args;
+    $driver_args{extra_capabilities} = { firefox_profile => $encoded };
+    my $driver = Selenium::Remote::Driver->new(%driver_args);
 
     ok(defined $driver, "made a driver without dying");
 
@@ -184,8 +172,10 @@ CROAKING: {
 
     {
         eval {
+            my %driver_args = %selenium_args;
+            $driver_args{firefox_profile} = 'clearly invalid';
             my $croakingDriver = Selenium::Remote::Driver->new(
-                firefox_profile => 'clearly invalid!'
+                %driver_args
             );
         };
         ok ($@ =~ /coercion.*failed/, "caught invalid extension in driver constructor");

+ 12 - 5
t/Test-Selenium-Remote-Driver-google.t

@@ -3,16 +3,23 @@ use strict;
 use warnings;
 use Test::More;
 use Test::Selenium::Remote::Driver;
+use Selenium::Remote::Mock::RemoteConnection;
 
-my ($host, $port) = Test::Selenium::Remote::Driver->server_is_running;
-unless ($host and $port) {
-    plan skip_all => "No Webdriver server found!";
-    exit 0;
+use FindBin;
+use lib $FindBin::Bin . '/lib';
+use TestHarness;
+
+my $harness = TestHarness->new(
+    this_file => $FindBin::Script
+);
+my %selenium_args = %{ $harness->base_caps };
+unless ($harness->mocks_exist_for_platform) {
+    plan skip_all => "Mocking of tests is not been enabled for this platform";
 }
 
 # Try to find
 my $t = Test::Selenium::Remote::Driver->new(
-    remote_server_addr => $host, port => $port,
+    %selenium_args
 );
 $t->get_ok('http://www.google.com');
 $t->title_like(qr/Google/);

+ 24 - 118
t/Test-Selenium-Remote-Driver.t

@@ -1,125 +1,31 @@
 #!/usr/bin/env perl
-use Test::Tester;
 use Test::More;
-use Test::MockObject;
-use Test::MockObject::Extends;
+use Test::Exception;
 use Test::Selenium::Remote::Driver;
 use Selenium::Remote::WebElement;
-use Carp;
-
-my $successful_driver = Test::Selenium::Remote::Driver->new( testing => 1 );
-$successful_driver = Test::MockObject::Extends->new($successful_driver);
-
-my $element = Test::Selenium::Remote::WebElement->new(
-    id     => '1342835311100',
-    parent => $successful_driver,
+use Selenium::Remote::Mock::Commands;
+use Selenium::Remote::Mock::RemoteConnection;
+
+my $spec = {
+    findElement => sub {
+        my (undef,$searched_item) = @_;
+        return { status => 'OK', return => { ELEMENT => '123456' } }
+          if ( $searched_item->{value} eq 'q' );
+        return { status => 'NOK', return => 0, error => 'element not found' };
+    },
+    getPageSource => sub { return 'this output matches regex'},
+};
+my $mock_commands = Selenium::Remote::Mock::Commands->new;
+
+my $successful_driver =
+  Test::Selenium::Remote::Driver->new(
+    remote_conn => Selenium::Remote::Mock::RemoteConnection->new( spec => $spec, mock_cmds => $mock_commands ),
+    commands => $mock_commands,
 );
-
-
-# find_element_ok
-{
-    $successful_driver->mock( 'find_element', sub {$element} );
-    check_tests(
-        sub {
-            my $rc = $successful_driver->find_element_ok( 'q',
-                'find_element_ok works' );
-            is( $rc, 1, 'returns true' );
-        },
-        [   {   ok   => 1,
-                name => "find_element_ok works",
-                diag => "",
-            },
-            {   ok   => 1,
-                name => "returns true",
-                diag => "",
-            },
-        ]
-    );
-
-    $successful_driver->mock( 'find_element', sub {0} );
-    check_tests(
-        sub {
-            my $rc = $successful_driver->find_element_ok( 'q',
-                'find_element_ok works, falsey test' );
-            is( $rc, 0, 'returns false' );
-        },
-        [   {   ok   => 0,
-                name => "find_element_ok works, falsey test",
-                diag => "",
-            },
-            {   ok   => 1,
-                name => "returns false",
-                diag => "",
-            },
-        ]
-    );
-}
-
-# find_no_element_ok
-{
-    $successful_driver->mock( 'find_element', sub { die $_[1] } );
-    check_tests(
-        sub {
-            my $rc = $successful_driver->find_no_element_ok( 'BOOM',
-                'find_no_element_ok works, expecting to find nothing.' );
-            is( $rc, 1, 'returns true' );
-        },
-        [   {   ok   => 1,
-                name => "find_no_element_ok works, expecting to find nothing.",
-                diag => "",
-            },
-            {   ok   => 1,
-                name => "returns true",
-                diag => "",
-            },
-        ]
-    );
-
-    $successful_driver->mock( 'find_element', sub {$element} );
-    check_tests(
-        sub {
-            my $rc =
-              $successful_driver->find_no_element_ok( 'q',
-                'find_no_element_ok works, expecting a false value if a element exists'
-              );
-            is( $rc, 0, 'returns false' );
-        },
-        [   {   ok => 0,
-                name =>
-                  "find_no_element_ok works, expecting a false value if a element exists",
-                diag => "",
-            },
-            {   ok   => 1,
-                name => "returns false",
-                diag => "",
-            },
-        ]
-    );
-
-
-}
-
-# content_like
-{
-    $successful_driver->mock( 'get_page_source', sub { 'this output matches regex' } );
-    check_tests(
-        sub {
-            my $rc = $successful_driver->content_like( qr/matches/,
-                'content_like works' );
-            is( $rc, 1, 'returns true' );
-        },
-        [   {   ok   => 1,
-                name => "content_like works",
-                diag => "",
-            },
-            {   ok   => 1,
-                name => "returns true",
-                diag => "",
-            },
-        ]
-    );
-
-}
-
+$successful_driver->find_element_ok('q','find_element_ok works');
+dies_ok { $successful_driver->find_element_ok('notq') } 'find_element_ok dies if element not found';
+$successful_driver->find_no_element_ok('notq','find_no_element_ok works');
+$successful_driver->content_like( qr/matches/, 'content_like works');
+$successful_driver->content_unlike( qr/nomatch/, 'content_unlike works');
 
 done_testing();

+ 45 - 272
t/Test-Selenium-Remote-WebElement.t

@@ -1,281 +1,55 @@
-
-use Test::Tester;
+#!perl
 use Test::More;
-use Test::MockObject::Extends;
-
+use Selenium::Remote::Mock::Commands;
+use Selenium::Remote::Mock::RemoteConnection;
+use Test::Selenium::Remote::Driver;
 use Test::Selenium::Remote::WebElement;
 
 # Start off by faking a bunch of Selenium::Remote::WebElement calls succeeding
-my $successful_element = Test::Selenium::Remote::WebElement->new;
-$successful_element = Test::MockObject::Extends->new($successful_element);
-
-$successful_element->set_true(
-    qw/
-      clear
-      click
-      submit
-      is_selected
-      is_enabled
-      is_displayed
-      send_keys
-      /
-);
-
-$successful_element->mock( 'get_tag_name', sub {'iframe'} );
-$successful_element->mock( 'get_value',    sub {'my_value'} );
-$successful_element->mock( 'get_text',     sub {"my_text\nis fantastic"} );
-
-# Given input 'foo' to 'get_attribute', return 'my_foo';
-$successful_element->mock( 'get_attribute', sub { 'my_' . $_[1] } );
-
-check_test(
-  sub { $successful_element->clear_ok },
-  {
-    ok => 1,
-    name => "clear",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->clear_ok('test_name') },
-  {
-    ok => 1,
-    name => "test_name",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->click_ok },
-  {
-    ok => 1,
-    name => "click",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->submit_ok },
-  {
-    ok => 1,
-    name => "submit",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->is_selected_ok },
-  {
-    ok => 1,
-    name => "is_selected",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->is_enabled_ok },
-  {
-    ok => 1,
-    name => "is_enabled",
-    diag => "",
-  }
-);
-
-check_test(
-  sub { $successful_element->is_displayed_ok },
-  {
-    ok => 1,
-    name => "is_displayed",
-    diag => "",
-  }
-);
+my $mock_commands = Selenium::Remote::Mock::Commands->new;
+my $spec = { };
 
-check_test(
-  sub { $successful_element->send_keys_ok('Hello World', 'I sent keys') },
-  {
-    ok => 1,
-    name => "I sent keys",
-    diag => "",
-  }
-);
-
-# tag_name_*
-{
-    check_test(
-        sub {
-            $successful_element->tag_name_is( 'iframe', 'Got an iframe tag?' );
-        },
-        {   ok   => 1,
-            name => "Got an iframe tag?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub { $successful_element->tag_name_isnt( 'BOOM', 'Not BOOM.' ) },
-        {   ok   => 1,
-            name => "Not BOOM.",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->tag_name_like( qr/frame/,
-                'Matches iframe tag?' );
-        },
-        {   ok   => 1,
-            name => "Matches iframe tag?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->tag_name_unlike( qr/BOOM/,
-                "tag_name doesn't match BOOM" );
-        },
-        {   ok   => 1,
-            name => "tag_name doesn't match BOOM",
-            diag => "",
-        }
-    );
-}
-
-# value_*
-{
-    check_test(
-        sub {
-            $successful_element->value_is( 'my_value',
-                'Got an my_value value?' );
-        },
-        {   ok   => 1,
-            name => "Got an my_value value?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub { $successful_element->value_isnt( 'BOOM', 'Not BOOM.' ) },
-        {   ok   => 1,
-            name => "Not BOOM.",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->value_like( qr/val/,
-                'Matches my_value value?' );
-        },
-        {   ok   => 1,
-            name => "Matches my_value value?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->value_unlike( qr/BOOM/,
-                "value doesn't match BOOM" );
-        },
-        {   ok   => 1,
-            name => "value doesn't match BOOM",
-            diag => "",
-        }
-    );
+foreach my $k (
+    qw/clearElement clickElement submitElement sendKeysToElement isElementSelected isElementEnabled isElementDisplayed/
+  ) {
+      $spec->{$k} = sub { return { status => 'OK', return => 1 }};
 }
 
-# text_*
-{
-    check_test(
-        sub {
-            $successful_element->text_is( "my_text\nis fantastic",
-                'Got an my_text value?' );
-        },
-        {   ok   => 1,
-            name => "Got an my_text value?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub { $successful_element->text_isnt( 'BOOM', 'Not BOOM.' ) },
-        {   ok   => 1,
-            name => "Not BOOM.",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->text_like( qr/tex/,
-                'Matches my_text value?' );
-        },
-        {   ok   => 1,
-            name => "Matches my_text value?",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->text_unlike( qr/BOOM/,
-                "text doesn't match BOOM" );
-        },
-        {   ok   => 1,
-            name => "text doesn't match BOOM",
-            diag => "",
-        }
-    );
-
-}
-{ 
-    check_test(
-        sub {
-            $successful_element->attribute_is( 'foo', 'my_foo',
-                'attribute_is matched' );
-        },
-        {   ok   => 1,
-            name => "attribute_is matched",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->attribute_isnt( 'foo', 'not_foo',
-                'attribute_is not_foo' );
-        },
-        {   ok   => 1,
-            name => "attribute_is not_foo",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->attribute_like( 'foo',qr/foo/,
-                'Matches my_attribute' );
-        },
-        {   ok   => 1,
-            name => "Matches my_attribute",
-            diag => "",
-        }
-    );
-
-    check_test(
-        sub {
-            $successful_element->attribute_unlike( 'bar',qr/foo/,
-                "Attribute does not match foo" );
-        },
-        {   ok   => 1,
-            name => "Attribute does not match foo",
-            diag => "",
-        }
-    );
-}
+$spec->{getElementTagName} = sub { return { status => 'OK', return => 'iframe' }};
+$spec->{getElementValue} = sub { return { status => 'OK', return => 'my_value' }};
+$spec->{getElementText} = sub { return { status => 'OK', return => "my_text\nis fantastic" }};
+$spec->{getElementAttribute}  = sub { my @args = @_; my $name = $args[0]->{name};  return { status => 'OK', return => "my_$name" }};
+
+my $driver =
+  Test::Selenium::Remote::Driver->new(
+    remote_conn => Selenium::Remote::Mock::RemoteConnection->new( spec => $spec, mock_cmds => $mock_commands ),
+    commands => $mock_commands,
+);
+
+
+my $successful_element = Test::Selenium::Remote::WebElement->new(driver => $driver);
+$successful_element->clear_ok;
+$successful_element->click_ok;
+$successful_element->submit_ok;
+$successful_element->is_selected_ok;
+$successful_element->is_enabled_ok;
+$successful_element->is_displayed_ok;
+$successful_element->send_keys_ok('Hello World');
+$successful_element->tag_name_is( 'iframe', 'we got an iframe tag' );
+$successful_element->tag_name_isnt( 'BOOM', 'tag name is not boom' );
+$successful_element->tag_name_unlike( qr/BOOM/, "tag_name doesn't match BOOM" );
+$successful_element->value_is( 'my_value', 'Got an my_value value?' );
+$successful_element->value_isnt( 'BOOM', 'Not BOOM.' );
+$successful_element->value_like( qr/val/, 'Matches my_value value?' );
+$successful_element->value_unlike( qr/BOOM/, "value doesn't match BOOM" );
+$successful_element->text_is( "my_text\nis fantastic", 'Got an my_text value?' );
+$successful_element->text_isnt( 'BOOM', 'Not BOOM.' );
+$successful_element->text_like( qr/tex/, 'Matches my_text value?' );
+$successful_element->text_unlike( qr/BOOM/, "text doesn't match BOOM" );
+$successful_element->attribute_is( 'foo', 'my_foo', 'attribute_is matched' );
+$successful_element->attribute_isnt( 'foo', 'not_foo', 'attribute_is not_foo' );
+$successful_element->attribute_like( 'foo',qr/foo/, 'Matches my_attribute' );
+$successful_element->attribute_unlike( 'bar',qr/foo/, "Attribute does not match foo" );
 
 
 
@@ -284,5 +58,4 @@ check_test(
 #  css_attribute_like($attr_name,$match_re,$test_name);
 #  css_attribute_unlike($attr_name,$match_re,$test_name);
 
-
 done_testing();

+ 32 - 36
t/bin/record.pl

@@ -2,53 +2,44 @@
 
 use strict;
 use warnings;
-use Cwd qw/abs_path/;
-
-my $this_file = abs_path(__FILE__);
-my $srd_folder = $this_file;
-$srd_folder =~ s/t\/bin\/record\.pl//;
 
-resetEnv();
-startServer();
-
-print 'Cleaning...and building...
-';
-print `cd $srd_folder && dzil build`;
+use Cwd qw/abs_path/;
+use FindBin;
+# We can only dzil from the root of the repository.
+my $this_folder = $FindBin::Bin . '/../../'; # t/bin/../../
+my $repo_root = abs_path($this_folder) . '/';
+
+reset_env();
+start_server();
+
+my $built_lib = glob('Selenium-Remote-Driver-*/lib');
+if (not defined $built_lib) {
+    print ' Building a dist.';
+    print `cd $repo_root && dzil build`;
+}
+# If built_lib wasn't around in the first place, we'll have to glob
+# for it again.
+$built_lib = $repo_root . ($built_lib || glob('Selenium-Remote-Driver-*/lib'));
 
 if ($^O eq 'linux') {
     print "Headless and need a webdriver server started? Try\n\n\tDISPLAY=:1 xvfb-run --auto-servernum java -jar /usr/lib/node_modules/protractor/selenium/selenium-server-standalone-2.42.2.jar\n\n";
 }
 
-my @files = map {
-    $srd_folder . $_
-} (
-    't/01-driver.t',
-    't/02-webelement.t',
-    't/Firefox-Profile.t'
-);
-
-my $srdLib = glob($srd_folder . 'Selenium-Remote-Driver*/lib');
-my $tLib = glob($srd_folder . 'Selenium-Remote-Driver*');
-my $executeTests = join( ' && ', map {
-    'perl -I' . $srdLib
-      . ' -I' . $tLib
-      . ' ' . $_
-  } @files);
-
 my $export = $^O eq 'MSWin32' ? 'set' : 'export';
-print `$export WD_MOCKING_RECORD=1 && $executeTests`;
-resetEnv();
+my $wait = $^O eq 'MSWin32' ? 'START /WAIT' : '';
+print `$export WD_MOCKING_RECORD=1 && cd $repo_root && prove -I$built_lib -rv t/`;
+reset_env();
 
-sub startServer {
+sub start_server {
     if ($^O eq 'MSWin32') {
-        system('start "TEMP_HTTP_SERVER" /MIN perl ' . $srd_folder . 't/http-server.pl');
+        system('start "TEMP_HTTP_SERVER" /MIN perl ' . $repo_root . 't/http-server.pl');
     }
     else {
-        system('perl ' . $srd_folder . 't/http-server.pl > /dev/null &');
+        system('perl ' . $repo_root . 't/http-server.pl > /dev/null &');
     }
 }
 
-sub killServer {
+sub kill_server {
     if ($^O eq 'MSWin32') {
         system("taskkill /FI \"WINDOWTITLE eq TEMP_HTTP_SERVER\"");
     }
@@ -57,7 +48,12 @@ sub killServer {
     }
 }
 
-sub resetEnv {
-    `cd $srd_folder && dzil clean`;
-    killServer();
+
+sub reset_env {
+    if (@ARGV && $ARGV[0] eq 'reset') {
+        print 'Cleaning. ';
+        `cd $repo_root && dzil clean`;
+    }
+    print 'Taking out any existing servers. ';
+    kill_server();
 }

+ 0 - 114
t/lib/MockSeleniumWebDriver.pm

@@ -1,114 +0,0 @@
-package t::lib::MockSeleniumWebDriver;
-use strict;
-use warnings;
-
-use LWP::Protocol::PSGI 0.04;
-use JSON;
-
-our $MockSeleniumWebDriverObj;
-
-sub save_recording {
-  my ($self) = @_;
-  open(my $fh, '>', $self->{file});
-  print $fh encode_json($self->{req_resp});
-  close $fh;
-}
-
-sub load_recording {
-  my ($self) = @_;
-  open(my $fh, '<', $self->{file});
-  my @lines = <$fh>;
-  $self->{req_resp} = decode_json(join('', @lines));
-  close $fh;
-}
-
-sub register {
-  my $record = shift;
-  $record = 0 if !defined $record;
-  my $file = shift;
-  my $self = {record => $record,
-              req_index => 0,
-              file => $file};
-  bless $self,__PACKAGE__;
-  if ($record) {
-    require LWP::UserAgent;
-    require HTTP::Headers;
-    require HTTP::Request;
-    $self->{req_resp} = [];
-  } else {
-    $self->load_recording;
-  }
-  LWP::Protocol::PSGI->register(\&t::lib::MockSeleniumWebDriver::psgi_app);
-  $MockSeleniumWebDriverObj = $self;
-}
-
-sub psgi_app {
-  my $env = shift;
-  my $self = $MockSeleniumWebDriverObj;
-  my $uri =
-      $env->{'psgi.url_scheme'} . '://'
-    . $env->{SERVER_NAME} . ':'
-    . $env->{SERVER_PORT}
-    . $env->{REQUEST_URI};
-  my $content = '';
-  my $s;
-  while (read($env->{'psgi.input'}, $s, 100)) {
-    $content .= $s;
-  }
-  my $req_index = \$self->{req_index};
-  if (!$self->{record}) {
-    my $expected = $self->{req_resp}->[$$req_index]->{request}->{content};
-    $expected = $expected eq "" ? $expected : decode_json($expected);
-    my $actual = $content eq "" ? $content : decode_json($content);
-
-    if (  $self->{req_resp}->[$$req_index]->{request}->{verb} eq $env->{REQUEST_METHOD}
-      and $self->{req_resp}->[$$req_index]->{request}->{uri} eq $uri
-      and (   $self->{req_resp}->[$$req_index]->{request}->{content} eq $content
-           or deeply_equal($expected, $actual)))  {
-      return $self->{req_resp}->[$$req_index++]->{response};
-    } else {
-      die
-"Request information has changed since recording... do you need to record webdriver responses again?";
-    }
-  } else {
-    my $ua = LWP::UserAgent->new;
-    my $h  = HTTP::Headers->new;
-    $h->header('Content-Type' => $env->{CONTENT_TYPE});
-    $h->header('Accept'       => $env->{HTTP_ACCEPT});
-    my $req = HTTP::Request->new($env->{REQUEST_METHOD}, $uri, $h, $content);
-    LWP::Protocol::PSGI->unregister;
-    my $res = $ua->request($req);
-    LWP::Protocol::PSGI->register(\&psgi_app);
-    my $head    = $res->{_headers}->clone;
-    my $newhead = [];
-
-    for my $key (keys %{$head}) {
-      push @{$newhead}, $key;
-      push @{$newhead}, $head->{$key};
-    }
-    my $response = [$res->code, $newhead, [$res->content]];
-    my $request = {
-      verb    => $env->{REQUEST_METHOD},
-      uri     => $uri,
-      content => $content
-    };
-    push @{$self->{req_resp}}, {request => $request, response => $response};
-    return $response;
-  }
-}
-
-sub deeply_equal {
-  my ( $a_ref, $b_ref ) = @_;
-
-  local $Storable::canonical = 1;
-  return Storable::freeze( $a_ref ) eq Storable::freeze( $b_ref );
-}
-
-sub DESTROY {
-  my ($self) = @_;
-  if($self->{record}) {
-    $self->save_recording;
-  }
-}
-
-1;

+ 130 - 0
t/lib/TestHarness.pm

@@ -0,0 +1,130 @@
+package TestHarness;
+
+# ABSTRACT: Take care of set up for recording/replaying mocks
+use Moo;
+use FindBin;
+use Selenium::Remote::Mock::RemoteConnection;
+
+=head1 SYNOPSIS
+
+    my $harness = TestHarness->new(
+        this_file => $FindBin::Script
+    );
+    my %selenium_args = %{ $harness->base_caps };
+    unless ($harness->mocks_exist_for_platform) {
+        plan skip_all => "Mocking of tests is not been enabled for this platform";
+    }
+
+=attr this_file
+
+Required. Pass in the short name of the test file in use so we can
+figure out where the corresponding recording belongs. For a test file
+named C<t/01-driver.t>, we'd expect this argument to be
+C<01-driver.t>.
+
+=cut
+
+has calling_file => (
+    is => 'ro',
+    init_arg => 'this_file',
+    required => 1
+);
+
+has record => (
+    is => 'ro',
+    init_args => undef,
+    default => sub {
+        if (defined $ENV{WD_MOCKING_RECORD}
+              && $ENV{WD_MOCKING_RECORD} == 1) {
+            return 1;
+        }
+        else {
+            return 0;
+        }
+    }
+);
+
+has os => (
+    is => 'ro',
+    init_args => undef,
+    default => sub {
+        my $os  = $^O;
+        if ($os =~ m/(aix|freebsd|openbsd|sunos|solaris)/) {
+            $os = 'linux';
+        }
+
+        return $os;
+    }
+);
+
+has base_caps => (
+    is => 'rw',
+    lazy => 1,
+    default => sub {
+        my ($self) = @_;
+        my $args = {
+            browser_name => 'firefox',
+            remote_conn => $self->mock_remote_conn
+        };
+
+        return $args;
+    }
+);
+
+has mock_remote_conn => (
+    is => 'ro',
+    lazy => 1,
+    builder => sub {
+        my ($self) = @_;
+        if ($self->record) {
+            return Selenium::Remote::Mock::RemoteConnection->new(
+                record => 1
+            );
+        }
+        else {
+            return Selenium::Remote::Mock::RemoteConnection->new(
+                replay      => 1,
+                replay_file => $self->mock_file
+            );
+        }
+    }
+);
+
+has mock_file => (
+    is => 'ro',
+    lazy => 1,
+    builder => sub {
+        my ($self) = @_;
+
+        # Since FindBin uses a Begin block, and we're using it in the
+        # tests themselves, $FindBin::Bin will already be initialized
+        # 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);
+        $test_name =~ s/\.t$//;
+
+        return $mock_folder . $test_name . '-mock-' . $self->os . '.json';
+    }
+);
+
+sub mocks_exist_for_platform {
+    my ($self) = @_;
+    if ($self->record) {
+        return 1;
+    }
+    else {
+        # When we're replaying a test, we need recordings to be able
+        # to do anything
+        return -e $self->mock_file;
+    }
+}
+
+sub DEMOLISH {
+    my ($self) = @_;
+    if ($self->record) {
+        $self->mock_remote_conn->dump_session_store($self->mock_file);
+    }
+}
+
+1;

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/01-driver-mock-MSWin32.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/01-driver-mock-darwin.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/01-driver-mock-linux.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/02-webelement-mock-MSWin32.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/02-webelement-mock-darwin.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/02-webelement-mock-linux.json


+ 41 - 0
t/mock-recordings/10-switch-to-window-mock-MSWin32.json

@@ -0,0 +1,41 @@
+{
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":true,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:47 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 579\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:49 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":{\"platform\":\"WINDOWS\",\"javascriptEnabled\":true,\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"version\":\"27.0.1\",\"databaseEnabled\":true,\"cssSelectorsEnabled\":true,\"handlesAlerts\":true,\"browserConnectionEnabled\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":16713347}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/window {\"name\":\"{f4196e1b-e1f2-4daa-90f1-33e517a3652c}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":19291211}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/window {\"name\":\"{cc6e2bcc-83ea-4687-bb07-8aaf04a3437f}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 156\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":2891677}\n"
+   ],
+   "GET session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/window_handles {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 195\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":[\"{f4196e1b-e1f2-4daa-90f1-33e517a3652c}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":22491606}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 234\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":[\"{f4196e1b-e1f2-4daa-90f1-33e517a3652c}\",\"{cc6e2bcc-83ea-4687-bb07-8aaf04a3437f}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":882921}\n"
+   ],
+   "GET session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":26584453}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":31571419}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 208\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":20583685}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":31339085}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 208\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":16320796}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 197\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":524315}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/url {\"url\":\"http://perl.org/\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:49 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":12952445}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/window {\"name\":\"perlorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":27181780}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/execute {\"args\":[],\"script\":\"$(window.open('http://cpan.org/', 'cpanorg'))\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":15344435}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/window {\"name\":\"cpanorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":26896919}\n"
+   ],
+   "DELETE session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38 {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:51 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 156\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:51 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":4029956}\n"
+   ],
+   "POST session/32a11855-a9b5-4d71-8eb0-7988cbd4cc38/execute {\"args\":[],\"script\":\"return window.name = 'perlorg';\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:21:50 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 162\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:21:50 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"32a11855-a9b5-4d71-8eb0-7988cbd4cc38\",\"status\":0,\"value\":\"perlorg\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":31238286}\n"
+   ]
+}

+ 41 - 0
t/mock-recordings/10-switch-to-window-mock-darwin.json

@@ -0,0 +1,41 @@
+{
+   "GET session/82f30735-7a7d-4910-84f2-120bef012fc8/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 201\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1550993760}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 201\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1604018747}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 210\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1668181854}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 200\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":879188863}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 209\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":152898470}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 200\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":937148019}\n"
+   ],
+   "DELETE session/82f30735-7a7d-4910-84f2-120bef012fc8 {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1523042119}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/url {\"url\":\"http://perl.org/\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:30 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 158\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":123803258}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/execute {\"args\":[],\"script\":\"$(window.open('http://cpan.org/', 'cpanorg'))\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1480787563}\n"
+   ],
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":true,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:28 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 544\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:30 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":{\"platform\":\"MAC\",\"acceptSslCerts\":true,\"javascriptEnabled\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"version\":\"32.0.3\",\"cssSelectorsEnabled\":true,\"databaseEnabled\":true,\"handlesAlerts\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":766936722}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/window {\"name\":\"perlorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1190294908}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/window {\"name\":\"cpanorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 156\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1239918}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/execute {\"args\":[],\"script\":\"return window.name = 'perlorg';\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 164\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":\"perlorg\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1366758756}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/window {\"name\":\"{15417340-a084-6e4f-89f0-d994eb49b06c}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1145963262}\n"
+   ],
+   "POST session/82f30735-7a7d-4910-84f2-120bef012fc8/window {\"name\":\"{6f536b00-1785-e842-9e7e-823560277bfd}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:33 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 158\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:33 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":635067349}\n"
+   ],
+   "GET session/82f30735-7a7d-4910-84f2-120bef012fc8/window_handles {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 197\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":[\"{6f536b00-1785-e842-9e7e-823560277bfd}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1319097904}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:32 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 238\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:32 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"82f30735-7a7d-4910-84f2-120bef012fc8\",\"value\":[\"{6f536b00-1785-e842-9e7e-823560277bfd}\",\"{15417340-a084-6e4f-89f0-d994eb49b06c}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1499207751}\n"
+   ]
+}

+ 41 - 0
t/mock-recordings/10-switch-to-window-mock-linux.json

@@ -0,0 +1,41 @@
+{
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/window {\"name\":\"{05f41b66-fc1d-4df0-a01a-4c5dc67c49d6}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":32240074}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/window {\"name\":\"cpanorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":23597132}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/execute {\"args\":[],\"script\":\"$(window.open('http://cpan.org/', 'cpanorg'))\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":12631714}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/window {\"name\":\"perlorg\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":19019092}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/execute {\"args\":[],\"script\":\"return window.name = 'perlorg';\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 162\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"perlorg\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":25177851}\n"
+   ],
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":true,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:20 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 577\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:21 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":{\"platform\":\"LINUX\",\"javascriptEnabled\":true,\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"version\":\"27.0.1\",\"databaseEnabled\":true,\"cssSelectorsEnabled\":true,\"handlesAlerts\":true,\"browserConnectionEnabled\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":15619754}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/url {\"url\":\"http://perl.org/\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:21 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":17139390}\n"
+   ],
+   "GET session/b386a2ca-2306-4709-be42-d09a92f160f3/window_handles {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 195\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":[\"{22e3e38b-f78e-45a5-a1bd-bc31215d40f7}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":17616123}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 235\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":[\"{22e3e38b-f78e-45a5-a1bd-bc31215d40f7}\",\"{05f41b66-fc1d-4df0-a01a-4c5dc67c49d6}\"],\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":6291029}\n"
+   ],
+   "POST session/b386a2ca-2306-4709-be42-d09a92f160f3/window {\"name\":\"{22e3e38b-f78e-45a5-a1bd-bc31215d40f7}\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":17047244}\n"
+   ],
+   "DELETE session/b386a2ca-2306-4709-be42-d09a92f160f3 {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":33393986}\n"
+   ],
+   "GET session/b386a2ca-2306-4709-be42-d09a92f160f3/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":19516563}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:23 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":12399603}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:23 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 208\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":28413730}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":30812635}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 208\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Comprehensive Perl Archive Network - www.cpan.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":10700066}\n",
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:24 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 199\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:24 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"b386a2ca-2306-4709-be42-d09a92f160f3\",\"value\":\"The Perl Programming Language - www.perl.org\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":28599715}\n"
+   ]
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/firefox-profile-mock-MSWin32.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/firefox-profile-mock-darwin.json


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
t/mock-recordings/firefox-profile-mock-linux.json


+ 20 - 0
t/mock-recordings/test-selenium-remote-driver-google-mock-MSWin32.json

@@ -0,0 +1,20 @@
+{
+   "POST session/e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc/element {\"using\":\"xpath\",\"value\":\"//body\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:06 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 168\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:06 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":{\"ELEMENT\":\"0\"},\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":29461354}\n"
+   ],
+   "DELETE session/e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:06 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:06 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":27277408}\n"
+   ],
+   "GET session/e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:06 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 161\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:06 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":\"Google\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":11985412}\n"
+   ],
+   "POST session/e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc/url {\"url\":\"http://www.google.com\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:05 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:06 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":26389886}\n"
+   ],
+   "GET session/e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc/element/0/text {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:06 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 269\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:06 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":\"+You\\nGmail\\nImages\\nSign in\\nGoogle SearchI'm Feeling Lucky\\nPrivacy & Terms Settings\\nAdvertising Business About\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":15815733}\n"
+   ],
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":false,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Wed, 29 Oct 2014 04:22:03 GMT\nServer: Jetty/5.1.x (Windows 7/6.1 x86 java/1.7.0_51\nContent-Length: 579\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Wed, 29 Oct 2014 04:22:05 GMT\nClient-Peer: ::1:4444\nClient-Response-Num: 1\n\n{\"sessionId\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"status\":0,\"value\":{\"platform\":\"WINDOWS\",\"javascriptEnabled\":true,\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"e3bc154c-c91e-4c7d-970e-f35f5cf9e8dc\",\"version\":\"27.0.1\",\"databaseEnabled\":true,\"cssSelectorsEnabled\":true,\"handlesAlerts\":true,\"browserConnectionEnabled\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":29262222}\n"
+   ]
+}

+ 20 - 0
t/mock-recordings/test-selenium-remote-driver-google-mock-darwin.json

@@ -0,0 +1,20 @@
+{
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":false,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:36 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 545\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:38 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":{\"platform\":\"MAC\",\"acceptSslCerts\":true,\"javascriptEnabled\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"version\":\"32.0.3\",\"cssSelectorsEnabled\":true,\"databaseEnabled\":true,\"handlesAlerts\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1464603432}\n"
+   ],
+   "GET session/857403b3-67e7-4a4c-95a1-961a9cb6e8e7/element/0/text {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:39 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 270\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:39 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":\"+You\\nGmail\\nImages\\nSign in\\nGoogle SearchI'm Feeling Lucky\\nPrivacy & Terms Settings\\nAdvertising Business About\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":405977978}\n"
+   ],
+   "POST session/857403b3-67e7-4a4c-95a1-961a9cb6e8e7/url {\"url\":\"http://www.google.com\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:38 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:39 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":2044769903}\n"
+   ],
+   "POST session/857403b3-67e7-4a4c-95a1-961a9cb6e8e7/element {\"using\":\"xpath\",\"value\":\"//body\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:39 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 170\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:39 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":{\"ELEMENT\":\"0\"},\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1640781879}\n"
+   ],
+   "DELETE session/857403b3-67e7-4a4c-95a1-961a9cb6e8e7 {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:39 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 159\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:39 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":1567670287}\n"
+   ],
+   "GET session/857403b3-67e7-4a4c-95a1-961a9cb6e8e7/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:30:39 GMT\nServer: Jetty/5.1.x (Mac OS X/10.9.5 x86_64 java/1.7.0_67\nContent-Length: 162\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:30:39 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"857403b3-67e7-4a4c-95a1-961a9cb6e8e7\",\"value\":\"Google\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":649262877}\n"
+   ]
+}

+ 20 - 0
t/mock-recordings/test-selenium-remote-driver-google-mock-linux.json

@@ -0,0 +1,20 @@
+{
+   "POST session {\"desiredCapabilities\":{\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"javascriptEnabled\":false,\"platform\":\"ANY\",\"version\":null}}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:25 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 576\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:26 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":{\"platform\":\"LINUX\",\"javascriptEnabled\":true,\"acceptSslCerts\":true,\"browserName\":\"firefox\",\"rotatable\":false,\"locationContextEnabled\":true,\"webdriver.remote.sessionid\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"version\":\"27.0.1\",\"databaseEnabled\":true,\"cssSelectorsEnabled\":true,\"handlesAlerts\":true,\"browserConnectionEnabled\":true,\"webStorageEnabled\":true,\"nativeEvents\":false,\"applicationCacheEnabled\":true,\"takesScreenshot\":true},\"state\":null,\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":3615585}\n"
+   ],
+   "DELETE session/7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:28 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:28 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":24084578}\n"
+   ],
+   "POST session/7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c/url {\"url\":\"http://www.google.com\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:26 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 157\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:28 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":null,\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":17356447}\n"
+   ],
+   "GET session/7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c/title {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:28 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 161\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:28 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":\"Google\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":20162943}\n"
+   ],
+   "POST session/7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c/element {\"using\":\"xpath\",\"value\":\"//body\"}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:28 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 168\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:28 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":{\"ELEMENT\":\"0\"},\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":32498738}\n"
+   ],
+   "GET session/7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c/element/0/text {}" : [
+      "HTTP/1.1 200 OK\nCache-Control: no-cache\nCache-Control: no-cache\nConnection: close\nDate: Sat, 01 Nov 2014 01:35:28 GMT\nServer: Jetty/5.1.x (Linux/3.2.0-23-generic-pae i386 java/1.7.0_51\nContent-Length: 269\nContent-Type: application/json; charset=utf-8\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nClient-Date: Sat, 01 Nov 2014 01:35:28 GMT\nClient-Peer: 127.0.0.1:4444\nClient-Response-Num: 1\n\n{\"status\":0,\"sessionId\":\"7c2bc72a-e7a9-4ba5-ab2e-c40396cccf2c\",\"value\":\"+You\\nGmail\\nImages\\nSign in\\nGoogle SearchI'm Feeling Lucky\\nPrivacy & Terms Settings\\nAdvertising Business About\",\"state\":\"success\",\"class\":\"org.openqa.selenium.remote.Response\",\"hCode\":21288946}\n"
+   ]
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff