File Coverage

blib/lib/Selenium/Remote/Spec.pm
Criterion Covered Total %
statement 68 79 86.0
branch 34 48 70.8
condition 14 18 77.7
subroutine 10 13 76.9
pod 0 3 0.0
total 126 161 78.2


line stmt bran cond sub pod time code
1             package Selenium::Remote::Spec;
2             $Selenium::Remote::Spec::VERSION = '1.47';
3 15     15   533 use strict;
  15         79  
  15         423  
4 15     15   74 use warnings;
  15         26  
  15         392  
5              
6             # ABSTRACT: Implement commands for Selenium::Remote::Driver
7              
8              
9 15     15   61 use Carp qw{croak};
  15         28  
  15         666  
10 15     15   81 use List::Util qw{any};
  15         29  
  15         1300  
11              
12 15     15   86 use Moo;
  15         27  
  15         141  
13             extends 'Selenium::Remote::Commands';
14              
15             #Ripped from the headlines: https://w3c.github.io/webdriver/webdriver-spec.html
16             #then add 2 params for our use
17              
18             #Method URI Template no_content_success internal_name Command
19             our $spec = qq{
20             POST session 0 newSession New Session
21             POST session 0 getCapabilities Get Capabilities (v2->v3 shim)
22             DELETE session/:sessionId 1 quit Delete Session
23             GET status 0 status Status
24             GET session/:sessionId/timeouts 0 getTimeouts Get Timeouts
25             POST session/:sessionId/timeouts 1 setTimeout Set Page Load timeout (v2->v3 shim)
26             POST session/:sessionId/timeouts/async_script 1 setAsyncScriptTimeout Set Async script timeout (v2->v3 shim)
27             POST session/:sessionId/timeouts/implicit_wait 1 setImplicitWaitTimeout Set Implicit wait timeout (v2->v3 shim)
28             POST session/:sessionId/url 1 get Navigate To
29             GET session/:sessionId/url 0 getCurrentUrl Get Current URL
30             POST session/:sessionId/back 1 goBack Back
31             POST session/:sessionId/forward 1 goForward Forward
32             POST session/:sessionId/refresh 1 refresh Refresh
33             GET session/:sessionId/title 0 getTitle Get Title
34             GET session/:sessionId/window 0 getCurrentWindowHandle Get Currently Focused Window Handle
35             DELETE session/:sessionId/window 1 close Close Currently Focused Window
36             POST session/:sessionId/window 1 switchToWindow Switch To Window
37             GET session/:sessionId/window/handles 0 getWindowHandles Get Window Handles
38             POST session/:sessionId/frame 1 switchToFrame Switch To Frame
39             POST session/:sessionId/frame/parent 1 switchToParentFrame Switch To Parent Frame
40             GET session/:sessionId/window/rect 0 getWindowRect Get Window Size/Position (v2->v3 shim)
41             POST session/:sessionId/window/rect 1 setWindowRect Set Window Size/Position (v2->v3 shim)
42             POST session/:sessionId/window/maximize 1 maximizeWindow Maximize Window
43             POST session/:sessionId/window/minimize 1 minimizeWindow Minimize Window
44             POST session/:sessionId/window/fullscreen 1 fullscreenWindow Fullscreen Window
45             GET session/:sessionId/element/active 0 getActiveElement Get Active Element
46             POST session/:sessionId/element 0 findElement Find Element
47             POST session/:sessionId/elements 0 findElements Find Elements
48             POST session/:sessionId/element/:id/element 0 findChildElement Find Element From Element
49             POST session/:sessionId/element/:id/elements 0 findChildElements Find Elements From Element
50             GET session/:sessionId/element/:id/selected 0 isElementSelected Is Element Selected
51             GET session/:sessionId/element/:id/attribute/:name 0 getElementAttribute Get Element Attribute
52             GET session/:sessionId/element/:id/property/:name 0 getElementProperty Get Element Property
53             GET session/:sessionId/element/:id/css/:propertyName 0 getElementValueOfCssProperty Get Element CSS Value
54             GET session/:sessionId/element/:id/text 0 getElementText Get Element Text
55             GET session/:sessionId/element/:id/name 0 getElementTagName Get Element Tag Name
56             GET session/:sessionId/element/:id/rect 0 getElementRect Get Element Rect
57             GET session/:sessionId/element/:id/enabled 0 isElementEnabled Is Element Enabled
58             POST session/:sessionId/element/:id/click 1 clickElement Element Click
59             POST session/:sessionId/element/:id/clear 1 clearElement Element Clear
60             POST session/:sessionId/element/:id/value 1 sendKeysToElement Element Send Keys
61             GET session/:sessionId/source 0 getPageSource Get Page Source
62             POST session/:sessionId/execute/sync 0 executeScript Execute Script
63             POST session/:sessionId/execute/async 0 executeAsyncScript Execute Async Script
64             GET session/:sessionId/cookie 0 getAllCookies Get All Cookies
65             GET session/:sessionId/cookie/:name 0 getCookieNamed Get Named Cookie
66             POST session/:sessionId/cookie 1 addCookie Add Cookie
67             DELETE session/:sessionId/cookie/:name 1 deleteCookieNamed Delete Cookie
68             DELETE session/:sessionId/cookie 1 deleteAllCookies Delete All Cookies
69             POST session/:sessionId/actions 1 generalAction Perform Actions
70             DELETE session/:sessionId/actions 1 releaseGeneralAction Release Actions
71             POST session/:sessionId/alert/dismiss 1 dismissAlert Dismiss Alert
72             POST session/:sessionId/alert/accept 1 acceptAlert Accept Alert
73             GET session/:sessionId/alert/text 0 getAlertText Get Alert Text
74             POST session/:sessionId/alert/text 1 sendKeysToPrompt Send Alert Text
75             GET session/:sessionId/screenshot 0 screenshot Take Screenshot
76             GET session/:sessionId/moz/screenshot/full 0 mozScreenshotFull Take Full Screenshot
77             GET session/:sessionId/element/:id/screenshot 0 elementScreenshot Take Element Screenshot
78             };
79              
80             our $spec_parsed;
81              
82             sub get_spec {
83 2 100   2   638 return $spec_parsed if $spec_parsed;
84 1         19 my @split = split( /\n/, $spec );
85 1         3 foreach my $line (@split) {
86 59 100       96 next unless $line;
87 58         257 my ( $method, $uri, $nc_success, $key, @description ) =
88             split( / +/, $line );
89 58         237 $spec_parsed->{$key} = {
90             method => $method,
91             url => $uri,
92             no_content_success => int($nc_success)
93             , #XXX this *should* always be 0, but specs lie
94             description => join( ' ', @description ),
95             };
96             }
97 1         7 return $spec_parsed;
98             }
99              
100             has '_cmds' => (
101             is => 'lazy',
102             reader => 'get_cmds',
103             builder => \&get_spec,
104             );
105              
106              
107             has '_caps' => (
108             is => 'lazy',
109             reader => 'get_caps',
110             builder => sub {
111             return [
112 28     28   810 'browserName', 'acceptInsecureCerts',
113             'browserVersion', 'platformName',
114             'proxy', 'pageLoadStrategy',
115             'setWindowRect', 'timeouts',
116             'unhandledPromptBehavior', 'moz:firefoxOptions',
117             'goog:chromeOptions', 'goog:loggingPrefs',
118             ];
119             }
120             );
121              
122             has '_caps_map' => (
123             is => 'lazy',
124             reader => 'get_caps_map',
125             builder => sub {
126             return {
127 28     28   11407 browserName => 'browserName',
128             acceptSslCerts => 'acceptInsecureCerts',
129             version => 'browserVersion',
130             platform => 'platformName',
131             proxy => 'proxy',
132             };
133             }
134             );
135              
136             sub get_params {
137 8     8 0 2412 my ( $self, $args ) = @_;
138 8 50       19 if ( !( defined $args->{'session_id'} ) ) {
139 0         0 return;
140             }
141              
142             #Allow fall-back in the event the command passed doesn't exist
143 8 50       150 return unless $self->get_cmds()->{ $args->{command} };
144              
145 8         66 my $url = $self->get_url( $args->{command} );
146              
147 8         26 my $data = {};
148              
149             # Do the var substitutions.
150 8         35 $url =~ s/:sessionId/$args->{'session_id'}/;
151 8         24 $url =~ s/:id/$args->{'id'}/;
152 8         21 $url =~ s/:name/$args->{'name'}/;
153 8         20 $url =~ s/:propertyName/$args->{'property_name'}/;
154 8         22 $url =~ s/:other/$args->{'other'}/;
155 8         19 $url =~ s/:windowHandle/$args->{'window_handle'}/;
156              
157 8         25 $data->{'method'} = $self->get_method( $args->{command} );
158             $data->{'no_content_success'} =
159 8         64 $self->get_no_content_success( $args->{command} );
160 8         53 $data->{'url'} = $url;
161              
162             #URL & data polyfills for the way selenium2 used to do things, etc
163 8         15 $data->{payload} = {};
164 8 50       18 if ( $args->{type} ) {
165             $data->{payload}->{pageLoad} = $args->{ms}
166 8 100 100     33 if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'page load';
167             $data->{payload}->{script} = $args->{ms}
168 8 100 100     27 if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'script';
169             $data->{payload}->{implicit} = $args->{ms}
170 8 100 100     26 if $data->{url} =~ m/timeouts$/ && $args->{type} eq 'implicit';
171             }
172              
173             #finder polyfills
174             #orig: class, class_name, css, id, link, link_text, partial_link_text, tag_name, name, xpath
175             #new: "css selector", "link text", "partial link text", "tag name", "xpath"
176             #map: class, class_name, id, name, link = 'css selector'
177 8 50 33     29 if ( $args->{using} && $args->{value} ) {
178             $data->{payload}->{using} = 'css selector'
179 8 50       16 if grep { $args->{using} eq $_ } ( 'id', 'class name', 'name' );
  24         52  
180             $data->{payload}->{value} = "[id='$args->{value}']"
181 8 100       23 if $args->{using} eq 'id';
182             $data->{payload}->{value} = ".$args->{value}"
183 8 100       18 if $args->{using} eq 'class name';
184             $data->{payload}->{value} = "[name='$args->{value}']"
185 8 100       17 if $args->{using} eq 'name';
186             }
187 8 100       21 if ( $data->{url} =~ s/timeouts\/async_script$/timeouts/g ) {
188 1         3 $data->{payload}->{script} = $args->{ms};
189 1         2 $data->{payload}->{type} = 'script'; #XXX chrome doesn't follow the spec
190             }
191 8 100       27 if ( $data->{url} =~ s/timeouts\/implicit_wait$/timeouts/g ) {
192 4         6 $data->{payload}->{implicit} = $args->{ms};
193             $data->{payload}->{type} =
194 4         11 'implicit'; #XXX chrome doesn't follow the spec
195             }
196             $data->{payload}->{value} = $args->{text}
197 8 100 66     24 if $args->{text} && $args->{command} ne 'sendKeysToElement';
198             $data->{payload}->{handle} = $args->{window_handle}
199 8 50       11 if grep { $args->{command} eq $_ }
  24         45  
200             qw{fullscreenWindow minimizeWindow maximizeWindow};
201 8         37 return $data;
202             }
203              
204             sub parse_response {
205 2     2 0 725 my ( $self, undef, $resp ) = @_;
206              
207 2 50       9 if ( ref($resp) eq 'HASH' ) {
208 2 100 66     12 if ( $resp->{cmd_status} && $resp->{cmd_status} eq 'OK' ) {
209 1         5 return $resp->{cmd_return};
210             }
211 1         3 my $msg = "Error while executing command";
212 1 50       5 if ( ref $resp->{cmd_return} eq 'HASH' ) {
213             $msg .= ": $resp->{cmd_return}{error}"
214 1 50       6 if $resp->{cmd_return}{error};
215             $msg .= ": $resp->{cmd_return}{message}"
216 1 50       5 if $resp->{cmd_return}{message};
217             }
218             else {
219 0         0 $msg .= ": $resp->{cmd_return}";
220             }
221 1         170 croak $msg;
222             }
223              
224 0           return $resp;
225             }
226              
227             #Utility
228              
229             sub get_spec_differences {
230 0     0 0   my $v2_spec = Selenium::Remote::Commands->new()->get_cmds();
231 0           my $v3_spec = Selenium::Remote::Spec->new()->get_cmds();
232              
233 0           foreach my $key ( keys(%$v2_spec) ) {
234             print "v2 $key NOT present in v3 spec!!!\n"
235 0 0   0     unless any { $_ eq $key } keys(%$v3_spec);
  0            
236             }
237 0           foreach my $key ( keys(%$v3_spec) ) {
238             print "v3 $key NOT present in v2 spec!!!\n"
239 0 0   0     unless any { $_ eq $key } keys(%$v2_spec);
  0            
240             }
241             }
242              
243             1;
244              
245             __END__