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

React应用Puppeteer登录流程测试在无头模式下运行失败求解

问题原因及解决方案

核心原因

两种模式运行结果不一致,通常是以下几个因素导致:

  • Puppeteer旧版headless: true的无头模式与有头模式存在原生行为差异,包括UA标识、Cookie策略、渲染逻辑都不一致,Puppeteer v19+推出的headless: 'new'新版无头模式已完全对齐有头模式的行为。
  • 默认视口尺寸差异:无头模式默认视口尺寸远小于普通桌面浏览器尺寸,可能导致元素未渲染在可视区域内,触发点击失效、选择器无法匹配的问题。
  • User-Agent标识差异:旧版无头模式的UA会携带HeadlessChrome字样,多数站点的安全策略、反爬规则会直接拦截该类请求,导致登录弹窗无法加载、请求被拒绝。
  • 第三方Cookie限制:无头模式默认禁用第三方Cookie,若你的登录弹窗为OAuth第三方授权登录,会导致授权流程被中断。
  • 弹出窗口拦截:无头模式默认可能阻止页面弹出新窗口,导致你监听的popup事件始终无法触发,流程卡在等待弹窗的步骤超时。

修复方案

1. 优先使用新版无头模式

修改puppeteer.launch配置,替换旧版无头模式:

browser = await puppeteer.launch({
  // 仅Puppeteer v19及以上版本支持,行为完全和有头模式一致
  headless: 'new', 
  slowMo: 50,
  args: [
    // 禁用沙箱,避免Linux环境下启动失败
    '--no-sandbox',
    '--disable-setuid-sandbox',
    // 允许弹出窗口
    '--disable-popup-blocking',
    // 禁用第三方Cookie限制,适配第三方登录场景
    '--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure'
  ]
})
// 手动设置视口为常规桌面尺寸
await page.setViewport({ width: 1920, height: 1080 })

2. 替换User-Agent伪装普通浏览器

在页面加载前手动设置正常浏览器的UA,绕过站点拦截:

await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36')
await page.goto("http://localhost:5000/test_site");

3. 优化弹窗获取逻辑

避免popup事件监听失效的问题,可直接通过浏览器页面列表获取弹窗:

await page.click("#login-button");
// 等待弹窗加载完成
await page.waitForTimeout(2000);
// 获取所有打开的页面,最后一个即为新弹出的登录窗口
const allPages = await browser.pages();
const popup = allPages[allPages.length - 1];

4. 延长超时时间+添加日志排查

给所有waitForSelector方法添加自定义超时,同时在报错时截图定位问题:

test("Authentication Process by logging in", async () => {
  try {
    const username = 'test123@gmail.com';
    const password = 'pw123';
    await page.waitForSelector("#login-button", {timeout: 15000});
    await page.click("#login-button");
    await page.waitForTimeout(2000);
    const allPages = await browser.pages();
    const popup = allPages[allPages.length - 1];
    await popup.waitForSelector("#usernameOrEmail", {timeout: 15000});
    await popup.type("#usernameOrEmail", username);
    await popup.waitForSelector("#password", {timeout: 15000});
    await popup.type("#password", password);
    await popup.click("#submitButton");
    await page.waitForSelector("#logout-button", {timeout: 15000})
    const text = await page.$eval("#logout-button", (e) => e.textContent);
    expect(text).toBe('Logout');
  } catch (err) {
    // 报错时截图,方便定位当前页面状态
    await page.screenshot({path: 'test-error.png', fullPage: true});
    throw err;
  }
}, 20000) // 给单测试用例设置20s超时,避免默认10s不够用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:00:01