pest icon indicating copy to clipboard operation
pest copied to clipboard

[Bug]: AwaitableWebpage::click times out when the next page is slow to load

Open mattford opened this issue 3 months ago • 7 comments

What Happened

When using ->click() or ->press() within a browser test, if the element clicked causes a navigation and the next page takes >5s to load, the action fails (even though the element was successfully clicked)

This is possibly an issue with Playwright but I'm starting here as I'm not as familiar with that side of things.

In my example the test fails at the click line:

   FAILED  Tests\Browser\WelcomePageTest > clicking on button
  Execution context was destroyed, most likely because of a navigation A screenshot of the page has been saved to [Tests/Browser/Screenshots/clicking_on_button].

  at tests/Browser/WelcomePageTest.php:4
      1▕ <?php
      2▕ test('clicking on button', function (): void {
      3▕    visit('/')
  ➜   4▕      ->click('Click here!')
      5▕      ->assertSee('Hello, World!');
      6▕ });

However the screenshot produced shows the loaded "Hello, World!" page, so it appears that the test should be successful. I put a dump in the sendMessage method and saw that it was repeatedly sending the click command to Playwright, given the navigation already occurred these later calls likely didn't find the element to click on.

PHPUnit\Framework\ExpectationFailedException^ {#4035
  #message: "Timeout 1000ms exceeded."
  #code: 0
  #file: "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Client.php"
  #line: 101
  #serializableTrace: array:30 [
    0 => array:3 [
      "function" => "execute"
      "class" => "Pest\Browser\Playwright\Client"
      "type" => "->"
    ]
    1 => array:3 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Concerns/InteractsWithPlaywright.php"
      "line" => 105
      "function" => "iterator_to_array"
    ]
    2 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Locator.php"
      "line" => 137
      "function" => "processVoidResponse"
      "class" => "Pest\Browser\Playwright\Locator"
      "type" => "->"
    ]
    3 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php"
      "line" => 169
      "function" => "click"
      "class" => "Pest\Browser\Playwright\Locator"
      "type" => "->"
    ]
    4 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php"
      "line" => 55
      "function" => "press"
      "class" => "Pest\Browser\Api\Webpage"
      "type" => "->"
    ]
    5 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Playwright.php"
      "line" => 196
      "function" => "Pest\Browser\Api\{closure}"
      "class" => "Pest\Browser\Api\AwaitableWebpage"
      "type" => "->"
    ]
    6 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Execution.php"
      "line" => 149
      "function" => "usingTimeout"
      "class" => "Pest\Browser\Playwright\Playwright"
      "type" => "::"
    ]
    7 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php"
      "line" => 53
      "function" => "waitForExpectation"
      "class" => "Pest\Browser\Execution"
      "type" => "->"
    ]
    8 => array:5 [
      "file" => "/var/www/html/tests/Browser/AdminDashboardBulkActionsTest.php"
      "line" => 71
      "function" => "__call"
      "class" => "Pest\Browser\Api\AwaitableWebpage"
      "type" => "->"
    ]
    9 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php"
      "line" => 168
      "function" => "{closure}"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    10 => array:3 [
      "function" => "Pest\Factories\{closure}"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    11 => array:3 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 429
      "function" => "call_user_func_array"
    ]
    12 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Support/ExceptionTrace.php"
      "line" => 26
      "function" => "Pest\Concerns\{closure}"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    13 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 429
      "function" => "ensure"
      "class" => "Pest\Support\ExceptionTrace"
      "type" => "::"
    ]
    14 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php"
      "line" => 331
      "function" => "__callClosure"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    15 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Factories/TestCaseFactory.php(169) : eval()'d code"
      "line" => 20
      "function" => "__runTest"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    16 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 1316
      "function" => "__pest_evaluable__admin_dashboard_bulk_actions__→_apply_an_action_to_an_application"
      "class" => "P\Tests\Browser\AdminDashboardBulkActionsTest"
      "type" => "->"
    ]
    17 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 516
      "function" => "runTest"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    18 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php"
      "line" => 99
      "function" => "runBare"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    19 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 357
      "function" => "run"
      "class" => "PHPUnit\Framework\TestRunner"
      "type" => "->"
    ]
    20 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 374
      "function" => "run"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    21 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 374
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    22 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 374
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    23 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 374
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    24 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php"
      "line" => 64
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    25 => array:5 [
      "file" => "/var/www/html/vendor/phpunit/phpunit/src/TextUI/Application.php"
      "line" => 229
      "function" => "run"
      "class" => "PHPUnit\TextUI\TestRunner"
      "type" => "->"
    ]
    26 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/src/Kernel.php"
      "line" => 103
      "function" => "run"
      "class" => "PHPUnit\TextUI\Application"
      "type" => "->"
    ]
    27 => array:5 [
      "file" => "/var/www/html/vendor/pestphp/pest/bin/pest"
      "line" => 184
      "function" => "handle"
      "class" => "Pest\Kernel"
      "type" => "->"
    ]
    28 => array:3 [
      "file" => "/var/www/html/vendor/pestphp/pest/bin/pest"
      "line" => 192
      "function" => "{closure}"
    ]
    29 => array:3 [
      "file" => "/var/www/html/vendor/bin/pest"
      "line" => 119
      "function" => "include"
    ]
  ]
  #comparisonFailure: null
  trace: {
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Client.php:101 { …}
    Pest\Browser\Playwright\Client->execute() {}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Concerns/InteractsWithPlaywright.php:105 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Locator.php:137 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php:169 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:55 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Playwright/Playwright.php:196 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Execution.php:149 { …}
    /var/www/html/vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:53 { …}
    /var/www/html/tests/Browser/AdminDashboardBulkActionsTest.php:71 {
      P\Tests\Browser\AdminDashboardBulkActionsTest->{closure}^
      › ->click('Current stage')\r
      › ->press('.action.reinstate')\r
      › ->assertSeeIn('.tab-pane h2', 'Application Review');\r
      arguments: {
        $name: "press"
        $arguments: array:1 [ …1]
      }
    }
    /var/www/html/vendor/pestphp/pest/src/Factories/TestCaseMethodFactory.php:168 { …}
    P\Tests\Browser\AdminDashboardBulkActionsTest->Pest\Factories\{closure}() {}
    /var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php:429 { …}
    /var/www/html/vendor/pestphp/pest/src/Support/ExceptionTrace.php:26 { …}
    /var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php:429 { …}
    /var/www/html/vendor/pestphp/pest/src/Concerns/Testable.php:331 { …}
    /var/www/html/vendor/pestphp/pest/src/Factories/TestCaseFactory.php:169 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:1316 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:516 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php:99 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php:357 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:374 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:374 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:374 { …}
    /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:374 { …}
    /var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:64 { …}
    /var/www/html/vendor/phpunit/phpunit/src/TextUI/Application.php:229 { …}
    /var/www/html/vendor/pestphp/pest/src/Kernel.php:103 { …}
    /var/www/html/vendor/pestphp/pest/bin/pest:184 { …}
    /var/www/html/vendor/pestphp/pest/bin/pest:192 { …}
    /var/www/html/vendor/bin/pest:119 { …}
  }
} // vendor/pestphp/pest-plugin-browser/src/Execution.php:152

