File Coverage

blib/lib/HTTP/WebTest/Plugin/Click.pm
Criterion Covered Total %
statement 89 89 100.0
branch 37 42 88.1
condition 14 17 82.3
subroutine 9 9 100.0
pod 1 5 20.0
total 150 162 92.5


line stmt bran cond sub pod time code
1             # $Id: Click.pm,v 1.18 2003/09/05 20:01:51 m_ilya Exp $
2              
3             package HTTP::WebTest::Plugin::Click;
4              
5             =head1 NAME
6              
7             HTTP::WebTest::Plugin::Click - Click buttons and links on web page
8              
9             =head1 SYNOPSIS
10              
11             plugins = ( ::Click )
12              
13             test_name = Some test
14             click_link = Name of the link
15             end_test
16              
17             test_name = Another test
18             click_button = Name of the button
19             end_test
20              
21             =head1 DESCRIPTION
22              
23             This plugin lets you use the names of links and buttons on HTML pages to
24             build test requests.
25              
26             =cut
27              
28 1     1   6 use strict;
  1         4  
  1         43  
29 1     1   2380 use HTML::TokeParser;
  1         25426  
  1         31  
30 1     1   10 use URI;
  1         3  
  1         26  
31              
32 1     1   82 use base qw(HTTP::WebTest::Plugin);
  1         2  
  1         1520  
