playwright保持网站的登录状态的几种方法

Playwright 提供了多种方法来保持网站的登录状态,避免每次测试都重新登录。以下是几种最常用和有效的方式:

1. 保存和恢复 Storage State(推荐)​

这是最常用且最可靠的方法,通过保存浏览器的存储状态(cookies、localStorage、sessionStorage)来保持登录状态。

图片[1]_playwright保持网站的登录状态的几种方法_知途无界

保存 Storage State

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 登录操作
  await page.goto('https://example.com/login');
  await page.fill('#username', 'your-username');
  await page.fill('#password', 'your-password');
  await page.click('#login-button');
  
  // 等待登录完成
  await page.waitForURL('https://example.com/dashboard');
  
  // 保存 storage state 到文件
  await context.storageState({ path: 'auth.json' });
  
  await browser.close();
})();

使用保存的 Storage State

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  
  // 使用保存的 storage state 创建上下文
  const context = await browser.newContext({
    storageState: 'auth.json'
  });
  
  const page = await context.newPage();
  await page.goto('https://example.com/dashboard');
  
  // 此时已经是登录状态,可以直接访问需要认证的页面
  console.log(await page.title());
  
  await browser.close();
})();

2. 在测试框架中全局共享 Context

在使用 Jest、Playwright Test 等测试框架时,可以在全局设置中创建带状态的 context。

Playwright Test 示例

// playwright.config.js
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    storageState: 'auth.json', // 所有测试共享同一个登录状态
  },
});
// global-setup.js
import { chromium } from '@playwright/test';

export default async function globalSetup() {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 执行登录
  await page.goto('https://example.com/login');
  await page.fill('#username', 'test-user');
  await page.fill('#password', 'test-pass');
  await page.click('#login-button');
  await page.waitForURL('**/dashboard');
  
  // 保存状态
  await context.storageState({ path: 'tests/auth.json' });
  
  await browser.close();
}
// tests/login.spec.js
import { test } from '@playwright/test';

test('should access protected page', async ({ page }) => {
  await page.goto('/dashboard');
  // 已经是登录状态,可以直接测试
  await expect(page.locator('.welcome-message')).toBeVisible();
});

3. 手动管理 Cookies

对于简单的场景,可以手动获取和设置 cookies。

获取 Cookies

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto('https://example.com/login');
  await page.fill('#username', 'your-username');
  await page.fill('#password', 'your-password');
  await page.click('#login-button');
  
  // 获取所有 cookies
  const cookies = await context.cookies();
  console.log(cookies);
  
  // 保存到文件
  const fs = require('fs');
  fs.writeFileSync('cookies.json', JSON.stringify(cookies));
  
  await browser.close();
})();

设置 Cookies

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  
  // 从文件读取 cookies
  const fs = require('fs');
  const cookies = JSON.parse(fs.readFileSync('cookies.json'));
  
  // 设置 cookies
  await context.addCookies(cookies);
  
  const page = await context.newPage();
  await page.goto('https://example.com/dashboard');
  
  // 验证登录状态
  await expect(page.locator('.user-profile')).toBeVisible();
  
  await browser.close();
})();

4. 使用 API 登录并设置 Token

对于现代 Web 应用,通常可以通过 API 登录获取 token,然后直接设置到 localStorage 或 headers 中。

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  // 通过 API 登录
  const loginResponse = await page.request.post('https://api.example.com/login', {
    data: {
      username: 'your-username',
      password: 'your-password'
    }
  });
  
  const { token } = await loginResponse.json();
  
  // 设置 token 到 localStorage
  await page.goto('https://example.com');
  await page.evaluate((authToken) => {
    localStorage.setItem('auth-token', authToken);
  }, token);
  
  // 保存状态
  await context.storageState({ path: 'api-auth.json' });
  
  await browser.close();
})();

5. 复用 Browser Context

在同一个测试文件中,可以复用 browser context 来保持状态。

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

test.describe.configure({ mode: 'serial' }); // 串行执行

let page;
let context;

test.beforeAll(async ({ browser }) => {
  context = await browser.newContext();
  page = await context.newPage();
  
  // 执行一次登录
  await page.goto('https://example.com/login');
  await page.fill('#username', 'test-user');
  await page.fill('#password', 'test-pass');
  await page.click('#login-button');
  await page.waitForURL('**/dashboard');
});

test('test 1: should see dashboard', async () => {
  await expect(page.locator('.dashboard-stats')).toBeVisible();
});

test('test 2: should access profile', async () => {
  await page.click('.profile-link');
  await expect(page.locator('.profile-form')).toBeVisible();
});

test.afterAll(async () => {
  await context.close();
});

最佳实践建议

  1. 优先使用 Storage State​:这是最完整的方法,包含所有认证相关的存储数据。
  2. 定期更新登录状态​:某些网站的 session 会过期,建议定期重新生成 auth 文件。
  3. 环境隔离​:为不同环境(开发、测试、生产)保存不同的 auth 文件。
  4. 敏感信息安全​: // 不要将包含真实密码的脚本提交到版本控制 // 使用环境变量 const password = process.env.TEST_PASSWORD;
  5. 处理动态内容​:有些网站使用 JavaScript 动态设置认证信息,确保在页面完全加载后再保存状态。
// 等待网络空闲后再保存状态
await page.waitForLoadState('networkidle');
await context.storageState({ path: 'auth.json' });

选择哪种方法取决于你的具体需求:

  • 完整测试套件​:使用 Storage State + 全局 setup
  • 单次测试​:手动登录并保存状态
  • API 驱动的网站​:使用 API 登录 + token 设置
  • 简单场景​:手动管理 cookies
© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞38 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容