class Domino

To create a basic Domino class, inherit from Domino and define a selector and attributes:

module Dom
  class Post < Domino
    selector '#posts .post'
    attribute :title # selector defaults to .title
    attribute :body, '.post-body' # example of selector override

    # can define attributes on the selected node
    attribute :uuid, "&[data-uuid]"

    # can define states based on classes of the selected node
    attribute :active, "&.active"

    # accepts blocks as callbacks these are run only if attribute exists
    attribute :comments do |text|
      text.to_i
    end
  end
end

Now in your integration test you can use some of Domino's methods:

assert_equal 4, Dom::Post.count
refute_nil Dom::Post.find_by_title('First Post')

What makes it really powerful is defining scoped actions:

module Dom
  class Post < Domino
    def delete
      within(id) { click_button 'Delete' }
    end
  end
end

refute_nil Dom::Post.find_by_title('First Post')
Dom::Post.find_by_title('First Post').delete
assert_nil Dom::Post.find_by_title('First Post')

Attributes

node[R]

Direct access to the capybara node, in case you need anything special

Public Class Methods

all() click to toggle source

Get an array of all the Dominos

# File lib/domino.rb, line 67
def all
  map { |domino| domino }
end
attribute(attribute, selector = nil, &callback) click to toggle source

Define an attribute for this Domino

module Dom
  class Post
    attribute :title # defaults to selector '.title'
    attribute :body, '.post-body' # use a custom selector
  end
end

This will define an attr_reader on the Domino and also a find_by_attribute method:

Dom::Post.all.first.title
Dom::Post.find_by_title("First Post")
Dom::Post.find_by_title(/^First/)
# File lib/domino.rb, line 136
def attribute(attribute, selector = nil, &callback)
  selector ||= %(.#{attribute.to_s.tr('_', '-')})

  attribute_definitions[attribute] = Attribute.new(attribute, selector, &callback)

  define_method :"#{attribute}" do |&block|
    if block.is_a?(Proc)
      block.call(self.class.attribute_definitions[attribute].element(node))
    else
      self.class.attribute_definitions[attribute].value(node)
    end
  end

  define_singleton_method :"find_by_#{attribute}" do |value = nil, &predicate|
    find_by_attribute(attribute, value, &predicate)
  end
end
attribute_definitions() click to toggle source
# File lib/domino.rb, line 117
def attribute_definitions
  @attribute_definitions ||= {}
end
attributes() click to toggle source
# File lib/domino.rb, line 113
def attributes
  attribute_definitions.keys
end
each() { |new(node)| ... } click to toggle source

Iterate over all the Dominos

# File lib/domino.rb, line 60
def each
  nodes.each do |node|
    yield new(node)
  end
end
find!() click to toggle source

Returns Domino for capybara node matching selector.

Raises an error if no matching node is found. For drivers that support asynchronous behavior, this method waits for a matching node to appear.

# File lib/domino.rb, line 76
def find!
  require_selector!
  new(Capybara.current_session.find(@selector))
end
find_by(attributes) click to toggle source

Returns Domino for capybara node matching all attributes.

# File lib/domino.rb, line 82
def find_by(attributes)
  where(attributes).first
end
find_by!(attributes) click to toggle source

Returns Domino for capybara node matching all attributes.

Raises an error if no matching node is found.

# File lib/domino.rb, line 89
def find_by!(attributes)
  find_by(attributes) || raise(Capybara::ElementNotFound)
end
new(node) click to toggle source

Store the capybara node internally

# File lib/domino.rb, line 199
def initialize(node)
  @node = node
end
selector(s) click to toggle source

Define the selector for this Domino

module Dom
  class Post
    selector '#posts .post'
  end
end
# File lib/domino.rb, line 109
def selector(s)
  @selector = s
end
where(attributes) click to toggle source

Returns collection of Dominos for capybara node matching all attributes.

# File lib/domino.rb, line 94
def where(attributes)
  select do |domino|
    attributes.all? do |key, value|
      domino.send(key) == value if domino.respond_to?(key)
    end
  end
end

Private Class Methods

find_by_attribute(attribute, value = nil, &predicate) click to toggle source

Internal method for finding nodes by a selector

# File lib/domino.rb, line 163
def find_by_attribute(attribute, value = nil, &predicate)
  detect do |domino|
    attribute_definitions[attribute].match_value?(domino.node, value, &predicate)
  end
end
nodes() click to toggle source

Return capybara nodes for this object

# File lib/domino.rb, line 157
def nodes
  require_selector!
  Capybara.current_session.all(@selector)
end
require_selector!() click to toggle source
# File lib/domino.rb, line 169
def require_selector!
  raise Domino::Error, 'You must define a selector' if @selector.nil?
end

Public Instance Methods

attribute(selector, &callback) click to toggle source

Get the text of the first dom element matching a selector:

Dom::Post.all.first.attribute('.title')

Or get the value of the attribute of this dom element:

Dom::Post.all.first.attribute('&[href]')
# File lib/domino.rb, line 181
def attribute(selector, &callback)
  Attribute.new(nil, selector, &callback).value(node)
end
attributes() click to toggle source
# File lib/domino.rb, line 190
def attributes
  self.class.attributes.each_with_object({}) do |attribute, memo|
    memo[attribute] = send(attribute)
  end
end
id() click to toggle source

Dom id for this object.

# File lib/domino.rb, line 186
def id
  node['id'].nil? ? nil : %(##{node['id']})
end