【问题标题】:How do you paste text using Puppeteer?如何使用 Puppeteer 粘贴文本?
【发布时间】:2021-07-16 14:36:56
【问题描述】:

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

我希望通过使用 Puppeteer,我可以将文本粘贴到输入中,然后验证页面是否正确更新。不幸的是,我找不到任何可行的例子来说明如何做到这一点。

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

我还尝试使用诸如clipboardy 之类的库来写入和读取操作系统剪贴板。虽然剪贴板确实适用于写入(复制),但读取(粘贴)似乎不会影响 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 粘贴文本?

【问题讨论】:

    标签: puppeteer


    【解决方案1】:

    这适用于我 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()
    })
    

    【讨论】:

      【解决方案2】:

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

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

      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 方面发挥相当大的创造力,才能弄清楚如何解决所有限制并同时保持一定程度的开发人员舒适度。

      【讨论】:

      • 我非常爱你
      猜你喜欢
      • 2019-10-26
      • 1970-01-01
      • 2013-02-25
      • 2015-03-09
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 2020-01-08
      相关资源
      最近更新 更多