line  
 stmt  
 bran  
 cond  
 sub  
 pod  
 time  
 code  
 
1 
 
  
 
   
 
 
 
 
 
 
 
 
 
 
 
 package WWW::Mechanize::PhantomJS;  
 
2 
 
33
 
 
 
 
 
  
33
   
 
 
 
2199993
 
 use strict;  
 
  
 
33
 
 
 
 
 
 
 
 
 
363
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
944
 
    
 
3 
 
33
 
 
 
 
 
  
33
   
 
 
 
1008
 
 use 5.010;  
 
  
 
33
 
 
 
 
 
 
 
 
 
137
 
    
 
4 
 
33
 
 
 
 
 
  
33
   
 
 
 
196
 
 use warnings;  
 
  
 
33
 
 
 
 
 
 
 
 
 
63
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1167
 
    
 
5 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
6 
 
33
 
 
 
 
 
  
33
   
 
 
 
17008
 
 use Filter::signatures;  
 
  
 
33
 
 
 
 
 
 
 
 
 
898657
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
224
 
    
 
7 
 
33
 
 
 
 
 
  
33
   
 
 
 
1275
 
 no warnings 'experimental::signatures';  
 
  
 
33
 
 
 
 
 
 
 
 
 
70
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1163
 
    
 
8 
 
33
 
 
 
 
 
  
33
   
 
 
 
213
 
 use feature 'signatures';  
 
  
 
33
 
 
 
 
 
 
 
 
 
87
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
990
 
    
 
9 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
10 
 
33
 
 
 
 
 
  
33
   
 
 
 
30253
 
 use Selenium::Remote::Driver;  
 
  
 
33
 
 
 
 
 
 
 
 
 
9248531
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1362
 
    
 
11 
 
33
 
 
 
 
 
  
33
   
 
 
 
17508
 
 use WWW::Mechanize::Plugin::Selector;  
 
  
 
33
 
 
 
 
 
 
 
 
 
98
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1230
 
    
 
12 
 
33
 
 
 
 
 
  
33
   
 
 
 
253
 
 use HTTP::Response;  
 
  
 
33
 
 
 
 
 
 
 
 
 
81
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1039
 
    
 
13 
 
33
 
 
 
 
 
  
33
   
 
 
 
189
 
 use HTTP::Headers;  
 
  
 
33
 
 
 
 
 
 
 
 
 
72
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
860
 
    
 
14 
 
33
 
 
 
 
 
  
33
   
 
 
 
188
 
 use Scalar::Util qw( blessed );  
 
  
 
33
 
 
 
 
 
 
 
 
 
71
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1755
 
    
 
15 
 
33
 
 
 
 
 
  
33
   
 
 
 
267
 
 use File::Basename;  
 
  
 
33
 
 
 
 
 
 
 
 
 
66
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
3257
 
    
 
16 
 
33
 
 
 
 
 
  
33
   
 
 
 
222
 
 use Carp qw(croak carp);  
 
  
 
33
 
 
 
 
 
 
 
 
 
79
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1467
 
    
 
17 
 
33
 
 
 
 
 
  
33
   
 
 
 
16215
 
 use WWW::Mechanize::Link;  
 
  
 
33
 
 
 
 
 
 
 
 
 
13629
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
1097
 
    
 
18 
 
33
 
 
 
 
 
  
33
   
 
 
 
17877
 
 use IO::Socket::INET;  
 
  
 
33
 
 
 
 
 
 
 
 
 
432312
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
194
 
    
 
19 
 
33
 
 
 
 
 
  
33
   
 
 
 
15894
 
 use Time::HiRes qw(time sleep);  
 
  
 
33
 
 
 
 
 
 
 
 
 
87
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
380
 
    
 
20 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
21 
 
 
 
 
 
 
 
 
 
 
 
 
 
 our $VERSION= '0.24';  
 
22 
 
 
 
 
 
 
 
 
 
 
 
 
 
 our @CARP_NOT=qw(Selenium::Remote::Driver);  
 
23 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
24 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 NAME  
 
25 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
26 
 
 
 
 
 
 
 
 
 
 
 
 
 
 WWW::Mechanize::PhantomJS - automate the PhantomJS browser  
 
27 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
28 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 SYNOPSIS  
 
29 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
30 
 
 
 
 
 
 
 
 
 
 
 
 
 
   use WWW::Mechanize::PhantomJS;  
 
31 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my $mech = WWW::Mechanize::PhantomJS->new();  
 
32 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->get('http://google.com');  
 
33 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
34 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->eval_in_page('alert("Hello PhantomJS")');  
 
35 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my $png= $mech->content_as_png();  
 
36 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
37 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< WWW::Mechanize::PhantomJS->new %options >>  
 
38 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
39 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my $mech = WWW::Mechanize::PhantomJS->new();  
 
40 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
41 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
42 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
43 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
44 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
45 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Control whether HTTP errors are fatal.  
 
46 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
47 
 
 
 
 
 
 
 
 
 
 
 
 
 
   autodie => 0, # make HTTP errors non-fatal  
 
48 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
49 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The default is to have HTTP errors fatal,  
 
50 
 
 
 
 
 
 
 
 
 
 
 
 
 
 as that makes debugging much easier than expecting  
 
51 
 
 
 
 
 
 
 
 
 
 
 
 
 
 you to actually check the results of every action.  
 
52 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
53 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
54 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
55 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specify the port where PhantomJS should listen  
 
56 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
57 
 
 
 
 
 
 
 
 
 
 
 
 
 
   port => 8910  
 
58 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
59 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
60 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
61 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specify the log level of PhantomJS  
 
62 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
63 
 
 
 
 
 
 
 
 
 
 
 
 
 
   log => 'OFF'   # Also INFO, WARN, DEBUG  
 
64 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
65 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
66 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
67 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specify the path to the PhantomJS executable.  
 
68 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
69 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The default is C as found via C<$ENV{PATH}>.   
 
70 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can also provide this information from the outside  
 
71 
 
 
 
 
 
 
 
 
 
 
 
 
 
 by setting C<$ENV{PHANTOMJS_EXE}>.  
 
72 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
73 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
74 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
75 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Additional command line arguments to C.  (phantomjs -h)   
 
76 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
77 
 
 
 
 
 
 
 
 
 
 
 
 
 
   phantomjs_arg => ["--proxy=$ENV{HTTP_PROXY}"]  
 
78 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
79 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
80 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
81 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Filename of the C Javascript code   
 
82 
 
 
 
 
 
 
 
 
 
 
 
 
 
 to launch. The default is the file distributed with this module.  
 
83 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
84 
 
 
 
 
 
 
 
 
 
 
 
 
 
   launch_ghostdriver => "devel/my/ghostdriver/main.js",  
 
85 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
86 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
87 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
88 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specify additional parameters to the Ghostdriver script.  
 
89 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
90 
 
 
 
 
 
 
 
 
 
 
 
 
 
   launch_arg => [ "--some-new-parameter=foo" ],  
 
91 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
92 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Some interesting parameters are:  
 
93 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
94 
 
 
 
 
 
 
 
 
 
 
 
 
 
   "--webdriver=$port",  
 
95 
 
 
 
 
 
 
 
 
 
 
 
 
 
   '--webdriver-logfile=/tmp/webdriver',  
 
96 
 
 
 
 
 
 
 
 
 
 
 
 
 
   '--webdriver-loglevel=DEBUG',  
 
97 
 
 
 
 
 
 
 
 
 
 
 
 
 
   '--debug=true',  
 
98 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
99 
 
 
 
 
 
 
 
 
 
 
 
 
 
   note: these set config.xxx values in ghostrdriver/config.js  
 
100 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
101 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
102 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
103 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Cookies are not directly persisted. If you pass in a path here,  
 
104 
 
 
 
 
 
 
 
 
 
 
 
 
 
 that file will be used to store or retrieve cookies.  
 
105 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
106 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
107 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
108 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If you want C to ignore SSL errors, pass a true value here.   
 
109 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
110 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
111 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
112 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A premade L object.   
 
113 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
114 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item B   
 
115 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
116 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If set to 1, after each request tests for Javascript errors and warns. Useful  
 
117 
 
 
 
 
 
 
 
 
 
 
 
 
 
 for testing with C.   
 
