Playwright 提供了多种方法来保持网站的登录状态,避免每次测试都重新登录。以下是几种最常用和有效的方式:
1. 保存和恢复 Storage State(推荐)
这是最常用且最可靠的方法,通过保存浏览器的存储状态(cookies、localStorage、sessionStorage)来保持登录状态。
![图片[1]_playwright保持网站的登录状态的几种方法_知途无界](https://zhituwujie.com/wp-content/uploads/2026/01/d2b5ca33bd20260125102916.png)
保存 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();
});
最佳实践建议
- 优先使用 Storage State:这是最完整的方法,包含所有认证相关的存储数据。
- 定期更新登录状态:某些网站的 session 会过期,建议定期重新生成 auth 文件。
- 环境隔离:为不同环境(开发、测试、生产)保存不同的 auth 文件。
- 敏感信息安全:
// 不要将包含真实密码的脚本提交到版本控制 // 使用环境变量 const password = process.env.TEST_PASSWORD; - 处理动态内容:有些网站使用 JavaScript 动态设置认证信息,确保在页面完全加载后再保存状态。
// 等待网络空闲后再保存状态
await page.waitForLoadState('networkidle');
await context.storageState({ path: 'auth.json' });
选择哪种方法取决于你的具体需求:
- 完整测试套件:使用 Storage State + 全局 setup
- 单次测试:手动登录并保存状态
- API 驱动的网站:使用 API 登录 + token 设置
- 简单场景:手动管理 cookies
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
























暂无评论内容