如何使用Puppeteer粘贴文本?

时间:2019-07-18 19:28:41

标签: puppeteer

我正在尝试为我的React应用程序中的输入编写一个测试(使用jest-puppeteer),以独特的方式处理自动完成或复制/粘贴字符串。

我希望使用Puppeteer,可以将文本粘贴到输入中,然后验证页面是否正确更新。不幸的是,我找不到任何可行的示例。

我曾尝试使用page.keyboard模拟CMD+CCMD+V,但似乎这些命令在Puppeteer中均不起作用。

我还尝试使用clipboardy之类的库来写入和读取OS剪贴板。尽管剪贴板确实可用于写入(复制),但似乎读取(粘贴)不会影响Puppeteer运行的页面。

我已经使用多种方法成功复制了文本,但是无法粘贴到输入中。我已通过向文档添加"copy""paste"的事件侦听器来验证此假设。 "copy"事件被触发,但是没有方法导致"paste"事件被触发。

以下是我尝试过的几种方法:

await clipboardy.write('1234'); // writes "1234" to clipboard
await page.focus("input");
await clipboardy.read(); // Supposedly pastes from clipboard
// assert input has updated
await clipboardy.write('1234');
await page.focus("input");
await page.keyboard.down('Meta');
await page.keyboard.press('KeyV');
await page.keyboard.up('Meta');
// assert input has updated
await page.evaluate(() => {
  const input = document.createElement('input');
  document.body.appendChild(input);
  input.value = '1234';
  input.focus();
  input.select();
  document.execCommand('copy');
  document.body.removeChild(input);
});
wait page.focus("input");
await page.keyboard.down('Meta');
await page.keyboard.press('KeyV');
await page.keyboard.up('Meta');

我认为这里唯一缺少的部分是粘贴文本。但是如何使用Puppeteer粘贴文本?

2 个答案:

答案 0 :(得分:0)

这对clipboardy来说适用于我,但是当我无头启动它时无效:

await clipboardy.write('foo')

const input= await puppeteerPage.$(inputSelector)
await input.focus()

await puppeteerPage.keyboard.down('Control')
await puppeteerPage.keyboard.press('V')
await puppeteerPage.keyboard.up('Control')

如果让它毫无意义地工作,请告诉我。

我也尝试过clipBoard API,但无法编译:

const browser = await getBrowser()
const context = browser.defaultBrowserContext();
// set clipBoard API permissions
context.clearPermissionOverrides()
context.overridePermissions(config.APPLICATION_URL, ['clipboard-write'])
puppeteerPage = await browser.newPage()

await puppeteerPage.evaluate((textToCopy) =>{
  navigator.clipboard.writeText(textToCopy)
}, 'bar')

const input= await puppeteerPage.$(inputSelector)
await input.focus()

await puppeteerPage.evaluate(() =>{
  navigator.clipboard.readText()
})

答案 1 :(得分:0)

我想出了一个有趣的解决方法,如何将长文本粘贴到React组件中,以使该更改可以被该组件注册,并且无需花费很长时间就可以像通常使用 type那样键入命令:

对于文本复制,我使用Puppeteer文档中的方法(例如,我想从页面的前两个段落中选择文本)。我假设您已经知道如何设置剪贴板读写权限(例如,上面的答案之一显示了如何做到这一点)。

const fromJSHandle = await page.evaluateHandle(() =>Array.from(document.querySelectorAll('p'))[0])
const toJSHandle   = await page.evaluateHandle(() =>Array.from(document.querySelectorAll('p'))[1])

// from puppeteer docs
await page.evaluate((from, to) => {
     const selection = from.getRootNode().getSelection();
     const range = document.createRange();
     range.setStartBefore(from);
     range.setEndAfter(to);
     selection.removeAllRanges();
     selection.addRange(range);
}, fromJSHandle, toJSHandle);

await page.bringToFront();
await page.evaluate(() => {
     document.execCommand('copy') // Copy the selected content to the clipboard
     return navigator.clipboard.readText() // Obtain the content of the clipboard as a string
})

此方法不适用于粘贴(至少在Mac上是这样):document.execCommand('paste')

所以我要粘贴:

await page.$eval('#myInput', (el, value) =>{ el.value = value }, myLongText)
await page.type(`#myInput`,' ') // this assumes your app trims the input value in the end so the whitespace doesn't bother you

没有最后的键入步骤(空白),React不会注册更改/输入事件。因此,在提交表单(例如,输入是其中的一部分)之后,输入值仍为“”。 这是输入空白的地方-它触发更改事件,我们可以提交表单。

似乎需要与Puppeteer进行一些独创性研究,以弄清如何克服所有限制并同时保持一定水平的开发人员舒适度。