Emulating a clipboard copy/paste with Selinum + Capybara

拈花ヽ惹草 提交于 2020-06-27 09:44:20

问题


I have a "Copy Link" button in my frontend UI. When clicked, the URL inside an input box is copied to the user's clipboard with this JS:

const copyTextarea = document.querySelector("#copy-link-button");
copyTextarea.focus();
copyTextarea.select();
document.execCommand('copy');

When I try it out locally, this functionality works perfectly so I know the feature itself is working correctly.

However I'm unable to test the copy with Capybara. I know from this post that Capybara does not provide a clipboard API, but my workaround is to -

  1. Copy the link using the "Copy Link" button
  2. Navigate to some other input/text field
  3. Paste into the field with CTRL+V and read the contents of the field to verify

My test:

# Copy the link
page.find("#copy-link-button").click
wait_for_ajax

# Visit some other page that I know has an input/text field
visit account_settings_path

input = page.find("#user_email")

# Clear the field
fill_in("user[email]", with: "")

# Paste in the contents of the clipboard
input.base.send_keys([:control, "v"])

# Validate
expect(input.value).to eq("some value");

However nothing gets pasted into that input (input.value and input.text return "").

Is this a valid approach? Is the issue here with copying the text in the first place or did I make an error in pasting the data?

Thanks!


回答1:


There are lots of security rules around access to the clipboard content, so trying to get paste working from Capybara is really going to be an exercise in frustration. Additionally most browsers won't actually do anything when ctrl/command v is sent as a keystroke since it's a system triggered action not the browser.

However, since you just want to verify the copy works you don't actually need to trigger the paste, you just need to get around the permission requirements to use the clipboard API. If you're using Chrome (in a non-headless configuration - doesn't currently work headless) you can do that by setting the profile.content_settings.exceptions.clipboard preference in your driver registration

Capybara.register_driver :chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_preference('profile.content_settings.exceptions.clipboard', {
    '*': {'setting': 1}
  })
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

If you are running in headless mode and using up-to-date Capybara and selenium with Chrome another option is to use CDP to grant the permissions

page.driver.browser.execute_cdp('Browser.grantPermissions', origin: page.server_url, permissions: ['clipboardRead', 'clipboardWrite'])

Once you have the permissions worked out you can then use evaluate_async_script to access the clipboard data

clip_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])')

Notes: 1. there is no need to use base to call send_keys on an element, just call it on the element 2. expect(input.value).to eq("some value") will lead to flaky tests, instead you should use the Capybara provided matchers like expect(page).to have_field(with: 'some value') or expect(input).to match_selector(:field, with: 'some value')



来源:https://stackoverflow.com/questions/58034127/emulating-a-clipboard-copy-paste-with-selinum-capybara

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!