minkphp / minkphp/Mink

Timeout doesn't work as expected.

Open
#302 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
1.6k
Forks
286
PR merge metrics
No merged PRs in 30d

Description

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');
  }

?>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Mink step definitions for page visits and link following, then compare the Goutte and Selenium paths with the existing wait() and spin-function behavior described in the issue. Done means page-load timeouts are enforced for both driver cases without hanging, with the timeout behavior covered by relevant tests if the existing test location can be identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.