我正在尝试为我的React应用程序中的输入编写一个测试(使用jest-puppeteer),以独特的方式处理自动完成或复制/粘贴字符串。
我希望使用Puppeteer,可以将文本粘贴到输入中,然后验证页面是否正确更新。不幸的是,我找不到任何可行的示例。
我曾尝试使用page.keyboard
模拟CMD+C
和CMD+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粘贴文本?
答案 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进行一些独创性研究,以弄清如何克服所有限制并同时保持一定水平的开发人员舒适度。