File Coverage

lib/Brownie/Driver/SeleniumServer.pm
Criterion Covered Total %
statement 36 99 36.3
branch 1 24 4.1
condition 0 17 0.0
subroutine 12 28 42.8
pod 12 15 80.0
total 61 183 33.3


line stmt bran cond sub pod time code
1             package Brownie::Driver::SeleniumServer;
2              
3 2     2   4166 use strict;
  2         5  
  2         90  
4 2     2   13 use warnings;
  2         3  
  2         390  
5 2     2   13 use parent 'Brownie::Driver';
  2         5  
  2         18  
6 2     2   3664 use Selenium::Remote::Driver;
  2         959588  
  2         154  
7 2     2   2302 use Selenium::Server;
  2         23867  
  2         92  
8 2     2   22 use Scalar::Util qw(blessed);
  2         5  
  2         149  
9 2     2   12 use URI;
  2         5  
  2         59  
10 2     2   13 use File::Slurp qw(write_file);
  2         6  
  2         104  
11 2     2   2135 use MIME::Base64 qw(decode_base64);
  2         1737  
  2         146  
12              
13 2     2   13 use Brownie::XPath;
  2         5  
  2         49  
14 2     2   697 use Brownie::Node::SeleniumServer;
  2         5  
  2         2315  
