Class: Capybara::Compose::TestHelper

Inherits:
Object
  • Object
show all
Includes:
Actions, Assertions, Finders, Matchers, Selectors, Synchronization, DSL
Defined in:
lib/capybara/compose/test_helper.rb

Overview

Public: Base class to create test helpers that have full access to the Capybara DSL, while easily defining custom assertions, getters, and actions.

It also supports locator aliases to prevent duplication and keep tests easier to understand and to maintain.

Constant Summary

Constants included from Synchronization

Synchronization::EXPECTATION_ERRORS

Constants included from Selectors

Selectors::SELECTOR_SEPARATOR

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Assertions

#have, #have_value, #invert_expectation, #not_to, #should, #should_not

Methods included from Actions

#blur, #focus, #type_in

Methods included from Finders

#all

Methods included from Selectors

included, #resolve_alias_for_selector_query, #selectors

Constructor Details

#initialize(query_context, test_context: query_context, negated: nil) ⇒ TestHelper

Returns a new instance of TestHelper.



33
34
35
# File 'lib/capybara/compose/test_helper.rb', line 33

def initialize(query_context, test_context: query_context, negated: nil)
  @query_context, @test_context, @negated = query_context, test_context, negated
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Capybara::Compose::Assertions

Instance Attribute Details

#query_contextObject (readonly)

Returns the value of attribute query_context.



31
32
33
# File 'lib/capybara/compose/test_helper.rb', line 31

def query_context
  @query_context
end

#test_contextObject (readonly)

Returns the value of attribute test_context.



31
32
33
# File 'lib/capybara/compose/test_helper.rb', line 31

def test_context
  @test_context
end

Class Method Details

.delegate_to_test_context(*method_names) ⇒ Object

Public: Make methods in the test context available in the helpers.



134
135
136
# File 'lib/capybara/compose/test_helper.rb', line 134

def delegate_to_test_context(*method_names)
  delegate(*method_names, to: :test_context)
end

.method_added(method_name) ⇒ Object

Internal: Fail early if a reserved method is redefined.



164
165
166
167
168
169
# File 'lib/capybara/compose/test_helper.rb', line 164

def method_added(method_name)
  return unless Capybara::Compose::RESERVED_METHODS.include?(method_name)

  raise "A method with the name #{ method_name.inspect } is part of the Capybara DSL," \
    ' overriding it could cause unexpected issues that could be very hard to debug.'
end

.on_test_helper_loadObject

Internal: Allows to perform certain actions just before a test helper will be loaded for the first time.



159
160
161
# File 'lib/capybara/compose/test_helper.rb', line 159

def on_test_helper_load
  define_getters_for_selectors
end

.use_test_helpers(*helper_names) ⇒ Object

Public: Allows to make other test helpers available.

NOTE: When you call a helper the “negated” state is preserved for assertions.

NOTE: You can also pass an element to a test helper to “wrap” a specified element with the specified test helper class.

Example:

dropdown(element).toggle_menu


147
148
149
150
151
152
153
154
155
# File 'lib/capybara/compose/test_helper.rb', line 147

def use_test_helpers(*helper_names)
  helper_names.each do |helper_name|
    private define_method(helper_name) { |element = nil|
      test_helper = test_context.get_test_helper(helper_name)
      test_helper = test_helper.wrap_element(element) if element
      @negated.nil? ? test_helper : test_helper.should(@negated)
    }
  end
end

Instance Method Details

#friendly_nameObject

Internal: Returns the name of the class without the suffix.

Example: ‘current_page’ for CurrentPageTestHelper.



99
100
101
# File 'lib/capybara/compose/test_helper.rb', line 99

def friendly_name
  self.class.name.chomp('TestHelper').underscore
end

#inspectObject

Public: To make the benchmark log less verbose.



38
39
40
41
42
# File 'lib/capybara/compose/test_helper.rb', line 38

def inspect
  %(#<#{ self.class.name } #{ current_element? ? %(tag="#{ base.tag_name }") : object_id }>)
rescue *page.driver.invalid_element_errors
  %(#<#{ self.class.name } #{ object_id }>)
end

#inspect_nodeObject

Public: Makes it easier to inspect the current element.



45
46
47
# File 'lib/capybara/compose/test_helper.rb', line 45

def inspect_node
  to_capybara_node.inspect
end

#to_capybara_nodeObject

Public: Casts the current context as a Capybara::Node::Element.

NOTE: Uses the :el convention, which means actions can be performed directly on the test helper if an :el selector is defined.



53
54
55
56
57
58
# File 'lib/capybara/compose/test_helper.rb', line 53

def to_capybara_node
  return current_context if current_element?
  return find_element(:el) if selectors.key?(:el)

  raise_missing_element_error
end

#within(*args, **kwargs, &block) ⇒ Object

Public: Scopes the Capybara queries in the block to be inside the specified selector.



82
83
84
85
86
# File 'lib/capybara/compose/test_helper.rb', line 82

def within(*args, **kwargs, &block)
  return be_within(*args, **kwargs) unless block_given? # RSpec matcher.

  within_element(*args, **kwargs, &block)
end

#within_documentObject

Public: Unscopes the inner block from any previous ‘within` calls.



89
90
91
92
93
94
# File 'lib/capybara/compose/test_helper.rb', line 89

def within_document
  page.instance_exec { scopes << nil }
  yield wrap_element(page.document)
ensure
  page.instance_exec { scopes.pop }
end

#within_element(*args, **kwargs, &block) ⇒ Object

Public: Scopes the Capybara queries in the block to be inside the specified selector.



74
75
76
77
78
# File 'lib/capybara/compose/test_helper.rb', line 74

def within_element(*args, **kwargs, &block)
  locator = args.empty? ? [self] : args
  kwargs[:test_helper] = self
  page.within(*locator, **kwargs, &block)
end

#wrap_element(element) ⇒ Object

Public: Wraps a Capybara::Node::Element or test helper with a test helper object of this class.



62
63
64
65
66
67
68
69
70
# File 'lib/capybara/compose/test_helper.rb', line 62

def wrap_element(element)
  if element.is_a?(Enumerable)
    element.map { |node| wrap_element(node) }
  else
    raise ArgumentError, "#{ element.inspect } must be a test helper or element." unless element.respond_to?(:to_capybara_node)

    self.class.new(element.to_capybara_node, test_context: test_context)
  end
end