module Testable::Pages::Element

Private Instance Methods

accessor_aspects(element, *signature) click to toggle source

This method provides the means to get the aspects of an accessor signature. The “aspects” refer to the locator information and any qualifier information that was provided along with the locator. This is important because the qualifier is not used to locate an element but rather to put conditions on how the state of the element is checked as it is being looked for.

Note that “qualifiers” here refers to Watir boolean methods.

# File lib/testable/element.rb, line 129
def accessor_aspects(element, *signature)
  identifier = signature.shift
  locator_args = {}
  qualifier_args = {}
  gather_aspects(identifier, element, locator_args, qualifier_args)
  [locator_args, qualifier_args]
end
context_from_signature(*signature, &block) click to toggle source

Returns the block or proc that serves as a context for an element definition. Consider the following element definitions:

ul   :facts, id: 'fact-list'
span :fact, -> { facts.span(class: 'site-item')}

Here the second element definition provides a proc that contains a context for another element definition. That leads to the following construction being sent to the browser:

@browser.ul(id: 'fact-list').span(class: 'site-item')
# File lib/testable/element.rb, line 112
def context_from_signature(*signature, &block)
  if block_given?
    block
  else
    context = signature.shift
    context.is_a?(Proc) && signature.empty? ? context : nil
  end
end
define_element_accessor(identifier, *signature, element, &block) click to toggle source

Defines an accessor method for an element that allows the “friendly name” (identifier) of the element to be proxied to a Watir element object that corresponds to the element type. When this identifier is referenced, it generates an accessor method for that element in the browser. Consider this element definition defined on a class with an instance of `page`:

text_field :username, id: 'username'

This allows:

page.username.set 'tester'

So any element identifier can be called as if it were a method on the interface (class) on which it is defined. Because the method is proxied to Watir, you can use the full Watir API by calling methods (like `set`, `click`, etc) on the element identifier.

It is also possible to have an element definition like this:

text_field :password

This would allow access like this:

page.username(id: 'username').set 'tester'

This approach would lead to the *values variable having an array like this: [{:id => 'username'}].

A third approach would be to utilize one element definition within the context of another. Consider the following element definitions:

article :practice, id: 'practice'

a :page_link do |text|
  practice.a(text: text)
end

This would allow access like this:

page.page_link('Drag and Drop').click

This approach would lead to the *values variable having an array like this: [“Drag and Drop”].

# File lib/testable/element.rb, line 224
def define_element_accessor(identifier, *signature, element, &block)
  locators, qualifiers = accessor_aspects(element, signature)

  include(Module.new do
    define_method(identifier.to_s) do |*values|
      if block_given?
        instance_exec(*values, &block)
      else
        locators = values[0] if locators.empty?
        access_element(element, locators, qualifiers)
      end
    end
  end)
end
gather_aspects(identifier, element, locator_args, qualifier_args) click to toggle source

This method is used to separate the two aspects of an accessor – the locators and the qualifiers. Part of this process involves querying the Watir driver library to determine what qualifiers it handles natively. Consider the following:

select_list :accounts, id: 'accounts', selected: 'Select Option'

Given that, this method will return with the following:

locator_args: {:id=>"accounts"}
qualifier_args: {:selected=>"Select Option"}

Consider this:

p :login_form, id: 'open', index: 0, visible: true

Given that, this method will return with the following:

locator_args: {:id=>"open", :index=>0, :visible=>true}
qualifier_args: {}

Notice that the `visible` qualifier is part of the locator arguments as opposed to being a qualifier argument, like `selected` was in the previous example. This is because Watir 6.x handles the `visible` qualifier natively. “Handling natively” means that when a qualifier is part of the locator, Watir knows how to intrpret the qualifier as a condition on the element, not as a way to locate the element.

# File lib/testable/element.rb, line 164
def gather_aspects(identifier, element, locator_args, qualifier_args)
  identifier.each_with_index do |hashes, index|
    next if hashes.nil? || hashes.is_a?(Proc)

    hashes.each do |k, v|
      methods = Watir.element_class_for(element).instance_methods
      if methods.include?(:"#{k}?") && !NATIVE_QUALIFIERS.include?(k)
        qualifier_args[k] = identifier[index][k]
      else
        locator_args[k] = v
      end
    end
  end
  [locator_args, qualifier_args]
end
parse_signature(signature) click to toggle source

A “signature” consists of a full element definition. For example:

text_field :username, id: 'username'

The signature of this element definition is:

[:username, {:id=>"username"}]

This is the identifier of the element (`username`) and the locator provided for it. This method separates out the identifier and the locator.

# File lib/testable/element.rb, line 97
def parse_signature(signature)
  [signature.shift, signature.shift]
end