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.49';
3             # ABSTRACT: utility class to mock the responses from Selenium server
4              
5 10     10   140496 use strict;
  10         25  
  10         299  
6 10     10   56 use warnings;
  10         31  
  10         237  
7              
8 10     10   94 use Moo;
  10         26  
  10         97  
9 10     10   4077 use JSON;
  10         10586  
  10         127  
10 10     10   1453 use Carp;
  10         29  
  10         583  
11 10     10   552 use Try::Tiny;
  10         1144  
  10         621  
12 10     10   512 use HTTP::Response;
  10         28345  
  10         329  
13 10     10   697 use Data::Dumper;
  10         6965  
  10         12334  
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   507 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 150 my $self = shift;
61 16 50 66     138 croak 'Cannot define replay and record attributes at the same time'
62             if ( ( $self->replay ) && ( $self->record ) );
63 16 50 66     110 croak 'replay_file attribute needs to be defined'
64             if ( ( $self->replay ) && !( $self->replay_file ) );
65 16 50 66     110 croak 'replay attribute needs to be defined'
66             if ( !( $self->replay ) && ( $self->replay_file ) );
67 16         123 $self->port('4444');
68 16 100       220 if ( $self->replay ) {
69 8         48 $self->load_session_store( $self->replay_file );
70             }
71             }
72              
73             sub check_status {
74 18     18 1 247 return;
75             }
76              
77             sub load_session_store {
78 8     8 0 20 my $self = shift;
79 8         26 my $file = shift;
80 8 50       193 croak "'$file' is not a valid file" unless ( -f $file );
81 8 50       389 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         65 local $/ = undef;
86              
87 8         167 my $json = JSON->new;
88 8         69 $json->allow_blessed;
89 8         25834 my $decoded_json = $json->allow_nonref(1)->utf8(1)->decode(<$fh>);
90 8         524 close($fh);
91 8         283 $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 2558 my $self = shift;
112 299         661 my ( $resource, $params ) = @_;
113 299         636 my $method = $resource->{method};
114 299         567 my $url = $resource->{url};
115 299   50     739 my $no_content_success = $resource->{no_content_success} // 0;
116 299         875 my $content = '';
117 299         1384 my $json = JSON->new;
118 299         1163 $json->allow_blessed;
119              
120 299 50       747 if ($params) {
121 299         3380 $content = $json->allow_nonref->utf8->canonical(1)->encode($params);
122             }
123 299         686 my $url_params = $resource->{url_params};
124              
125 299 100       2861 print "REQ: $method, $url, $content\n" if $self->debug;
126              
127 299 50       1090 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       830 if ( $self->replay ) {
134 201         325 my $resp;
135 201   100     1525 my $arr_of_resps = $self->session_store->{"$method $url $content"}
136             // [];
137 201 100       508 if ( scalar(@$arr_of_resps) ) {
138 200         445 $resp = shift @$arr_of_resps;
139 200         931 $resp = HTTP::Response->parse($resp);
140             }
141             else {
142 1         9 $resp = HTTP::Response->new( '501', "Failed to find a response" );
143             }
144 201         148949 return $self->_process_response( $resp, $no_content_success );
145             }
146 98         207 my $mock_cmds = $self->mock_cmds;
147 98         176 my $spec = $self->spec;
148 98         417 my $cmd = $mock_cmds->get_method_name_from_parameters(
149             { method => $method, url => $url } );
150 98         403 my $ret = { cmd_status => 'OK', cmd_return => 1 };
151 98 100       264 if ( defined( $spec->{$cmd} ) ) {
152 88         160 my $return_sub = $spec->{$cmd};
153 88         286 my $mock_return = $return_sub->( $url_params, $params );
154 88 100       828 if ( ref($mock_return) eq 'HASH' ) {
155 59         115 $ret->{cmd_status} = $mock_return->{status};
156 59         106 $ret->{cmd_return} = $mock_return->{return};
157 59   100     207 $ret->{cmd_error} = $mock_return->{error} // '';
158             }
159             else {
160 29         54 $ret = $mock_return;
161             }
162 88 100       1328 $ret->{session_id} = $self->fake_session_id if ( ref($ret) eq 'HASH' );
163             }
164             else {
165 10         210 $ret->{sessionId} = $self->fake_session_id;
166             }
167 98         1009 return $ret;
168             }
169              
170             1;
171              
172             __END__