http://www.perlmonks.org?node_id=315745

cees has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to write some UI tests for a web app using WWW::Mechanize. I have however run into a snag while writing tests to handle some edge cases. I am trying to make sure my backend code can handle an enduser messing with radio button values (ie saving the form, changing the radio button values and re-submitting).

While writing these tests I found out that I can not submit a form using WWW::Mechanize with an invalid entry entered into a radio button field. WWW::Mechanize uses the HTML::Form module to handle form parsing/filling/submitting, and that module happens to be very strict about the values you can assign to a field that is a radio button (or a select box for that matter)...

Has anyone run into this before? Is there a clean solution? Did I miss something obvious?

A quick example of what I am trying follows:

use Test::More qw(no_plan); use Test::HTML::Lint; use WWW::Mechanize; my $a = WWW::Mechanize->new(); $a->get( $url ); is( $a->status, 200, 'Fetched OK' ); like( $a->content, qr/Details/, "Correct page"); html_ok( $a->content, "Details HTML" ); $a->form_name('details'); $a->field( a_radio_button => 'invalid_value' ); # <-- dies here $a->click();

The above code will fail and die at the call to $a->field(...). I have tried making calls directly to the HTML::Form object to no avail, but it looks like according to the perldocs for HTML::Form that it is working exactly as advertized. Is there another way to do what I want?

Update:I was silly for not including the error message I got. HTML::Form is doing exactly what is advertized in the docs. It will die with an error message when an bad value is assigned to a radio button or select box. I am looking for another way of doing the same thing (ie using something besides HTML::Form to build a request object, or convincing HTML::Form to accept a bad value...)

The error message HTML::Form spits out is as follows: Illegal value 'invalid_value' for field 'a_radio_button' at /usr/local/share/perl/5.8.2/HTML/Form.pm line 426

- Cees

Replies are listed 'Best First'.
Re: HTTP::Form and invalid radio button values
by PodMaster (Abbot) on Dec 19, 2003 at 08:10 UTC
    Modifying your code so I can run this ... I get Illegal value 'invalid_value' for field 'new_animals' at C:/Perl/site/lib/WWW/Mechanize.pm line 541 (you should've mentioned the error message you got).

    So I crack open WWW/Mechanize.pm and see this is resulting from a ->value call on a form.

    So I check the HTML::Form docs for value and read If the input only can take an enumerated list of values, then it is an error to try to set it to something else and the method will croak if you try.

    So what do I do, that's right, I bust out Data::Dumper and discover (via ->find_input)

    $VAR1 = bless( { 'seen' => [ 1, 0 ], 'menu' => [ undef, 'baboon' ], 'multiple' => 'multiple', 'name' => 'new_animals', 'current' => 0, 'size' => '10', 'type' => 'option', 'value_names' => [ 'off', 'baboon' ] }, 'HTML::Form::ListInput' );
    Can you guess what I'd try next?

    I hope this has been informational :)

    update: on a sidenote, for testing purposes I was using the cookie.cgi file from the CGI.pm distribution (i was not calling anyone a baboon)

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Modifying your code so I can run this ... I get Illegal value 'invalid_value' for field 'new_animals' at C:/Perl/site/lib/WWW/Mechanize.pm line 541 (you should've mentioned the error message you got).

      You're right, I should have included the error message. I did mention that HTML::Form performed as advertized, but I see now that it was not very clear.

      So what do I do, that's right, I bust out Data::Dumper and discover (via ->find_input). Can you guess what I'd try next?

      You want me to play with the class data directly??? I guess I may need to resort to that, but that would make my code brittle. I guess HTML::Form is stable enough that it's internal class data will probably not change in the future, but that is somethng I can not guarantee... I guess it if does happen my test will just fail, and I will be notified that there is a problem and can hunt it down, so it's not terrible.

      Thanks

      - Cees

Re: HTTP::Form and invalid radio button values
by Roger (Parson) on Dec 19, 2003 at 05:30 UTC
    While writing these tests I found out that I can not submit a form using WWW::Mechanize with an invalid entry entered into a radio button field. WWW::Mechanize uses the HTML::Form module to handle form parsing/filling/submitting, and that module happens to be very strict about the values you can assign to a field that is a radio button (or a select box for that matter)

    Well, what do you expect your Web Browser to behave on radio boxes? Will the browser allow you to select some non-existant radio button? WWW::Mechanize is imitating what a web browser is doing - by not allowing you to make invalid selections. Somehow I fail to see why you would want to do invalid radio button selection, sounds more like hacking to me. ;-)

      I think his test case is valid. When you test, you don't assume that the users will always use the system in the way it is supposed to be, you don't assume that the other applications that interface you will always behave as it should be. We not only test normal cases, but also test exceptional cases.

      If your system talks to a browser, the browser can be buggy, so you probably want to test what if the browser send me some buggy data.

      On the other hand, it is an imperfect design for WWW::Mechanize to die without any error msg, unless it cored. (As the OP pointed out, the bug might be in HTML::Form)

      Somehow I fail to see why you would want to do invalid radio button selection, sounds more like hacking to me. ;-)

      Exactly! I want to make sure that my application can handle an enduser hacking the HTML. When I validate my parameters on the server side I always check to make sure that the user hasn't fudged any data, and I want to add a test to make sure that code is always working correctly. I know it is working right now, but I may break it in the future for all I know. Hence the need for a test.

      - Cees

Re: HTTP::Form and invalid radio button values
by Anonymous Monk on Dec 19, 2003 at 07:18 UTC
    Why don't you just feed WWW::Mechanize a bad file?
Re: HTTP::Form and invalid radio button values
by cees (Curate) on Dec 19, 2003 at 16:11 UTC

    Just finishing up this thread in case someone else runs into this same issue. It turns out that WWW::Mechanize allows you to build and use your own HTTP::Request object through the use of the $a->request( $request ); method. This bypasses the need for HTML::Form, and allows you to enter any information into the form fields.

    Here is a code snippet that shows how it can work:

    use Test::More qw(no_plan); use WWW::Mechanize; use HTTP::Request::Common; my $url = 'http://starting.url/'; my $a = WWW::Mechanize->new(); isa_ok( $a, "WWW::Mechanize" ) or die; $a->get( $url ); is( $a->status, 200, 'Fetched OK' ); my $form = $a->form_name('details'); ok($form, 'Details form'); my $action = $form->action(); # build a request object my $request = HTTP::Request::Common::POST($action, [ a_radio_button => 'invalid_value', ]); # Add any cookies into the request object $a->cookie_jar->add_cookie_header( $request ); # make the request $a->request( $request ); is( $a->status, 200, 'Fetched OK' );

    Thanks for the help and suggestions

    - Cees