2

I'm using WWW::Mechanize::Firefox and am trying to use the synchronize method like so:

$mech->get('http://example.com/wp-login.php');
$mech->submit_form( with_fields => {log => 'admin', pwd => 'password'});
$self->synchronize( 'DOMContentLoaded', sub {print Dumper($self->title()); });
exit;

The title of the newly loaded page prints but then the script just hangs. It never exits. What am I missing?

StevieD
  • 2,329
  • 13
  • 30
  • 1
    `DOMConentLoaded` should be `DOMContentLoaded`. Also, note that the callback that you supply should generally be an action (such as a call to `click`) that will give rise to the given event. Clearly a simple `print` statement won't do that. What are you trying to achieve? – Borodin Mar 27 '16 at 03:23
  • I want to wait for the page to load before taking the next action without a `sleep` command. – StevieD Mar 27 '16 at 03:37
  • The next action is to check the title of the page to see if the login was successful. If I don't `sleep` it returns the title of the login page. – StevieD Mar 27 '16 at 04:13
  • @StevieD: Try putting the call to `submit_form` inside the anonymous subroutine and moving the `print` to after the `synchronize` call. That's at least the way it's supposed to work. I can't write the code for you as I'm on a tablet – Borodin Mar 27 '16 at 04:37
  • @StevieD What came out of this? I'd be curious to know whether the answers work, as they do for me. – zdim Jun 27 '16 at 10:57

2 Answers2

2

The subroutine that you pass to synchronize is meant to do something that kicks off an update to the browser page. synchronize calls it and then waits for the event you have specified before it returns

Clearly your print statement won't change the web page at all, so no events will fire and your code will be suspended indefinitely

I suggest you put the call to submit_form in the subroutine you pass to synchronize. That at least stands a chance of causing DOMContentLoaded to fire

It would look like this

$mech->get('http://example.com/wp-login.php');

$mech->synchronize('DOMContentLoaded', sub {
    $mech->submit_form( with_fields => { log => 'admin', pwd => 'password' });  
});

print Dumper $self->title;
Borodin
  • 123,915
  • 9
  • 66
  • 138
  • This is something I have already tried and the same thing happens: the new page gets loaded and then the script just hangs. – StevieD Mar 27 '16 at 10:18
  • @StevieD: Then it's really hard to know what to suggest. Can you tell us the name of the site so that I can test? – Borodin Mar 27 '16 at 10:48
  • It's just a generic WordPress site. I can't give you the login credentials for it, however. – StevieD Mar 27 '16 at 12:00
2

Short   Two solutions below -- Don't specify the event to wait for (so that its default list is used), or use click method which does wait on its own, instead of submit_form.


I see the same problem with form_submit, and with the synchronize method. Either the next call still gets the page being submitted, or the script hangs with synchronize (used, correctly, as in Borodin's answer). I test with a site which does a bit of work as a form is submitted.

Wrapping calls in synchronize is borne with some subtleties. What events are fired or not is not clear and can also be affected (earlier in the code). I found that the code works when no events are specified in the call, and the default list of events() is thus checked for.

mech->synchronize( sub { 
    $mech->submit_form( with_fields => { log => 'admin', pwd => 'password' } );
});
$mech->save_content('after_submit.html');

The following call gets the correct page.


The documentation never mentions waiting with form methods, so some synchronization is needed. However, the click method does wait, by default (one can change that with synchronize option).

So I found this to solve the problem as well: Fill the form and click it.

# Get the page with the form
$mech->fields( log => 'admin', pwd => 'password' );
$mech->click( name => 'Login' );  # whatever the name is  
$mech->save_content('after_submit.html');

The next call after click gets the actual next page.

In case the form has no name on <input>, for example, this works as well

$mech->click_button(input => 'submit');
zdim
  • 53,586
  • 4
  • 45
  • 72