如何在Jest的setupFilesAfterEnv中启动Playwright浏览器(TypeScript)并解决报错
问题解决:Jest setupFilesAfterEnv中Playwright浏览器实例未正确初始化的问题
核心原因
你直接把chromium.launch()返回的Promise赋值给了global.browser,此时global.browser是一个Promise对象而非实际的Browser实例,调用newContext()自然会抛出"Cannot read properties of undefined"错误——因为Promise上没有这个方法。此外,TypeScript默认不识别扩展的全局变量,还需要补充类型声明。
解决方案步骤
1. 修正setup.ts:异步等待浏览器启动
修改setup.ts,使用async/await等待浏览器实例初始化完成,同时确保Jest等待这个异步操作完成后再执行测试:
import { chromium, Browser } from 'playwright-chromium'; // 异步初始化浏览器 (async () => { global.browser = await chromium.launch({ headless: false }); global.my_val = '10'; })(); // 测试结束后清理浏览器实例,避免资源泄漏 afterAll(async () => { await global.browser.close(); });
2. 添加TypeScript全局类型声明
在项目根目录创建global.d.ts文件,扩展Node.js的Global类型,让TypeScript识别自定义全局变量:
declare global { namespace NodeJS { interface Global { browser: import('playwright-chromium').Browser; my_val: string; } } } export {};
确保你的tsconfig.json包含这个声明文件的路径,比如:
{ "compilerOptions": { "typeRoots": ["./node_modules/@types", "./src/types"] }, "include": ["src/**/*", "global.d.ts"] }
3. 验证测试文件逻辑
测试文件中的beforeEach无需修改,但建议添加测试后的清理步骤,避免资源占用:
describe("Test", () => { let context; let page; beforeEach(async () => { console.log("Global 10") console.log(global.my_val) context = await global.browser.newContext(); page = await context.newPage(); }); // 测试后清理上下文和页面 afterEach(async () => { await page.close(); await context.close(); }); test('示例测试', async () => { await page.goto('https://example.com'); const title = await page.title(); expect(title).toBe('Example Domain'); }); });
4. 补充Jest配置(可选)
如果你的TypeScript需要Babel转译,确保jest.config.cjs添加transform配置:
const config = { testTimeout: 20000, setupFilesAfterEnv: ["<rootDir>/setup.ts"], transform: { '^.+\\.tsx?$': 'babel-jest', }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], }; module.exports = config;
关键要点
- 永远不要直接把Promise赋值给全局变量,必须
await后再赋值,确保拿到实际的实例对象。 - TypeScript环境下必须扩展全局类型,避免类型检查报错。
- 务必添加清理步骤(
afterAll关闭浏览器,afterEach关闭上下文和页面),防止测试结束后残留进程占用资源。
内容的提问来源于stack exchange,提问作者Jakub Bujak
相关产品推荐
相关产品推荐

