Rspec&Capybara:使用jQuery将焦点设置到元素上不适用于`:focus` CSS

9

我在网页中为盲人和键盘用户设置了跳转链接,这些链接被移出视口以在视觉上隐藏它们; 当它们获得焦点时,它们会移动到视口内。

我想使用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()),但对结果有些不确定,因为在控制台中,链接并未出现,但当点击浏览器视图时,它会出现一小段时间,然后又消失了(因为它不再具有焦点)。在我看来,JS 执行后应该直接显示。

这让我有些不安。非常感谢任何帮助。

更新

我现在已经得出结论,Chrome 的行为是正常的:焦点保持在控制台中,因此元素实际上并没有真正获得焦点,也不会显示。

我还得出结论,Capybara 似乎无法正确处理聚焦元素(和应用 :focus 样式)。

我创建了以下 CSS 规则:

a#jump_to_navigation color: black

&: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的问题吗?
我很高兴能够找到解决此问题的方法。
2个回答

4

这对我来说是可行的,可以让页面上的元素首先可见。 我不得不在一些拖放测试之前使用它作为先决条件。

page.execute_script("document.getElementById('foo').scrollIntoView()")

2
我通过使用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

这似乎有效。我没有检查Capybara是否也能识别这种方式的CSS更改,但对于我的情况来说,这已经足够了。
重要提示:顺便说一下,你应该使用execute_script而不是evaluate_script,因为后者会有巨大的性能影响

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接