minkphp / Mink

PHP web browser emulator abstraction
https://mink.behat.org/
MIT License
1.6k stars 280 forks source link

Timeout doesn't work as expected. #302

Open pradeeprkara opened 11 years ago

pradeeprkara commented 11 years ago

For steps such as "I visit "/url"" OR I follow "link", sometimes with Goutte, the timeout doesn't seem to be thrown when it is needed and it keeps on hanging. One possible solution suggested is using the spin functions as explained in http://docs.behat.org/cookbook/using_spin_functions.html, but this cannot be applied to steps that include page loads. Probably the spin method needs to be incorporated with the core code that handles the above mentioned steps?

Also as of now, there is no effective way to time out a page load when Selenium is running. I am already using the wait() method and checking the document.readystate but we can't write an effective way to put a callback that checks the status repeatedly and returns true after a timeout value. It would be great if the corresponding mink step definitions can be modified to meet this requirement.

Below is the way I have implemented the spin method.

<?php
  public function iWaitUntilThePageLoads($callback = null) {
    // Manual timeout in seconds
    $timeout = 60;
    // Default callback
    if (empty($callback)) {
      if ($this->getSession()->getDriver() instanceof Behat\Mink\Driver\GoutteDriver) {
        $callback = function($context) {
          // If the page is completely loaded and the footer text is found
          if(200 == $context->getSession()->getDriver()->getStatusCode()) {
            return true;
          }
          return false;
        };
      }
      else {
        // Convert $timeout value to milliseconds
        // document.readyState becomes 'complete' when the page is fully loaded
        $this->getSession()->wait($timeout*1000, "document.readyState == 'complete'");
        return;
      }
    }
    if (!is_callable($callback)) {
      throw new Exception('The given callback is invalid/doesn\'t exist');
    }
    // Try out the callback until $timeout is reached
    for ($i = 0; $i < $timeout/2; $i++) {
      if ($callback($this)) {
        return true;
      }
      // Try every 2 seconds
      sleep(2);
    }
    throw new Exception('The request is timed out');
  }

?>
handrus commented 11 years ago

+1. Right now I have a IE8 stuck with a page that never ends loading. It been 5 min and counting. The same applies to Selenium2 Driver.

handrus commented 11 years ago

After some research sounds like the problem in on instaclick dependency. I believe instaclick must merge last commits from facebook phpwebdriver. Particularly this one: https://github.com/facebook/php-webdriver/commit/c19952fb77cd5fd8eabedcbc5567e6295195e651