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

使用Laravel Dusk测试PayPal支付时出现No such window错误

问题:Laravel Dusk测试PayPal标准结账时无法切换回原窗口

我正在编写集成测试以测试PayPal标准结账功能,点击PayPal按钮会弹出一个窗口。通过php artisan dusk --browse本地运行测试时,能成功切换到PayPal弹窗,填写输入框并点击最终支付按钮。但切换回原窗口对支付确认页进行断言时,出现如下错误:

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

为何无法切换回原窗口?

我的Laravel Dusk测试代码如下:

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(); // 获取当前窗口
        $paypalWindow = collect($browser->driver->getWindowHandles())->last(); // 获取最新打开的窗口
        $browser->driver->switchTo()->window($paypalWindow); // 切换到PayPal窗口
        $browser
        ->waitFor("#email", 7)
        ->keys('#email', "paypal-sandbox@personal.example.com")
        ->click("#btnNext")
        ->waitFor("#password")
        ->keys('#password', "pass1")
        ->click("#btnLogin")
        ->waitFor("#payment-submit-btn")
        ->click("#payment-submit-btn")
        ->waitFor("@payment-header")
        ->driver->switchTo()->window($mainWindow); // 此处失败
        $browser->assertSeeIn("@payment-header", "Payment was successful");
    });
}

原因分析与解决方案

核心原因

  1. 主窗口句柄获取时机错误:你在打开PayPal弹窗后才获取主窗口句柄,此时浏览器窗口上下文可能已变化,拿到的句柄不准确;后续支付流程可能导致原窗口被关闭或刷新,使句柄直接失效。
  2. 切换窗口时机过早:点击支付按钮后,PayPal窗口的流程尚未完全结束(比如跳转、关闭),此时原窗口可能还在加载确认页,或已被关闭,导致切换失败。

修复方案

1. 提前获取主窗口句柄

将获取主窗口句柄的代码移到打开PayPal弹窗之前,确保拿到的是未受弹窗影响的原始主窗口句柄。

2. 等待PayPal窗口完成流程

点击支付按钮后,等待PayPal窗口关闭(或从窗口列表中消失),再切换回主窗口,避免在流程未结束时操作。

3. 切换后主窗口等待页面加载

切换回主窗口后,先等待确认页的元素加载完成,再执行断言,避免页面未就绪导致的元素找不到问题。

修改后的测试代码

public function test_paypal_payments_are_working()
{
    $this->browse(function (Browser $browser) {
        // 提前获取主窗口句柄,确保是打开弹窗前的原始窗口
        $mainWindow = $browser->driver->getWindowHandle();

        $browser->visit("/products/payment")
            ->withinFrame('#paypal-button-container iframe', function($browser) {
                $browser
                    ->waitFor(".paypal-button")
                    ->click(".paypal-button");
            });

        // 获取PayPal弹窗的句柄
        $paypalWindow = collect($browser->driver->getWindowHandles())->last();
        $browser->driver->switchTo()->window($paypalWindow);

        // 完成PayPal登录与支付流程
        $browser
            ->waitFor("#email", 7)
            ->keys('#email', "paypal-sandbox@personal.example.com")
            ->click("#btnNext")
            ->waitFor("#password")
            ->keys('#password', "pass1")
            ->click("#btnLogin")
            ->waitFor("#payment-submit-btn")
            ->click("#payment-submit-btn");

        // 等待PayPal窗口关闭,确保支付流程完全结束
        $browser->driver->wait()->until(function ($driver) use ($paypalWindow) {
            return !in_array($paypalWindow, $driver->getWindowHandles());
        });

        // 切换回主窗口
        $browser->driver->switchTo()->window($mainWindow);

        // 等待支付确认页加载完成后,执行断言
        $browser->waitFor("@payment-header")
            ->assertSeeIn("@payment-header", "Payment was successful");
    });
}

额外注意事项

  • 如果支付完成后主窗口发生跳转,原句柄依然有效,但必须等待页面加载完成才能进行断言。
  • 若主窗口被意外关闭,可以通过$browser->driver->getWindowHandles()获取当前所有窗口,选择第一个(或对应主窗口的句柄)进行切换。

内容的提问来源于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.28 20:23:10