Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Workflow:Teamcapybara Capybara Custom Selector Definition

From Leeroopedia
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

Execution Diagram

GitHub URL

Workflow Repository