How to Reproduce

Checkout https://github.com/mattford/pest-repro composer/npm install Run vendor/bin/pest

Sample Repository

No response

Pest Version

4.1.0

PHP Version

8.4.12

Operation System

Linux

Notes

I am using WSL2 to execute Pest, same occurs within the php8.4-cli docker image

mattford avatar Sep 11 '25 14:09 mattford

I'm seeing the same thing. The following page is loaded correctly, but it's still hanging on the previous click.

   FAILED  Tests\Feature\BrowserTest > it verifies login and logout
  Timeout 5000ms exceeded. A screenshot of the page has been saved to [Tests/Browser/Screenshots/it_verifies_login_and_logout].

  at tests/Feature/BrowserTest.php:20
     16▕         ->submit()
     17▕         ->type('passwd', 'password')
     18▕         ->submit()
     19▕         ->check('DontShowAgain')
  ➜  20▕         ->click('No')

FrittenKeeZ avatar Oct 01 '25 15:10 FrittenKeeZ

I am also getting this same error.

Even if I increase the timeout to 60 seconds it still just times out. While watching with the network open I am not seeing any network requests or console errors, it seems like the full page loads successfully.

This is a flakey error though, as sometimes the test passes, and other times it fails with the timeout across Chrome, Safari, and Firefox.

It does seem to be related to using the sync queue driver in tests. If I fake the queue, and then perform the queue work outside of the visit, it does seem to pass more reliably.

Queue::assertPushed(function(UpgradeUser $upgrade_user) {
    $upgrade_user->handle();
    return true;
});

$user = $this->user->fresh();
$this->assertNotEquals('guest', $user->role);

skylerkatz avatar Oct 21 '25 16:10 skylerkatz

I've been running into the same thing. I've just PR'd an --attempts api that will reattempt failed tests before marking them as failed. Definitely not fixing the root cause but this would solve most of my pains

https://github.com/pestphp/pest/pull/1558

ozziexsh avatar Oct 29 '25 21:10 ozziexsh

We are experiencing the same issue. Adding an extra assertSee before the click has seemed to make the occurrence of the issue drop

matdehaast avatar Oct 31 '25 05:10 matdehaast

This is related to https://github.com/microsoft/playwright/issues/36181 which won't be fixed. The timeout just needs to be big enough to allow full loading. Except that Pest\Browser\Execution::waitForExpectation has a hard coded timeout of 1 second (1_000 milliseconds). I don't see any reason to run click through this method anyway?

public function waitForExpectation(callable $callback): mixed
    {
        $timeout = Playwright::timeout();

        $originalCount = Assert::getCount();

        $start = microtime(true);
        $end = $start + ($timeout / 1_000);

        while (microtime(true) < $end) {
            try {
                return Playwright::usingTimeout(1_000, $callback);
            } catch (ExpectationFailedException) {
                //
            }

            $this->resetAssertions($originalCount);

            self::instance()->tick();
        }

        return $callback();
    }

Jonathan-384481 avatar Oct 31 '25 13:10 Jonathan-384481

I have the same issue.

it('may not login', function () {
    $page = visit('http://localhost/login');

    $page->assertUrlIs('http://localhost/login')
        ->assertSee('Connexion')
        ->fill('username', 'user.name')
        ->fill('password', 'PasWord123!')
        ->press('Se connecter')
        ->assertSee('Invalid credentials');
});

And I got the error :

Execution context was destroyed, most likely because of a navigation

Skytech61 avatar Nov 20 '25 13:11 Skytech61

I am getting this same issue. Im submitting a form, and then looking for a success message. In the screenshot I see the success message but it hangs and fails on the click even though the click went through successfully.

romanmartushev avatar Dec 05 '25 14:12 romanmartushev