Node 是一个进程,Playwright 启动的是另外一个浏览器进程(或多个 context),那 Node 中设置的
globalThis
怎么能影响浏览器端?
✅ 回答简要:
不能直接影响。
Node(Playwright 测试脚本运行环境)和浏览器(被测页面的运行环境)之间的 globalThis
是完全隔离的内存空间,你在 Node 侧设置:
globalThis.__TEST_MODE__ = true;
是 Playwright 脚本的上下文变量,它不会自动同步到浏览器打开的页面里的 globalThis
。
✅ 那怎么实现“设置浏览器端 globalThis”的效果?
你可以通过 Playwright 提供的 API:page.addInitScript()
来显式注入变量:
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
(globalThis as any).__TEST_MODE__ = true;
});
await page.goto('http://localhost:5173');
});
这段代码的效果是:
- 在浏览器页面加载之前
- 注入一段 JS 脚本
- 设置浏览器内的
window.__TEST_MODE__ = true
这样,你就可以在 React 应用的代码中用 globalThis.__TEST_MODE__
判断是否为测试模式,实现“影响浏览器页面行为”的目的。
✅ 图示理解(进程与作用域)
┌─────────────────────────────┐
│ Node.js 进程(测试代码) │
│ Playwright 脚本运行在这里 │
│ └─ globalThis.__TEST_MODE__ ❌ ← 不会影响浏览器 │
└─────────────────────────────┘
│
▼
Playwright 启动浏览器
│
┌─────────────────────────────┐
│ 浏览器进程(React 应用) │
│ page.goto("localhost:5173") │
│ └─ globalThis.__TEST_MODE__ ✅ ← 需要通过 addInitScript 注入 │
└─────────────────────────────┘
✅ 示例完整流程(推荐)
test('test with __TEST_MODE__ flag', async ({ page }) => {
await page.addInitScript(() => {
(globalThis as any).__TEST_MODE__ = true;
});
await page.goto('http://localhost:5173');
// 在 React App 中可以读取 globalThis.__TEST_MODE__
await expect(page.getByText('测试模式已开启')).toBeVisible();
});
你的 React App 可以这么判断:
const isTest = typeof window !== 'undefined' && (window as any).__TEST_MODE__;
if (isTest) {
// 启用测试功能,比如跳过登录
}
✅ 结论
误区 | 说明 |
---|---|
❌ Playwright Node 脚本中设置 globalThis 就能影响页面 | 不成立,进程隔离,需注入 |
✅ 正确做法 | 使用 page.addInitScript() 将 JS 注入浏览器页面,全局变量会在加载前生效 |
如你使用 React Router + Playwright,建议你通过 globalThis.__TEST_FLAGS__
统一管理测试逻辑开关,同时保持隔离性与可测性。
BUTBUT
但是如果是 SSR 就不行了 ,兄弟!!!!
SSR 渲染是在 Node.js 服务端进行的,不是浏览器。
addInitScript() 是注入到 浏览器端(客户端 JS)执行前,它无法“回到服务器”去影响已经完成的 SSR 输出。
所以,SSR 过程根本就看不到你通过 addInitScript() 注入的全局变量。
评论