Dealing with cookie banner when testing PayPal payments with Laravel Dusk

173 Views Asked by At

I have a web app which has both Stripe and PayPal integrated. I have integrated tests set up for both of these via Laravel Dusk. The PayPal test fails about 50% of the time on GitHub Actions, even with conditional logic, because for some absolutely unhinged reason PayPal have decided that their sandbox needs to display a cookie banner, and even then only often enough so as to be completely unpredictable.

Short of PayPal fixing their sandbox, what can be done to fix this? Why does the if condition I'm using to test if the cookie banner exists only work some of the time?

Here is a simplified version of my Dusk test:

public function test_paypal_payments_are_working()
{
    $this->browse(function (Browser $browser) {
        $browser->visit("/product1")
        ->waitForLocation('/payment')
        ->resize(1920, 2000) # Hack to make sure PayPal button is always clickable
        ->withinFrame('#paypal-button-container iframe', function($browser) {
            $browser
            ->waitFor(".paypal-button")
            ->click(".paypal-button");
        });
        $mainWindow = $browser->driver->getWindowHandle();
        $paypalWindow = collect($browser->driver->getWindowHandles())->last(); // Get the PayPal popup window
        $browser->driver->switchTo()->window($paypalWindow); // Switch to it
        $browser
        ->disableFitOnFailure() # Force screenshots to show screen as interacted with
        ->click("#btnLogin")
        ->storeSource("debug"); # Verify the ID of the PayPal cookie banner button
        # Check the cookie banner button exists and if so, accept it
        if ($browser->element('#acceptAllButton')) {
            $browser
            ->click("#acceptAllButton");
        }
        $browser
        ->waitFor("#payment-submit-btn")
        ->click("#payment-submit-btn");
        $browser->driver->switchTo()->window($mainWindow); // Switch back to original window
        $browser->waitFor("@payment-success", 15)
        ->assertSeeIn("@payment-success");
    });
}
3

There are 3 best solutions below

3
oelimoe On

$browser->element() is not the best method to use in this case. I believe with the method $browser->assertPresent($selector) wil fix your problem

0
Hashim Aziz On

Unfortunately after testing $browser->assertPresent($selector) for a few runs this didn't work either. Although I haven't yet been able to find a single Laravel Dusk/Selenium method that can successfully check for the existence of PayPal's cookie banner and accept it, I think I may have stumbled on a workaround for this issue, or at least an answer to what causes it.

For whatever reason, the PayPal sandbox seems to trigger the cookie banner prompt when it determines you're pushing "too often" - in my experience this was about 4 times within the space of an hour. After seeing a failed push, waiting about 20 mins before pushing again seems to be enough for PayPal to stop showing the cookie banner and allow my GitHub Action run to pass as expected.

The issue is both a failure of Laravel Dusk to have any documented, working methods for conditional existence of elements, and of PayPal for deciding to serve a cookie banner in a sandbox designed for testing, but since I don't currently have the time or energy to chase up either, this is the closest thing to a solution it seems there will be.

0
Damon On

I am having the same issue and noticed on the failure screenshots that the cookie banner annoyingly sits on top of the payment button, even though you should be able to make purchases while ignoring the cookie banner.

In my pipeline I remove the element via javascript. It doesn't give any issues when the banner doesn't appear, but silently removes it when it does show up.

Right before I run $browser->click("#payment-submit-btn");

$browser->script('document.getElementById("gdprCookieBanner").remove()');