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
相关产品推荐
相关产品推荐