118 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
119 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
120 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
121 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
122 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
123 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub build_command_line {  
 
124 
 
1
 
 
 
 
 
  
1
   
 
  
0
   
 
3
 
     my( $class, $options )= @_;  
 
125 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
126 
 
1
 
 
 
  
 50
   
 
 
 
 
 
7
 
     $options->{ "log" } ||= 'OFF';  
 
127 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
128 
 
1
 
 
 
  
 50
   
 
 
 
 
 
11
 
     $options->{ launch_exe } ||= $ENV{PHANTOMJS_EXE} || 'phantomjs';  
 
  
 
 
 
 
 
  
 33
   
 
 
 
 
 
 
 
    
 
129 
 
1
 
 
 
 
 
 
 
 
 
7
 
     (my $ghostdir_default= __FILE__) =~ s!\.pm$!!;  
 
130 
 
1
 
 
 
 
 
 
 
 
 
22
 
     $ghostdir_default= File::Spec->catfile( $ghostdir_default, 'ghostdriver', 'main.js' );  
 
131 
 
1
 
 
 
  
 33
   
 
 
 
 
 
7
 
     $options->{ launch_ghostdir } ||= $ghostdir_default;  
 
132 
 
1
 
 
 
  
 50
   
 
 
 
 
 
8
 
     $options->{ launch_arg } ||= [];  
 
133 
 
1
 
 
 
  
 50
   
 
 
 
 
 
6
 
     $options->{ phantomjs_arg } ||= [];  
 
134 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
135 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # config.js defaults config.port to 8910  
 
136 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # this is the proper way to overwrite it (not sure wtf the PhantomJS parameter does above)  
 
137 
 
1
 
  
 50
   
 
 
 
 
 
 
 
3
 
     if ($options->{port}) {  
 
138 
 
1
 
 
 
 
 
 
 
 
 
2
 
         push @{ $options->{ launch_arg }}, "--port=$options->{ port }";  
 
  
 
1
 
 
 
 
 
 
 
 
 
5
 
    
 
139 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  # PhantomJS version 1.9.7  
 
140 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
141 
 
1
 
 
 
 
 
 
 
 
 
2
 
     push @{ $options->{ launch_arg }}, "--logLevel=\U$options->{ log }";  
 
  
 
1
 
 
 
 
 
 
 
 
 
6
 
    
 
142 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
143 
 
1
 
  
 50
   
 
 
 
 
 
 
 
5
 
     if( my $cookie_file= delete $options->{ cookie_file }) {  
 
144 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
         push @{ $options->{ phantomjs_arg }}, "--cookies-file=$cookie_file";  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
    
 
145 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
146 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
147 
 
1
 
  
 50
   
 
 
 
 
 
 
 
4
 
     if( my $ignore_ssl_errors= delete $options->{ ignore_ssl_errors }) {  
 
148 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
         push @{ $options->{ phantomjs_arg }}, "--ignore-ssl-errors=yes";  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
    
 
149 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
150 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
151 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $program = ($^O =~ /mswin/i and $options->{ launch_exe } =~ /\s/)  
 
152 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   ? qq("$options->{ launch_exe }")  
 
153 
 
1
 
  
 50
   
 
  
 33
   
 
 
 
 
 
9
 
                   : $options->{ launch_exe };  
 
154 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
155 
 
1
 
 
 
 
 
 
 
 
 
2
 
     my @cmd=( "|-", $program, @{ $options->{phantomjs_arg}}, $options->{ launch_ghostdir }, @{ $options->{ launch_arg } } );  
 
  
 
1
 
 
 
 
 
 
 
 
 
2
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
4
 
    
 
156 
 
1
 
  
 50
   
 
 
 
 
 
 
 
5
 
     if( $^O =~ /mswin/i ) {  
 
157 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Windows Perl doesn't support pipe-open with list  
 
158 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
         shift @cmd; # remove pipe-open  
 
159 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
         @cmd= "| " . join " ", @cmd;  
 
160 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
161 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
162 
 
 
 
 
 
 
 
 
 
 
 
 
 
     @cmd  
 
163 
 
1
 
 
 
 
 
 
 
 
 
5
 
 };  
 
164 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
165 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub new {  
 
166 
 
1
 
 
 
 
 
  
1
   
 
  
1
   
 
5
 
     my ($class, %options) = @_;  
 
167 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
168 
 
1
 
 
 
 
 
 
 
 
 
3
 
     my $localhost = '127.0.0.1';  
 
169 
 
1
 
  
 50
   
 
  
 33
   
 
 
 
 
 
5
 
     unless ( defined $options{ port } and !$options{pid}) {  
 
170 
 
1
 
 
 
 
 
 
 
 
 
2
 
         my $port = 8910;  
 
171 
 
1
 
 
 
 
 
 
 
 
 
3
 
         while (1) {  
 
172 
 
1
 
 
 
 
 
 
 
 
 
9
 
             my $sock = IO::Socket::INET->new(  
 
173 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 Proto    => 'tcp',  
 
174 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 PeerAddr => $localhost,  
 
175 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 PeerPort => $port,  
 
176 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 Timeout => 1,  
 
177 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #V6Only   => 1,  
 
178 
 
 
 
 
 
 
 
 
 
 
 
 
 
             );  
 
179 
 
1
 
  
 50
   
 
 
 
 
 
 
 
2835
 
             if( $sock ) {  
 
180 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
                 $port++;  
 
181 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
                 $sock->close;  
 
182 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
                 sleep 0.1+rand(0.1);  
 
183 
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
                 next;  
 
184 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
185 
 
1
 
 
 
 
 
 
 
 
 
2
 
             last;  
 
186 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
187 
 
1
 
 
 
 
 
 
 
 
 
3
 
         $options{ port } = $port;  
 
188 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
189 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
190 
 
1
 
  
 50
   
 
 
 
 
 
 
 
4
 
     if (! exists $options{ autodie }) { $options{ autodie } = 1 };  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
0
 
    
 
191 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
192 
 
1
 
  
 50
   
 
 
 
 
 
 
 
4
 
     if( ! exists $options{ frames }) {  
 
193 
 
1
 
 
 
 
 
 
 
 
 
2
 
         $options{ frames }= 1;  
 
194 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
195 
 
1
 
  
 50
   
 
 
 
 
 
 
 
4
 
     unless ($options{pid}) {  
 
196 
 
1
 
 
 
 
 
 
 
 
 
9
 
         my @cmd= $class->build_command_line( \%options );  
 
197 
 
1
 
 
 
 
 
 
 
 
 
3
 
         $options{ kill_pid } = 1;  
 
198 
 
1
 
  
 50
   
 
 
 
 
 
 
 
5
 
         if( @cmd > 1 ) {  
 
199 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # We can do a proper pipe-open  
 
200 
 
1
 
 
 
 
 
 
 
 
 
3
 
             my $mode = shift @cmd;  
 
201 
 
1
 
  
 50
   
 
 
 
 
 
 
 
3649
 
             $options{ pid } = open $options{fh}, $mode, @cmd  
 
202 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 or die "Couldn't launch [@cmd]: $! / $?";  
 
203 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } else {  
 
204 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # We can't do a proper pipe-open, so do the single-arg open  
 
205 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # in the hope that everything has been set up properly  
 
206 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             $options{ pid } = open $options{fh}, $cmd[0]  
 
207 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 or die "Couldn't launch [$cmd[0]]: $! / $?";  
 
208 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
209 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
210 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Just to give PhantomJS time to start up, make sure it accepts connections  
 
211 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         my $wait = time + ($options{ wait } || 20);  
 
212 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         while ( time < $wait ) {  
 
213 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $t = time;  
 
214 
 
 
 
 
 
 
 
 
 
 
 
 
 
             my $socket = IO::Socket::INET->new(  
 
215 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 PeerHost => $localhost,  
 
216 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 PeerPort => $options{ port },  
 
217 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 Proto    => 'tcp',  
 
218 
 
 
 
 
 
 
 
 
 
 
 
 
 
             );  
 
219 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if( $socket ) {  
 
220 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 close $socket;  
 
221 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 sleep 0.1;  
 
222 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 last;  
 
223 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
224 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             sleep 0.1 if time - $t < 1;  
 
225 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
226 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
227 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
228 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Connect to it  
 
229 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     eval {  
 
230 
 
 
 
 
 
 
 
 
 
 
 
 
 
         $options{ driver } ||= Selenium::Remote::Driver->new(  
 
231 
 
 
 
 
 
 
 
 
 
 
 
 
 
             'port' => $options{ port },  
 
232 
 
 
 
 
 
 
 
 
 
 
 
 
 
             remote_server_addr => $localhost,  
 
233 
 
 
 
 
 
 
 
 
 
 
 
 
 
             auto_close => 0,  
 
234 
 
 
 
 
 
 
 
 
 
 
 
 
 
             error_handler => sub {  
 
235 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn ref$_[0];  
 
236 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn "<<@CARP_NOT>>";  
 
237 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn ((caller($_))[0,1,2])  
 
238 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #    for 1..4;  
 
239 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
                 local @CARP_NOT = (@CARP_NOT, ref $_[0],'Try::Tiny');  
 
240 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 # Reraise the error  
 
241 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 croak $_[1]  
 
242 
 
 
 
 
 
 
 
 
 
 
 
 
 
             },  
 
243 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         );  
 
244 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # (Monkey)patch Selenium::Remote::Driver  
 
245 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options{ driver }->commands->get_cmds->{get}->{no_content_success}= 0;  
 
246 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
247 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
248 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # if PhantomJS started, but so slow or unresponsive that SRD cannot connect to it,  
 
249 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # kill it manually to avoid waiting for it indefinitely  
 
250 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ( $@ ) {  
 
251 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         kill 9, delete $options{ pid } if $options{ kill_pid };  
 
252 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         die $@;  
 
253 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
254 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
255 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
      my $self= bless \%options => $class;  
 
256 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
257 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
      $self->eval_in_phantomjs(<<'JS');  
 
258 
 
 
 
 
 
 
 
 
 
 
 
 
 
          var page= this;  
 
259 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.errors= [];  
 
260 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.alerts= [];  
 
261 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.confirms= {};  
 
262 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.onError= function(msg, trace) {  
 
263 
 
 
 
 
 
 
 
 
 
 
 
 
 
              //_log.warn("Caught JS error", msg);  
 
264 
 
 
 
 
 
 
 
 
 
 
 
 
 
              page.errors.push({ "message": msg, "trace": trace });  
 
265 
 
 
 
 
 
 
 
 
 
 
 
 
 
          };  
 
266 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.onConsoleMessage= function(msg, line, file) {  
 
267 
 
 
 
 
 
 
 
 
 
 
 
 
 
             // line and file are declared but will never be used :(  
 
268 
 
 
 
 
 
 
 
 
 
 
 
 
 
              page.errors.push({ "message": msg, "trace": [{"line":line,"file":file}] });  
 
269 
 
 
 
 
 
 
 
 
 
 
 
 
 
          };  
 
270 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.onAlert = function(msg) {  
 
271 
 
 
 
 
 
 
 
 
 
 
 
 
 
              page.alerts.push(msg);  
 
272 
 
 
 
 
 
 
 
 
 
 
 
 
 
          };  
 
273 
 
 
 
 
 
 
 
 
 
 
 
 
 
          page.onConfirm= function(msg) {  
 
274 
 
 
 
 
 
 
 
 
 
 
 
 
 
              return page.confirms[msg];  
 
275 
 
 
 
 
 
 
 
 
 
 
 
 
 
          };  
 
276 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
277 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
278 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
      $self  
 
279 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
280 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
281 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->phantomjs_version >>  
 
282 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
283 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->phantomjs_version;  
 
284 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
285 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the version of the PhantomJS executable that is used.  
 
286 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
287 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
288 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
289 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub phantomjs_version {  
 
290 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self )= @_;  
 
291 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $self->{phantomjs_version} ||= do {  
 
292 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $version= `$self->{ launch_exe } --version`;  
 
293 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $version=~ s!\s+!!g;  
 
294 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $version  
 
295 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
296 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
297 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
298 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->ghostdriver_version >>  
 
299 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
300 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->ghostdriver_version;  
 
301 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
302 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the version of the ghostdriver script that is used.  
 
303 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
304 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
305 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
306 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub ghostdriver_version {  
 
307 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self )= @_;  
 
308 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $self->{ghostdriver_version} ||= do {  
 
309 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->eval_in_phantomjs('return ghostdriver.version');  
 
310 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
311 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
312 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
313 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->driver >>  
 
314 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
315 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $selenium= $mech->driver  
 
316 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
317 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Access the L instance connecting to PhantomJS.   
 
318 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
319 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
320 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
321 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub driver {  
 
322 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $_[0]->{driver}  
 
323 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
 };  
 
324 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
325 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub autodie {  
 
326 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self, $val )= @_;  
 
327 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $self->{autodie} = $val  
 
328 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if @_ == 2;  
 
329 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $_[0]->{autodie}  
 
330 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
 }  
 
331 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
332 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub allow {  
 
333 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my($self,%options)= @_;  
 
334 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for my $opt (keys %options) {  
 
335 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if( 'javascript' eq $opt ) {  
 
336 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $self->eval_in_phantomjs(<<'JS', $options{ $opt });  
 
337 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 this.settings.javascriptEnabled= arguments[0]  
 
338 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
339 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } else {  
 
340 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             warn "->allow('$opt', ...) is currently a dummy.";  
 
341 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
342 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
343 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
344 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
345 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->js_alerts() >>  
 
346 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
347 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print for $mech->js_alerts();  
 
348 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
349 
 
 
 
 
 
 
 
 
 
 
 
 
 
 An interface to the Javascript Alerts  
 
350 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
351 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the list of alerts  
 
352 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
353 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
354 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
355 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
 sub js_alerts { @{ shift->eval_in_phantomjs('return this.alerts') } }  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
356 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
357 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->clear_js_alerts() >>  
 
358 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
359 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->clear_js_alerts();  
 
360 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
361 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Clears all saved alerts  
 
362 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
363 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
364 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
365 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
 sub clear_js_alerts { shift->eval_in_phantomjs('this.alerts = [];') }  
 
366 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
367 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->js_errors() >>  
 
368 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
369 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->{message}  
 
370 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->js_errors();  
 
371 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
372 
 
 
 
 
 
 
 
 
 
 
 
 
 
 An interface to the Javascript Error Console  
 
373 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
374 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the list of errors in the JEC  
 
375 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
376 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Maybe this should be called C or   
 
377 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C instead.   
 
378 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
379 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
380 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
381 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub js_errors {  
 
382 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
383 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $errors= $self->eval_in_phantomjs(<<'JS');  
 
384 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return this.errors  
 
385 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
386 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     @$errors  
 
387 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
388 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
389 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->clear_js_errors() >>  
 
390 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
391 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->clear_js_errors();  
 
392 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
393 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Clears all Javascript messages from the console  
 
394 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
395 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
396 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
397 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub clear_js_errors {  
 
398 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
399 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $errors= $self->eval_in_phantomjs(<<'JS');  
 
400 
 
 
 
 
 
 
 
 
 
 
 
 
 
         this.errors= [];  
 
401 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
402 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
403 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
404 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
405 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->confirm( 'Really do this?' [ => 1 ]) >>  
 
406 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
407 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Records a confirmation (which is "1" or "ok" by default), to be used  
 
408 
 
 
 
 
 
 
 
 
 
 
 
 
 
 whenever javascript fires a confirm dialog. If the message is not found,  
 
409 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the answer is "cancel".  
 
410 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
411 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
412 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
413 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub confirm  
 
414 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
415 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ( $self, $msg, $affirmative ) = @_;  
 
416 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $affirmative = 1 unless defined $affirmative;  
 
417 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $affirmative = $affirmative ? 'true' : 'false';  
 
418 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs("this.confirms['$msg']=$affirmative;");  
 
419 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
420 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
421 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->eval_in_page( $str, @args ) >>  
 
422 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
423 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->eval( $str, @args ) >>  
 
424 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
425 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my ($value, $type) = $mech->eval( '2+2' );  
 
426 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
427 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Evaluates the given Javascript fragment in the  
 
428 
 
 
 
 
 
 
 
 
 
 
 
 
 
 context of the web page.  
 
429 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns a pair of value and Javascript type.  
 
430 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
431 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This allows access to variables and functions declared  
 
432 
 
 
 
 
 
 
 
 
 
 
 
 
 
 "globally" on the web page.  
 
433 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
434 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is special to WWW::Mechanize::PhantomJS.  
 
435 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
436 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
437 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
438 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub eval_in_page {  
 
439 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$str,@args) = @_;  
 
440 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
441 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Report errors from scope of caller  
 
442 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # This feels weirdly backwards here, but oh well:  
 
443 
 
 
 
 
 
 
 
 
 
 
 
 
 
     local @Selenium::Remote::Driver::CARP_NOT  
 
444 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         = (@Selenium::Remote::Driver::CARP_NOT, (ref $self)); # we trust this  
 
445 
 
 
 
 
 
 
 
 
 
 
 
 
 
     local @CARP_NOT  
 
446 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         = (@CARP_NOT, 'Selenium::Remote::Driver', (ref $self)); # we trust this  
 
447 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $eval_in_sandbox = $self->driver->execute_script("return $str", @args);  
 
448 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->post_process;  
 
449 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $eval_in_sandbox;  
 
450 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
451 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
452 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
453 
 
33
 
 
 
 
 
  
33
   
 
 
 
68893
 
     no warnings 'once';  
 
  
 
33
 
 
 
 
 
 
 
 
 
106
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
39439
 
    
 
454 
 
 
 
 
 
 
 
 
 
 
 
 
 
     *eval = \&eval_in_page;  
 
455 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
456 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
457 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->eval_in_phantomjs $code, @args >>  
 
458 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
459 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->eval_in_phantomjs(<<'JS', "Foobar/1.0");  
 
460 
 
 
 
 
 
 
 
 
 
 
 
 
 
       this.settings.userAgent= arguments[0]  
 
461 
 
 
 
 
 
 
 
 
 
 
 
 
 
   JS  
 
462 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
463 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Evaluates Javascript code in the context of PhantomJS.  
 
464 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
465 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This allows you to modify properties of PhantomJS.  
 
466 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
467 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
468 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
469 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub eval_in_phantomjs {  
 
470 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $code, @args) = @_;  
 
471 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $tab = $self->tab;  
 
472 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
473 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $cmds= $self->driver->commands->get_cmds; # Initialize  
 
474 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $cmds->{'phantomExecute'}||= {  
 
475 
 
 
 
 
 
 
 
 
 
 
 
 
 
         'method' => 'POST',  
 
476 
 
 
 
 
 
 
 
 
 
 
 
 
 
         'url' => "session/:sessionId/phantom/execute"  
 
477 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
478 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
479 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $params= {  
 
480 
 
 
 
 
 
 
 
 
 
 
 
 
 
         args => \@args,  
 
481 
 
 
 
 
 
 
 
 
 
 
 
 
 
         script => $code,  
 
482 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
483 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->driver->_execute_command({ command => 'phantomExecute' }, $params);  
 
484 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
485 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
486 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub agent {  
 
487 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my($self, $ua) = @_;  
 
488 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # page.settings.userAgent = 'Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/7.0';  
 
489 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs(<<'JS', $ua);  
 
490 
 
 
 
 
 
 
 
 
 
 
 
 
 
        this.settings.userAgent= arguments[0]  
 
491 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
492 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
493 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
494 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub DESTROY {  
 
495 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
     my $pid= delete $_[0]->{pid};  
 
496 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
497 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Purge the filehandle - we should've opened that to /dev/null anyway:  
 
498 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( my $child_out = $_[0]->{ fh }) {  
 
499 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         local $/;  
 
500 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         1 while <$child_out>;  
 
501 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
502 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
503 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     eval {  
 
504 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $dr= delete $_[0]->{ driver };  
 
505 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $dr->quit;  
 
506 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         undef $dr;  
 
507 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
508 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( $pid ) {  
 
509 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         kill 'SIGKILL' => $pid;  
 
510 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
511 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     %{ $_[0] }= (); # clean out all other held references  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
512 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
513 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
514 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->highlight_node( @nodes ) >>  
 
515 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
516 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @links = $mech->selector('a');  
 
517 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->highlight_node(@links);  
 
518 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print $mech->content_as_png();  
 
519 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
520 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Convenience method that marks all nodes in the arguments  
 
521 
 
 
 
 
 
 
 
 
 
 
 
 
 
 with  
 
522 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
523 
 
 
 
 
 
 
 
 
 
 
 
 
 
   background: red;  
 
524 
 
 
 
 
 
 
 
 
 
 
 
 
 
   border: solid black 1px;  
 
525 
 
 
 
 
 
 
 
 
 
 
 
 
 
   display: block; /* if the element was display: none before */  
 
526 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
527 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is convenient if you need visual verification that you've  
 
528 
 
 
 
 
 
 
 
 
 
 
 
 
 
 got the right nodes.  
 
529 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
530 
 
 
 
 
 
 
 
 
 
 
 
 
 
 There currently is no way to restore the nodes to their original  
 
531 
 
 
 
 
 
 
 
 
 
 
 
 
 
 visual state except reloading the page.  
 
532 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
533 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
534 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
535 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub highlight_node {  
 
536 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,@nodes) = @_;  
 
537 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for (@nodes) {  
 
538 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $style= $self->eval_in_page(<
   
539 
 
 
 
 
 
 
 
 
 
 
 
 
 
         (function(el) {  
 
540 
 
 
 
 
 
 
 
 
 
 
 
 
 
             if( 'none' == el.style.display ) {  
 
541 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 el.style.display= 'block';  
 
542 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
543 
 
 
 
 
 
 
 
 
 
 
 
 
 
             el.style.background= 'red';  
 
544 
 
 
 
 
 
 
 
 
 
 
 
 
 
             el.style.border= 'solid black 1px';  
 
545 
 
 
 
 
 
 
 
 
 
 
 
 
 
         })(arguments[0]);  
 
546 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
547 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
548 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
549 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
550 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 NAVIGATION METHODS  
 
551 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
552 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->get( $url, %options ) >>  
 
553 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
554 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->get( $url  );  
 
555 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
556 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Retrieves the URL C.   
 
557 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
558 
 
 
 
 
 
 
 
 
 
 
 
 
 
 It returns a faked L object for interface compatibility   
 
559 
 
 
 
 
 
 
 
 
 
 
 
 
 
 with L. It seems that Selenium and thus L    
 
560 
 
 
 
 
 
 
 
 
 
 
 
 
 
 have no concept of HTTP status code and thus no way of returning the  
 
561 
 
 
 
 
 
 
 
 
 
 
 
 
 
 HTTP status code.  
 
562 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
563 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Note that PhantomJs does not support download of files.  
 
564 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
565 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
566 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
567 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub update_response {  
 
568 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my( $self, $phantom_res ) = @_;  
 
569 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
570 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # just 1 means success  
 
571 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     $phantom_res = {  
 
572 
 
 
 
 
 
 
 
 
 
 
 
 
 
         status     => 200,  
 
573 
 
 
 
 
 
 
 
 
 
 
 
 
 
         statusText => 'OK',  
 
574 
 
 
 
 
 
 
 
 
 
 
 
 
 
         headers    => [{  
 
575 
 
 
 
 
 
 
 
 
 
 
 
 
 
             name  => 'x-www-mechanize-phantomjs-fake-success',  
 
576 
 
 
 
 
 
 
 
 
 
 
 
 
 
             value => 1,  
 
577 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }],  
 
578 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } if ref($phantom_res) eq '' and $phantom_res eq '1';  
 
579 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
580 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Now add a status code of 4xx if we don't have one.  
 
581 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( ! $phantom_res->{status}) {  
 
582 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $phantom_res->{status}= 400;  
 
583 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $phantom_res->{statusText}= "Unknown error (added by " . __PACKAGE__ . ")";  
 
584 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
585 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
586 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @headers= map {;@{$_}{qw(name value)}} @{ $phantom_res->{headers} };  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
587 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $res= HTTP::Response->new( $phantom_res->{status}, $phantom_res->{statusText}, \@headers );  
 
588 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
589 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Should we fetch the response body?!  
 
590 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
591 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     delete $self->{ current_form };  
 
592 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
593 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{response} = $res;  
 
594 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $res  
 
595 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
596 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
597 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub get {  
 
598 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $url, %options ) = @_;  
 
599 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # We need to stringify $url so it can pass through JSON  
 
600 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $phantom_res= $self->driver->get( "$url" );  
 
601 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->post_process;  
 
602 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
603 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->update_response( $phantom_res );  
 
604 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
605 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
606 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->get_local( $filename , %options ) >>  
 
607 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
608 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->get_local('test.html');  
 
609 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
610 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Shorthand method to construct the appropriate  
 
611 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< file:// >> URI and load it into PhantomJS. Relative  
 
612 
 
 
 
 
 
 
 
 
 
 
 
 
 
 paths will be interpreted as relative to C<$0>.  
 
613 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
614 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method accepts the same options as C<< ->get() >>.  
 
615 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
616 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is special to WWW::Mechanize::PhantomJS but could  
 
617 
 
 
 
 
 
 
 
 
 
 
 
 
 
 also exist in WWW::Mechanize through a plugin.  
 
618 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
619 
 
 
 
 
 
 
 
 
 
 
 
 
 
 B: PhantomJs does not handle local files well. Especially   
 
620 
 
 
 
 
 
 
 
 
 
 
 
 
 
 subframes do not get loaded properly.  
 
621 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
622 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
623 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
624 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub get_local {  
 
625 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $htmlfile, %options) = @_;  
 
626 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     require Cwd;  
 
627 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     require File::Spec;  
 
628 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     my $fn= File::Spec->file_name_is_absolute( $htmlfile )  
 
629 
 
 
 
 
 
 
 
 
 
 
 
 
 
           ? $htmlfile  
 
630 
 
 
 
 
 
 
 
 
 
 
 
 
 
           : File::Spec->rel2abs(  
 
631 
 
 
 
 
 
 
 
 
 
 
 
 
 
                  File::Spec->catfile(dirname($0),$htmlfile),  
 
632 
 
 
 
 
 
 
 
 
 
 
 
 
 
                  Cwd::getcwd(),  
 
633 
 
 
 
 
 
 
 
 
 
 
 
 
 
              );  
 
634 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $fn =~ s!\\!/!g; # fakey "make file:// URL"  
 
635 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $url;  
 
636 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( $^O =~ /mswin/i ) {  
 
637 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $url= "file:///$fn";  
 
638 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
639 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $url= "file://$fn";  
 
640 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
641 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $res= $self->get($url, %options);  
 
642 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # PhantomJS is not helpful with its error messages for local URLs  
 
643 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if( 0+$res->headers->header_field_names and ([$res->headers->header_field_names]->[0] ne 'x-www-mechanize-phantomjs-fake-success' or $self->uri ne 'about:blank')) {  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
644 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # We need to fake the content headers from   tags too...  
 
645 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Maybe this even needs to go into ->get()  
 
646 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $res->code( 200 );  
 
647 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
648 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $res->code( 400 ); # Must have been "not found"  
 
649 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
650 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $res  
 
651 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
652 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
653 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->post( $url, %options ) >>  
 
654 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
655 
 
 
 
 
 
 
 
 
 
 
 
 
 
 B   
 
656 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
657 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Selenium currently does not allow a raw POST message  
 
658 
 
 
 
 
 
 
 
 
 
 
 
 
 
 and the code for constructing a form on the fly is not working  
 
659 
 
 
 
 
 
 
 
 
 
 
 
 
 
 so this method is not implemented.  
 
660 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
661 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->post( 'http://example.com',  
 
662 
 
 
 
 
 
 
 
 
 
 
 
 
 
       params => { param => "Hello World" },  
 
663 
 
 
 
 
 
 
 
 
 
 
 
 
 
       headers => {  
 
664 
 
 
 
 
 
 
 
 
 
 
 
 
 
         "Content-Type" => 'application/x-www-form-urlencoded',  
 
665 
 
 
 
 
 
 
 
 
 
 
 
 
 
       },  
 
666 
 
 
 
 
 
 
 
 
 
 
 
 
 
       charset => 'utf-8',  
 
667 
 
 
 
 
 
 
 
 
 
 
 
 
 
   );  
 
668 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
669 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Sends a POST request to C<$url>.  
 
670 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
671 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A C header will be automatically calculated if   
 
672 
 
 
 
 
 
 
 
 
 
 
 
 
 
 it is not given.  
 
673 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
674 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The following options are recognized:  
 
675 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
676 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
677 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
678 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
679 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
680 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - a hash of HTTP headers to send. If not given,   
 
681 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the content type will be generated automatically.  
 
682 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
683 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
684 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
685 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - the raw data to send, if you've encoded it already.   
 
686 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
687 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
688 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
689 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
690 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
691 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub post {  
 
692 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $url, %options) = @_;  
 
693 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $b = $self->tab->{linkedBrowser};  
 
694 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->clear_current_form;  
 
695 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
696 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $flags = 0;  
 
697 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #if ($options{no_cache}) {  
 
698 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #  $flags = $self->repl->constant('nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE');  
 
699 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #};  
 
700 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
701 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # If we don't have data, encode the parameters:  
 
702 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( !$options{ data }) {  
 
703 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $req= HTTP::Request::Common::POST( $url, $options{params} );  
 
704 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn $req->content;  
 
705 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         carp "Faking content from parameters is not yet supported.";  
 
706 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #$options{ data } = $req->content;  
 
707 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
708 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
709 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$options{ charset } ||= 'utf-8';  
 
710 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$options{ headers } ||= {};  
 
711 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$options{ headers }->{"Content-Type"} ||= "application/x-www-form-urlencoded";  
 
712 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #if( $options{ charset }) {  
 
713 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #    $options{ headers }->{"Content-Type"} .= "; charset=$options{ charset }";  
 
714 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #};  
 
715 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
716 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Javascript POST implementation taken from  
 
717 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # http://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit  
 
718 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval(<<'JS', $url, $options{ params }, 'POST');  
 
719 
 
 
 
 
 
 
 
 
 
 
 
 
 
         function (path, params, method) {  
 
720 
 
 
 
 
 
 
 
 
 
 
 
 
 
             method = method || "post"; // Set method to post by default if not specified.  
 
721 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
722 
 
 
 
 
 
 
 
 
 
 
 
 
 
             // The rest of this code assumes you are not using a library.  
 
723 
 
 
 
 
 
 
 
 
 
 
 
 
 
             // It can be made less wordy if you use one.  
 
724 
 
 
 
 
 
 
 
 
 
 
 
 
 
             var form = document.createElement("form");  
 
725 
 
 
 
 
 
 
 
 
 
 
 
 
 
             form.setAttribute("method", method);  
 
726 
 
 
 
 
 
 
 
 
 
 
 
 
 
             form.setAttribute("action", path);  
 
727 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
728 
 
 
 
 
 
 
 
 
 
 
 
 
 
             for(var key in params) {  
 
729 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 if(params.hasOwnProperty(key)) {  
 
730 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     var hiddenField = document.createElement("input");  
 
731 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     hiddenField.setAttribute("type", "hidden");  
 
732 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     hiddenField.setAttribute("name", key);  
 
733 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     hiddenField.setAttribute("value", params[key]);  
 
734 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
735 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     form.appendChild(hiddenField);  
 
736 
 
 
 
 
 
 
 
 
 
 
 
 
 
                  }  
 
737 
 
 
 
 
 
 
 
 
 
 
 
 
 
             }  
 
738 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
739 
 
 
 
 
 
 
 
 
 
 
 
 
 
             document.body.appendChild(form);  
 
740 
 
 
 
 
 
 
 
 
 
 
 
 
 
             form.submit();  
 
741 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
742 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
743 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Now, how to trick Selenium into fetching the response?  
 
744 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
745 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
746 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->add_header( $name => $value, ... ) >>  
 
747 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
748 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->add_header(  
 
749 
 
 
 
 
 
 
 
 
 
 
 
 
 
         'X-WWW-Mechanize-PhantomJS' => "I'm using it",  
 
750 
 
 
 
 
 
 
 
 
 
 
 
 
 
         Encoding => 'text/klingon',  
 
751 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
752 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
753 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method sets up custom headers that will be sent with B HTTP(S)   
 
754 
 
 
 
 
 
 
 
 
 
 
 
 
 
 request that PhantomJS makes.  
 
755 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
756 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Note that currently, we only support one value per header.  
 
757 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
758 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
759 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
760 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub add_header {  
 
761 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, @headers) = @_;  
 
762 
 
33
 
 
 
 
 
  
33
   
 
 
 
316
 
     use Data::Dumper;  
 
  
 
33
 
 
 
 
 
 
 
 
 
642
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
8863
 
    
 
763 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn Dumper $headers;  
 
764 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
765 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     while( my ($k,$v) = splice @headers, 0, 2 ) {  
 
766 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->eval_in_phantomjs(<<'JS', , $k, $v);  
 
767 
 
 
 
 
 
 
 
 
 
 
 
 
 
             var h= this.customHeaders;  
 
768 
 
 
 
 
 
 
 
 
 
 
 
 
 
             h[arguments[0]]= arguments[1];  
 
769 
 
 
 
 
 
 
 
 
 
 
 
 
 
             this.customHeaders= h;  
 
770 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
771 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
772 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
773 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
774 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->delete_header( $name , $name2... ) >>  
 
775 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
776 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->delete_header( 'User-Agent' );  
 
777 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
778 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Removes HTTP headers from the agent's list of special headers. Note  
 
779 
 
 
 
 
 
 
 
 
 
 
 
 
 
 that PhantomJS may still send a header with its default value.  
 
780 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
781 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
782 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
783 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub delete_header {  
 
784 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, @headers) = @_;  
 
785 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
786 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs(<<'JS', @headers);  
 
787 
 
 
 
 
 
 
 
 
 
 
 
 
 
         var headers= this.customHeaders;  
 
788 
 
 
 
 
 
 
 
 
 
 
 
 
 
         for( var i = 0; i < arguments.length; i++ ) {  
 
789 
 
 
 
 
 
 
 
 
 
 
 
 
 
             delete headers[arguments[i]];  
 
790 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
791 
 
 
 
 
 
 
 
 
 
 
 
 
 
         this.customHeaders= headers;  
 
792 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
793 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
794 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
795 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->reset_headers >>  
 
796 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
797 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->reset_headers();  
 
798 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
799 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Removes all custom headers and makes PhantomJS send its defaults again.  
 
800 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
801 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
802 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
803 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub reset_headers {  
 
804 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
805 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs('this.customHeaders= {}');  
 
806 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
807 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
808 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->res() >> / C<< $mech->response(%options) >>  
 
809 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
810 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $response = $mech->response(headers => 0);  
 
811 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
812 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current response as a L object.   
 
813 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
814 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
815 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
816 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
 sub response { $_[0]->{response} };  
 
817 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
818 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
819 
 
33
 
 
 
 
 
  
33
   
 
 
 
309
 
     no warnings 'once';  
 
  
 
33
 
 
 
 
 
 
 
 
 
78
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
39058
 
    
 
820 
 
 
 
 
 
 
 
 
 
 
 
 
 
     *res = \&response;  
 
821 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
822 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
823 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Call croak or carp, depending on the C< autodie > setting  
 
824 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub signal_condition {  
 
825 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my ($self,$msg) = @_;  
 
826 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($self->{autodie}) {  
 
827 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         croak $msg  
 
828 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
829 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         carp $msg  
 
830 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
831 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
832 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
833 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Call croak on the C< autodie > setting if we have a non-200 status  
 
834 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub signal_http_status {  
 
835 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my ($self) = @_;  
 
836 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($self->{autodie}) {  
 
837 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
         if ($self->status and $self->status !~ /^2/ and $self->status != 0) {  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
838 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # there was an error  
 
839 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
             croak ($self->response(headers => 0)->message || sprintf "Got status code %d", $self->status );  
 
840 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
841 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
842 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # silent  
 
843 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
844 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
845 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
846 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->success() >>  
 
847 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
848 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->get('http://google.com');  
 
849 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print "Yay"  
 
850 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if $mech->success();  
 
851 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
852 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns a boolean telling whether the last request was successful.  
 
853 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If there hasn't been an operation yet, returns false.  
 
854 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
855 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is a convenience function that wraps C<< $mech->res->is_success >>.  
 
856 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
857 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
858 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
859 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub success {  
 
860 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my $res = $_[0]->response( headers => 0 );  
 
861 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $res and $res->is_success  
 
862 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
863 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
864 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->status() >>  
 
865 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
866 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->get('http://google.com');  
 
867 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print $mech->status();  
 
868 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # 200  
 
869 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
870 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the HTTP status code of the response.  
 
871 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is a 3-digit number like 200 for OK, 404 for not found, and so on.  
 
872 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
873 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
874 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
875 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub status {  
 
876 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
877 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->response( headers => 0 )->code  
 
878 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
879 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
880 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->back() >>  
 
881 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
882 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->back();  
 
883 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
884 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Goes one page back in the page history.  
 
885 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
886 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the (new) response.  
 
887 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
888 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
889 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
890 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub back {  
 
891 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
892 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
893 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->driver->go_back;  
 
894 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
895 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
896 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->forward() >>  
 
897 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
898 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->forward();  
 
899 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
900 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Goes one page forward in the page history.  
 
901 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
902 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the (new) response.  
 
903 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
904 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
905 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
906 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub forward {  
 
907 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
908 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->driver->go_forward;  
 
909 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
910 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
911 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->uri() >>  
 
912 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
913 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print "We are at " . $mech->uri;  
 
914 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
915 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current document URI.  
 
916 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
917 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
918 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
919 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub uri {  
 
920 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     URI->new( $_[0]->driver->get_current_url )  
 
921 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
922 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
923 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 CONTENT METHODS  
 
924 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
925 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->document() >>  
 
926 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
927 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the document object as a WebElement.  
 
928 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
929 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is WWW::Mechanize::PhantomJS specific.  
 
930 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
931 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
932 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
933 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub document {  
 
934 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     $_[0]->driver->find_element('html','tag_name');  
 
935 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
936 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
937 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # If things get nasty, we could fall back to PhantomJS.webpage.plainText  
 
938 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # var page = require('webpage').create();  
 
939 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # page.open('http://somejsonpage.com', function () {  
 
940 
 
 
 
 
 
 
 
 
 
 
 
 
 
 #     var jsonSource = page.plainText;  
 
941 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub decoded_content {  
 
942 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     $_[0]->driver->get_page_source  
 
943 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
944 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
945 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->content( %options ) >>  
 
946 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
947 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->content;  
 
948 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->content( format => 'html' ); # default  
 
949 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->content( format => 'text' ); # identical to ->text  
 
950 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
951 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This always returns the content as a Unicode string. It tries  
 
952 
 
 
 
 
 
 
 
 
 
 
 
 
 
 to decode the raw content according to its input encoding.  
 
953 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This currently only works for HTML pages, not for images etc.  
 
954 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
955 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Recognized options:  
 
956 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
957 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
958 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
959 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
960 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
961 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - the stuff to return   
 
962 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
963 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The allowed values are C and C. The default is C.   
 
964 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
965 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
966 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
967 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
968 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
969 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub content {  
 
970 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %options) = @_;  
 
971 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $options{ format } ||= 'html';  
 
972 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $format = delete $options{ format } || 'html';  
 
973 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
974 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $content;  
 
975 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( 'html' eq $format ) {  
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
976 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $content= $self->driver->get_page_source  
 
977 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif ( $format eq 'text' ) {  
 
978 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $content= $self->text;  
 
979 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
980 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->die( qq{Unknown "format" parameter "$format"} );  
 
981 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
982 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
983 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
984 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->text() >>  
 
985 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
986 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print $mech->text();  
 
987 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
988 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the text of the current HTML content.  If the content isn't  
 
989 
 
 
 
 
 
 
 
 
 
 
 
 
 
 HTML, $mech will die.  
 
990 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
991 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
992 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
993 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub text {  
 
994 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my $self = shift;  
 
995 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
996 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Waugh - this is highly inefficient but conveniently short to write  
 
997 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Maybe this should skip SCRIPT nodes...  
 
998 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     join '', map { $_->get_text() } $self->xpath('//*/text()');  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
999 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1000 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1001 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->content_encoding() >>  
 
1002 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1003 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print "The content is encoded as ", $mech->content_encoding;  
 
1004 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1005 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the encoding that the content is in. This can be used  
 
1006 
 
 
 
 
 
 
 
 
 
 
 
 
 
 to convert the content from UTF-8 back to its native encoding.  
 
1007 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1008 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1009 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1010 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub content_encoding {  
 
1011 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
1012 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Let's trust the  
  
1013 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Also, a pox on PhantomJS for not having lower-case or upper-case  
 
1014 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if(( my $meta )= $self->xpath( q{//meta[translate(@http-equiv,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')="content-type"]}, first => 1 )) {  
 
1015 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         (my $ct= $meta->get_attribute('content')) =~ s/^.*;\s*charset=\s*//i;  
 
1016 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         return $ct  
 
1017 
 
 
 
 
 
 
 
 
 
 
 
 
 
             if( $ct );  
 
1018 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1019 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->response->header('Content-Type');  
 
1020 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1021 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1022 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->update_html( $html ) >>  
 
1023 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1024 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->update_html($html);  
 
1025 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1026 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Writes C<$html> into the current document. This is mostly  
 
1027 
 
 
 
 
 
 
 
 
 
 
 
 
 
 implemented as a convenience method for L.   
 
1028 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1029 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1030 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1031 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub update_html {  
 
1032 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$content) = @_;  
 
1033 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs('this.setContent(arguments[0], arguments[1])', $content);  
 
1034 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1035 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1036 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->base() >>  
 
1037 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1038 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->base;  
 
1039 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1040 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the URL base for the current page.  
 
1041 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1042 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The base is either specified through a C   
 
1043 
 
 
 
 
 
 
 
 
 
 
 
 
 
 tag or is the current URL.  
 
1044 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1045 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is specific to WWW::Mechanize::PhantomJS.  
 
1046 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1047 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1048 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1049 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub base {  
 
1050 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
1051 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     (my $base) = $self->selector('base');  
 
1052 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $base = $base->{href}  
 
1053 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if $base;  
 
1054 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $base ||= $self->uri;  
 
1055 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1056 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1057 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->content_type() >>  
 
1058 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1059 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->ct() >>  
 
1060 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1061 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->content_type;  
 
1062 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1063 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the content type of the currently loaded document  
 
1064 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1065 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1066 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1067 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub content_type {  
 
1068 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
1069 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Let's trust the  
  
1070 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Also, a pox on PhantomJS for not having lower-case or upper-case  
 
1071 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $ct;  
 
1072 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if(my( $meta )= $self->xpath( q{//meta[translate(@http-equiv,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')="content-type"]}, first => 1 )) {  
 
1073 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $ct= $meta->get_attribute('content');  
 
1074 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1075 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if(!$ct and my $r= $self->response ) {  
 
1076 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $h= $r->headers;  
 
1077 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $ct= $h->header('Content-Type');  
 
1078 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1079 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $ct =~ s/;.*$// if defined $ct;  
 
1080 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $ct  
 
1081 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1082 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1083 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
1084 
 
33
 
 
 
 
 
  
33
   
 
 
 
708
 
     no warnings 'once';  
 
  
 
33
 
 
 
 
 
 
 
 
 
121
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
21756
 
    
 
1085 
 
 
 
 
 
 
 
 
 
 
 
 
 
     *ct = \&content_type;  
 
1086 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1087 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1088 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->is_html() >>  
 
1089 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1090 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->is_html();  
 
1091 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1092 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns true/false on whether our content is HTML, according to the  
 
1093 
 
 
 
 
 
 
 
 
 
 
 
 
 
 HTTP headers.  
 
1094 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1095 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1096 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1097 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub is_html {  
 
1098 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my $self = shift;  
 
1099 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     return defined $self->ct && ($self->ct eq 'text/html');  
 
1100 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1101 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1102 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->title() >>  
 
1103 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1104 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print "We are on page " . $mech->title;  
 
1105 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1106 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current document title.  
 
1107 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1108 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1109 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1110 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub title {  
 
1111 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     $_[0]->driver->get_title;  
 
1112 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1113 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1114 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 EXTRACTION METHODS  
 
1115 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1116 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->links() >>  
 
1117 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1118 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->text . " -> " . $_->url . "\n"  
 
1119 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->links;  
 
1120 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1121 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns all links in the document as L objects.   
 
1122 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1123 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Currently accepts no parameters. See C<< ->xpath >>  
 
1124 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or C<< ->selector >> when you want more control.  
 
1125 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1126 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1127 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1128 
 
 
 
 
 
 
 
 
 
 
 
 
 
 our %link_spec = (  
 
1129 
 
 
 
 
 
 
 
 
 
 
 
 
 
     a      => { url => 'href', },  
 
1130 
 
 
 
 
 
 
 
 
 
 
 
 
 
     area   => { url => 'href', },  
 
1131 
 
 
 
 
 
 
 
 
 
 
 
 
 
     frame  => { url => 'src', },  
 
1132 
 
 
 
 
 
 
 
 
 
 
 
 
 
     iframe => { url => 'src', },  
 
1133 
 
 
 
 
 
 
 
 
 
 
 
 
 
     link   => { url => 'href', },  
 
1134 
 
 
 
 
 
 
 
 
 
 
 
 
 
     meta   => { url => 'content', xpath => (join '',  
 
1135 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     q{translate(@http-equiv,'ABCDEFGHIJKLMNOPQRSTUVWXYZ',},  
 
1136 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     q{'abcdefghijklmnopqrstuvwxyz')="refresh"}), },  
 
1137 
 
 
 
 
 
 
 
 
 
 
 
 
 
 );  
 
1138 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # taken from WWW::Mechanize. This should possibly just be reused there  
 
1139 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub make_link {  
 
1140 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my ($self,$node,$base) = @_;  
 
1141 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1142 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $tag = lc $node->get_tag_name;  
 
1143 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $url;  
 
1144 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($tag) {  
 
1145 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if( ! exists $link_spec{ $tag }) {  
 
1146 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             carp "Unknown link-spec tag '$tag'";  
 
1147 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $url= '';  
 
1148 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } else {  
 
1149 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $url = $node->get_attribute( $link_spec{ $tag }->{url} );  
 
1150 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1151 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1152 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1153 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($tag eq 'meta') {  
 
1154 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $content = $url;  
 
1155 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ( $content =~ /^\d+\s*;\s*url\s*=\s*(\S+)/i ) {  
 
1156 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $url = $1;  
 
1157 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             $url =~ s/^"(.+)"$/$1/ or $url =~ s/^'(.+)'$/$1/;  
 
1158 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
1159 
 
 
 
 
 
 
 
 
 
 
 
 
 
         else {  
 
1160 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             undef $url;  
 
1161 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
1162 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1163 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1164 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (defined $url) {  
 
1165 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $res = WWW::Mechanize::Link->new({  
 
1166 
 
 
 
 
 
 
 
 
 
 
 
 
 
             tag   => $tag,  
 
1167 
 
 
 
 
 
 
 
 
 
 
 
 
 
             name  => $node->get_attribute('name'),  
 
1168 
 
 
 
 
 
 
 
 
 
 
 
 
 
             base  => $base,  
 
1169 
 
 
 
 
 
 
 
 
 
 
 
 
 
             url   => $url,  
 
1170 
 
 
 
 
 
 
 
 
 
 
 
 
 
             text  => $node->get_text(),  
 
1171 
 
 
 
 
 
 
 
 
 
 
 
 
 
             attrs => {},  
 
1172 
 
 
 
 
 
 
 
 
 
 
 
 
 
         });  
 
1173 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1174 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $res  
 
1175 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
1176 
 
 
 
 
 
 
 
 
 
 
 
 
 
         ()  
 
1177 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1178 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1179 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1180 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub links {  
 
1181 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self) = @_;  
 
1182 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @links = $self->selector( join ",", sort keys %link_spec);  
 
1183 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $base = $self->base;  
 
1184 
 
 
 
 
 
 
 
 
 
 
 
 
 
     return map {  
 
1185 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->make_link($_,$base)  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1186 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } @links;  
 
1187 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1188 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1189 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->selector( $css_selector, %options ) >>  
 
1190 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1191 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my @text = $mech->selector('p.content');  
 
1192 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1193 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns all nodes matching the given CSS selector. If  
 
1194 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<$css_selector> is an array reference, it returns  
 
1195 
 
 
 
 
 
 
 
 
 
 
 
 
 
 all nodes matched by any of the CSS selectors in the array.  
 
1196 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1197 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This takes the same options that C<< ->xpath >> does.  
 
1198 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1199 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is implemented via L.   
 
1200 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1201 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1202 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
1203 
 
33
 
 
 
 
 
  
33
   
 
 
 
330
 
     no warnings 'once';  
 
  
 
33
 
 
 
 
 
 
 
 
 
76
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
83566
 
    
 
1204 
 
 
 
 
 
 
 
 
 
 
 
 
 
     *selector = \&WWW::Mechanize::Plugin::Selector::selector;  
 
1205 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1206 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1207 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->find_link_dom( %options ) >>  
 
1208 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1209 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->{innerHTML} . "\n"  
 
1210 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->find_link_dom( text_contains => 'CPAN' );  
 
1211 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1212 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A method to find links, like L's   
 
1213 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->find_links >> method. This method returns DOM objects from  
 
1214 
 
 
 
 
 
 
 
 
 
 
 
 
 
 PhantomJS instead of WWW::Mechanize::Link objects.  
 
1215 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1216 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Note that PhantomJS  
 
1217 
 
 
 
 
 
 
 
 
 
 
 
 
 
 might have reordered the links or frame links in the document  
 
1218 
 
 
 
 
 
 
 
 
 
 
 
 
 
 so the absolute numbers passed via C   
 
1219 
 
 
 
 
 
 
 
 
 
 
 
 
 
 might not be the same between  
 
1220 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L and L.    
 
1221 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1222 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The supported options are:  
 
1223 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1224 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
1225 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1226 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1227 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1228 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< text >> and C<< text_contains >> and C<< text_regex >>  
 
1229 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1230 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Match the text of the link as a complete string, substring or regular expression.  
 
1231 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1232 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Matching as a complete string or substring is a bit faster, as it is  
 
1233 
 
 
 
 
 
 
 
 
 
 
 
 
 
 done in the XPath engine of PhantomJS.  
 
1234 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1235 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1236 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1237 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< id >> and C<< id_contains >> and C<< id_regex >>  
 
1238 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1239 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Matches the C attribute of the link completely or as part   
 
1240 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1241 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1242 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1243 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< name >> and C<< name_contains >> and C<< name_regex >>  
 
1244 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1245 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Matches the C attribute of the link   
 
1246 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1247 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1248 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1249 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< url >> and C<< url_regex >>  
 
1250 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1251 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Matches the URL attribute of the link (C, C or C).     
 
1252 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1253 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1254 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1255 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< class >> - the C attribute of the link   
 
1256 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1257 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1258 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1259 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< n >> - the (1-based) index. Defaults to returning the first link.  
 
1260 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1261 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1262 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1263 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< single >> - If true, ensure that only one element is found. Otherwise croak  
 
1264 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or carp, depending on the C parameter.   
 
1265 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1266 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1267 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1268 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< one >> - If true, ensure that at least one element is found. Otherwise croak  
 
1269 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or carp, depending on the C parameter.   
 
1270 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1271 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The method Cs if no link is found. If the C option is true,    
 
1272 
 
 
 
 
 
 
 
 
 
 
 
 
 
 it also Cs when more than one link is found.   
 
1273 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1274 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
1275 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1276 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1277 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1278 
 
 
 
 
 
 
 
 
 
 
 
 
 
 our %xpath_quote = (  
 
1279 
 
 
 
 
 
 
 
 
 
 
 
 
 
     '"' => '\"',  
 
1280 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #"'" => "\\'",  
 
1281 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #'[' => '[',  
 
1282 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #']' => ']',  
 
1283 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #'[' => '[\[]',  
 
1284 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #'[' => '\[',  
 
1285 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #']' => '[\]]',  
 
1286 
 
 
 
 
 
 
 
 
 
 
 
 
 
 );  
 
1287 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1288 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
 sub quote_xpath($) {  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1289 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     local $_ = $_[0];  
 
1290 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     s/(['"\[\]])/$xpath_quote{$1} || $1/ge;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1291 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $_  
 
1292 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1293 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1294 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Copied from WWW::Mechanize 1.97  
 
1295 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Used by find_links to check for matches  
 
1296 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # The logic is such that ALL param criteria that are given must match  
 
1297 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
 sub _match_any_link_params( $self, $link, $p ) {  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1298 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # No conditions, anything matches  
 
1299 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     return 1 unless keys %$p;  
 
1300 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1301 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{url}           && !($link->url eq $p->{url} );  
 
1302 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{url_regex}     && !($link->url =~ $p->{url_regex} );  
 
1303 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{url_abs}       && !($link->url_abs eq $p->{url_abs} );  
 
1304 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{url_abs_regex} && !($link->url_abs =~ $p->{url_abs_regex} );  
 
1305 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{text}          && !(defined($link->text) && $link->text eq $p->{text} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1306 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{text_regex}    && !(defined($link->text) && $link->text =~ $p->{text_regex} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1307 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{name}          && !(defined($link->name) && $link->name eq $p->{name} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1308 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{name_regex}    && !(defined($link->name) && $link->name =~ $p->{name_regex} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1309 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{tag}           && !($link->tag && $link->tag eq $p->{tag} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1310 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{tag_regex}     && !($link->tag && $link->tag =~ $p->{tag_regex} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1311 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1312 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{id}            && !($link->attrs->{id} && $link->attrs->{id} eq $p->{id} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1313 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{id_regex}      && !($link->attrs->{id} && $link->attrs->{id} =~ $p->{id_regex} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1314 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{class}         && !($link->attrs->{class} && $link->attrs->{class} eq $p->{class} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1315 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return if defined $p->{class_regex}   && !($link->attrs->{class} && $link->attrs->{class} =~ $p->{class_regex} );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
1316 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1317 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Success: everything that was defined passed.  
 
1318 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return 1;  
 
1319 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1320 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1321 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub find_link_dom {  
 
1322 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%opts) = @_;  
 
1323 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my %xpath_options;  
 
1324 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1325 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for (qw(node document frames)) {  
 
1326 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Copy over XPath options that were passed in  
 
1327 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if (exists $opts{ $_ }) {  
 
1328 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $xpath_options{ $_ } = delete $opts{ $_ };  
 
1329 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1330 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1331 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1332 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $single = delete $opts{ single };  
 
1333 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $one = delete $opts{ one } || $single;  
 
1334 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if ($single and exists $opts{ n }) {  
 
1335 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         croak "It doesn't make sense to use 'single' and 'n' option together"  
 
1336 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1337 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $n = (delete $opts{ n } || 1);  
 
1338 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $n--  
 
1339 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if ($n ne 'all'); # 1-based indexing  
 
1340 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @spec;  
 
1341 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1342 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Decode text and text_contains into XPath  
 
1343 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for my $lvalue (qw( text id name class )) {  
 
1344 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my %lefthand = (  
 
1345 
 
 
 
 
 
 
 
 
 
 
 
 
 
             text => 'text()',  
 
1346 
 
 
 
 
 
 
 
 
 
 
 
 
 
         );  
 
1347 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my %match_op = (  
 
1348 
 
 
 
 
 
 
 
 
 
 
 
 
 
             '' => q{%s="%s"},  
 
1349 
 
 
 
 
 
 
 
 
 
 
 
 
 
             'contains' => q{contains(%s,"%s")},  
 
1350 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # Ideally we would also handle *_regex here, but PhantomJS XPath  
 
1351 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # does not support fn:matches() :-(  
 
1352 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #'regex' => q{matches(%s,"%s","%s")},  
 
1353 
 
 
 
 
 
 
 
 
 
 
 
 
 
         );  
 
1354 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         my $lhs = $lefthand{ $lvalue } || '@'.$lvalue;  
 
1355 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         for my $op (keys %match_op) {  
 
1356 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $v = $match_op{ $op };  
 
1357 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             $op = '_'.$op if length($op);  
 
1358 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $key = "${lvalue}$op";  
 
1359 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1360 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if (exists $opts{ $key }) {  
 
1361 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 my $p = delete $opts{ $key };  
 
1362 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 push @spec, sprintf $v, $lhs, $p;  
 
1363 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
1364 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1365 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1366 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1367 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (my $p = delete $opts{ url }) {  
 
1368 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         push @spec, sprintf '@href = "%s" or @src="%s"', quote_xpath $p, quote_xpath $p;  
 
1369 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
1370 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @tags = (sort keys %link_spec);  
 
1371 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (my $p = delete $opts{ tag }) {  
 
1372 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @tags = $p;  
 
1373 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1374 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (my $p = delete $opts{ tag_regex }) {  
 
1375 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @tags = grep /$p/, @tags;  
 
1376 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1377 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $q = join '|',  
 
1378 
 
 
 
 
 
 
 
 
 
 
 
 
 
             map {  
 
1379 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
                 my $xp= exists $link_spec{ $_ } ? $link_spec{$_}->{xpath} : undef;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1380 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 my @full = map {qq{($_)}} grep {defined} (@spec, $xp);  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1381 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
                 if (@full) {  
 
1382 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                     sprintf "//%s[%s]", $_, join " and ", @full;  
 
1383 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 } else {  
 
1384 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                     sprintf "//%s", $_  
 
1385 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 };  
 
1386 
 
 
 
 
 
 
 
 
 
 
 
 
 
             }  (@tags);  
 
1387 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn $q;  
 
1388 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1389 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @res = $self->xpath($q, %xpath_options );  
 
1390 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1391 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (keys %opts) {  
 
1392 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # post-filter the remaining links through WWW::Mechanize  
 
1393 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # for all the options we don't support with XPath  
 
1394 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1395 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $base = $self->base;  
 
1396 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         require WWW::Mechanize;  
 
1397 
 
 
 
 
 
 
 
 
 
 
 
 
 
         @res = grep {  
 
1398 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $self->_match_any_link_params($self->make_link($_,$base),\%opts)  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1399 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } @res;  
 
1400 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1401 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1402 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($one) {  
 
1403 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if (0 == @res) { $self->signal_condition( "No link found matching '$q'" )};  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1404 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ($single) {  
 
1405 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if (1 <  @res) {  
 
1406 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 $self->highlight_node(@res);  
 
1407 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 $self->signal_condition(  
 
1408 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     sprintf "%d elements found found matching '%s'", scalar @res, $q  
 
1409 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 );  
 
1410 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
1411 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1412 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1413 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1414 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($n eq 'all') {  
 
1415 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return @res  
 
1416 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1417 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $res[$n]  
 
1418 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1419 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1420 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->find_link( %options ) >>  
 
1421 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1422 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->text . "\n"  
 
1423 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->find_link( text_contains => 'CPAN' );  
 
1424 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1425 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A method quite similar to L's method.   
 
1426 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options are documented in C<< ->find_link_dom >>.  
 
1427 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1428 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns a L object.   
 
1429 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1430 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This defaults to not look through child frames.  
 
1431 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1432 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1433 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1434 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub find_link {  
 
1435 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%opts) = @_;  
 
1436 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $base = $self->base;  
 
1437 
 
 
 
 
 
 
 
 
 
 
 
 
 
     croak "Option 'all' not available for ->find_link. Did you mean to call ->find_all_links()?"  
 
1438 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
         if 'all' eq ($opts{n} || '');  
 
1439 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (my $link = $self->find_link_dom(frames => 0, %opts)) {  
 
1440 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         return $self->make_link($link, $base)  
 
1441 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
1442 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return  
 
1443 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1444 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1445 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1446 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->find_all_links( %options ) >>  
 
1447 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1448 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->text . "\n"  
 
1449 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->find_all_links( text_regex => qr/google/i );  
 
1450 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1451 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Finds all links in the document.  
 
1452 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options are documented in C<< ->find_link_dom >>.  
 
1453 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1454 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns them as list or an array reference, depending  
 
1455 
 
 
 
 
 
 
 
 
 
 
 
 
 
 on context.  
 
1456 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1457 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This defaults to not look through child frames.  
 
1458 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1459 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1460 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1461 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub find_all_links {  
 
1462 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %opts) = @_;  
 
1463 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $opts{ n } = 'all';  
 
1464 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $base = $self->base;  
 
1465 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @matches = map {  
 
1466 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->make_link($_, $base);  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1467 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } $self->find_all_links_dom( frames => 0, %opts );  
 
1468 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     return @matches if wantarray;  
 
1469 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return \@matches;  
 
1470 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1471 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1472 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->find_all_links_dom %options >>  
 
1473 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1474 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $_->{innerHTML} . "\n"  
 
1475 
 
 
 
 
 
 
 
 
 
 
 
 
 
       for $mech->find_all_links_dom( text_regex => qr/google/i );  
 
1476 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1477 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Finds all matching linky DOM nodes in the document.  
 
1478 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options are documented in C<< ->find_link_dom >>.  
 
1479 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1480 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns them as list or an array reference, depending  
 
1481 
 
 
 
 
 
 
 
 
 
 
 
 
 
 on context.  
 
1482 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1483 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This defaults to not look through child frames.  
 
1484 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1485 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1486 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1487 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub find_all_links_dom {  
 
1488 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%opts) = @_;  
 
1489 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $opts{ n } = 'all';  
 
1490 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @matches = $self->find_link_dom( frames => 0, %opts );  
 
1491 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     return @matches if wantarray;  
 
1492 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return \@matches;  
 
1493 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1494 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1495 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->follow_link( $link ) >>  
 
1496 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1497 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->follow_link( %options ) >>  
 
1498 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1499 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->follow_link( xpath => '//a[text() = "Click here!"]' );  
 
1500 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1501 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Follows the given link. Takes the same parameters that C   
 
1502 
 
 
 
 
 
 
 
 
 
 
 
 
 
 uses.  
 
1503 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1504 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Note that C<< ->follow_link >> will only try to follow link-like  
 
1505 
 
 
 
 
 
 
 
 
 
 
 
 
 
 things like C tags.   
 
1506 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1507 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1508 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1509 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub follow_link {  
 
1510 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$link,%opts);  
 
1511 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (@_ == 2) { # assume only a link parameter  
 
1512 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         ($self,$link) = @_;  
 
1513 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->click($link);  
 
1514 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
1515 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         ($self,%opts) = @_;  
 
1516 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         _default_limiter( one => \%opts );  
 
1517 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $link = $self->find_link_dom(%opts);  
 
1518 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->click({ dom => $link, %opts });  
 
1519 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
1520 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1521 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1522 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # We need to trace the path from the root element to every webelement  
 
1523 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # because stupid GhostDriver/Selenium caches elements per document,  
 
1524 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # and not globally, keyed by document. Switching the implied reference  
 
1525 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # document makes lots of API calls fail :-(  
 
1526 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub activate_parent_container {  
 
1527 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my( $self, $doc )= @_;  
 
1528 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->activate_container( $doc, 1 );  
 
1529 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1530 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1531 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub activate_container {  
 
1532 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my( $self, $doc, $just_parent )= @_;  
 
1533 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $driver= $self->driver;  
 
1534 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1535 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( ! $doc->{__path}) {  
 
1536 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         die "Invalid document without __path encountered. I'm sorry.";  
 
1537 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1538 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Activate the root window/frame  
 
1539 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn "Activating root frame:";  
 
1540 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$driver->switch_to_frame();  
 
1541 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn "Activating root frame done.";  
 
1542 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1543 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for my $el ( @{ $doc->{__path} }) {  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1544 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn "Switching frames downwards ($el)";  
 
1545 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn "Tag: " . $el->get_tag_name;  
 
1546 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #use Data::Dumper;  
 
1547 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn Dumper $el;  
 
1548 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn sprintf "Switching during path to %s %s", $el->get_tag_name, $el->get_attribute('src');  
 
1549 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $driver->switch_to_frame( $el );  
 
1550 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1551 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1552 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( ! $just_parent ) {  
 
1553 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn sprintf "Activating container %s too", $doc->{id};  
 
1554 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Now, unless it's the root frame, activate the container. The root frame  
 
1555 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # already is activated above.  
 
1556 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn "Getting tag";  
 
1557 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $tag= $doc->get_tag_name;  
 
1558 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #my $src= $doc->get_attribute('src');  
 
1559 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
         if( 'html' ne $tag and '' ne $tag) {  
 
1560 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #warn sprintf "Switching to final container %s %s", $tag, $src;  
 
1561 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $driver->switch_to_frame( $doc );  
 
1562 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1563 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn sprintf "Switched to final/main container %s %s", $tag, $src;  
 
1564 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1565 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn $self->driver->get_current_url;  
 
1566 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn $self->driver->get_title;  
 
1567 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $body= $doc->get_attribute('contentDocument');  
 
1568 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $body= $driver->find_element('/*', 'xpath');  
 
1569 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( $body ) {  
 
1570 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn "Now active container: " . $body->get_attribute('innerHTML');  
 
1571 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #$body= $body->get_attribute('document');  
 
1572 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn $body->get_attribute('innerHTML');  
 
1573 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1574 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1575 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1576 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->xpath( $query, %options ) >>  
 
1577 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1578 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $link = $mech->xpath('//a[id="clickme"]', one => 1);  
 
1579 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # croaks if there is no link or more than one link found  
 
1580 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1581 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @para = $mech->xpath('//p');  
 
1582 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Collects all paragraphs  
 
1583 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1584 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @para_text = $mech->xpath('//p/text()', type => $mech->xpathResult('STRING_TYPE'));  
 
1585 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Collects all paragraphs as text  
 
1586 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1587 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Runs an XPath query in PhantomJS against the current document.  
 
1588 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1589 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If you need more information about the returned results,  
 
1590 
 
 
 
 
 
 
 
 
 
 
 
 
 
 use the C<< ->xpathEx() >> function.  
 
1591 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1592 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options allow the following keys:  
 
1593 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1594 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
1595 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1596 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1597 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1598 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< document >> - document in which the query is to be executed. Use this to  
 
1599 
 
 
 
 
 
 
 
 
 
 
 
 
 
 search a node within a specific subframe of C<< $mech->document >>.  
 
1600 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1601 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1602 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1603 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< frames >> - if true, search all documents in all frames and iframes.  
 
1604 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This may or may not conflict with C. This will default to the   
 
1605 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C setting of the WWW::Mechanize::PhantomJS object.   
 
1606 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1607 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1608 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1609 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< node >> - node relative to which the query is to be executed. Note  
 
1610 
 
 
 
 
 
 
 
 
 
 
 
 
 
 that you will have to use a relative XPath expression as well. Use  
 
1611 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1612 
 
 
 
 
 
 
 
 
 
 
 
 
 
   .//foo  
 
1613 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1614 
 
 
 
 
 
 
 
 
 
 
 
 
 
 instead of  
 
1615 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1616 
 
 
 
 
 
 
 
 
 
 
 
 
 
   //foo  
 
1617 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1618 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1619 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1620 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< single >> - If true, ensure that only one element is found. Otherwise croak  
 
1621 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or carp, depending on the C parameter.   
 
1622 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1623 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1624 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1625 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< one >> - If true, ensure that at least one element is found. Otherwise croak  
 
1626 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or carp, depending on the C parameter.   
 
1627 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1628 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1629 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1630 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< maybe >> - If true, ensure that at most one element is found. Otherwise  
 
1631 
 
 
 
 
 
 
 
 
 
 
 
 
 
 croak or carp, depending on the C parameter.   
 
1632 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1633 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1634 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1635 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< all >> - If true, return all elements found. This is the default.  
 
1636 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can use this option if you want to use C<< ->xpath >> in scalar context  
 
1637 
 
 
 
 
 
 
 
 
 
 
 
 
 
 to count the number of matched elements, as it will otherwise emit a warning  
 
1638 
 
 
 
 
 
 
 
 
 
 
 
 
 
 for each usage in scalar context without any of the above restricting options.  
 
1639 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1640 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1641 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1642 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< any >> - no error is raised, no matter if an item is found or not.  
 
1643 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1644 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1645 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1646 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< type >> - force the return type of the query.  
 
1647 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1648 
 
 
 
 
 
 
 
 
 
 
 
 
 
   type => $mech->xpathResult('ORDERED_NODE_SNAPSHOT_TYPE'),  
 
1649 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1650 
 
 
 
 
 
 
 
 
 
 
 
 
 
 WWW::Mechanize::PhantomJS tries a best effort in giving you the appropriate  
 
1651 
 
 
 
 
 
 
 
 
 
 
 
 
 
 result of your query, be it a DOM node or a string or a number. In the case  
 
1652 
 
 
 
 
 
 
 
 
 
 
 
 
 
 you need to restrict the return type, you can pass this in.  
 
1653 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1654 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The allowed strings are documented in the MDN. Interesting types are  
 
1655 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1656 
 
 
 
 
 
 
 
 
 
 
 
 
 
   ANY_TYPE     (default, uses whatever things the query returns)  
 
1657 
 
 
 
 
 
 
 
 
 
 
 
 
 
   STRING_TYPE  
 
1658 
 
 
 
 
 
 
 
 
 
 
 
 
 
   NUMBER_TYPE  
 
1659 
 
 
 
 
 
 
 
 
 
 
 
 
 
   ORDERED_NODE_SNAPSHOT_TYPE  
 
1660 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1661 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
1662 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1663 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the matched results.  
 
1664 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1665 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can pass in a list of queries as an array reference for the first parameter.  
 
1666 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The result will then be the list of all elements matching any of the queries.  
 
1667 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1668 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is a method that is not implemented in WWW::Mechanize.  
 
1669 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1670 
 
 
 
 
 
 
 
 
 
 
 
 
 
 In the long run, this should go into a general plugin for  
 
1671 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L.   
 
1672 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1673 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1674 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1675 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub xpath {  
 
1676 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self, $query, %options) = @_;  
 
1677 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1678 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if ('ARRAY' ne (ref $query||'')) {  
 
1679 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $query = [$query];  
 
1680 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1681 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1682 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( not exists $options{ frames }) {  
 
1683 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options{ frames }= $self->{frames};  
 
1684 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1685 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1686 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $single = $options{ single };  
 
1687 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $first  = $options{ one };  
 
1688 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $maybe  = $options{ maybe };  
 
1689 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $any    = $options{ any };  
 
1690 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $return_first_element = ($single or $first or $maybe or $any );  
 
1691 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $options{ user_info }||= join "|", @$query;  
 
1692 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1693 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Construct some helper variables  
 
1694 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $zero_allowed = not ($single or $first);  
 
1695 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $two_allowed  = not( $single or $maybe);  
 
1696 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1697 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Sanity check for the common error of  
 
1698 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # my $item = $mech->xpath("//foo");  
 
1699 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if (! exists $options{ all } and not ($return_first_element)) {  
 
1700 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
         $self->signal_condition(join "\n",  
 
1701 
 
 
 
 
 
 
 
 
 
 
 
 
 
             "You asked for many elements but seem to only want a single item.",  
 
1702 
 
 
 
 
 
 
 
 
 
 
 
 
 
             "Did you forget to pass the 'single' option with a true value?",  
 
1703 
 
 
 
 
 
 
 
 
 
 
 
 
 
             "Pass 'all => 1' to suppress this message and receive the count of items.",  
 
1704 
 
 
 
 
 
 
 
 
 
 
 
 
 
         ) if defined wantarray and !wantarray;  
 
1705 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1706 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1707 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @res;  
 
1708 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1709 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Save the current frame, because maybe we switch frames while searching  
 
1710 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # We should ideally save the complete path here, not just the current position  
 
1711 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( $options{ document }) {  
 
1712 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn sprintf "Document %s", $options{ document }->{id};  
 
1713 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1714 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $original_frame= $self->current_frame;  
 
1715 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1716 
 
 
 
 
 
 
 
 
 
 
 
 
 
     DOCUMENTS: {  
 
1717 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         my $doc= $options{ document } || $self->document;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1718 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1719 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # This stores the path to this document  
 
1720 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         $doc->{__path}||= [];  
 
1721 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1722 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # @documents stores pairs of (containing document element, child element)  
 
1723 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my @documents= ($doc);  
 
1724 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1725 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # recursively join the results of sub(i)frames if wanted  
 
1726 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1727 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         while (@documents) {  
 
1728 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $doc = shift @documents;  
 
1729 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1730 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #$self->activate_container( $doc );  
 
1731 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1732 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $q = join "|", @$query;  
 
1733 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #warn $q;  
 
1734 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1735 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my @found;  
 
1736 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # Now find the elements  
 
1737 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if ($options{ node }) {  
 
1738 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #$doc ||= $options{ node }->get_attribute( 'documentElement' );  
 
1739 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #if( $options{ document } and $options{ document }->get_tag_name =~ /^i?frame$/i) {  
 
1740 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #    $self->driver->switch_to_frame( $options{ document });  
 
1741 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #} elsif( $options{ document } and $options{ document }->get_tag_name =~ /^html$/i) {  
 
1742 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #    $self->driver->switch_to_frame();  
 
1743 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #} elsif( $options{ document }) {  
 
1744 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #    die sprintf "Don't know how to switch to a '%s'", $options{ document }->get_tag_name;  
 
1745 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #};  
 
1746 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 @found= map { $self->driver->find_child_elements( $options{ node }, $_ => 'xpath' ) } @$query;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1747 
 
 
 
 
 
 
 
 
 
 
 
 
 
             } else {  
 
1748 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn "Collecting frames";  
 
1749 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #my $tag= $doc->get_tag_name;  
 
1750 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn "Searching $doc->{id} for @$query";  
 
1751 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 @found= map { $self->driver->find_elements( $_ => 'xpath' ) } @$query;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1752 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
                 if( ! @found ) {  
 
1753 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     #warn "Nothing found matching @$query in frame";  
 
1754 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     #warn $self->content;  
 
1755 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     #$self->driver->switch_to_frame();  
 
1756 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 };  
 
1757 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #$self->driver->switch_to_frame();  
 
1758 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn $doc->get_text;  
 
1759 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
1760 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1761 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # Remember the path to each found element  
 
1762 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             for( @found ) {  
 
1763 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 # We reuse the reference here instead of copying the list. So don't modify the list.  
 
1764 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 $_->{__path}= $doc->{__path};  
 
1765 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
1766 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1767 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             push @res, @found;  
 
1768 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1769 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # A small optimization to return if we already have enough elements  
 
1770 
 
 
 
 
 
 
 
 
 
 
 
 
 
             # We can't do this on $return_first as there might be more elements  
 
1771 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #if( @res and $options{ return_first } and grep { $_->{resultSize} } @res ) {  
 
1772 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #    @res= grep { $_->{resultSize} } @res;  
 
1773 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #    last DOCUMENTS;  
 
1774 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #};  
 
1775 
 
33
 
 
 
 
 
  
33
   
 
 
 
313
 
             use Data::Dumper;  
 
  
 
33
 
 
 
 
 
 
 
 
 
83
 
    
 
  
 
33
 
 
 
 
 
 
 
 
 
188902
 
    
 
1776 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #warn Dumper \@documents;  
 
1777 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
             if ($options{ frames } and not $options{ node }) {  
 
1778 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn "Expanding subframes";  
 
1779 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn ">Expanding below " . $doc->get_tag_name() . ' - ' . $doc->get_attribute('title');  
 
1780 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #local $nesting .= "--";  
 
1781 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 my @d; # = $self->expand_frames( $options{ frames }, $doc );  
 
1782 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 #warn sprintf("Found %s %s pointing to %s", $_->get_tag_name, $_->{id}, $_->get_attribute('src')) for @d;  
 
1783 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 push @documents, @d;  
 
1784 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
1785 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1786 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1787 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1788 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Restore frame context  
 
1789 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn "Switching back";  
 
1790 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$self->activate_container( $original_frame );  
 
1791 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1792 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #@res  
 
1793 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1794 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Determine if we want only one element  
 
1795 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #     or a list, like WWW::Mechanize::PhantomJS  
 
1796 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1797 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if (! $zero_allowed and @res == 0) {  
 
1798 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->signal_condition( "No elements found for $options{ user_info }" );  
 
1799 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1800 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if (! $two_allowed and @res > 1) {  
 
1801 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #$self->highlight_node(@res);  
 
1802 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         warn $_->get_text() || '' for @res;   
 
1803 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->signal_condition( (scalar @res) . " elements found for $options{ user_info }" );  
 
1804 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1805 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1806 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $return_first_element ? $res[0] : @res  
 
1807 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1808 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1809 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1810 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->by_id( $id, %options ) >>  
 
1811 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1812 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my @text = $mech->by_id('_foo:bar');  
 
1813 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1814 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns all nodes matching the given ids. If  
 
1815 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<$id> is an array reference, it returns  
 
1816 
 
 
 
 
 
 
 
 
 
 
 
 
 
 all nodes matched by any of the ids in the array.  
 
1817 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1818 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is equivalent to calling C<< ->xpath >> :  
 
1819 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1820 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $self->xpath(qq{//*[\@id="$_"], %options)  
 
1821 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1822 
 
 
 
 
 
 
 
 
 
 
 
 
 
 It is convenient when your element ids get mistaken for  
 
1823 
 
 
 
 
 
 
 
 
 
 
 
 
 
 CSS selectors.  
 
1824 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1825 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1826 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1827 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub by_id {  
 
1828 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$query,%options) = @_;  
 
1829 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if ('ARRAY' ne (ref $query||'')) {  
 
1830 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $query = [$query];  
 
1831 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1832 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $options{ user_info } ||= "id "  
 
1833 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
                             . join(" or ", map {qq{'$_'}} @$query)  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1834 
 
 
 
 
 
 
 
 
 
 
 
 
 
                             . " found";  
 
1835 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $query = [map { qq{.//*[\@id="$_"]} } @$query];  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1836 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->xpath($query, %options)  
 
1837 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1838 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1839 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->click( $name [,$x ,$y] ) >>  
 
1840 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1841 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->click( 'go' );  
 
1842 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->click({ xpath => '//button[@name="go"]' });  
 
1843 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1844 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Has the effect of clicking a button (or other element) on the current form. The  
 
1845 
 
 
 
 
 
 
 
 
 
 
 
 
 
 first argument is the C of the button to be clicked. The second and third   
 
1846 
 
 
 
 
 
 
 
 
 
 
 
 
 
 arguments (optional) allow you to specify the (x,y) coordinates of the click.  
 
1847 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1848 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If there is only one button on the form, C<< $mech->click() >> with  
 
1849 
 
 
 
 
 
 
 
 
 
 
 
 
 
 no arguments simply clicks that one button.  
 
1850 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1851 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If you pass in a hash reference instead of a name,  
 
1852 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the following keys are recognized:  
 
1853 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1854 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
1855 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1856 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1857 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1858 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - Find the element to click by the CSS selector   
 
1859 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1860 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1861 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1862 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - Find the element to click by the XPath query   
 
1863 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1864 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1865 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1866 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - Click on the passed DOM element   
 
1867 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1868 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can use this to click on arbitrary page elements. There is no convenient  
 
1869 
 
 
 
 
 
 
 
 
 
 
 
 
 
 way to pass x/y co-ordinates with this method.  
 
1870 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1871 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1872 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1873 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - Click on the element with the given id   
 
1874 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1875 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is useful if your document ids contain characters that  
 
1876 
 
 
 
 
 
 
 
 
 
 
 
 
 
 do look like CSS selectors. It is equivalent to  
 
1877 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1878 
 
 
 
 
 
 
 
 
 
 
 
 
 
     xpath => qq{//*[\@id="$id"]}  
 
1879 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1880 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
1881 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1882 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns a L object.   
 
1883 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1884 
 
 
 
 
 
 
 
 
 
 
 
 
 
 As a deviation from the WWW::Mechanize API, you can also pass a  
 
1885 
 
 
 
 
 
 
 
 
 
 
 
 
 
 hash reference as the first parameter. In it, you can specify  
 
1886 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the parameters to search much like for the C calls.   
 
1887 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1888 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
1889 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1890 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub click {  
 
1891 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$name,$x,$y) = @_;  
 
1892 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my %options;  
 
1893 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @buttons;  
 
1894 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1895 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if (! defined $name) {  
 
  
 
 
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
    
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
1896 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         croak("->click called with undef link");  
 
1897 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (ref $name and blessed($name) and $name->can('click')) {  
 
1898 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options{ dom } = $name;  
 
1899 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (ref $name eq 'HASH') { # options  
 
1900 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         %options = %$name;  
 
1901 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
1902 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options{ name } = $name;  
 
1903 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1904 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1905 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (exists $options{ name }) {  
 
1906 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         $name = quotemeta($options{ name }|| '');  
 
1907 
 
 
 
 
 
 
 
 
 
 
 
 
 
         $options{ xpath } = [  
 
1908 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                        sprintf( q{//*[(translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="button" and @name="%s") or (translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="input" and (@type="button" or @type="submit" or @type="image") and @name="%s")]}, $name, $name),  
 
1909 
 
 
 
 
 
 
 
 
 
 
 
 
 
         ];  
 
1910 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ($options{ name } eq '') {  
 
1911 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             push @{ $options{ xpath }},  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1912 
 
 
 
 
 
 
 
 
 
 
 
 
 
                        q{//*[(translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "button" or translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="input") and @type="button" or @type="submit" or @type="image"]},  
 
1913 
 
 
 
 
 
 
 
 
 
 
 
 
 
             ;  
 
1914 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
1915 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options{ user_info } = "Button with name '$name'";  
 
1916 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1917 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1918 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($options{ dom }) {  
 
1919 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @buttons = $options{ dom };  
 
1920 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
1921 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @buttons = $self->_option_query(%options);  
 
1922 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1923 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1924 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $buttons[0]->click();  
 
1925 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->post_process;  
 
1926 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1927 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (defined wantarray) {  
 
1928 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         return $self->response  
 
1929 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1930 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
1931 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1932 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Internal method to run either an XPath, CSS or id query against the DOM  
 
1933 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Returns the element(s) found  
 
1934 
 
 
 
 
 
 
 
 
 
 
 
 
 
 my %rename = (  
 
1935 
 
 
 
 
 
 
 
 
 
 
 
 
 
     xpath => 'xpath',  
 
1936 
 
 
 
 
 
 
 
 
 
 
 
 
 
     selector => 'selector',  
 
1937 
 
 
 
 
 
 
 
 
 
 
 
 
 
     id => 'by_id',  
 
1938 
 
 
 
 
 
 
 
 
 
 
 
 
 
     by_id => 'by_id',  
 
1939 
 
 
 
 
 
 
 
 
 
 
 
 
 
 );  
 
1940 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1941 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub _option_query {  
 
1942 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
     my ($self,%options) = @_;  
 
1943 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my ($method,$q);  
 
1944 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for my $meth (keys %rename) {  
 
1945 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if (exists $options{ $meth }) {  
 
1946 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $q = delete $options{ $meth };  
 
1947 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
             $method = $rename{ $meth } || $meth;  
 
1948 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
1949 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1950 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     _default_limiter( 'one' => \%options );  
 
1951 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     croak "Need either a name, a selector or an xpath key!"  
 
1952 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if not $method;  
 
1953 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->$method( $q, %options );  
 
1954 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1955 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1956 
 
 
 
 
 
 
 
 
 
 
 
 
 
 # Return the default limiter if no other limiting option is set:  
 
1957 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub _default_limiter {  
 
1958 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
     my ($default, $options) = @_;  
 
1959 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (! grep { exists $options->{ $_ } } qw(single one maybe all any)) {  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
1960 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options->{ $default } = 1;  
 
1961 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
1962 
 
 
 
 
 
 
 
 
 
 
 
 
 
     return ()  
 
1963 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
 };  
 
1964 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1965 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->click_button( ... ) >>  
 
1966 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1967 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->click_button( name => 'go' );  
 
1968 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->click_button( input => $mybutton );  
 
1969 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1970 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Has the effect of clicking a button on the current form by specifying its  
 
1971 
 
 
 
 
 
 
 
 
 
 
 
 
 
 name, value, or index. Its arguments are a list of key/value pairs. Only  
 
1972 
 
 
 
 
 
 
 
 
 
 
 
 
 
 one of name, number, input or value must be specified in the keys.  
 
1973 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1974 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
1975 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1976 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1977 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1978 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - name of the button   
 
1979 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1980 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1981 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1982 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - value of the button   
 
1983 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1984 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1985 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1986 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C  - DOM node  
 
1987 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1988 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1989 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1990 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - id of the button   
 
1991 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1992 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
1993 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1994 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C - number of the button   
 
1995 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1996 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
1997 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
1998 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If you find yourself wanting to specify a button through its  
 
1999 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C or C, consider using C<< ->click >> instead.    
 
2000 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2001 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2002 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2003 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub click_button {  
 
2004 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%options) = @_;  
 
2005 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $node;  
 
2006 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $xpath;  
 
2007 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $user_message;  
 
2008 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (exists $options{ input }) {  
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
2009 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $node = delete $options{ input };  
 
2010 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (exists $options{ name }) {  
 
2011 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $v = delete $options{ name };  
 
2012 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $xpath = sprintf( '//*[(translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "button" and @name="%s") or (translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="input" and @type="button" or @type="submit" and @name="%s")]', $v, $v);  
 
2013 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $user_message = "Button name '$v' unknown";  
 
2014 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (exists $options{ value }) {  
 
2015 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $v = delete $options{ value };  
 
2016 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $xpath = sprintf( '//*[(translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "button" and @value="%s") or (translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="input" and (@type="button" or @type="submit") and @value="%s")]', $v, $v);  
 
2017 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $user_message = "Button value '$v' unknown";  
 
2018 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (exists $options{ id }) {  
 
2019 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $v = delete $options{ id };  
 
2020 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $xpath = sprintf '//*[@id="%s"]', $v;  
 
2021 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $user_message = "Button name '$v' unknown";  
 
2022 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif (exists $options{ number }) {  
 
2023 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $v = delete $options{ number };  
 
2024 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $xpath = sprintf '//*[translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "button" or (translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") = "input" and @type="submit")][%s]', $v;  
 
2025 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $user_message = "Button number '$v' out of range";  
 
2026 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2027 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $node ||= $self->xpath( $xpath,  
 
2028 
 
 
 
 
 
 
 
 
 
 
 
 
 
                           node => $self->current_form,  
 
2029 
 
 
 
 
 
 
 
 
 
 
 
 
 
                           single => 1,  
 
2030 
 
 
 
 
 
 
 
 
 
 
 
 
 
                           user_message => $user_message,  
 
2031 
 
 
 
 
 
 
 
 
 
 
 
 
 
               );  
 
2032 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($node) {  
 
2033 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->click({ dom => $node, %options });  
 
2034 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2035 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2036 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->signal_condition($user_message);  
 
2037 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2038 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2039 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2040 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2041 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 FORM METHODS  
 
2042 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2043 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->current_form() >>  
 
2044 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2045 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print $mech->current_form->{name};  
 
2046 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2047 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current form.  
 
2048 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2049 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is incompatible with L.   
 
2050 
 
 
 
 
 
 
 
 
 
 
 
 
 
 It returns the DOM C<<  
 
2051 
 
 
 
 
 
 
 
 
 
 
 
 
 
 a L instance.   
 
2052 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2053 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The current form will be reset by WWW::Mechanize::PhantomJS  
 
2054 
 
 
 
 
 
 
 
 
 
 
 
 
 
 on calls to C<< ->get() >> and C<< ->get_local() >>,  
 
2055 
 
 
 
 
 
 
 
 
 
 
 
 
 
 and on calls to C<< ->submit() >> and C<< ->submit_with_fields >>.  
 
2056 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2057 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2058 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2059 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub current_form {  
 
2060 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self, %options )= @_;  
 
2061 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Find the first  
 
2062 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $self->form_number(1) unless $self->{current_form};  
 
2063 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form};  
 
2064 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2065 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2066 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub clear_current_form {  
 
2067 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     undef $_[0]->{current_form};  
 
2068 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2069 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2070 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub active_form {  
 
2071 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my( $self, %options )= @_;  
 
2072 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Find the first  
 
2073 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $focus= $self->driver->get_active_element;  
 
2074 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2075 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( !$focus ) {  
 
2076 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn "No active element, hence no active form";  
 
2077 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return  
 
2078 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2079 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2080 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $form= $self->xpath( './ancestor-or-self::FORM', node => $focus, maybe => 1 );  
 
2081 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2082 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2083 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2084 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->dump_forms( [$fh] ) >>  
 
2085 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2086 
 
 
 
 
 
 
 
 
 
 
 
 
 
   open my $fh, '>', 'form-log.txt'  
 
2087 
 
 
 
 
 
 
 
 
 
 
 
 
 
       or die "Couldn't open logfile 'form-log.txt': $!";  
 
2088 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->dump_forms( $fh );  
 
2089 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2090 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Prints a dump of the forms on the current page to  
 
2091 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the filehandle C<$fh>. If C<$fh> is not specified or is undef, it dumps  
 
2092 
 
 
 
 
 
 
 
 
 
 
 
 
 
 to C.   
 
2093 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2094 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2095 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2096 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub dump_forms {  
 
2097 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my $self = shift;  
 
2098 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $fh = shift || \*STDOUT;  
 
2099 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2100 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for my $form ( $self->forms ) {  
 
2101 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         print {$fh} "[FORM] ", $form->get_attribute('name') || '', ' ', $form->get_attribute('action'), "\n";   
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2102 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #for my $f ($self->xpath( './/*', node => $form )) {  
 
2103 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #for my $f ($self->xpath( './/*[contains(" "+translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")+" "," input textarea button select "  
 
2104 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #                                        )]', node => $form )) {  
 
2105 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         for my $f ($self->xpath( './/*[contains(" input textarea button select ",concat(" ",translate(local-name(.), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")," "))]', node => $form )) {  
 
2106 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $type;  
 
2107 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
             if($type= $f->get_attribute('type') || '' ) {  
 
2108 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 $type= " ($type)";  
 
2109 
 
 
 
 
 
 
 
 
 
 
 
 
 
             };  
 
2110 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2111 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
             print {$fh} "    [", $f->get_attribute('tagName'), $type, "] ", $f->get_attribute('name') || '', "\n";   
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2112 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2113 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2114 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return;  
 
2115 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2116 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2117 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->form_name( $name [, %options] ) >>  
 
2118 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2119 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->form_name( 'search' );  
 
2120 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2121 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Selects the current form by its name. The options  
 
2122 
 
 
 
 
 
 
 
 
 
 
 
 
 
 are identical to those accepted by the L<< /$mech->xpath >> method.  
 
2123 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2124 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2125 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2126 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub form_name {  
 
2127 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$name,%options) = @_;  
 
2128 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $name = quote_xpath $name;  
 
2129 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     _default_limiter( single => \%options );  
 
2130 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form} = $self->selector("form[name='$name']",  
 
2131 
 
 
 
 
 
 
 
 
 
 
 
 
 
         user_info => "form name '$name'",  
 
2132 
 
 
 
 
 
 
 
 
 
 
 
 
 
         %options  
 
2133 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2134 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2135 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2136 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->form_id( $id [, %options] ) >>  
 
2137 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2138 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->form_id( 'login' );  
 
2139 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2140 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Selects the current form by its C attribute.   
 
2141 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options  
 
2142 
 
 
 
 
 
 
 
 
 
 
 
 
 
 are identical to those accepted by the L<< /$mech->xpath >> method.  
 
2143 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2144 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is equivalent to calling  
 
2145 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2146 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->by_id($id,single => 1,%options)  
 
2147 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2148 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2149 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2150 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub form_id {  
 
2151 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$name,%options) = @_;  
 
2152 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2153 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     _default_limiter( single => \%options );  
 
2154 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form} = $self->by_id($name,  
 
2155 
 
 
 
 
 
 
 
 
 
 
 
 
 
         user_info => "form with id '$name'",  
 
2156 
 
 
 
 
 
 
 
 
 
 
 
 
 
         %options  
 
2157 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2158 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2159 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2160 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->form_number( $number [, %options] ) >>  
 
2161 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2162 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->form_number( 2 );  
 
2163 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2164 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Selects the Ith form.   
 
2165 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options  
 
2166 
 
 
 
 
 
 
 
 
 
 
 
 
 
 are identical to those accepted by the L<< /$mech->xpath >> method.  
 
2167 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2168 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2169 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2170 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub form_number {  
 
2171 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$number,%options) = @_;  
 
2172 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2173 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     _default_limiter( single => \%options );  
 
2174 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form} = $self->xpath("(//form)[$number]",  
 
2175 
 
 
 
 
 
 
 
 
 
 
 
 
 
         user_info => "form number $number",  
 
2176 
 
 
 
 
 
 
 
 
 
 
 
 
 
         %options  
 
2177 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2178 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2179 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2180 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->form_with_fields( [$options], @fields ) >>  
 
2181 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2182 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->form_with_fields(  
 
2183 
 
 
 
 
 
 
 
 
 
 
 
 
 
       'user', 'password'  
 
2184 
 
 
 
 
 
 
 
 
 
 
 
 
 
   );  
 
2185 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2186 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Find the form which has the listed fields.  
 
2187 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2188 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If the first argument is a hash reference, it's taken  
 
2189 
 
 
 
 
 
 
 
 
 
 
 
 
 
 as options to C<< ->xpath >>.  
 
2190 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2191 
 
 
 
 
 
 
 
 
 
 
 
 
 
 See also L<< /$mech->submit_form >>.  
 
2192 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2193 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2194 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2195 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub form_with_fields {  
 
2196 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,@fields) = @_;  
 
2197 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $options = {};  
 
2198 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (ref $fields[0] eq 'HASH') {  
 
2199 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $options = shift @fields;  
 
2200 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2201 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @clauses  = map { $self->element_query([qw[input select textarea]], { 'name' => $_ })} @fields;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2202 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2203 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2204 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $q = "//form[" . join( " and ", @clauses)."]";  
 
2205 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn $q;  
 
2206 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     _default_limiter( single => $options );  
 
2207 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form} = $self->xpath($q,  
 
2208 
 
 
 
 
 
 
 
 
 
 
 
 
 
         user_info => "form with fields [@fields]",  
 
2209 
 
 
 
 
 
 
 
 
 
 
 
 
 
         %$options  
 
2210 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2211 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn $form;  
 
2212 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->{current_form};  
 
2213 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2214 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2215 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->forms( %options ) >>  
 
2216 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2217 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my @forms = $mech->forms();  
 
2218 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2219 
 
 
 
 
 
 
 
 
 
 
 
 
 
 When called in a list context, returns a list  
 
2220 
 
 
 
 
 
 
 
 
 
 
 
 
 
 of the forms found in the last fetched page.  
 
2221 
 
 
 
 
 
 
 
 
 
 
 
 
 
 In a scalar context, returns a reference to  
 
2222 
 
 
 
 
 
 
 
 
 
 
 
 
 
 an array with those forms.  
 
2223 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2224 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The options  
 
2225 
 
 
 
 
 
 
 
 
 
 
 
 
 
 are identical to those accepted by the L<< /$mech->selector >> method.  
 
2226 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2227 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The returned elements are the DOM C<<  
 
2228 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2229 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2230 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2231 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub forms {  
 
2232 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %options) = @_;  
 
2233 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @res = $self->selector('form', %options);  
 
2234 
 
 
 
 
 
 
 
 
 
 
 
 
 
     return wantarray ? @res  
 
2235 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
                      : \@res  
 
2236 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2237 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2238 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->field( $selector, $value, [,\@pre_events [,\@post_events]] ) >>  
 
2239 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2240 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->field( user => 'joe' );  
 
2241 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->field( not_empty => '', [], [] ); # bypass JS validation  
 
2242 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2243 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Sets the field with the name given in C<$selector> to the given value.  
 
2244 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the value.  
 
2245 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2246 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The method understands very basic CSS selectors in the value for C<$selector>,  
 
2247 
 
 
 
 
 
 
 
 
 
 
 
 
 
 like the L find_input() method.   
 
2248 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2249 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A selector prefixed with '#' must match the id attribute of the input.  
 
2250 
 
 
 
 
 
 
 
 
 
 
 
 
 
 A selector prefixed with '.' matches the class attribute. A selector  
 
2251 
 
 
 
 
 
 
 
 
 
 
 
 
 
 prefixed with '^' or with no prefix matches the name attribute.  
 
2252 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2253 
 
 
 
 
 
 
 
 
 
 
 
 
 
 By passing the array reference C<@pre_events>, you can indicate which  
 
2254 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Javascript events you want to be triggered before setting the value.  
 
2255 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<@post_events> contains the events you want to be triggered  
 
2256 
 
 
 
 
 
 
 
 
 
 
 
 
 
 after setting the value.  
 
2257 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2258 
 
 
 
 
 
 
 
 
 
 
 
 
 
 By default, the events set in the  
 
2259 
 
 
 
 
 
 
 
 
 
 
 
 
 
 constructor for C and C    
 
2260 
 
 
 
 
 
 
 
 
 
 
 
 
 
 are triggered.  
 
2261 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2262 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2263 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2264 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub field {  
 
2265 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$name,$value,$pre,$post) = @_;  
 
2266 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->get_set_value(  
 
2267 
 
 
 
 
 
 
 
 
 
 
 
 
 
         name => $name,  
 
2268 
 
 
 
 
 
 
 
 
 
 
 
 
 
         value => $value,  
 
2269 
 
 
 
 
 
 
 
 
 
 
 
 
 
         pre => $pre,  
 
2270 
 
 
 
 
 
 
 
 
 
 
 
 
 
         post => $post,  
 
2271 
 
 
 
 
 
 
 
 
 
 
 
 
 
         node => $self->current_form,  
 
2272 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2273 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2274 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2275 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->value( $selector_or_element, [%options] ) >>  
 
2276 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2277 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print $mech->value( 'user' );  
 
2278 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2279 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the value of the field given by C<$selector_or_name> or of the  
 
2280 
 
 
 
 
 
 
 
 
 
 
 
 
 
 DOM element passed in.  
 
2281 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2282 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The legacy form of  
 
2283 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2284 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->value( name => value );  
 
2285 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2286 
 
 
 
 
 
 
 
 
 
 
 
 
 
 is also still supported but will likely be deprecated  
 
2287 
 
 
 
 
 
 
 
 
 
 
 
 
 
 in favour of the C<< ->field >> method.  
 
2288 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2289 
 
 
 
 
 
 
 
 
 
 
 
 
 
 For fields that can have multiple values, like a C field,   
 
2290 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the method is context sensitive and returns the first selected  
 
2291 
 
 
 
 
 
 
 
 
 
 
 
 
 
 value in scalar context and all values in list context.  
 
2292 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2293 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2294 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2295 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub value {  
 
2296 
 
  
0
   
 
  
  0
   
 
 
 
  
0
   
 
  
1
   
 
 
 
     if (@_ == 3) {  
 
2297 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my ($self,$name,$value) = @_;  
 
2298 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         return $self->field($name => $value);  
 
2299 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2300 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my ($self,$name,%options) = @_;  
 
2301 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         return $self->get_set_value(  
 
2302 
 
 
 
 
 
 
 
 
 
 
 
 
 
             node => $self->current_form,  
 
2303 
 
 
 
 
 
 
 
 
 
 
 
 
 
             %options,  
 
2304 
 
 
 
 
 
 
 
 
 
 
 
 
 
             name => $name,  
 
2305 
 
 
 
 
 
 
 
 
 
 
 
 
 
         );  
 
2306 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2307 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2308 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2309 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->get_set_value( %options ) >>  
 
2310 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2311 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Allows fine-grained access to getting/setting a value  
 
2312 
 
 
 
 
 
 
 
 
 
 
 
 
 
 with a different API. Supported keys are:  
 
2313 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2314 
 
 
 
 
 
 
 
 
 
 
 
 
 
   pre  
 
2315 
 
 
 
 
 
 
 
 
 
 
 
 
 
   post  
 
2316 
 
 
 
 
 
 
 
 
 
 
 
 
 
   name  
 
2317 
 
 
 
 
 
 
 
 
 
 
 
 
 
   value  
 
2318 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2319 
 
 
 
 
 
 
 
 
 
 
 
 
 
 in addition to all keys that C<< $mech->xpath >> supports.  
 
2320 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2321 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2322 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2323 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub _field_by_name {  
 
2324 
 
  
0
   
 
 
 
 
 
  
0
   
 
 
 
 
 
     my ($self,%options) = @_;  
 
2325 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @fields;  
 
2326 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $name  = delete $options{ name };  
 
2327 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $attr = 'name';  
 
2328 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($name =~ s/^\^//) { # if it starts with ^, it's supposed to be a name  
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
2329 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $attr = 'name'  
 
2330 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif ($name =~ s/^#//) {  
 
2331 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $attr = 'id'  
 
2332 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } elsif ($name =~ s/^\.//) {  
 
2333 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $attr = 'class'  
 
2334 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2335 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (blessed $name) {  
 
2336 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @fields = $name;  
 
2337 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2338 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         _default_limiter( single => \%options );  
 
2339 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $query = $self->element_query([qw[input select textarea]], { $attr => $name });  
 
2340 
 
 
 
 
 
 
 
 
 
 
 
 
 
         #warn $query;  
 
2341 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @fields = $self->xpath($query,%options);  
 
2342 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2343 
 
 
 
 
 
 
 
 
 
 
 
 
 
     @fields  
 
2344 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2345 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2346 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub escape  
 
2347 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
2348 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my $s = shift;  
 
2349 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $s =~ s/(["\\])/\\$1/g;  
 
2350 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $s =~ s/\n/\\n/g;  
 
2351 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $s =~ s/\r/\\r/g;  
 
2352 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $s;  
 
2353 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2354 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2355 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub get_set_value {  
 
2356 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%options) = @_;  
 
2357 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $set_value = exists $options{ value };  
 
2358 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $value = delete $options{ value };  
 
2359 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $pre   = delete $options{pre}  || $self->{pre_value};  
 
2360 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $post  = delete $options{post} || $self->{post_value};  
 
2361 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $name  = delete $options{ name };  
 
2362 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @fields = $self->_field_by_name(  
 
2363 
 
 
 
 
 
 
 
 
 
 
 
 
 
                      name => $name,  
 
2364 
 
 
 
 
 
 
 
 
 
 
 
 
 
                      user_info => "input with name '$name'",  
 
2365 
 
 
 
 
 
 
 
 
 
 
 
 
 
                      %options );  
 
2366 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $pre = [$pre]  
 
2367 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if (! ref $pre);  
 
2368 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     $post = [$post]  
 
2369 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if (! ref $post);  
 
2370 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2371 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($fields[0]) {  
 
2372 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         my $tag = $fields[0]->get_tag_name();  
 
2373 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ($set_value) {  
 
2374 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #for my $ev (@$pre) {  
 
2375 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #    $fields[0]->__event($ev);  
 
2376 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #};  
 
2377 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2378 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $get= $self->PhantomJS_elementToJS();  
 
2379 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $val= escape($value);  
 
2380 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             my $bool = $value ? 'true' : 'false';  
 
2381 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my $js= <
   
2382 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 var g=$get;  
 
2383 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 var el=g("$fields[0]->{id}");  
 
2384 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 if (el.type=='checkbox')  
 
2385 
 
 
 
 
 
 
 
 
 
 
 
 
 
                    el.checked=$bool;  
 
2386 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 else  
 
2387 
 
 
 
 
 
 
 
 
 
 
 
 
 
                    el.value="$val";  
 
2388 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2389 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $js= quotemeta($js);  
 
2390 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $self->eval("eval('$js')"); # for some reason, Selenium/Ghostdriver don't like the JS as plain JS  
 
2391 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2392 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #for my $ev (@$post) {  
 
2393 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #    $fields[0]->__event($ev);  
 
2394 
 
 
 
 
 
 
 
 
 
 
 
 
 
             #};  
 
2395 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2396 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # What about 'checkbox'es/radioboxes?  
 
2397 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2398 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Don't bother to fetch the field's value if it's not wanted  
 
2399 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         return unless defined wantarray;  
 
2400 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2401 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # We could save some work here for the simple case of single-select  
 
2402 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # dropdowns by not enumerating all options  
 
2403 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ('SELECT' eq uc $tag) {  
 
2404 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my @options = $self->xpath('.//option', node => $fields[0] );  
 
2405 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my @values = map { $_->{value} } grep { $_->{selected} } @options;  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2406 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if (wantarray) {  
 
2407 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 return @values  
 
2408 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             } else {  
 
2409 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 return $values[0];  
 
2410 
 
 
 
 
 
 
 
 
 
 
 
 
 
             }  
 
2411 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } else {  
 
2412 
 
 
 
 
 
 
 
 
 
 
 
 
 
             return $fields[0]->{value}  
 
2413 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2414 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2415 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return  
 
2416 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2417 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2418 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2419 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->submit( $form ) >>  
 
2420 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2421 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->submit;  
 
2422 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2423 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Submits the form. Note that this does B fire the C    
 
2424 
 
 
 
 
 
 
 
 
 
 
 
 
 
 event and thus also does not fire eventual Javascript handlers.  
 
2425 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Maybe you want to use C<< $mech->click >> instead.  
 
2426 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2427 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The default is to submit the current form as returned  
 
2428 
 
 
 
 
 
 
 
 
 
 
 
 
 
 by C<< $mech->current_form >>.  
 
2429 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2430 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2431 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2432 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub submit {  
 
2433 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,$dom_form) = @_;  
 
2434 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $dom_form ||= $self->current_form;  
 
2435 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ($dom_form) {  
 
2436 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $dom_form->submit();  
 
2437 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->signal_http_status;  
 
2438 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2439 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->clear_current_form;  
 
2440 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         1;  
 
2441 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2442 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         croak "I don't know which form to submit, sorry.";  
 
2443 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2444 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->post_process;  
 
2445 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->response;  
 
2446 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2447 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2448 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->submit_form( %options ) >>  
 
2449 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2450 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->submit_form(  
 
2451 
 
 
 
 
 
 
 
 
 
 
 
 
 
       with_fields => {  
 
2452 
 
 
 
 
 
 
 
 
 
 
 
 
 
           user => 'me',  
 
2453 
 
 
 
 
 
 
 
 
 
 
 
 
 
           pass => 'secret',  
 
2454 
 
 
 
 
 
 
 
 
 
 
 
 
 
       }  
 
2455 
 
 
 
 
 
 
 
 
 
 
 
 
 
   );  
 
2456 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2457 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method lets you select a form from the previously fetched page,  
 
2458 
 
 
 
 
 
 
 
 
 
 
 
 
 
 fill in its fields, and submit it. It combines the form_number/form_name,  
 
2459 
 
 
 
 
 
 
 
 
 
 
 
 
 
 set_fields and click methods into one higher level call. Its arguments are  
 
2460 
 
 
 
 
 
 
 
 
 
 
 
 
 
 a list of key/value pairs, all of which are optional.  
 
2461 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2462 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
2463 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2464 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
2465 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2466 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< form => $mech->current_form() >>  
 
2467 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2468 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specifies the form to be filled and submitted. Defaults to the current form.  
 
2469 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2470 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
2471 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2472 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< fields => \%fields >>  
 
2473 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2474 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Specifies the fields to be filled in the current form  
 
2475 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2476 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
2477 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2478 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< with_fields => \%fields >>  
 
2479 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2480 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Probably all you need for the common case. It combines a smart form selector  
 
2481 
 
 
 
 
 
 
 
 
 
 
 
 
 
 and data setting in one operation. It selects the first form that contains  
 
2482 
 
 
 
 
 
 
 
 
 
 
 
 
 
 all fields mentioned in \%fields. This is nice because you don't need to  
 
2483 
 
 
 
 
 
 
 
 
 
 
 
 
 
 know the name or number of the form to do this.  
 
2484 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2485 
 
 
 
 
 
 
 
 
 
 
 
 
 
 (calls L<< /$mech->form_with_fields() >> and L<< /$mech->set_fields() >>).  
 
2486 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2487 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If you choose this, the form_number, form_name, form_id and fields options  
 
2488 
 
 
 
 
 
 
 
 
 
 
 
 
 
 will be ignored.  
 
2489 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2490 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
2491 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2492 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2493 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2494 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub submit_form {  
 
2495 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self,%options) = @_;  
 
2496 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2497 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $form = delete $options{ form };  
 
2498 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $fields;  
 
2499 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (! $form) {  
 
2500 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ($fields = delete $options{ with_fields }) {  
 
2501 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             my @names = keys %$fields;  
 
2502 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $form = $self->form_with_fields( \%options, @names );  
 
2503 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             if (! $form) {  
 
2504 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 $self->signal_condition("Couldn't find a matching form for @names.");  
 
2505 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 return  
 
2506 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             };  
 
2507 
 
 
 
 
 
 
 
 
 
 
 
 
 
         } else {  
 
2508 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
             $fields = delete $options{ fields } || {};  
 
2509 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $form = $self->current_form;  
 
2510 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2511 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2512 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2513 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (! $form) {  
 
2514 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->signal_condition("No form found to submit.");  
 
2515 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return  
 
2516 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2517 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->do_set_fields( form => $form, fields => $fields );  
 
2518 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2519 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $response;  
 
2520 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ( $options{button} ) {  
 
2521 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
         $response = $self->click( $options{button}, $options{x} || 0, $options{y} || 0 );  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
2522 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2523 
 
 
 
 
 
 
 
 
 
 
 
 
 
     else {  
 
2524 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $response = $self->submit();  
 
2525 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2526 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $response;  
 
2527 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2528 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2529 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2530 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->set_fields( $name => $value, ... ) >>  
 
2531 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2532 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->set_fields(  
 
2533 
 
 
 
 
 
 
 
 
 
 
 
 
 
       user => 'me',  
 
2534 
 
 
 
 
 
 
 
 
 
 
 
 
 
       pass => 'secret',  
 
2535 
 
 
 
 
 
 
 
 
 
 
 
 
 
   );  
 
2536 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2537 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method sets multiple fields of the current form. It takes a list of  
 
2538 
 
 
 
 
 
 
 
 
 
 
 
 
 
 field name and value pairs. If there is more than one field with the same  
 
2539 
 
 
 
 
 
 
 
 
 
 
 
 
 
 name, the first one found is set. If you want to select which of the  
 
2540 
 
 
 
 
 
 
 
 
 
 
 
 
 
 duplicate field to set, use a value which is an anonymous array which  
 
2541 
 
 
 
 
 
 
 
 
 
 
 
 
 
 has the field value and its number as the 2 elements.  
 
2542 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2543 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2544 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2545 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub set_fields {  
 
2546 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %fields) = @_;  
 
2547 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $f = $self->current_form;  
 
2548 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (! $f) {  
 
2549 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         croak "Can't set fields: No current form set.";  
 
2550 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2551 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->do_set_fields(form => $f, fields => \%fields);  
 
2552 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2553 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2554 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub do_set_fields {  
 
2555 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my ($self, %options) = @_;  
 
2556 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $form = delete $options{ form };  
 
2557 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $fields = delete $options{ fields };  
 
2558 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2559 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     while (my($n,$v) = each %$fields) {  
 
2560 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if (ref $v) {  
 
2561 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             ($v,my $num) = @$v;  
 
2562 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
             warn "Index larger than 1 not supported, ignoring"  
 
2563 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 unless $num == 1;  
 
2564 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2565 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2566 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->get_set_value( node => $form, name => $n, value => $v, %options );  
 
2567 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2568 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2569 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2570 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->expand_frames( $spec ) >>  
 
2571 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2572 
 
 
 
 
 
 
 
 
 
 
 
 
 
   my @frames = $mech->expand_frames();  
 
2573 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2574 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Expands the frame selectors (or C<1> to match all frames)  
 
2575 
 
 
 
 
 
 
 
 
 
 
 
 
 
 into their respective PhantomJS nodes according to the current  
 
2576 
 
 
 
 
 
 
 
 
 
 
 
 
 
 document. All frames will be visited in breadth first order.  
 
2577 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2578 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is mostly an internal method.  
 
2579 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2580 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2581 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2582 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub expand_frames {  
 
2583 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $spec, $document) = @_;  
 
2584 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $spec ||= $self->{frames};  
 
2585 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     my @spec = ref $spec ? @$spec : $spec;  
 
2586 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $document ||= $self->document;  
 
2587 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2588 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     if (! ref $spec and $spec !~ /\D/ and $spec == 1) {  
 
  
 
 
 
 
 
  
  0
   
 
 
 
 
 
 
 
    
 
2589 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # All frames  
 
2590 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @spec = qw( frame iframe );  
 
2591 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2592 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2593 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Optimize the default case of only names in @spec  
 
2594 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @res;  
 
2595 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if (! grep {ref} @spec) {  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2596 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         @res = $self->selector(  
 
2597 
 
 
 
 
 
 
 
 
 
 
 
 
 
                         \@spec,  
 
2598 
 
 
 
 
 
 
 
 
 
 
 
 
 
                         document => $document,  
 
2599 
 
 
 
 
 
 
 
 
 
 
 
 
 
                         frames => 0, # otherwise we'll recurse :)  
 
2600 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     );  
 
2601 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } else {  
 
2602 
 
 
 
 
 
 
 
 
 
 
 
 
 
         @res =  
 
2603 
 
 
 
 
 
 
 
 
 
 
 
 
 
             map { #warn "Expanding $_";  
 
2604 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
                     ref $_  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2605 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   ? $_  
 
2606 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   # Just recurse into the above code path  
 
2607 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   : $self->expand_frames( $_, $document );  
 
2608 
 
 
 
 
 
 
 
 
 
 
 
 
 
             } @spec;  
 
2609 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2610 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2611 
 
 
 
 
 
 
 
 
 
 
 
 
 
     @res  
 
2612 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2613 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2614 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2615 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->current_frame >>  
 
2616 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2617 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $last_frame= $mech->current_frame;  
 
2618 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Switch frame somewhere else  
 
2619 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2620 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Switch back  
 
2621 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->activate_container( $last_frame );  
 
2622 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2623 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the currently active frame as a WebElement.  
 
2624 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2625 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This is mostly an internal method.  
 
2626 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2627 
 
 
 
 
 
 
 
 
 
 
 
 
 
 See also  
 
2628 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2629 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
2630 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2631 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Frames are currently not really supported.  
 
2632 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2633 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2634 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2635 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub current_frame {  
 
2636 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self )= @_;  
 
2637 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @res;  
 
2638 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $current= $self->make_WebElement( $self->eval('window'));  
 
2639 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     warn sprintf "Current_frame: bottom: %s", $current->{id};  
 
2640 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2641 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Now climb up until the root window  
 
2642 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $f= $current;  
 
2643 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my @chain;  
 
2644 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     warn "Walking up to root document";  
 
2645 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     while( $f= $self->driver->execute_script('return arguments[0].frameElement', $f )) {  
 
2646 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $f= $self->make_WebElement( $f );  
 
2647 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         unshift @res, $f;  
 
2648 
 
 
 
 
 
 
 
 
 
 
 
 
 
         warn sprintf "One more level up, now in %s",  
 
2649 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $f->{id};  
 
2650 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn $self->driver->execute_script('return arguments[0].title', $res[0]);  
 
2651 
 
 
 
 
 
 
 
 
 
 
 
 
 
         unshift @chain,  
 
2652 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             sprintf "Frame chain: %s %s", $res[0]->get_tag_name, $res[0]->{id};  
 
2653 
 
 
 
 
 
 
 
 
 
 
 
 
 
         # Activate that frame  
 
2654 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->switch_to_parent_frame();  
 
2655 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn "Going up once more, maybe";  
 
2656 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2657 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     warn "Chain complete";  
 
2658 
 
 
 
 
 
 
 
 
 
 
 
 
 
     warn $_  
 
2659 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         for @chain;  
 
2660 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2661 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Now fake the element into  
 
2662 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $el= $self->make_WebElement( $current );  
 
2663 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for( @res ) {  
 
2664 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         warn sprintf "Path has (web element) id %s", $_->{id};  
 
2665 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2666 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $el->{__path}= \@res;  
 
2667 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $el  
 
2668 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2669 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2670 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub switch_to_parent_frame {  
 
2671 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #use JSON;  
 
2672 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my ( $self ) = @_;  
 
2673 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2674 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $self->{driver}->{commands}->{'switchToParentFrame'}||= {  
 
2675 
 
 
 
 
 
 
 
 
 
 
 
 
 
         'method' => 'POST',  
 
2676 
 
 
 
 
 
 
 
 
 
 
 
 
 
         'url' => "session/:sessionId/frame/parent"  
 
2677 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2678 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2679 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #my $json_null = JSON::null;  
 
2680 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $params;  
 
2681 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$id = ( defined $id ) ? $id : $json_null;  
 
2682 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2683 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $res    = { 'command' => 'switchToParentFrame' };  
 
2684 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->driver->_execute_command( $res, $params );  
 
2685 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2686 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2687 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub make_WebElement {  
 
2688 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my( $self, $e )= @_;  
 
2689 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     return $e  
 
2690 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if( blessed $e and $e->isa('Selenium::Remote::WebElement'));  
 
2691 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     my $res= Selenium::Remote::WebElement->new( $e->{WINDOW} || $e->{ELEMENT}, $self->driver );  
 
2692 
 
 
 
 
 
 
 
 
 
 
 
 
 
     croak "No id in " . Dumper $res  
 
2693 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         unless $res->{id};  
 
2694 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2695 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $res  
 
2696 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2697 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2698 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 CONTENT RENDERING METHODS  
 
2699 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2700 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->content_as_png( [\%coordinates ] ) >>  
 
2701 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2702 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $png_data = $mech->content_as_png();  
 
2703 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2704 
 
 
 
 
 
 
 
 
 
 
 
 
 
     # Create scaled-down 480px wide preview  
 
2705 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $png_data = $mech->content_as_png(undef, { width => 480 });  
 
2706 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2707 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the given tab or the current page rendered as PNG image.  
 
2708 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2709 
 
 
 
 
 
 
 
 
 
 
 
 
 
 All parameters are optional.  
 
2710 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2711 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
2712 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2713 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item C< \%coordinates >  
 
2714 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2715 
 
 
 
 
 
 
 
 
 
 
 
 
 
 If the coordinates are given, that rectangle will be cut out.  
 
2716 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The coordinates should be a hash with the four usual entries,  
 
2717 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C,C,C,C.      
 
2718 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2719 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
2720 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2721 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is specific to WWW::Mechanize::PhantomJS.  
 
2722 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2723 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Currently, the data transfer between PhantomJS and Perl  
 
2724 
 
 
 
 
 
 
 
 
 
 
 
 
 
 is done Base64-encoded.  
 
2725 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2726 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2727 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2728 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub content_as_png {  
 
2729 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $rect) = @_;  
 
2730 
 
  
0
   
 
 
 
  
  0
   
 
 
 
 
 
 
 
     $rect ||= {};  
 
2731 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2732 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( scalar keys %$rect ) {  
 
2733 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2734 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $self->eval_in_phantomjs( 'this.clipRect= arguments[0]', $rect );  
 
2735 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2736 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2737 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->render_content( format => 'png' );  
 
2738 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2739 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2740 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->viewport_size >>  
 
2741 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2742 
 
 
 
 
 
 
 
 
 
 
 
 
 
   print Dumper $mech->viewport_size;  
 
2743 
 
 
 
 
 
 
 
 
 
 
 
 
 
   $mech->viewport_size({ width => 1388, height => 792 });  
 
2744 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2745 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns (or sets) the new size of the viewport (the "window").  
 
2746 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2747 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2748 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2749 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub viewport_size {  
 
2750 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my( $self, $new )= @_;  
 
2751 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2752 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs( <<'JS', $new );  
 
2753 
 
 
 
 
 
 
 
 
 
 
 
 
 
         if( arguments[0]) {  
 
2754 
 
 
 
 
 
 
 
 
 
 
 
 
 
             this.viewportSize= arguments[0];  
 
2755 
 
 
 
 
 
 
 
 
 
 
 
 
 
         };  
 
2756 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return this.viewportSize;  
 
2757 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2758 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2759 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2760 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->element_as_png( $element ) >>  
 
2761 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2762 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $shiny = $mech->selector('#shiny', single => 1);  
 
2763 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $i_want_this = $mech->element_as_png($shiny);  
 
2764 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2765 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns PNG image data for a single element  
 
2766 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2767 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2768 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2769 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub element_as_png {  
 
2770 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $element) = @_;  
 
2771 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2772 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $cliprect = $self->element_coordinates( $element );  
 
2773 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2774 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $code = <<'JS';  
 
2775 
 
 
 
 
 
 
 
 
 
 
 
 
 
        var old= this.clipRect;  
 
2776 
 
 
 
 
 
 
 
 
 
 
 
 
 
        this.clipRect= arguments[0];  
 
2777 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2778 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2779 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $old= $self->eval_in_phantomjs( $code, $cliprect );  
 
2780 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $png= $self->content_as_png();  
 
2781 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn Dumper $old;  
 
2782 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs( $code, $old );  
 
2783 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $png  
 
2784 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2785 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2786 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->render_element( %options ) >>  
 
2787 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2788 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $shiny = $mech->selector('#shiny', single => 1);  
 
2789 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $i_want_this= $mech->render_element(  
 
2790 
 
 
 
 
 
 
 
 
 
 
 
 
 
         element => $shiny,  
 
2791 
 
 
 
 
 
 
 
 
 
 
 
 
 
         format => 'pdf',  
 
2792 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2793 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2794 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the data for a single element  
 
2795 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or writes it to a file. It accepts  
 
2796 
 
 
 
 
 
 
 
 
 
 
 
 
 
 all options of C<< ->render_content >>.  
 
2797 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2798 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2799 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2800 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub render_element {  
 
2801 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %options) = @_;  
 
2802 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $element= delete $options{ element }  
 
2803 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         or croak "No element given to render.";  
 
2804 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2805 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $cliprect = $self->element_coordinates( $element );  
 
2806 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2807 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $code = <<'JS';  
 
2808 
 
 
 
 
 
 
 
 
 
 
 
 
 
        var old= this.clipRect;  
 
2809 
 
 
 
 
 
 
 
 
 
 
 
 
 
        this.clipRect= arguments[0];  
 
2810 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2811 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2812 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $old= $self->eval_in_phantomjs( $code, $cliprect );  
 
2813 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $res= $self->render_content(  
 
2814 
 
 
 
 
 
 
 
 
 
 
 
 
 
         %options  
 
2815 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2816 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #warn Dumper $old;  
 
2817 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs( $code, $old );  
 
2818 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $res  
 
2819 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2820 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2821 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->element_coordinates( $element ) >>  
 
2822 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2823 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $shiny = $mech->selector('#shiny', single => 1);  
 
2824 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my ($pos) = $mech->element_coordinates($shiny);  
 
2825 
 
 
 
 
 
 
 
 
 
 
 
 
 
     print $pos->{left},',', $pos->{top};  
 
2826 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2827 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the page-coordinates of the C<$element>  
 
2828 
 
 
 
 
 
 
 
 
 
 
 
 
 
 in pixels as a hash with four entries, C, C, C and C.      
 
2829 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2830 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function might get moved into another module more geared  
 
2831 
 
 
 
 
 
 
 
 
 
 
 
 
 
 towards rendering HTML.  
 
2832 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2833 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2834 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2835 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub element_coordinates {  
 
2836 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $element) = @_;  
 
2837 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $cliprect = $self->eval('arguments[0].getBoundingClientRect()', $element );  
 
2838 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2839 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2840 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->render_content(%options) >>  
 
2841 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2842 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $pdf_data = $mech->render( format => 'pdf' );  
 
2843 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2844 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->render_content(  
 
2845 
 
 
 
 
 
 
 
 
 
 
 
 
 
         format => 'jpg',  
 
2846 
 
 
 
 
 
 
 
 
 
 
 
 
 
         filename => '/path/to/my.jpg',  
 
2847 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2848 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2849 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current page rendered in the specified format  
 
2850 
 
 
 
 
 
 
 
 
 
 
 
 
 
 as a bytestring or stores the current page in the specified  
 
2851 
 
 
 
 
 
 
 
 
 
 
 
 
 
 filename.  
 
2852 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2853 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The filename must be absolute. We are dealing with external processes here!  
 
2854 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2855 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is specific to WWW::Mechanize::PhantomJS.  
 
2856 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2857 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Currently, the data transfer between PhantomJS and Perl  
 
2858 
 
 
 
 
 
 
 
 
 
 
 
 
 
 is done through a temporary file, so directly using  
 
2859 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the C option may be faster.   
 
2860 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2861 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2862 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2863 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub render_content {  
 
2864 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %options) = @_;  
 
2865 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$rect ||= {};  
 
2866 
 
 
 
 
 
 
 
 
 
 
 
 
 
     #$target_rect ||= {};  
 
2867 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $outname= $options{ filename };  
 
2868 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $format= $options{ format };  
 
2869 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $wantresult;  
 
2870 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2871 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my @delete;  
 
2872 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( ! $outname) {  
 
2873 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         require File::Temp;  
 
2874 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         (my $fh, $outname)= File::Temp::tempfile();  
 
2875 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         close $fh;  
 
2876 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         push @delete, $outname;  
 
2877 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $wantresult= 1;  
 
2878 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2879 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     require File::Spec;  
 
2880 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $outname= File::Spec->rel2abs($outname, '.');  
 
2881 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2882 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $self->eval_in_phantomjs(<<'JS', $outname, $format);  
 
2883 
 
 
 
 
 
 
 
 
 
 
 
 
 
         var outname= arguments[0];  
 
2884 
 
 
 
 
 
 
 
 
 
 
 
 
 
         var format= arguments[1];  
 
2885 
 
 
 
 
 
 
 
 
 
 
 
 
 
         this.render( outname, { "format": format });  
 
2886 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2887 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2888 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     my $result;  
 
2889 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if( $wantresult ) {  
 
2890 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         open my $fh, '<', $outname  
 
2891 
 
 
 
 
 
 
 
 
 
 
 
 
 
             or die "Couldn't read tempfile '$outname': $!";  
 
2892 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         binmode $fh, ':raw';  
 
2893 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         local $/;  
 
2894 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $result= <$fh>;  
 
2895 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2896 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2897 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     for( @delete ) {  
 
2898 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         unlink $_  
 
2899 
 
 
 
 
 
 
 
 
 
 
 
 
 
             or warn "Couldn't clean up tempfile: $_': $!";  
 
2900 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2901 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     $result  
 
2902 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2903 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2904 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->content_as_pdf(%options) >>  
 
2905 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2906 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $pdf_data = $mech->content_as_pdf();  
 
2907 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2908 
 
 
 
 
 
 
 
 
 
 
 
 
 
     $mech->content_as_pdf(  
 
2909 
 
 
 
 
 
 
 
 
 
 
 
 
 
         filename => '/path/to/my.pdf',  
 
2910 
 
 
 
 
 
 
 
 
 
 
 
 
 
     );  
 
2911 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2912 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the current page rendered in PDF format as a bytestring.  
 
2913 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2914 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This method is specific to WWW::Mechanize::PhantomJS.  
 
2915 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2916 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Currently, the data transfer between PhantomJS and Perl  
 
2917 
 
 
 
 
 
 
 
 
 
 
 
 
 
 is done through a temporary file, so directly using  
 
2918 
 
 
 
 
 
 
 
 
 
 
 
 
 
 the C option may be faster.   
 
2919 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2920 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2921 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2922 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub content_as_pdf {  
 
2923 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, %options) = @_;  
 
2924 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2925 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     return $self->render_content( format => 'pdf', %options );  
 
2926 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2927 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2928 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 INTERNAL METHODS  
 
2929 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2930 
 
 
 
 
 
 
 
 
 
 
 
 
 
 These are methods that are available but exist mostly as internal  
 
2931 
 
 
 
 
 
 
 
 
 
 
 
 
 
 helper methods. Use of these is discouraged.  
 
2932 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2933 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->element_query( \@elements, \%attributes ) >>  
 
2934 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2935 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my $query = $mech->element_query(['input', 'select', 'textarea'],  
 
2936 
 
 
 
 
 
 
 
 
 
 
 
 
 
                                { name => 'foo' });  
 
2937 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2938 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the XPath query that searches for all elements with Cs   
 
2939 
 
 
 
 
 
 
 
 
 
 
 
 
 
 in C<@elements> having the attributes C<%attributes>. The C<@elements>  
 
2940 
 
 
 
 
 
 
 
 
 
 
 
 
 
 will form an C condition, while the attributes will form an C    
 
2941 
 
 
 
 
 
 
 
 
 
 
 
 
 
 condition.  
 
2942 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2943 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2944 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2945 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub element_query {  
 
2946 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ($self, $elements, $attributes) = @_;  
 
2947 
 
 
 
 
 
 
 
 
 
 
 
 
 
         my $query =  
 
2948 
 
 
 
 
 
 
 
 
 
 
 
 
 
             './/*[(' .  
 
2949 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 join( ' or ',  
 
2950 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     map {  
 
2951 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                         sprintf qq{local-name(.)="%s"}, lc $_  
 
2952 
 
 
 
 
 
 
 
 
 
 
 
 
 
                     } @$elements  
 
2953 
 
 
 
 
 
 
 
 
 
 
 
 
 
                 )  
 
2954 
 
 
 
 
 
 
 
 
 
 
 
 
 
             . ') and '  
 
2955 
 
 
 
 
 
 
 
 
 
 
 
 
 
             . join( " and ",  
 
2956 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
                 map { sprintf q{@%s="%s"}, $_, $attributes->{$_} }  
 
  
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
    
 
2957 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   sort keys(%$attributes)  
 
2958 
 
 
 
 
 
 
 
 
 
 
 
 
 
             )  
 
2959 
 
 
 
 
 
 
 
 
 
 
 
 
 
             . ']';  
 
2960 
 
 
 
 
 
 
 
 
 
 
 
 
 
 };  
 
2961 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2962 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 C<< $mech->PhantomJS_elementToJS >>  
 
2963 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2964 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns the Javascript fragment to turn a Selenium::Remote::PhantomJS  
 
2965 
 
 
 
 
 
 
 
 
 
 
 
 
 
 id back to a Javascript object.  
 
2966 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2967 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
2968 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2969 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub PhantomJS_elementToJS {  
 
2970 
 
 
 
 
 
 
 
 
 
 
 
 
 
     <<'JS'  
 
2971 
 
 
 
 
 
 
 
 
 
 
 
 
 
     function(id,doc_opt){  
 
2972 
 
 
 
 
 
 
 
 
 
 
 
 
 
         var d = doc_opt || document;  
 
2973 
 
 
 
 
 
 
 
 
 
 
 
 
 
         var c= d['$wdc_'];  
 
2974 
 
 
 
 
 
 
 
 
 
 
 
 
 
         return c[id]  
 
2975 
 
 
 
 
 
 
 
 
 
 
 
 
 
     };  
 
2976 
 
 
 
 
 
 
 
 
 
 
 
 
 
 JS  
 
2977 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
 }  
 
2978 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2979 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub post_process  
 
2980 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
2981 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
0
   
 
 
 
     my $self = shift;  
 
2982 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
     if ( $self->{report_js_errors} ) {  
 
2983 
 
  
0
   
 
  
  0
   
 
 
 
 
 
 
 
 
 
         if ( my @errors = $self->js_errors ) {  
 
2984 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $self->report_js_errors(@errors);  
 
2985 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
             $self->clear_js_errors;  
 
2986 
 
 
 
 
 
 
 
 
 
 
 
 
 
         }  
 
2987 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
2988 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
2989 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
2990 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub report_js_errors  
 
2991 
 
 
 
 
 
 
 
 
 
 
 
 
 
 {  
 
2992 
 
  
0
   
 
 
 
 
 
  
0
   
 
  
1
   
 
 
 
     my ( $self, @errors ) = @_;  
 
2993 
 
 
 
 
 
 
 
 
 
 
 
 
 
     @errors = map {  
 
2994 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
         $_->{message} .  
 
2995 
 
  
0
   
 
 
 
 
 
 
 
 
 
 
 
     ( @{$_->{trace}} ? " at $_->{trace}->[-1]->{file} line $_->{trace}->[-1]->{line}" : '') .  
 
2996 
 
  
0
   
 
  
  0
   
 
  
  0
   
 
 
 
 
 
 
 
     ( @{$_->{trace}} && $_->{trace}->[-1]->{function} ? " in function $_->{trace}->[-1]->{function}" : '')  
 
  
 
 
 
  
  0
   
 
 
 
 
 
 
 
 
 
    
 
2997 
 
 
 
 
 
 
 
 
 
 
 
 
 
     } @errors;  
 
2998 
 
0
 
 
 
 
 
 
 
 
 
 
 
     Carp::carp("javascript error: @errors") ;  
 
2999 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
3000 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3001 
 
 
 
 
 
 
 
 
 
 
 
 
 
 1;  
 
3002 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3003 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 INCOMPATIBILITIES WITH WWW::Mechanize  
 
3004 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3005 
 
 
 
 
 
 
 
 
 
 
 
 
 
 As this module is in a very early stage of development,  
 
3006 
 
 
 
 
 
 
 
 
 
 
 
 
 
 there are many incompatibilities. The main thing is  
 
3007 
 
 
 
 
 
 
 
 
 
 
 
 
 
 that only the most needed WWW::Mechanize methods  
 
3008 
 
 
 
 
 
 
 
 
 
 
 
 
 
 have been implemented by me so far.  
 
3009 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3010 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 Unsupported Methods  
 
3011 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3012 
 
 
 
 
 
 
 
 
 
 
 
 
 
 At least the following methods are unsupported:  
 
3013 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3014 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
3015 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3016 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3017 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3018 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->find_all_inputs >>  
 
3019 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3020 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function is likely best implemented through C<< $mech->selector >>.  
 
3021 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3022 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3023 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3024 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->find_all_submits >>  
 
3025 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3026 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function is likely best implemented through C<< $mech->selector >>.  
 
3027 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3028 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3029 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3030 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->images >>  
 
3031 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3032 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function is likely best implemented through C<< $mech->selector >>.  
 
3033 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3034 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3035 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3036 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->find_image >>  
 
3037 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3038 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function is likely best implemented through C<< $mech->selector >>.  
 
3039 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3040 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3041 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3042 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->find_all_images >>  
 
3043 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3044 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This function is likely best implemented through C<< $mech->selector >>.  
 
3045 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3046 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3047 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3048 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 Functions that will likely never be implemented  
 
3049 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3050 
 
 
 
 
 
 
 
 
 
 
 
 
 
 These functions are unlikely to be implemented because  
 
3051 
 
 
 
 
 
 
 
 
 
 
 
 
 
 they make little sense in the context of PhantomJS.  
 
3052 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3053 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
3054 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3055 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3056 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3057 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->clone >>  
 
3058 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3059 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3060 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3061 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->credentials( $username, $password ) >>  
 
3062 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3063 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3064 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3065 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->get_basic_credentials( $realm, $uri, $isproxy ) >>  
 
3066 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3067 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3068 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3069 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->clear_credentials() >>  
 
3070 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3071 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3072 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3073 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->put >>  
 
3074 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3075 
 
 
 
 
 
 
 
 
 
 
 
 
 
 I have no use for it  
 
3076 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3077 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3078 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3079 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< ->post >>  
 
3080 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3081 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Selenium does not support POST requests  
 
3082 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3083 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3084 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3085 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 TODO  
 
3086 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3087 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
3088 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3089 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3090 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3091 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Add C<< limit >> parameter to C<< ->xpath() >> to allow an early exit-case  
 
3092 
 
 
 
 
 
 
 
 
 
 
 
 
 
 when searching through frames.  
 
3093 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3094 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3095 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3096 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Implement downloads via  
 
3097 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3098 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
3099 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3100 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3101 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3102 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Implement download progress  
 
3103 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3104 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3105 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3106 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 INSTALLING  
 
3107 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3108 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
3109 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3110 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3111 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3112 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 Install the C executable   
 
3113 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3114 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over  
 
3115 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3116 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3117 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3118 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Installing on Ubuntu  
 
3119 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3120 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Version: 1.9.8  
 
3121 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Platform: x86_64  
 
3122 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3123 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Install or update latest system software:  
 
3124 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3125 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo apt-get update >>  
 
3126 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3127 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo apt-get install build-essential chrpath libssl-dev libxft-dev >>  
 
3128 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3129 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Install the following packages needed by PhantomJS:  
 
3130 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3131 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo apt-get install libfreetype6 libfreetype6-dev >>  
 
3132 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3133 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo apt-get install libfontconfig1 libfontconfig1-dev >>  
 
3134 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3135 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Get PhantomJS from the L   
 
3136 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3137 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< cd ~ >>  
 
3138 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3139 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< export PHANTOM_JS="phantomjs-1.9.8-linux-x86_64" >>  
 
3140 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3141 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< wget https://bitbucket.org/ariya/phantomjs/downloads/$PHANTOM_JS.tar.bz2 >>  
 
3142 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3143 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo tar xvjf $PHANTOM_JS.tar.bz2 >>  
 
3144 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3145 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Once downloaded move Phantomjs folder:  
 
3146 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3147 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo mv $PHANTOM_JS /usr/local/share >>  
 
3148 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3149 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo ln -sf /usr/local/share/$PHANTOM_JS/bin/phantomjs /usr/local/bin >>  
 
3150 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3151 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< sudo ln -sf /usr/local/share/$PHANTOM_JS/bin/phantomjs /usr/bin/phantomjs >>  
 
3152 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3153 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Test it has been installed on your system:  
 
3154 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3155 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C<< phantomjs --version >>  
 
3156 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3157 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3158 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3159 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 SEE ALSO  
 
3160 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3161 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
3162 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3163 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3164 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3165 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L - the PhantomJS homepage   
 
3166 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3167 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3168 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3169 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L - the ghostdriver homepage   
 
3170 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3171 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3172 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3173 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L - the module whose API grandfathered this module   
 
3174 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3175 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3176 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3177 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L - another WWW::Mechanize-workalike with Javascript support   
 
3178 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3179 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item *  
 
3180 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3181 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L - a similar module with a visible application   
 
3182 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3183 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
3184 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3185 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 REPOSITORY  
 
3186 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3187 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The public repository of this module is  
 
3188 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L.   
 
3189 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3190 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 SUPPORT  
 
3191 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3192 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The public support forum of this module is  
 
3193 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L .  
 
3194 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3195 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 TALKS  
 
3196 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3197 
 
 
 
 
 
 
 
 
 
 
 
 
 
 I've given a talk about this module at Perl conferences:  
 
3198 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3199 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
3200 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3201 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
3202 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3203 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
3204 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3205 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =for html  
 
3206 
 
 
 
 
 
 
 
 
 
 
 
 
 
   
3207 
 
 
 
 
 
 
 
 
 
 
 
 
 
   src="https://www.youtube.com/watch?v=lH3Fhw6b5BI"  
 
3208 
 
 
 
 
 
 
 
 
 
 
 
 
 
   frameborder="0"/>  
 
3209 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3210 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 BUG TRACKER  
 
3211 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3212 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Please report bugs in this module via the RT CPAN bug queue at  
 
3213 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
3214 
 
 
 
 
 
 
 
 
 
 
 
 
 
 or via mail to L.   
 
3215 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3216 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 AUTHOR  
 
3217 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3218 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Max Maischein C   
 
3219 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3220 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 COPYRIGHT (c)  
 
3221 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3222 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Copyright 2014-2020 by Max Maischein C.   
 
3223 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3224 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 LICENSE  
 
3225 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3226 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This module is released under the same terms as Perl itself.  
 
3227 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3228 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This distribution includes a modified copy of the ghostdriver code,  
 
3229 
 
 
 
 
 
 
 
 
 
 
 
 
 
 which is released under the same terms as the ghostdriver code itself.  
 
3230 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The terms of the ghostdriver code are the BSD license, as found at  
 
3231 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L:   
 
3232 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3233 
 
 
 
 
 
 
 
 
 
 
 
 
 
     Copyright (c) 2014, Ivan De Marino    
 
3234 
 
 
 
 
 
 
 
 
 
 
 
 
 
     All rights reserved.  
 
3235 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3236 
 
 
 
 
 
 
 
 
 
 
 
 
 
     Redistribution and use in source and binary forms, with or without modification,  
 
3237 
 
 
 
 
 
 
 
 
 
 
 
 
 
     are permitted provided that the following conditions are met:  
 
3238 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3239 
 
 
 
 
 
 
 
 
 
 
 
 
 
     * Redistributions of source code must retain the above copyright notice,  
 
3240 
 
 
 
 
 
 
 
 
 
 
 
 
 
     this list of conditions and the following disclaimer.  
 
3241 
 
 
 
 
 
 
 
 
 
 
 
 
 
     * Redistributions in binary form must reproduce the above copyright notice,  
 
3242 
 
 
 
 
 
 
 
 
 
 
 
 
 
     this list of conditions and the following disclaimer in the documentation  
 
3243 
 
 
 
 
 
 
 
 
 
 
 
 
 
     and/or other materials provided with the distribution.  
 
3244 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3245 
 
 
 
 
 
 
 
 
 
 
 
 
 
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  
 
3246 
 
 
 
 
 
 
 
 
 
 
 
 
 
     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  
 
3247 
 
 
 
 
 
 
 
 
 
 
 
 
 
     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
 
3248 
 
 
 
 
 
 
 
 
 
 
 
 
 
     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  
 
3249 
 
 
 
 
 
 
 
 
 
 
 
 
 
     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  
 
3250 
 
 
 
 
 
 
 
 
 
 
 
 
 
     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  
 
3251 
 
 
 
 
 
 
 
 
 
 
 
 
 
     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON  
 
3252 
 
 
 
 
 
 
 
 
 
 
 
 
 
     ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
 
3253 
 
 
 
 
 
 
 
 
 
 
 
 
 
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
 
3254 
 
 
 
 
 
 
 
 
 
 
 
 
 
     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
3255 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3256 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The ghostdriver code includes the Selenium WebDriver fragments.  
 
3257 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3258 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut