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

Jos*_*eim 9 javascript jquery rspec capybara phantomjs

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

我想使用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
Run Code Online (Sandbox Code Playgroud)

JavaScript in evaluate_script似乎没有正确执行.我$('#jump_to_content > a').focus()在Chrome控制台中尝试了相同的JS(),我对结果有点不确定,因为在控制台中,链接没有出现,但是当点击进入浏览器视图时,它出现了部分一秒钟又消失了(它消失了,因为它不再具有焦点).在我看来,它应该在执行JS后直接显示.

这让我对这一切有点不安全.任何帮助都非常感谢.

更新

我同时得出结论,Chrome的行为是正常的:焦点保留在控制台中,因此该元素实际上并没有真正获得焦点而且没有显示.

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

我创建了以下CSS规则:

#jump_to_navigation颜色:黑色

&:focus
  color: red
Run Code Online (Sandbox Code Playgroud)

为了测试这个,我设置了这个非常具体的测试:

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
Run Code Online (Sandbox Code Playgroud)

测试打破了这样:

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 ==)
Run Code Online (Sandbox Code Playgroud)

因此焦点设置正确,但:focus不应用样式.我猜这是PhantomJS的一个问题?

我很乐意找到解决这个问题的方法.

Jos*_*eim 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
Run Code Online (Sandbox Code Playgroud)

这似乎有效。我没有检查这种方式是否也能被 Capybara 识别 CSS 更改,但对于我的情况来说,这已经足够了。

重要提示:顺便说一句,您应该使用execute_script而不是evaluate_script,因为后者对性能有巨大的影响