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.
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. 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). In my opinion it should be displayed directly after executing the 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.
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.
I have created the following CSS rules:
a#jump_to_navigation color: black
&: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. I guess this is a problem with 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.
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.
Important: By the way, you should use execute_script
instead of evaluate_script
, as the latter one has a huge performance impact!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With