Rspec & Capybara:使用 jQuery 将焦点设置到元素上不适用 `:focus` CSS
Rspec & Capybara: Setting focus to an element using jQuery doesn't apply `:focus` CSS
我在我的网页中为盲人和键盘用户设置了跳转 links,它们被移出视口以在视觉上隐藏它们;当他们获得焦点时,他们将移入视口。
我想使用 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
evaluate_script
中的JavaScript似乎没有正确执行。我在 Chrome 控制台中尝试了相同的 JS ($('#jump_to_content > a').focus()
),但我对结果有点不确定,因为在控制台中,link 没有出现,但是单击浏览器视图时,它会出现几秒钟然后再次消失(它消失是因为它不再具有焦点)。我个人认为应该是执行完JS后直接显示。
这让我对这一切有点不安。非常感谢任何帮助。
更新
同时我得出的结论是 Chrome 的行为是正常的:焦点保留在控制台中,因此该元素实际上并没有真正获得焦点并且没有显示。
我还得出结论,水豚似乎无法正确处理聚焦元素(并应用 :focus
样式)。
我创建了以下 CSS 规则:
一个#jump_to_navigation
颜色:黑色
&:focus
color: red
为了测试这个,我设置了这个非常具体的测试:
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
测试是这样中断的:
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 ==)
因此焦点设置正确,但未应用 :focus
样式。我想这是 PhantomJS 的问题?
我很乐意找到解决这个问题的方法。
这对我来说很有效,可以让一个元素首先在页面上可见。我不得不将其用作一些拖放测试的先驱。
page.execute_script("document.getElementById('foo').scrollIntoView()")
我通过使用 JavaScript 到 add/remove a class(在我的例子中,.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
这似乎有效。我没有检查这种方式是否也 CSS 更改被 Capybara 识别,但对于我来说,这就足够了。
重要提示:顺便说一句,你应该使用execute_script
而不是evaluate_script
,因为后者有一个huge performance impact!
我在我的网页中为盲人和键盘用户设置了跳转 links,它们被移出视口以在视觉上隐藏它们;当他们获得焦点时,他们将移入视口。
我想使用 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
evaluate_script
中的JavaScript似乎没有正确执行。我在 Chrome 控制台中尝试了相同的 JS ($('#jump_to_content > a').focus()
),但我对结果有点不确定,因为在控制台中,link 没有出现,但是单击浏览器视图时,它会出现几秒钟然后再次消失(它消失是因为它不再具有焦点)。我个人认为应该是执行完JS后直接显示。
这让我对这一切有点不安。非常感谢任何帮助。
更新
同时我得出的结论是 Chrome 的行为是正常的:焦点保留在控制台中,因此该元素实际上并没有真正获得焦点并且没有显示。
我还得出结论,水豚似乎无法正确处理聚焦元素(并应用 :focus
样式)。
我创建了以下 CSS 规则:
一个#jump_to_navigation 颜色:黑色
&:focus
color: red
为了测试这个,我设置了这个非常具体的测试:
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
测试是这样中断的:
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 ==)
因此焦点设置正确,但未应用 :focus
样式。我想这是 PhantomJS 的问题?
我很乐意找到解决这个问题的方法。
这对我来说很有效,可以让一个元素首先在页面上可见。我不得不将其用作一些拖放测试的先驱。
page.execute_script("document.getElementById('foo').scrollIntoView()")
我通过使用 JavaScript 到 add/remove a class(在我的例子中,.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
这似乎有效。我没有检查这种方式是否也 CSS 更改被 Capybara 识别,但对于我来说,这就足够了。
重要提示:顺便说一句,你应该使用execute_script
而不是evaluate_script
,因为后者有一个huge performance impact!