You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Laravel Dusk测试PayPal支付时如何处理Cookie横幅?

问题

我开发的Web应用集成了Stripe与PayPal,并用Laravel Dusk搭建了二者的集成测试。但PayPal测试在GitHub Actions上的失败率约50%,就算加了条件逻辑也没用——根源是PayPal沙盒会随机弹出Cookie横幅,而且出现时机完全没规律。

想问两个点:

  1. 在PayPal修复沙盒之前,有什么解决办法?
  2. 我写的检测Cookie横幅是否存在的if条件为什么只有时候生效?

以下是我的Dusk测试简化版本:

public function test_paypal_payments_are_working()
{
    $this->browse(function (Browser $browser) {
        $browser->visit("/product1")
        ->waitForLocation('/payment')
        ->resize(1920, 2000) # 临时方案:确保PayPal按钮始终可点击
        ->withinFrame('#paypal-button-container iframe', function($browser) {
            $browser
            ->waitFor(".paypal-button")
            ->click(".paypal-button");
        });
        $mainWindow = $browser->driver->getWindowHandle();
        $paypalWindow = collect($browser->driver->getWindowHandles())->last(); // 获取PayPal弹窗
        $browser->driver->switchTo()->window($paypalWindow); // 切换到弹窗
        $browser
        ->disableFitOnFailure() # 强制截图显示交互时的屏幕状态
        ->click("#btnLogin")
        ->storeSource("debug"); # 验证PayPal Cookie横幅按钮的ID
        # 检查Cookie横幅按钮是否存在,存在则点击接受
        if ($browser->element('#acceptAllButton')) {
            $browser
            ->click("#acceptAllButton");
        }
        $browser
        ->waitFor("#payment-submit-btn")
        ->click("#payment-submit-btn");
        $browser->driver->switchTo()->window($mainWindow); // 切回原窗口
        $browser->waitFor("@payment-success", 15)
        ->assertSeeIn("@payment-success");
    });
}
解决方案

为什么你的if条件仅有时生效?

  • 无等待机制:$browser->element('#acceptAllButton')是同步执行的,一旦Cookie横幅延迟加载(比如PayPal沙盒的网络波动导致),代码执行时元素还没渲染出来,就会直接判定为不存在,后续点击逻辑不执行,之后横幅弹出就会挡住操作。
  • 未处理异常:Dusk的element()方法在元素不存在时会抛出NoSuchElementException,而不是返回null,你的代码没做异常捕获,一旦元素不存在,整个测试直接崩溃,而非跳过点击步骤。

可行解决办法

办法1:用等待+异常捕获处理横幅

把原来的if判断换成带等待和异常捕获的逻辑,兼容横幅延迟出现的场景:

// 替换原来的if判断代码
try {
    // 最多等5秒,直到Cookie接受按钮出现
    $browser->waitFor('#acceptAllButton', 5)->click('#acceptAllButton');
} catch (\Facebook\WebDriver\Exception\TimeoutException $e) {
    // 没弹出横幅,直接跳过
}

waitFor会轮询查找元素,超时则捕获异常跳过,既解决了时机问题,也不会因为元素不存在导致测试崩溃。

办法2:通过浏览器配置禁用Cookie横幅

直接在Dusk的Chrome启动参数里添加禁用Cookie提示的配置,从根源上阻止横幅弹出。修改tests/DuskTestCase.php的driver()方法:

protected function driver()
{
    $options = (new ChromeOptions)->addArguments([
        '--disable-gpu',
        '--headless=new',
        // 添加以下参数禁用Cookie控制功能
        '--disable-features=CookieControls',
        '--disable-site-isolation-trials',
        '--allow-insecure-localhost',
        // 强制浏览器默认接受所有Cookie
        '--user-data-dir=/tmp/dusk-chrome',
        '--profile-directory=Default',
        '--disable-popup-blocking',
    ]);

    return RemoteWebDriver::create(
        'http://localhost:9515',
        DesiredCapabilities::chrome()->setCapability(
            ChromeOptions::CAPABILITY,
            $options
        )
    );
}

这个方法让Chrome默认跳过Cookie提示,适合稳定的CI环境(比如GitHub Actions)。

办法3:等待页面完全加载后再操作

切换到PayPal弹窗后,先等待页面所有资源加载完成,再执行后续逻辑:

$browser->driver->switchTo()->window($paypalWindow);
// 等待页面加载完成(document ready状态)
$browser->waitUntil(function ($browser) {
    return $browser->script('return document.readyState === "complete";')[0];
});
// 执行登录操作
$browser->disableFitOnFailure()->click("#btnLogin");
// 再处理Cookie横幅
try {
    $browser->waitFor('#acceptAllButton', 3)->click();
} catch (\Exception $e) {}

确保页面所有异步资源(包括延迟加载的Cookie横幅)都渲染完成后再判断,减少时机问题导致的检测失败。

内容的提问来源于stack exchange,提问作者Hashim Aziz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 05:42:54