[英]Rspec & Capybara: Setting focus to an element using jQuery doesn't apply `:focus` CSS
I have jump links for blind and keyboard users in my webpage which are moved out of the viewport to hide them visually; 我在我的网页中有盲人和键盘用户的跳转链接,这些用户被移出视口以便在视觉上隐藏它们; when they gain focus, they are moved into the viewport.
当他们获得焦点时,他们会被移动到视口中。
I want to test this behaviour using RSpec and Capybara, but it somehow doesn't work. 我想使用RSpec和Capybara测试这种行为,但它不知何故不起作用。
it 'moves the focus to the navigation when activating the corresponding link', js: true do
expect(page).not_to have_css '#main:focus'
page.evaluate_script "$('#jump_to_content > a').focus()"
click_link 'Jump to content'
expect(page).to have_css '#main:focus'
end
The JavaScript in evaluate_script
doesn't seem to be executed properly. evaluate_script
中的JavaScript似乎没有正确执行。 I tried the same JS ( $('#jump_to_content > a').focus()
) in the Chrome console, and I'm a bit unsure about the result, because while in the console, the link doesn't appear, but when clicking into the browser view, it appears for a part of a second and disappears again (it disappears because it doesn't have the focus anymore then). 我在Chrome控制台中尝试了相同的JS(
$('#jump_to_content > a').focus()
),我对结果有点不确定,因为在控制台中,链接没有出现,但是当点击进入浏览器视图时,它会显示一段时间并再次消失(它会消失,因为它不再具有焦点)。 In my opinion it should be displayed directly after executing the JS. 在我看来,它应该在执行JS后直接显示。
This makes me a bit insecure about all this. 这让我对这一切有点不安全。 Any help is highly appreciated.
任何帮助都非常感谢。
Update 更新
I meanwhile have come to the conclusion that the behaviour of Chrome is normal: focus is kept in the console, so the element in fact doesn't really receive focus and doesn't show. 我同时得出结论,Chrome的行为是正常的:焦点保留在控制台中,因此该元素实际上并没有真正获得焦点而且没有显示。
I have also come to the conclusion that Capybara doesn't seem to be able to handle focusing an element (and applying :focus
styles) properly. 我还得出结论,Capybara似乎无法正确处理一个元素(并应用
:focus
样式)。
I have created the following CSS rules: 我创建了以下CSS规则:
a#jump_to_navigation color: black #jump_to_navigation颜色:黑色
&:focus
color: red
For testing this, I have set up this very specific test: 为了测试这个,我设置了这个非常具体的测试:
visit root_path
selector = 'a#jump_to_navigation'
# Initial style
expect(page.evaluate_script('document.activeElement.id')).to eq '' # Make sure the link isn't focused yet
expect(page.evaluate_script("$('#{selector}').css('color')")).to eq 'rgb(0, 0, 0)' # Color initially is black
# Set focus
page.evaluate_script("$('#{selector}').focus()")
# Focused style
expect(page.evaluate_script('document.activeElement.id')).to eq 'jump_to_navigation' # Make sure the link is focused now
expect(page.evaluate_script("$('#{selector}').css('color')")).to eq 'rgb(255, 0, 0)' # Color is now red
The test breaks like this: 测试打破了这样:
1) Navigation jump links visually displays them only on focus
Failure/Error: expect(page.evaluate_script("$('#{selector}').css('color')")).to eq 'rgb(255, 0, 0)' # Color is now red
expected: "rgb(255, 0, 0)"
got: "rgb(0, 0, 0)"
(compared using ==)
So the focus is set properly, but the :focus
styles aren't applied. 因此焦点设置正确,但不应用
:focus
样式。 I guess this is a problem with PhantomJS? 我猜这是PhantomJS的一个问题?
I'd be very happy to find a solution around this problem. 我很乐意找到解决这个问题的方法。
This has worked for me to get an element visible on the page first. 这对我有用,首先在页面上显示一个元素。 I've had to use this as a precursor to some drag and drop tests.
我不得不使用它作为一些拖放测试的前身。
page.execute_script("document.getElementById('foo').scrollIntoView()")
I found a workaround by using JavaScript to add/remove a class (in my case, .sr-only
) instead of relying on CSS' :hover
mechanism. 我找到了一种解决方法,通过使用JavaScript来添加/删除一个类(在我的情况下,
.sr-only
)而不是依赖于CSS :hover
机制。
visit root_path
selector = '#jump_to_navigation'
expect(page.evaluate_script('document.activeElement.id')).to eq '' # Make sure the link isn't focused yet
# Initial (hidden) position
expect(page.evaluate_script("$('#{selector}')[0].className")).to eq 'sr-only' # Make sure the link has sr-only class
# Set focus
page.evaluate_script("$('#{selector}').focus()")
expect('#' + page.evaluate_script('document.activeElement.id')).to eq selector # Make sure the link is focused now
# Displayed position
expect(page.evaluate_script("$('#{selector}')[0].className")).to eq '' # Make sure the link doesn't have sr-only class
# Remove focus
page.evaluate_script("$('#{selector}').blur()")
expect(page.evaluate_script('document.activeElement.id')).to eq '' # Make sure the link is focused now
# Hidden position again
expect(page.evaluate_script("$('#{selector}')[0].className")).to eq 'sr-only' # Make sure the link has sr-only class
This seems to work. 这似乎有效。 I didn't check whether this way also CSS changes are recognised by Capybara, but for my case, it's enough.
我没有检查这种方式是否也被Capybara识别出来,但对于我的情况来说,这已经足够了。
Important: By the way, you should use execute_script
instead of evaluate_script
, as the latter one has a huge performance impact ! 重要提示:顺便说一句,您应该使用
execute_script
而不是evaluate_script
,因为后者会对性能产生巨大影响 !
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.