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() 注入的全局变量。