Workflow:Teamcapybara Capybara Custom Selector Definition
| Knowledge Sources | |
|---|---|
| Domains | Testing, Web_Automation, Selector_System |
| Last Updated | 2026-02-12 06:00 GMT |
Overview
End-to-end process for defining, registering, and using custom Capybara selectors to create reusable, domain-specific element locators with expression and node filters.
Description
This workflow covers how to extend Capybara's selector system by defining custom selectors. Custom selectors encapsulate complex element-finding logic into named, reusable units with built-in filtering capabilities. They leverage Capybara's Selector DSL to define CSS or XPath expressions, expression filters (applied at the query level to narrow the initial search), node filters (applied post-query to each result), and locator filters. The workflow also covers modifying existing selectors to add additional filters.
Usage
Execute this workflow when you find yourself repeatedly writing the same complex find(:css, ...) or find(:xpath, ...) expressions, or when you need domain-specific element location logic (e.g., finding data grid rows, custom component types, or application-specific widgets) that cannot be expressed cleanly with built-in selectors.
Execution Steps
Step 1: Identify_Selector_Need
Determine what kind of elements you need to locate repeatedly and what attributes or patterns distinguish them. Decide whether to create a new selector or modify an existing one. Review Capybara's 19 built-in selectors to see if one already covers the use case.
Built-in selectors include:
- :css, :xpath, :id, :element
- :field, :fillable_field, :file_field, :datalist_input
- :button, :link, :link_or_button
- :checkbox, :radio_button, :select, :option, :datalist_option
- :label, :fieldset, :frame, :table, :table_row
Step 2: Define_Selector_Expression
Use Capybara.add_selector to register a new selector with a name. Inside the block, define either a css or xpath block that receives the locator argument and returns the base expression used to find elements. This expression is the initial DOM query.
Pseudocode:
Call Capybara.add_selector with a symbol name Inside, define a css or xpath block The block receives the locator as its argument Return a CSS selector string or XPath expression The XPath gem can be used to build complex expressions
Key considerations:
- The expression block must return a valid CSS or XPath string
- The XPath gem provides a fluent builder API for constructing expressions
- The locator argument is what users pass as the second argument to find
- The selector name becomes the first argument to find (e.g., find(:my_selector, 'locator'))
Step 3: Add_Expression_Filters
Define expression filters that modify the generated CSS/XPath expression based on keyword options. These filters are applied before the DOM query executes, narrowing the search at the selector level for better performance.
Key considerations:
- Expression filters use expression_filter to declare named keyword options
- The filter block receives the current expression and the filter value
- Return a modified expression that incorporates the filter constraint
- Expression filters are applied before querying the DOM — they narrow the initial search
- Use filter_set to share filters between selectors
Step 4: Add_Node_Filters
Define node filters that run against each matching DOM element after the initial query. These filters inspect element attributes, properties, or state that cannot be expressed in CSS/XPath alone. Node filters receive the element node and the filter value and return a boolean.
Key considerations:
- Node filters use node_filter to declare named keyword options
- The filter block receives the Capybara Node and the filter value
- Return true to include the element, false to exclude it
- Node filters run in Ruby, so they are slower than expression filters
- Use node filters for dynamic checks (JavaScript state, computed styles, etc.)
Step 5: Register_And_Use
After defining the selector, use it in tests via Capybara's finder methods. The selector name is passed as the first argument to find, all, has_selector?, and related methods. The locator is the second argument, and keyword filters are additional keyword arguments.
Key considerations:
- find(:my_selector, 'locator', my_filter: value) uses the custom selector
- has_selector?(:my_selector, 'locator') works with matchers
- assert_selector(:my_selector, 'locator', count: 3) works with assertions
- Custom selectors integrate fully with Capybara's auto-wait mechanism
- Capybara.modify_selector(:existing) extends built-in selectors with new filters
Step 6: Test_Selector_Behavior
Verify the custom selector works correctly with various inputs, edge cases, and in combination with Capybara's matching and waiting behavior. Test with both exact and partial matching modes, and ensure filters behave as expected.
Key considerations:
- Test with different locator values including nil (if optional)
- Verify expression filters narrow the query correctly
- Verify node filters accept and reject elements as expected
- Test with count/minimum/maximum options
- Ensure the selector works with within scoping
- Test with the exact option for exact vs. substring matching