Playwright打开PDF.js打印对话框后DOM断言超时问题求解
问题原因
点击打印按钮后等待.printedPage超时的核心原因是浏览器原生打印弹窗会阻塞JS主线程:
PDF.js的打印逻辑是先往#printContainer容器里渲染.printedPage元素,渲染完成后立刻调用window.print()唤起系统打印对话框。而浏览器一旦接收到window.print()调用,会立刻暂停当前页面的所有JS执行和DOM更新,直到用户关闭打印对话框才会恢复。原有测试逻辑没有拦截这个原生打印调用,导致渲染流程被打断,自然等不到.printedPage元素挂载。
修复方案
在页面导航前提前注入脚本,重写原生window.print方法,拦截打印弹窗唤起逻辑,避免主线程被阻塞,再按原有流程做断言即可。
修正后的完整测试代码:
import { test, expect } from '@playwright/test'; test('page has print button', async ({ page }) => { // 导航到页面前注入拦截脚本,替换原生window.print方法 await page.addInitScript(() => { window.print = () => { // 打标记确认打印逻辑被触发 window.__printInvoked = true; }; }); await page.goto('https://mozilla.github.io/pdf.js/web/viewer.html'); await page.locator('.page').first().waitFor({ state: 'attached' }); const printBtn = page.locator('#print'); const printContainer = page.locator('#printContainer'); await expect(page.locator('.page')).not.toHaveCount(0); await expect(printBtn).toHaveAttribute('title','Print'); await expect(printContainer).toBeEmpty(); // 点击打印按钮,同时等待打印逻辑被触发 await Promise.all([ page.waitForFunction(() => window.__printInvoked === true), printBtn.click() ]); // 等待打印页元素挂载完成再断言 await page.locator('.printedPage').first().waitFor({ state: 'attached' }); await expect(page.locator('.printedPage')).not.toHaveCount(0); });
补充说明
- 用
page.addInitScript注入拦截脚本比修改响应体的方式更简洁,脚本会在页面所有JS执行前生效,不会出现拦截不及时的问题。 - 如果测试场景需要验证打印弹窗本身的行为,可以把拦截逻辑替换为Playwright的打印事件监听,不需要完全重写
window.print,但如果只需要断言DOM生成,拦截方案稳定性最高。
佐证截图(.printedPage仅在点击打印按钮后生成):
内容的提问来源于stack exchange,提问作者kmancusi
相关产品推荐
相关产品推荐

