Skip to content

Commit 57b845b

Browse files
gilmagnooalders
authored andcommitted
Fix the handling of fields of type "file"
1 parent 32e7e55 commit 57b845b

File tree

3 files changed

+112
-5
lines changed

3 files changed

+112
-5
lines changed

lib/WWW/Mechanize.pm

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,24 @@ C<L<< form_name()|/"$mech->form_name( $name [, \%args ] )" >>> or
19071907
C<L<< form_number()|/"$mech->form_number($number)" >>>
19081908
method or defaulting to the first form on the page).
19091909
1910+
If the field is of type "file", its value should be an arrayref. Example:
1911+
1912+
$mech->field( $file_input, ['/tmp/file.txt'] );
1913+
1914+
Value examples for "file" inputs, followed by explanation of what each
1915+
index mean:
1916+
1917+
['/tmp/file.txt']
1918+
['/tmp/file.txt', 'filename.txt']
1919+
['/tmp/file.txt', 'filename.txt', @headers]
1920+
['/tmp/file.txt', 'filename.txt', Content => 'some content']
1921+
[undef, 'filename.txt', Content => 'content here']
1922+
1923+
Index 0 is the filepath that will be read from disk. Index 1 is the
1924+
filename which will be used in the HTTP request body; if not given,
1925+
filepath (index 0) is used instead. If "Content => 'content here'" is
1926+
informed as shown, then filepath will be ignored.
1927+
19101928
The optional C<$number> parameter is used to distinguish between two fields
19111929
with the same name. The fields are numbered from 1.
19121930
@@ -1922,7 +1940,16 @@ sub field {
19221940
}
19231941
else {
19241942
if ( ref($value) eq 'ARRAY' ) {
1925-
$form->param($name, $value);
1943+
my $input = $form->find_input($name);
1944+
1945+
if ( $input->type eq 'file' ) {
1946+
$input->file( shift @$value );
1947+
$input->filename( shift @$value );
1948+
$input->headers( @$value );
1949+
}
1950+
else {
1951+
$form->param($name, $value);
1952+
}
19261953
}
19271954
else {
19281955
$form->value($name => $value);
@@ -2041,6 +2068,19 @@ which has the field value and its number as the 2 elements.
20412068
# set the second $name field to 'foo'
20422069
$mech->set_fields( $name => [ 'foo', 2 ] );
20432070
2071+
The value of a field of type "file" should be an arrayref as described
2072+
in C<L<< field()|$mech->field( $name, $value, $number ) >>>. Examples:
2073+
2074+
$mech->set_fields( $file_field => ['/tmp/file.txt'] );
2075+
$mech->set_fields( $file_field => ['/tmp/file.txt', 'filename.txt'] );
2076+
2077+
The value for a "file" input can also be an arrayref containing an
2078+
arrayref and a number, as documented in
2079+
C<L<< submit_form()|$mech->submit_form( ... ) >>>.
2080+
The number will be used to find the field in the form. Example:
2081+
2082+
$mech->set_fields( $file_field => [['/tmp/file.txt'], 1] );
2083+
20442084
The fields are numbered from 1.
20452085
20462086
For fields that have a predefined set of values, you may also provide a
@@ -2065,10 +2105,20 @@ sub set_fields {
20652105
FIELD:
20662106
for my $field ( keys %fields ) {
20672107
my $value = $fields{$field};
2108+
my $number = 1;
20682109

20692110
if ( ref $value eq 'ARRAY' ) {
2070-
$form->find_input( $field, undef,
2071-
$value->[1])->value($value->[0] );
2111+
my $input = $form->find_input($field);
2112+
2113+
# Honor &submit_form's documentation, that says that a
2114+
# "file" input's value can be in the form of
2115+
# "[[$filepath, $filename], 1]".
2116+
if (
2117+
$input->type ne 'file'
2118+
|| ( $input->type eq 'file' && ref( $value->[0] ) eq 'ARRAY' )
2119+
) {
2120+
( $value, $number ) = ( $value->[0], $value->[1] );
2121+
}
20722122
}
20732123
else {
20742124
if ( ref $value eq 'SCALAR' ) {
@@ -2086,9 +2136,8 @@ sub set_fields {
20862136
}
20872137
$value = $possible_values[ $$value ];
20882138
}
2089-
2090-
$form->value($field => $value);
20912139
}
2140+
$self->field($field, $value, $number);
20922141
}
20932142
}
20942143

t/file_upload.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<form method="post" enctype="multipart/form-data">
2+
<input type="file" name="document">
3+
<input type="submit">
4+
</form>

t/file_upload.t

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use strict;
2+
use warnings;
3+
use Test::More;
4+
use WWW::Mechanize;
5+
use URI::file;
6+
7+
my $file = 't/file_upload.html';
8+
my $filename = 'the_file_upload.html';
9+
my $mc = WWW::Mechanize->new;
10+
my $uri = URI::file->new_abs( 't/file_upload.html' )->as_string;
11+
my ($form, $input);
12+
13+
# &field
14+
15+
$mc->get( $uri );
16+
$mc->field( 'document', [$file, $filename] );
17+
($form) = $mc->forms;
18+
like( $form->make_request->as_string, qr! filename="$filename" !x,
19+
q/$mc->field( 'document', [$file, $filename] )/ );
20+
21+
$mc->get( $uri );
22+
$mc->field( 'document', [$file, $filename, Content => 'content'] );
23+
($form) = $mc->forms;
24+
like( $form->make_request->as_string, qr! filename="$filename" !x,
25+
q/$mc->field( 'document', [$file, $filename, Content => 'content'] )/ );
26+
27+
# &set_fields
28+
29+
$mc->get( $uri );
30+
$mc->set_fields( 'document' => [ $file, $filename ] );
31+
($form) = $mc->forms;
32+
like( $form->make_request->as_string, qr! filename="$filename" !x,
33+
q/$mc->set_fields( 'document' => [ $file, $filename ] )/ );
34+
35+
$mc->get( $uri );
36+
$mc->set_fields( 'document' => [ $file, $filename, Content => 'content' ] );
37+
($form) = $mc->forms;
38+
like( $form->make_request->as_string, qr! filename="$filename" !x,
39+
q/$mc->set_fields( 'document' => [ $file, $filename, Content => 'content' ] )/ );
40+
41+
$mc->get( $uri );
42+
$mc->set_fields( 'document' => [[ $file, $filename ], 1] );
43+
($form) = $mc->forms;
44+
like( $form->make_request->as_string, qr! filename="$filename" !x,
45+
q/$mc->set_fields( 'document' => [[ $file, $filename ], 1] )/ );
46+
47+
$mc->get( $uri );
48+
$mc->set_fields
49+
( 'document' => [[ $file, $filename, Content => 'content' ], 1] );
50+
($form) = $mc->forms;
51+
like( $form->make_request->as_string, qr! filename="$filename" !x,
52+
q/$mc->set_fields( 'document' => [[ $file, $filename, Content => 'content' ], 1] )/ );
53+
54+
done_testing;

0 commit comments

Comments
 (0)