Rspec& Capybara:使用jQuery将焦点设置为元素并不适用`:focus` CSS

时间:2015-03-23 13:11:52

标签: javascript jquery rspec phantomjs capybara

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

我想使用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     颜色:黑色

&: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 个答案:

答案 0 :(得分:4)

这对我有用,首先在页面上显示一个元素。我不得不使用它作为一些拖放测试的前兆。

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

答案 1 :(得分: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识别出来,但对于我的情况来说,它已经足够了。

重要提示:顺便说一下,您应该使用execute_script代替evaluate_script,因为后者有huge performance impact