如何从 headless puppeteer 测试中访问剪贴板的内容?

How do I access the contents of the clipboard from within a headless puppeteer test?

我正在编写一个测试,该测试使用 puppeteer 来测试一个组件,该组件在与之交互时将某些内容复制到剪贴板。我想测试交互后剪贴板的内容是否正确。 this github issue mention using a tool like clipboardy 等其他资源来完成此任务。我尝试使用它并且它在本地工作,但是当 运行 在我的无头 CI 服务器中时,它抱怨无法访问 X 环境。有没有办法在不启动 X 服务器的情况下访问剪贴板?

我正在编写这样的测试:

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://mypage.com');

await page.click('#my-component');

// This fails in a headless environment
expect(clipboardy.readSync()).toEqual("Some text");

通过将 'clipboard-read' 权限添加到 puppeteer 并使用 剪贴板API,可以运行navigator.clipboard.readText()从 测试中的剪贴板。这甚至可以在无头环境中工作:

const browser = await puppeteer.launch();
const context = browser.defaultBrowserContext();
context.overridePermissions(/* browser origin */, ['clipboard-read'])
const page = await browser.newPage();
await page.goto('https://mypage.com');

await page.click('#my-component');

expect(await page.evaluate(() => navigator.clipboard.readText()))
  .toEqual("Some text");

Documentation 共 context.overridePermissions()

在我的例子中,我无法像 Eduard 所建议的那样覆盖权限,因为它需要将 origin 作为参数提供。我通过 setContent 将测试中的 html 内容注入页面,因此页面地址为 about:blank。将 origin 设置为 "*" 也不起作用,undefined.

也不起作用

我最终模拟了剪贴板api:

await page.evaluate((dataInternal) => {
    // mock clipboard
    let clipboardText = null;
    window["navigator"]["clipboard"] = {
        writeText: text => new Promise(resolve => clipboardText = text),
        readText: () => new Promise(resolve => resolve(clipboardText)),
    }
}

然后你可以做下面的断言:

expect(await page.evaluate(() => navigator.clipboard.readText())).toBe("your text in clipboard");