|
|
@@ -6,6 +6,7 @@ use Moo;
|
|
|
use JSON;
|
|
|
use Carp;
|
|
|
use Try::Tiny;
|
|
|
+use HTTP::Response;
|
|
|
|
|
|
extends 'Selenium::Remote::RemoteConnection';
|
|
|
|
|
|
@@ -32,8 +33,16 @@ has 'record' => (
|
|
|
default => sub { 0 }
|
|
|
);
|
|
|
|
|
|
+has 'replay' => (
|
|
|
+ is => 'ro',
|
|
|
+);
|
|
|
+
|
|
|
+has 'replay_file' => (
|
|
|
+ is => 'ro',
|
|
|
+);
|
|
|
+
|
|
|
has 'session_store' => (
|
|
|
- is => 'ro',
|
|
|
+ is => 'rw',
|
|
|
default => sub { {} }
|
|
|
);
|
|
|
|
|
|
@@ -44,14 +53,38 @@ has 'session_id' => (
|
|
|
|
|
|
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);
|
|
|
+
|
|
|
+ my $s_id = $self->fake_session_id;
|
|
|
+ $self->session_store->{$s_id} = $decoded_json;
|
|
|
+}
|
|
|
+
|
|
|
sub dump_session_store {
|
|
|
my $self = shift;
|
|
|
my ($file,$session_id) = @_;
|
|
|
@@ -61,23 +94,28 @@ sub dump_session_store {
|
|
|
foreach my $path (keys %{$session_store->{$session_id}}) {
|
|
|
$dump->{$path} = $session_store->{$session_id}->{$path};
|
|
|
}
|
|
|
- my $json = JSON->new;
|
|
|
- $json->allow_blessed;
|
|
|
+ my $json = JSON->new;
|
|
|
+ $json->allow_blessed;
|
|
|
my $json_session = $json->allow_nonref->utf8->encode($dump);
|
|
|
print $fh $json_session;
|
|
|
close ($fh);
|
|
|
}
|
|
|
|
|
|
-sub request {
|
|
|
+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 ( $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) && ( $params ne '' ) ) {
|
|
|
+ $content = $json->allow_nonref->utf8->encode($params);
|
|
|
+ }
|
|
|
my $url_params = $resource->{url_params};
|
|
|
if ( $self->record ) {
|
|
|
- my $json = JSON->new;
|
|
|
- $json->allow_blessed;
|
|
|
my $response = $self->SUPER::request( $resource, $params, 1 );
|
|
|
|
|
|
if ( ( $response->message ne 'No Content' )
|
|
|
@@ -85,41 +123,48 @@ sub request {
|
|
|
{
|
|
|
if ( $response->content_type =~ m/json/i ) {
|
|
|
my $decoded_json =
|
|
|
- $json->allow_nonref(1)->utf8(1)->decode( $response->content );
|
|
|
+ $json->allow_nonref(1)->utf8(1)
|
|
|
+ ->decode( $response->content );
|
|
|
$self->session_id( $decoded_json->{'sessionId'} )
|
|
|
unless $self->session_id;
|
|
|
}
|
|
|
}
|
|
|
- my $content = '';
|
|
|
- if (($params) && ($params ne '')) {
|
|
|
- $content = $json->allow_nonref->utf8->encode($params);
|
|
|
- }
|
|
|
- $self->session_store->{$self->session_id}->{"$method $url $content"} = $response if ($self->session_id);
|
|
|
- return $self->_process_response($response,$no_content_success);
|
|
|
+ $self->session_store->{ $self->session_id }->{"$method $url $content"}
|
|
|
+ = $response
|
|
|
+ if ( $self->session_id );
|
|
|
+ return $self->_process_response( $response, $no_content_success );
|
|
|
+ }
|
|
|
+ if ( $self->replay ) {
|
|
|
+ my $resp =
|
|
|
+ $self->session_store->{ $self->fake_session_id }
|
|
|
+ ->{"$method $url $content"} // HTTP::Response->new( '501',
|
|
|
+ "No response available from the mocking file" );
|
|
|
+ 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 $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) {
|
|
|
+ if ($no_content_success) {
|
|
|
$ret->{cmd_return} = 1;
|
|
|
}
|
|
|
- else {
|
|
|
- my $mock_return = $return_sub->($url_params,$params);
|
|
|
- if (ref($mock_return) eq 'HASH') {
|
|
|
+ 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} // ''
|
|
|
+ $ret->{cmd_error} = $mock_return->{error} // '';
|
|
|
}
|
|
|
- else {
|
|
|
+ else {
|
|
|
$ret = $mock_return;
|
|
|
}
|
|
|
}
|
|
|
- $ret->{session_id} = $self->fake_session_id if (ref($ret) eq 'HASH');
|
|
|
+ $ret->{session_id} = $self->fake_session_id if ( ref($ret) eq 'HASH' );
|
|
|
}
|
|
|
- else {
|
|
|
+ else {
|
|
|
$ret->{sessionId} = $self->fake_session_id;
|
|
|
}
|
|
|
return $ret;
|