15              
16             our $NodeClass = 'Brownie::Node::SeleniumServer';
17              
18             sub new {
19 0     0 1 0 my ($class, %args) = @_;
20              
21 0 0 0     0 if ($ENV{SELENIUM_REMOTE_SERVER_HOST} && $ENV{SELENIUM_REMOTE_SERVER_PORT}) {
22 0         0 $args{server_host} = $ENV{SELENIUM_REMOTE_SERVER_HOST};
23 0         0 $args{server_port} = $ENV{SELENIUM_REMOTE_SERVER_PORT};
24             }
25             else {
26 0         0 my $server = $class->_create_selenium_server(%args);
27 0 0       0 if ($server) {
28 0         0 $args{server} = $server;
29 0         0 $args{server_host} = $server->host;
30 0         0 $args{server_port} = $server->port,
31             }
32             }
33              
34 0   0     0 $args{browser_name} ||= ($ENV{SELENIUM_BROWSER_NAME} || 'firefox');
      0        
35              
36 0         0 return $class->SUPER::new(%args);
37             }
38              
39             sub _create_selenium_server {
40 0     0   0 my ($class, %args) = @_;
41              
42 0         0 my $server = Selenium::Server->new;
43 0 0       0 $server->start if $server;
44              
45 0         0 $server;
46             }
47              
48             sub DESTROY {
49 5     5   9 my $self = shift;
50              
51 5         24 delete $self->{browser};
52              
53 5 50       36 if ($self->{server}) {
54 0           $self->{server}->stop;
55 0           delete $self->{server};
56             }
57             }
58              
59 0     0 0   sub server_host { shift->{server_host} }
60 0     0 0   sub server_port { shift->{server_port} }
61 0     0 0   sub browser_name { shift->{browser_name} }
62              
63             sub browser {
64 0     0 1   my $self = shift;
65              
66 0   0       $self->{browser} ||= Selenium::Remote::Driver->new(
67             remote_server_addr => $self->server_host,
68             port => $self->server_port,
69             browser_name => $self->browser_name,
70             );
71              
72 0           return $self->{browser};
73             }
74              
75             sub visit {
76 0     0 1   my ($self, $url) = @_;
77 0           $self->browser->get("$url"); # stringify for URI
78             }
79              
80             sub current_url {
81 0     0 1   my $self = shift;
82 0           return URI->new($self->browser->get_current_url);
83             }
84              
85             sub current_path {
86 0     0 1   my $self = shift;
87 0           return $self->current_url->path;
88             }
89              
90             sub title {
91 0     0 1   my $self = shift;
92 0           return $self->browser->get_title;
93             }
94              
95             sub source {
96 0     0 1   my $self = shift;
97 0           return $self->browser->get_page_source;
98             }
99              
100             sub screenshot {
101 0     0 1   my ($self, $file) = @_;
102 0           my $image = decode_base64($self->browser->screenshot);
103 0           write_file($file, { binmode => ':raw' }, $image);
104             }
105              
106             sub find {
107 0     0 1   my ($self, $locator, %args) = @_;
108              
109 0           my $element;
110 0           my $xpath = Brownie::XPath::to_xpath($locator);
111              
112 0 0         if (my $base = $args{base}) {
113 0 0 0       my $node = (blessed($base) and $base->can('native')) ? $base->native : $base;
114 0 0         $xpath = ".$xpath" unless $xpath =~ /^\./;
115 0           $element = eval { $self->browser->find_child_element($node, $xpath) }; # abs2rel
  0            
116             }
117             else {
118 0           $element = eval { $self->browser->find_element($xpath) };
  0            
119             }
120              
121 0 0         return $element ? $NodeClass->new(driver => $self, native => $element) : undef;
122             }
123              
124             sub all {
125 0     0 1   my ($self, $locator, %args) = @_;
126              
127 0           my @elements = ();
128 0           my $xpath = Brownie::XPath::to_xpath($locator);
129              
130 0 0         if (my $base = $args{base}) {
131 0 0 0       my $node = (blessed($base) and $base->can('native')) ? $base->native : $base;
132 0 0         $xpath = ".$xpath" unless $xpath =~ /^\./;
133 0           @elements = eval { $self->browser->find_child_elements($node, $xpath) }; # abs2rel
  0            
134             }
135             else {
136 0           @elements = eval { $self->browser->find_elements($xpath) };
  0            
137             }
138              
139 0 0         return @elements ? map { $NodeClass->new(driver => $self, native => $_) } @elements : ();
  0            
140             }
141              
142             sub execute_script {
143 0     0 1   my ($self, $script) = @_;
144 0           $self->browser->execute_script($script);
145             }
146              
147             sub evaluate_script {
148 0     0 1   my ($self, $script) = @_;
149 0           return $self->browser->execute_script("return $script");
150             }
151              
152             1;
153              
154             =head1 NAME
155              
156             Brownie::Driver::SeleniumServer - Selenium RemoteWebDriver bridge
157              
158             =head1 SYNOPSIS
159              
160             # use default browser (firefox)
161             my $driver = Brownie::Driver::SeleniumServer->new;
162              
163             # specify browser
164             my $driver = Brownie::Driver::SeleniumServer->new(browser_name => 'chrome');
165              
166             $driver->visit($url);
167             my $title = $driver->title;
168              
169             =head1 METHODS
170              
171             =head2 IMPLEMENTED
172              
173             =over 4
174              
175             =item * C
176              
177             my $driver = Brownie::Driver::SeleniumServer->new(%args);
178              
179             C<%args> are:
180              
181             * browser_name: selenium-server's browser name (default: "firefox")
182              
183             You can also set selenium-server parameters using C<%ENV>:
184              
185             * SELENIUM_BROWSER_NAME
186              
187             =item * C
188              
189             =item * C
190              
191             =item * C
192              
193             =item * C
194              
195             =item * C </td> </tr> <tr> <td class="h" > <a name="196">196</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="197">197</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<source> </td> </tr> <tr> <td class="h" > <a name="198">198</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="199">199</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<screenshot($filename)> </td> </tr> <tr> <td class="h" > <a name="200">200</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="201">201</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<execute_script($javascript)> </td> </tr> <tr> <td class="h" > <a name="202">202</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="203">203</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<evaluate_script($javascript)> </td> </tr> <tr> <td class="h" > <a name="204">204</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="205">205</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<find($locator)> </td> </tr> <tr> <td class="h" > <a name="206">206</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="207">207</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<all($locator)> </td> </tr> <tr> <td class="h" > <a name="208">208</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="209">209</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="210">210</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="211">211</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 NOT SUPPORTED </td> </tr> <tr> <td class="h" > <a name="212">212</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="213">213</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="214">214</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="215">215</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<status_code> </td> </tr> <tr> <td class="h" > <a name="216">216</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="217">217</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item * C<response_headers> </td> </tr> <tr> <td class="h" > <a name="218">218</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="219">219</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="220">220</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="221">221</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 TIPS </td> </tr> <tr> <td class="h" > <a name="222">222</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="223">223</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Use external selenium server </td> </tr> <tr> <td class="h" > <a name="224">224</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="225">225</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> If you secify "SELENIUM_REMOTE_SERVER_HOST" and "SELENIUM_REMOTE_SERVER_PORT" enviromnent valiables, Brownie uses its server for selenium server. By this, you can quicken the execution of your tests. </td> </tr> <tr> <td class="h" > <a name="226">226</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="227">227</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 AUTHOR </td> </tr> <tr> <td class="h" > <a name="228">228</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="229">229</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> NAKAGAWA Masaki E<lt>masaki@cpan.orgE<gt> </td> </tr> <tr> <td class="h" > <a name="230">230</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="231">231</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 LICENSE </td> </tr> <tr> <td class="h" > <a name="232">232</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="233">233</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This library is free software; you can redistribute it and/or modify </td> </tr> <tr> <td class="h" > <a name="234">234</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> it under the same terms as Perl itself. </td> </tr> <tr> <td class="h" > <a name="235">235</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="236">236</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 SEE ALSO </td> </tr> <tr> <td class="h" > <a name="237">237</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="238">238</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<Brownie::Driver>, L<Selenium::Remote::Driver>, L<Brownie::Node::SeleniumServer> </td> </tr> <tr> <td class="h" > <a name="239">239</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="240">240</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<http://code.google.com/p/selenium/wiki/RemoteWebDriver> </td> </tr> <tr> <td class="h" > <a name="241">241</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="242">242</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<http://code.google.com/p/selenium/wiki/RemoteWebDriverServer> </td> </tr> <tr> <td class="h" > <a name="243">243</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="244">244</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> </table> </body> </html>