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.47';
3             # ABSTRACT: utility class to mock the responses from Selenium server
4              
5 10     10   116372 use strict;
  10         24  
  10         282  
6 10     10   51 use warnings;
  10         22  
  10         211  
7              
8 10     10   42 use Moo;
  10         20  
  10         61  
9 10     10   3403 use JSON;
  10         9216  
  10         84  
10 10     10   1136 use Carp;
  10         21  
  10         488  
11 10     10   517 use Try::Tiny;
  10         995  
  10         448  
12 10     10   450 use HTTP::Response;
  10         23034  
  10         303  
13 10     10   698 use Data::Dumper;
  10         6125  
  10         10003  
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   590 my $id = join '',
28             map +( 0 .. 9, 'a' .. 'z', 'A' .. 'Z' )[ rand( 10 + 26 * 2 ) ],
29             1 .. 50;
30 8         62 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     136 croak 'Cannot define replay and record attributes at the same time'
62             if ( ( $self->replay ) && ( $self->record ) );
63 16 50 66     101 croak 'replay_file attribute needs to be defined'
64             if ( ( $self->replay ) && !( $self->replay_file ) );
65 16 50 66     122 croak 'replay attribute needs to be defined'
66             if ( !( $self->replay ) && ( $self->replay_file ) );
67 16         122 $self->port('4444');
68 16 100       217 if ( $self->replay ) {
69 8         36 $self->load_session_store( $self->replay_file );
70             }
71             }
72              
73             sub check_status {
74 18     18 1 197 return;
75             }
76              
77             sub load_session_store {
78 8     8 0 18 my $self = shift;
79 8         16 my $file = shift;
80 8 50       159 croak "'$file' is not a valid file" unless ( -f $file );
81 8 50       308 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         52 local $/ = undef;
86              
87 8         111 my $json = JSON->new;
88 8         54 $json->allow_blessed;
89 8         18909 my $decoded_json = $json->allow_nonref(1)->utf8(1)->decode(<$fh>);
90 8         370 close($fh);
91 8         212 $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 1993 my $self = shift;
112 299         543 my ( $resource, $params ) = @_;
113 299         560 my $method = $resource->{method};
114 299         429 my $url = $resource->{url};
115 299   50     695 my $no_content_success = $resource->{no_content_success} // 0;
116 299         445 my $content = '';
117 299         1184 my $json = JSON->new;
118 299         940 $json->allow_blessed;
119              
120 299 50       604 if ($params) {
121 299         2799 $content = $json->allow_nonref->utf8->canonical(1)->encode($params);
122             }
123 299         551 my $url_params = $resource->{url_params};
124              
125 299 100       3132 print "REQ: $method, $url, $content\n" if $self->debug;
126              
127 299 50       971 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       674 if ( $self->replay ) {
134 201         256 my $resp;
135 201   100     1178 my $arr_of_resps = $self->session_store->{"$method $url $content"}
136             // [];
137 201 100       415 if ( scalar(@$arr_of_resps) ) {
138 200         376 $resp = shift @$arr_of_resps;
139 200         738 $resp = HTTP::Response->parse($resp);
140             }
141             else {
142 1         15 $resp = HTTP::Response->new( '501', "Failed to find a response" );
143             }
144 201         120686 return $self->_process_response( $resp, $no_content_success );
145             }
146 98         191 my $mock_cmds = $self->mock_cmds;
147 98         164 my $spec = $self->spec;
148 98         336 my $cmd = $mock_cmds->get_method_name_from_parameters(
149             { method => $method, url => $url } );
150 98         346 my $ret = { cmd_status => 'OK', cmd_return => 1 };
151 98 100       259 if ( defined( $spec->{$cmd} ) ) {
152 88         134 my $return_sub = $spec->{$cmd};
153 88         225 my $mock_return = $return_sub->( $url_params, $params );
154 88 100       670 if ( ref($mock_return) eq 'HASH' ) {
155 59         88 $ret->{cmd_status} = $mock_return->{status};
156 59         90 $ret->{cmd_return} = $mock_return->{return};
157 59   100     194 $ret->{cmd_error} = $mock_return->{error} // '';
158             }
159             else {
160 29         46 $ret = $mock_return;
161             }
162 88 100       1095 $ret->{session_id} = $self->fake_session_id if ( ref($ret) eq 'HASH' );
163             }
164             else {
165 10         184 $ret->{sessionId} = $self->fake_session_id;
166             }
167 98         839 return $ret;
168             }
169              
170             1;
171              
172             __END__