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

Playwright测试无法获取Next-Auth会话令牌,无法复用认证状态

问题:Playwright测试无法获取Next-Auth会话令牌,无法复用认证状态

需求

按照Playwright官方文档实现测试时无需重复登录,复用认证状态。

问题详情

Next-Auth通过next-auth.session-token验证认证状态,但按照文档操作后,storageState.json中从未存储该令牌。手动添加该令牌到JSON文件后,测试可正常运行。

已搭建极简仓库,仅包含登录按钮和测试用例。

相关代码

Next-Auth配置文件 ([...nextAuth].js)

import GithubProvider from "next-auth/providers/github";

export const authOptions = {
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  debug: true,
};

export default NextAuth(authOptions);

Playwright全局设置文件 (global-setup.js)

module.exports = async () => {
  const browser = await chromium.launch({
    headless: false,
  });
  const page = await browser.newPage();

  await page.goto('http://localhost:3000/');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await page.getByRole('button', { name: 'Sign in with GitHub' }).click();
  await page
    .getByLabel('Username or email address')
    .fill('email');
  await page.getByLabel('Password').fill('password');
  await page.getByRole('button', { name: 'Sign in' }).click();

  await page.context().storageState({ path: 'storageState.json' });
  await browser.close();
};

端到端测试代码

const { test, expect } = require("@playwright/test");

test.use({
  storageState: "storageState.json",
});

test("sign in through github", async ({ page }) => {
  await page.goto("http://localhost:3000");
  await expect(page.getByText("Signed in as")).not.toBeEmpty();
});

期望结果

global-setup.js能将完整的认证状态(包含next-auth.session-token)存储到storageState.json中,使测试无需重复登录即可通过。


解决方案

问题出在登录后未等待会话令牌写入Cookie就立即导出storageState。OAuth登录流程中,GitHub跳转回你的应用后,Next-Auth需要一点时间生成并设置next-auth.session-token Cookie,直接调用storageState会漏掉这个Cookie。

修改global-setup.js,添加等待逻辑:

优化后的全局设置代码

module.exports = async () => {
  const browser = await chromium.launch({
    headless: false,
  });
  const page = await browser.newPage();

  await page.goto('http://localhost:3000/');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await page.getByRole('button', { name: 'Sign in with GitHub' }).click();
  await page.getByLabel('Username or email address').fill('email');
  await page.getByLabel('Password').fill('password');
  await page.getByRole('button', { name: 'Sign in' }).click();

  // 二选一即可,推荐方案2更可靠
  // 方案1:等待目标Cookie出现
  await page.waitForCookie('next-auth.session-token');
  // 方案2:等待页面显示登录成功文本,确保整个流程完成
  // await page.waitForSelector('text=Signed in as', { timeout: 10000 });

  await page.context().storageState({ path: 'storageState.json' });
  await browser.close();
};

补充说明

  • 若用waitForCookie,确认Cookie名称和Next-Auth配置一致(默认是next-auth.session-token)。
  • 用页面元素等待(方案2)更稳妥,能确保登录流程完全结束,而不是仅Cookie写入。
  • 检查Next-Auth的secret配置是否正确,配置错误会导致令牌生成失败,Cookie无法正常写入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:40:32