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

如何在Playwright中使用Supabase持久化会话?测试认证页面报错

解决Playwright E2E测试中Supabase会话持久化与Setup脚本执行问题

一、Supabase会话未持久化(Cookie未设置)的解决方法

1. 确保登录后等待会话完全落地

页面操作登录后,不要立刻保存状态,需等待Supabase会话初始化完成,避免Cookie还未写入就被存储:

// auth.setup.ts
import { test as setup } from '@playwright/test';

setup('完成登录并保存状态', async ({ browser }) => {
  const context = await browser.newContext();
  const page = await context.newPage();

  // 执行登录操作
  await page.goto('/login');
  await page.fill('#email', 'test@example.com');
  await page.fill('#password', 'your-test-password');
  await page.click('#submit-btn');

  // 等待会话确认:可通过页面元素或直接调用Supabase API验证
  await page.waitForSelector('#user-profile-avatar'); // 等待登录后出现的认证元素
  // 或者直接在浏览器上下文里校验会话
  const hasValidSession = await page.evaluate(async () => {
    const { supabase } = window;
    const { data } = await supabase.auth.getSession();
    return !!data.session;
  });
  if (!hasValidSession) throw new Error('登录后未获取到有效Supabase会话');

  // 保存状态到文件
  await context.storageState({ path: 'playwright/.auth/user-state.json' });
  await context.close();
});

2. 正确加载存储状态

确保在创建浏览器上下文时加载状态,而非页面创建后:

// test.spec.ts
import { test } from '@playwright/test';

// 全局应用存储状态
test.use({ storageState: 'playwright/.auth/user-state.json' });

test('访问认证专属页面', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page.locator('#dashboard-welcome')).toBeVisible();
});

3. 校验Supabase Cookie配置

确认Supabase的会话Cookie(sb-access-token、sb-refresh-token)未被标记为跨域且域名与测试环境一致,Playwright默认会捕获所有HttpOnly Cookie,只要上下文域名匹配即可。


二、Setup脚本不再每次测试前执行的解决方法

1. 区分「一次性前置Setup」和「每个测试前置Setup」

  • 一次性前置:如果只需要在所有测试前执行一次登录,在playwright.config.ts中配置项目依赖:
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name: 'auth-setup',
      testMatch: /auth\.setup\.ts/,
    },
    {
      name: 'chromium',
      use: { storageState: 'playwright/.auth/user-state.json' },
      dependencies: ['auth-setup'], // 依赖Setup项目,仅执行一次
    },
  ],
});
  • 每个测试前置:若需要每个测试用例都重新登录,将登录逻辑放入test.beforeEach:
// test.spec.ts
import { test } from '@playwright/test';

test.beforeEach(async ({ browser }) => {
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 重复登录逻辑
  await page.goto('/login');
  await page.fill('#email', 'test@example.com');
  await page.fill('#password', 'your-test-password');
  await page.click('#submit-btn');
  await page.waitForSelector('#user-profile-avatar');

  // 保存临时状态供当前测试用例使用
  await context.storageState({ path: 'playwright/.auth/temp-state.json' });
  await context.close();
});

test('测试1', async ({ page }) => {
  await page.goto('/dashboard');
  // ...测试逻辑
});

2. Node端Supabase客户端登录的正确姿势

如果用Node端@supabase/supabase-js创建客户端,需手动将会话Cookie注入浏览器上下文,避免和浏览器端会话脱节:

// auth.setup.ts
import { test as setup } from '@playwright/test';
import { createClient } from '@supabase/supabase-js';

setup('通过Supabase API登录并设置Cookie', async ({ browser }) => {
  const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!);
  const { data, error } = await supabase.auth.signInWithPassword({
    email: 'test@example.com',
    password: 'your-test-password',
  });
  if (error) throw error;

  const context = await browser.newContext();
  const supabaseDomain = new URL(process.env.SUPABASE_URL!).hostname;
  // 手动注入Supabase会话Cookie
  await context.addCookies([
    {
      name: 'sb-access-token',
      value: data.session!.access_token,
      domain: supabaseDomain,
      path: '/',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
    },
    {
      name: 'sb-refresh-token',
      value: data.session!.refresh_token,
      domain: supabaseDomain,
      path: '/',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
    },
  ]);

  await context.storageState({ path: 'playwright/.auth/user-state.json' });
  await context.close();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 02:46:02