File Coverage

blib/lib/Selenium/Remote/Mock/RemoteConnection.pm
Criterion Covered Total %
statement 80 97 82.4
branch 21 30 70.0
condition 11 15 73.3
subroutine 13 14 92.8
pod 2 5 40.0
total 127 161 78.8


line stmt bran cond sub pod time code
1             package Selenium::Remote::Mock::RemoteConnection;
2             $Selenium::Remote::Mock::RemoteConnection::VERSION = '1.48';
3             # ABSTRACT: utility class to mock the responses from Selenium server
4              
5 10     10   140611 use strict;
  10         32  
  10         301  
6 10     10   78 use warnings;
  10         26  
  10         237  
7              
8 10     10   60 use Moo;
  10         64  
  10         106  
9 10     10   4200 use JSON;
  10         10856  
  10         98  
10 10     10   1410 use Carp;
  10         25  
  10         612  
11 10     10   535 use Try::Tiny;
  10         1129  
  10         557  
12 10     10   506 use HTTP::Response;
  10         27866  
  10         389  
13 10     10   778 use Data::Dumper;
  10         7224  
  10         12279  
14              
15             extends 'Selenium::Remote::RemoteConnection';
16              
17             has 'spec' => (
18             is => 'ro',
19             default => sub { {} },
20             );
21              
22             has 'mock_cmds' => ( is => 'ro', );
23              
24             has 'fake_session_id' => (
25             is => 'lazy',
26             builder => sub {
27 8     8   583 my $id = join '',
28             map +( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' )[ rand( 10 + 26 * 2 ) ],
29             1 .. 50;
30 8         64 return $id;
31             },
32             );
33              
34             has 'record' => (
35             is => 'ro',
36             default => sub { 0 }
37             );
38              
39             has 'replay' => ( is => 'ro', );
40              
41             has 'replay_file' => ( is => 'ro', );
42              
43             has 'session_store' => (
44             is => 'rw',
45             default => sub { {} }
46             );
47              
48             has 'session_id' => (
49             is => 'rw',
50             default => sub { undef },
51             );
52              
53             has 'remote_server_addr' => (
54             is => 'lazy',
55             default => sub { 'localhost' }
56             );
57              
58              
59             sub BUILD {
60 16     16 0 136 my $self = shift;
61 16 50 66     146 croak 'Cannot define replay and record attributes at the same time'
62             if ( ( $self->replay ) && ( $self->record ) );
63 16 50 66     102 croak 'replay_file attribute needs to be defined'
64             if ( ( $self->replay ) && !( $self->replay_file ) );
65 16 50 66     113 croak 'replay attribute needs to be defined'
66             if ( !( $self->replay ) && ( $self->replay_file ) );
67 16         127 $self->port('4444');
68 16 100       219 if ( $self->replay ) {
69 8         80 $self->load_session_store( $self->replay_file );
70             }
71             }
72              
73             sub check_status {
74 18     18 1 237 return;
75             }
76              
77             sub load_session_store {
78 8     8 0 24 my $self = shift;
79 8         20 my $file = shift;
80 8 50       190 croak "'$file' is not a valid file" unless ( -f $file );
81 8 50       412 open( my $fh, '<', $file ) or croak "Opening '$file' failed";
82              
83             # here we use a fake session id since we have no way of figuring out
84             # which session is good or not
85 8         95 local $/ = undef;
86              
87 8         171 my $json = JSON->new;
88 8         66 $json->allow_blessed;
89 8         24191 my $decoded_json = $json->allow_nonref(1)->utf8(1)->decode(<$fh>);
90 8         490 close($fh);
91 8         280 $self->session_store($decoded_json);
92             }
93              
94             sub dump_session_store {
95 0     0 0 0 my $self = shift;
96 0         0 my ($file) = @_;
97 0 0       0 open( my $fh, '>', $file ) or croak "Opening '$file' failed";
98 0         0 my $session_store = $self->session_store;
99 0         0 my $dump = {};
100 0         0 foreach my $path ( keys %{$session_store} ) {
  0         0  
101 0         0 $dump->{$path} = $session_store->{$path};
102             }
103 0         0 my $json = JSON->new;
104 0         0 $json->allow_blessed;
105 0         0 my $json_session = $json->allow_nonref->utf8->pretty->encode($dump);
106 0         0 print $fh $json_session;
107 0         0 close($fh);
108             }
109              
110             sub request {
111 299     299 1 2383 my $self = shift;
112 299         598 my ( $resource, $params ) = @_;
113 299         718 my $method = $resource->{method};
114 299         521 my $url = $resource->{url};
115 299   50     762 my $no_content_success = $resource->{no_content_success} // 0;
116 299         510 my $content = '';
117 299         1317 my $json = JSON->new;
118 299         1087 $json->allow_blessed;
119              
120 299 50       741 if ($params) {
121 299         3440 $content = $json->allow_nonref->utf8->canonical(1)->encode($params);
122             }
123 299         652 my $url_params = $resource->{url_params};
124              
125 299 100       3734 print "REQ: $method, $url, $content\n" if $self->debug;
126              
127 299 50       1062 if ( $self->record ) {
128 0         0 my $response = $self->SUPER::request( $resource, $params, 1 );
129 0         0 push @{ $self->session_store->{"$method $url $content"} },
  0         0  
130             $response->as_string;
131 0         0 return $self->_process_response( $response, $no_content_success );
132             }
133 299 100       793 if ( $self->replay ) {
134 201         314 my $resp;
135 201   100     1490 my $arr_of_resps = $self->session_store->{"$method $url $content"}
136             // [];
137 201 100       520 if ( scalar(@$arr_of_resps) ) {
138 200         400 $resp = shift @$arr_of_resps;
139 200         885 $resp = HTTP::Response->parse($resp);
140             }
141             else {
142 1         15 $resp = HTTP::Response->new( '501', "Failed to find a response" );
143             }
144 201         145624 return $self->_process_response( $resp, $no_content_success );
145             }
146 98         208 my $mock_cmds = $self->mock_cmds;
147 98         228 my $spec = $self->spec;
148 98         395 my $cmd = $mock_cmds->get_method_name_from_parameters(
149             { method => $method, url => $url } );
150 98         399 my $ret = { cmd_status => 'OK', cmd_return => 1 };
151 98 100       334 if ( defined( $spec->{$cmd} ) ) {
152 88         161 my $return_sub = $spec->{$cmd};
153 88         300 my $mock_return = $return_sub->( $url_params, $params );
154 88 100       802 if ( ref($mock_return) eq 'HASH' ) {
155 59         120 $ret->{cmd_status} = $mock_return->{status};
156 59         103 $ret->{cmd_return} = $mock_return->{return};
157 59   100     211 $ret->{cmd_error} = $mock_return->{error} // '';
158             }
159             else {
160 29         60 $ret = $mock_return;
161             }
162 88 100       1261 $ret->{session_id} = $self->fake_session_id if ( ref($ret) eq 'HASH' );
163             }
164             else {
165 10         203 $ret->{sessionId} = $self->fake_session_id;
166             }
167 98         984 return $ret;
168             }
169              
170             1;
171              
172             __END__