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

Laravel 12 中使用 PEST 4 测试基于 Fetch API 提交 FormData 的表单时数据丢失问题求助

我之前遇到过类似的问题,Laravel Dusk(PEST浏览器测试底层基于它)在处理通过Fetch API提交的FormData时偶尔会出现后端无法解析数据的情况,结合你的场景,这里有几个排查和解决的方向:

1. 先确认后端端点本身是否正常

首先排除后端代码的问题,写一个简单的单元测试直接POST请求端点:

it('test backend endpoint directly', function () {
    $response = $this->post('/test', ['test_input' => 'Hello from JS!']);
    $response->assertJson(['message' => 'Hello from JS!']);
});

如果这个测试通过,说明后端逻辑没问题,问题出在浏览器测试的JS交互模拟上。

2. 确保测试等待异步请求完成

Fetch是异步操作,点击按钮后立即执行assertSee会导致断言在AJAX响应返回前执行。修改测试代码,添加等待逻辑:

it('test js fetch', function () {
    $page = visit('/test');

    $page->click('Test')
         ->waitFor('#response', 5) // 等待5秒,直到响应元素加载或更新
         ->assertSee('Hello from JS!')
         ->screenshot();
});

不过从你的截图看,页面已经显示了"No input provided",说明后端已经返回了响应,这个可能不是核心问题,但加上等待逻辑能避免异步时序问题。

3. 检查ChromeDriver版本兼容性

Dusk依赖ChromeDriver,版本不匹配会导致各种JS交互异常。运行Laravel自带的命令更新ChromeDriver:

php artisan dusk:chrome-driver

确保ChromeDriver版本和你本地安装的Chrome浏览器版本一致(可以在Chrome的chrome://version/查看版本号)。

4. 处理CSRF Token(虽然浏览器中正常,但测试环境可能需要)

你的视图中没有添加CSRF meta标签,虽然浏览器中可能通过Cookie自动传递XSRF-TOKEN,但Dusk的模拟环境偶尔会出现问题。修改视图添加CSRF标签:

<head>
    <title>Test page</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>

然后在JS代码中手动带上CSRF头:

document.getElementById('test_btn').addEventListener('click', () => {
    const formData = new FormData();
    formData.append('test_input', 'Hello from JS!');
    const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
    
    fetch('/test', {
        method: 'POST',
        headers: {
            'X-CSRF-TOKEN': csrfToken
        },
        body: formData
    })
    .then(async response => {
        const respJson = await response.json();
        document.getElementById('response').innerHTML = respJson.message;
    });
});

5. 尝试关闭Headless模式

Chrome的Headless模式偶尔会有兼容性问题,修改config/dusk.php中的Chrome配置,注释掉Headless参数:

'chrome' => [
    'driver' => 'chrome',
    'options' => [
        '--disable-gpu',
        // '--headless=new', // 暂时注释这行
    ],
],

重新运行测试,看看是否正常。

6. 换用$request->input()代替$request->get()

虽然get()方法通常能获取到数据,但在multipart/form-data请求下,input()方法的解析逻辑可能更稳定:

public function test(Request $request): View|JsonResponse {
    if ($request->isMethod('POST')) {
        return response()->json(['message' => $request->input('test_input', 'No input provided')]);
    }
    return view('test');
}

如果以上方法都不行,可以在控制器中输出请求的详细信息,帮助排查:

public function test(Request $request): View|JsonResponse {
    if ($request->isMethod('POST')) {
        return response()->json([
            'message' => $request->input('test_input', 'No input provided'),
            'request_all' => $request->all(),
            'content_type' => $request->header('Content-Type'),
            'post_data' => $request->post()
        ]);
    }
    return view('test');
}

然后查看测试截图中的response元素内容,就能知道后端到底收到了什么请求数据,从而定位问题。

内容的提问来源于stack exchange,提问作者constantin.iordan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 10:49:07