You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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仅在点击打印按钮后生成):
.printedPage div元素仅在点击打印按钮后出现


内容的提问来源于stack exchange,提问作者kmancusi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:27:26