使用 Selinum + Capybara 模拟剪贴板 copy/paste
Emulating a clipboard copy/paste with Selinum + Capybara
我的前端有一个 "Copy Link" 按钮 UI。单击时,将输入框内的 URL 复制到用户剪贴板,并使用此 JS:
const copyTextarea = document.querySelector("#copy-link-button");
copyTextarea.focus();
copyTextarea.select();
document.execCommand('copy');
当我在本地试用时,此功能完美运行,因此我知道该功能本身运行正常。
但是我无法用 Capybara 测试副本。我从 得知 Capybara 不提供剪贴板 API,但我的解决方法是 -
- 使用 "Copy Link" 按钮复制 link
- 导航到其他一些 input/text 字段
- 使用 CTRL+V 粘贴到字段中并读取字段内容以验证
我的测试:
# 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");
但是没有任何内容被粘贴到该输入中(input.value
和 input.text
return ""
)。
这是一种有效的方法吗?问题是首先复制文本还是我在粘贴数据时出错?
谢谢!
注意:由于此 Chrome 的原始发布已经更改了可用的权限类型。对于无头解决方案,请转到 https://chromedevtools.github.io/devtools-protocol/tot/Browser/#type-PermissionType 查看当前可用的权限类型
有很多关于访问剪贴板内容的安全规则,所以试图从 Capybara 中粘贴工作确实是一个令人沮丧的练习。此外,当 ctrl/command v 作为击键发送时,大多数浏览器实际上不会执行任何操作,因为它是系统触发的操作而不是浏览器。
但是,由于您只是想验证复制是否有效,因此实际上不需要触发粘贴,您只需要绕过使用剪贴板的权限要求即可 API。如果您使用的是 Chrome(在非无头配置中 - 当前无法无头工作),您可以通过在驱动程序注册中设置 profile.content_settings.exceptions.clipboard
首选项来做到这一点
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
如果您 运行 处于无头模式并且使用最新的 Capybara 和 selenium Chrome 另一种选择是使用 CDP 授予权限
page.driver.browser.execute_cdp('Browser.grantPermissions', origin: page.server_url, permissions: ['clipboardRead', 'clipboardWrite'])
获得权限后,您可以使用 evaluate_async_script
访问剪贴板数据
clip_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])')
备注:
- 不需要用
base
在元素上调用send_keys
,直接在元素 上调用即可
expect(input.value).to eq("some value")
会导致不稳定的测试,相反你应该使用 Capybara 提供的匹配器,比如 expect(page).to have_field(with: 'some value')
或 expect(input).to match_selector(:field, with: 'some value')
我的前端有一个 "Copy Link" 按钮 UI。单击时,将输入框内的 URL 复制到用户剪贴板,并使用此 JS:
const copyTextarea = document.querySelector("#copy-link-button");
copyTextarea.focus();
copyTextarea.select();
document.execCommand('copy');
当我在本地试用时,此功能完美运行,因此我知道该功能本身运行正常。
但是我无法用 Capybara 测试副本。我从
- 使用 "Copy Link" 按钮复制 link
- 导航到其他一些 input/text 字段
- 使用 CTRL+V 粘贴到字段中并读取字段内容以验证
我的测试:
# 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");
但是没有任何内容被粘贴到该输入中(input.value
和 input.text
return ""
)。
这是一种有效的方法吗?问题是首先复制文本还是我在粘贴数据时出错?
谢谢!
注意:由于此 Chrome 的原始发布已经更改了可用的权限类型。对于无头解决方案,请转到 https://chromedevtools.github.io/devtools-protocol/tot/Browser/#type-PermissionType 查看当前可用的权限类型
有很多关于访问剪贴板内容的安全规则,所以试图从 Capybara 中粘贴工作确实是一个令人沮丧的练习。此外,当 ctrl/command v 作为击键发送时,大多数浏览器实际上不会执行任何操作,因为它是系统触发的操作而不是浏览器。
但是,由于您只是想验证复制是否有效,因此实际上不需要触发粘贴,您只需要绕过使用剪贴板的权限要求即可 API。如果您使用的是 Chrome(在非无头配置中 - 当前无法无头工作),您可以通过在驱动程序注册中设置 profile.content_settings.exceptions.clipboard
首选项来做到这一点
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
如果您 运行 处于无头模式并且使用最新的 Capybara 和 selenium Chrome 另一种选择是使用 CDP 授予权限
page.driver.browser.execute_cdp('Browser.grantPermissions', origin: page.server_url, permissions: ['clipboardRead', 'clipboardWrite'])
获得权限后,您可以使用 evaluate_async_script
访问剪贴板数据
clip_text = page.evaluate_async_script('navigator.clipboard.readText().then(arguments[0])')
备注:
- 不需要用
base
在元素上调用send_keys
,直接在元素 上调用即可
expect(input.value).to eq("some value")
会导致不稳定的测试,相反你应该使用 Capybara 提供的匹配器,比如expect(page).to have_field(with: 'some value')
或expect(input).to match_selector(:field, with: 'some value')