如何使用Ruby Selenium/Capybara测试Web应用的Tab键切换顺序
I’ve run into this exact issue before—testing tab order feels tricky at first because Capybara’s send_keys can feel tied to specific elements, but there’s a straightforward way to track focus as you tab through elements. Here’s how to approach it:
The Core Idea
Instead of trying to target elements to send Tab to, you’ll want to track the currently focused element in the browser after each Tab press. Capybara lets you access the underlying browser driver’s API to get the active element, which is key here.
Step-by-Step Example
Let’s say your /home page has three inputs with IDs input-1, input-2, and input-3. Here’s how to verify their tab order:
visit '/home' # First, ensure the page has focus (sometimes browsers leave focus in the address bar initially) find('body').click # Define your expected elements in the order you want to test first_input = find('#input-1') second_input = find('#input-2') third_input = find('#input-3') # Verify initial focus (if your page sets focus to the first input on load, skip the body click above) expect(page.driver.browser.switch_to.active_element).to eq(first_input.native) # Press Tab and check focus moves to the second input page.send_keys(:tab) expect(page.driver.browser.switch_to.active_element).to eq(second_input.native) # Press Tab again and check focus moves to the third input page.send_keys(:tab) expect(page.driver.browser.switch_to.active_element).to eq(third_input.native)
Key Details to Note
page.send_keys(:tab): You don’t need to target a specific element here—this sends the Tab key to the currently focused element in the page (which is why we click the body first to ensure the page has focus).switch_to.active_element: This is a driver-level API that fetches the element currently holding focus. We useelement.nativebecause Capybara wraps elements, and we need to compare against the raw browser element.- Handling Custom
tabindex: If your elements usetabindexto override the natural DOM order, just adjust theexpected_elementslist to match the intended tab flow.
Helper Method for Reusability
If you need to test tab order across multiple pages, wrap this logic in a helper method to keep your tests clean:
def assert_tab_order(expected_elements) # Ensure page has focus find('body').click expected_elements.each_with_index do |element, index| # Press Tab before checking all elements except the first page.send_keys(:tab) if index > 0 expect(page.driver.browser.switch_to.active_element).to eq(element.native) end end # Usage in your test visit '/home' assert_tab_order([find('#input-1'), find('#input-2'), find('#input-3')])
Driver Compatibility
This approach works with most Capybara drivers (Selenium, Cuprite, etc.). Note that some headless drivers might have minor differences, but switch_to.active_element is widely supported.
内容的提问来源于stack exchange,提问作者Zack

