Filtering with Blocks 🌪️

If you need to restrict the found elements based on additional checks on the elements, you can do so by passing a filter block to any of the finders.

The filter block will be invoked once per found element, and should return a truthy value if the element meets the condition, or falsy to discard it from the results.

Elements passed to the block are wrapped, so you can call any of the test helper methods.

class UsersTestHelper < BaseTestHelper
  def admin?
    has_content?('Admin')
  end

  def find_admin(name)
    find('tr.user', text: name) { |user_row| user_row.admin? }
  end
end
users.find_admin('John')

# same as

find('tr.user', text: 'John') { |row| row.has_content?('Admin') }

# similar but with more guarantees around ambiguity than

find_all('tr.user', text: 'John').select { |row| row.has_content?('Admin') }.first

Filter blocks provide a huge amount of flexibility, and can be an elegant solution in certain scenarios.

Depending on the type of checks you perform in the block, you might be better off adding a custom selector, or adding a filter to an existing selector, which you can then easily reuse.