33              
34             =head1 TEST PARAMETERS
35              
36             =for pod_merge copy opt_params
37              
38             =head2 click_button
39              
40             Given name of submit button (i.e. C<> tag or
41             C<> inside of C<> tag) on previously
42             requested HTML page, builds test request to the submitted page.
43              
44             Note that you still need to pass all form parameters yourself using
45             C test parameter.
46              
47             =head3 Example
48              
49             See example in L.
50              
51             =head2 click_link
52              
53             Given name of link (i.e. C<> tag) on previosly requested HTML
54             page, builds test request to the linked page.
55              
56             =head3 Example
57              
58             See example in L.
59              
60             =head2 form_name
61              
62             Give form name attribute (i.e. C<
>) on previously
63             requested HTML page, builds test request to the submitted page.
64              
65             Note that you still need to pass all form parameters yourself using
66             C test parameter.
67              
68             =cut
69              
70             sub param_types {
71 32     32 1 392 return q(click_button scalar
72             click_link scalar
73             form_name scalar);
74             }
75              
76             sub prepare_request {
77 32     32 0 57 my $self = shift;
78              
79 32         135 $self->validate_params(qw(click_button click_link form_name));
80              
81             # get current request object
82 32         147 my $request = $self->webtest->current_request;
83              
84             # get number of previous test if any
85 32         111 my $prev_test_num = $self->webtest->current_test_num - 1;
86 32 100       122 return if $prev_test_num < 0;
87              
88             # get previous response object
89 23         80 my $response = $self->webtest->tests->[$prev_test_num]->response;
90              
91             # no response - nothing to do
92 23 50       66 return unless defined $response;
93              
94             # do nothing unless it is HTML
95 23 100       116 return unless $response->content_type eq 'text/html';
96              
97             # get various params we handle
98 16         712 my $click_button = $self->test_param('click_button');
99 16         51 my $click_link = $self->test_param('click_link');
100 16         61 my $form_name = $self->test_param('form_name');
101              
102 16 100       87 if(defined $click_link) {
    100          
    100          
103             # find matching link
104 4         19 my $link = $self->find_link(response => $response,
105             pattern => $click_link);
106              
107 4 100       751 $request->base_uri($link)
108             if defined $link;
109             } elsif(defined $click_button) {
110             # find action which corresponds to requested submit button
111 9         49 my $action = $self->find_form(response => $response,
112             pattern => $click_button);
113              
114 9 100       1837 $request->base_uri($action)
115             if defined $action;
116             } elsif(defined $form_name) {
117             # find action which corresponds to requested form name
118 2         12 my $action = $self->find_form(response => $response,
119             form_name => $form_name);
120              
121 2 50       437 $request->base_uri($action)
122             if defined $action;
123             }
124             }
125              
126             sub find_base {
127 15     15 0 27 my $self = shift;
128 15         27 my $response = shift;
129              
130 15         90 my $base = $response->base;
131 15         4242 my $content = $response->content;
132              
133             # look for base tag inside of head tag
134 15         329 my $parser = HTML::TokeParser->new(\$content);
135 15         2940 my $token = $parser->get_tag('head');
136 15 50       4198 if(defined $token) {
137 15         62 $token = $parser->get_tag('base', '/head');
138 15 100       2117 if($token->[0] eq 'base') {
139 1         5 $base = $token->[1]{href};
140             }
141             }
142              
143 15         389 return $base;
144             }
145              
146             sub find_link {
147 4     4 0 8 my $self = shift;
148 4         15 my %param = @_;
149              
150 4         8 my $response = $param{response};
151 4         10 my $pattern = $param{pattern};
152              
153 4         15 my $base = $self->find_base($response);
154 4         17 my $content = $response->content;
155              
156             # look for matching link tag
157 4         52 my $parser = HTML::TokeParser->new(\$content);
158 4         439 my $link = undef;
159 4         17 while(my $token = $parser->get_tag('a')) {
160 6         957 my $uri = $token->[1]{href};
161 6 50       16 next unless defined $uri;
162 6 50       16 if($token->[0] eq 'a') {
163 6         25 my $text = $parser->get_trimmed_text('/a');
164 6 100       439 if($text =~ /$pattern/i) {
165 3         6 $link = $uri;
166 3         6 last;
167             }
168             }
169             }
170              
171             # we haven't found anything
172 4 100       111 return unless defined $link;
173              
174             # return link
175 3         14 return URI->new_abs($link, $base);
176             }
177              
178             sub find_form {
179 11     11 0 27 my $self = shift;
180 11         51 my %param = @_;
181              
182 11         28 my $response = $param{response};
183 11         24 my $pattern = $param{pattern};
184 11         22 my $form_name = $param{form_name};
185              
186 11         51 my $base = $self->find_base($response);
187 11         51 my $content = $response->content;
188              
189             # look for form
190 11         151 my $parser = HTML::TokeParser->new(\$content);
191 11         1260 my $uri = undef;
192             FORM:
193 11         45 while(my $token = $parser->get_tag('form')) {
194             # get action from form tag param
195 16   33     4071 my $action = $token->[1]{action} || $base;
196              
197 16 100 66     96 if ( $token->[1]{name} and $form_name
      100        
198             and ( $token->[1]{name} eq $form_name ) ){
199 2         6 $uri = $action;
200 2         7 last FORM;
201             }
202 14 100       43 next unless $pattern;
203             # find matching submit button or end of form
204 13         49 while(my $token = $parser->get_tag('input', '/form')) {
205 20         574 my $tag = $token->[0];
206              
207 20 100       53 if($tag eq '/form') {
208             # end of form: let's look for another form
209 5         31 next FORM;
210             }
211              
212             # check if right input control is found
213 15   100     57 my $type = $token->[1]{type} || 'text';
214 15   100     49 my $name = $token->[1]{name} || '';
215 15   100     82 my $value = $token->[1]{value} || '';
216 15   100     57 my $src = $token->[1]{src} || ''; # to handle image submit button
217 15 100       91 next unless $type =~ /^(?:submit|image)$/i;
218 13 100       223 next unless grep /$pattern/i, $name, $value, $src;
219              
220             # stop searching
221 8         15 $uri = $action;
222 8         25 last FORM;
223             }
224             }
225              
226             # we haven't found anything
227 11 100       139 return unless defined $uri;
228              
229             # return method and link
230 10         53 return URI->new_abs($uri, $base);
231             }
232              
233             =head1 COPYRIGHT
234              
235             Copyright (c) 2001-2003 Ilya Martynov. All rights reserved.
236              
237             This program is free software; you can redistribute it and/or modify
238             it under the same terms as Perl itself.
239              
240             =head1 SEE ALSO
241              
242             L
243              
244             L
245              
246             L
247              
248             L
249              
250             =cut
251              
252             1;