Search code examples
phplaravelautomated-testsintegration-testinglaravel-dusk

"No such window" error when testing PayPal payments with Laravel Dusk


I'm trying to write an integration test to test PayPal's Standard Checkout, which appears in a popup window when the PayPal button is clicked. I've managed to come up with the test below, and watching it run locally with php artisan dusk --browse shows me that it successfully switches into the PayPal popup/modal, fills in the inputs and clicks on the final payment button. However, when switching back to the original window in order to do an assertion on the redirected payment confirmation page, it fails with the following error:

Facebook\WebDriver\Exception\NoSuchWindowException: no such window: target window already closed
from unknown error: web view not found

Why am I not able to switch back to the original window?

My Laravel Dusk test:

public function test_paypal_payments_are_working()
{
    $this->browse(function (Browser $browser) {
        $browser->visit("/products/payment")
        ->withinFrame('#paypal-button-container iframe', function($browser) {
            $browser
            ->waitFor(".paypal-button")
            ->click(".paypal-button");
        });
        $mainWindow = $browser->driver->getWindowHandle(); // Get current window
        $paypalWindow = collect($browser->driver->getWindowHandles())->last(); // Get the most recently opened window
        $browser->driver->switchTo()->window($paypalWindow); // Switch to it
        $browser
        ->waitFor("#email", 7)
        ->keys('#email', "[email protected]")
        ->click("#btnNext")
        ->waitFor("#password")
        ->keys('#password', "pass1")
        ->click("#btnLogin")
        ->waitFor("#payment-submit-btn")
        ->click("#payment-submit-btn")
        ->waitFor("@payment-header")
        ->driver->switchTo()->window($mainWindow); // Fails here
        $browser->assertSeeIn("@payment-header", "Payment was successful");
    });
}

Solution

  • After some more hacking away at this I finally stumbled across the solution. It turns out that for some reason it's not possible to chain any methods you call on the Chrome driver. I modified my test to reflect this:

    ->waitFor("#payment-submit-btn")
    ->click("#payment-submit-btn");
    $browser->driver->switchTo()->window($mainWindow);
    $browser->waitFor("@payment-header") // Fails here
    ->assertSeeIn("@payment-header", "radio code is");
    

    ...and it now successfully tests the PayPal checkout modal.

    Also make sure that you're not calling driver as a method, because for a while I had been without realising that it's not a method like almost everything else you call in Dusk.