class Chop::Diff

Attributes

header_transformations[RW]
transformations[RW]

Public Class Methods

diff!(selector, table, session: Capybara.current_session, &block) click to toggle source
# File lib/chop/diff.rb, line 8
def self.diff! selector, table, session: Capybara.current_session, &block
  new(selector, table, session, block).diff!
end
new(selector = nil, table = nil, session = Capybara.current_session, block = nil, &other_block) click to toggle source
Calls superclass method
# File lib/chop/diff.rb, line 26
def initialize selector = nil, table = nil, session = Capybara.current_session, block = nil, &other_block
  super
  self.selector ||= default_selector
  self.header_transformations = []
  self.transformations = []
  instance_eval &block if block.respond_to?(:call)
  instance_eval &other_block if block_given?
end

Public Instance Methods

allow_not_found() click to toggle source
# File lib/chop/diff.rb, line 109
def allow_not_found
  @allow_not_found = true
end
cell_to_image_filename(cell) click to toggle source
# File lib/chop/diff.rb, line 12
def cell_to_image_filename cell
  cell.all("img").map do |img|
    File.basename(img[:src] || "").split("?")[0].sub(/-[0-9a-f]{64}/, '')
  end.first
end
cells(&block) click to toggle source
# File lib/chop/diff.rb, line 101
def cells &block
  self.cells_finder = block
end
diff!(cucumber_table = table) click to toggle source
# File lib/chop/diff.rb, line 138
def diff! cucumber_table = table
  actual = to_a
  # FIXME should just delegate to Cucumber's #diff!. Cucumber needs to handle empty tables better.
  if !cucumber_table.raw.flatten.empty? && !actual.flatten.empty?
    cucumber_table.diff! actual
  elsif cucumber_table.raw.flatten != actual.flatten
    raise Cucumber::MultilineArgument::DataTable::Different.new(cucumber_table)
  end
end
field(key) { |row| ... } click to toggle source
# File lib/chop/diff.rb, line 81
def field key
  hash_transformation do |hashes|
    hashes.map! do |row|
      row.merge key => yield(row[key])
    end
  end
end
hash_transformation() { |hashes| ... } click to toggle source
# File lib/chop/diff.rb, line 65
def hash_transformation &block
  transformation do |rows|
    header = rows[0]
    keys = header.to_a.map.with_index do |cell, index|
      key = cell.text.parameterize.underscore
      next key if key.present?
      next cell.text if cell.text.present?
      index + 1
    end
    body = rows[1..-1]
    hashes = body.map { |row| HashWithIndifferentAccess[keys.zip(row)] }
    yield hashes
    [header] + hashes.map(&:values)
  end
end
header(index=nil) { |row| ... } click to toggle source
# File lib/chop/diff.rb, line 39
def header index=nil, &block
  if index
    header_transformation do |row|
      if index.is_a?(Symbol)
        index = row.index do |cell|
          text_finder.call(cell).parameterize.underscore.to_sym == index
        end
      end
      row[index] = yield(row[index])
      row
    end
  else
    if block.arity.zero?
      @new_header = yield
    else
      header_transformation do |row|
        yield(row)
      end
    end
  end
end
header_transformation(&block) click to toggle source
# File lib/chop/diff.rb, line 35
def header_transformation &block
  header_transformations << block
end
image(*keys) click to toggle source
# File lib/chop/diff.rb, line 89
def image *keys
  keys.each do |key|
    field(key) do |cell|
      cell_to_image_filename(cell)
    end
  end
end
rows(&block) click to toggle source
# File lib/chop/diff.rb, line 97
def rows &block
  self.rows_finder = block
end
text(&block) click to toggle source
# File lib/chop/diff.rb, line 105
def text &block
  self.text_finder = block
end
to_a() click to toggle source
# File lib/chop/diff.rb, line 113
def to_a
  rows = rows_finder.call(root).map { |row| cells_finder.call(row).to_a }
  rows = normalize(rows)

  header = @new_header ? normalize([@new_header]).first : rows.shift || []
  header = header_transformations.reduce(header) do |header, transformation|
    header = transformation.call(header)
    normalize([header]).first
  end

  if header
    rows = [header] + rows
    rows = normalize(rows)
  end

  rows = transformations.reduce(rows) do |rows, transformation|
    rows = transformation.call(rows)
    normalize(rows)
  end

  rows.map do |row|
    row.map { |cell| text_finder.call(cell) }
  end
end
transformation(&block) click to toggle source
# File lib/chop/diff.rb, line 61
def transformation &block
  transformations << block
end

Private Instance Methods

Node(value) click to toggle source
# File lib/chop/diff.rb, line 171
def Node value
  if value.respond_to?(:text)
    value
  else
    Capybara::Node::Simple.new(value.to_s)
  end
end
normalize(rows) click to toggle source
# File lib/chop/diff.rb, line 150
def normalize rows
  max = rows.map(&:count).max
  rows.map do |row|
    row.to_a << "" while row.length < max
    row.map { |cell| Node(cell) }
  end
end
root() click to toggle source
# File lib/chop/diff.rb, line 158
def root
  @root ||= begin
    if selector.is_a?(Capybara::Node::Element)
      selector
    else
      session.find(selector)
    end
  rescue Capybara::ElementNotFound
    raise unless @allow_not_found
    Node("")
  end
end