benSlaughter/capybara-table

View on GitHub
lib/capybara-table.rb

Summary

Maintainability
A
1 hr
Test Coverage
require 'hashie'
require 'capybara'
require 'capybara/dsl'

class Table
  include Capybara::DSL

  def initialize element = "table"
    @element     = element
    @headers     = Hashie::Mash.new
    @row_headers = Hashie::Mash.new

    parse_body
    parse_headers
    parse_row_headers
  end

  def parse_body
    @table_body = all("#{@element} > tbody > tr").map{ |h| h.all("td").map{| e| e.text.downcase } }
  end

  def parse_headers
    all("#{@element} > thead > tr").map{ |h| h.all "th" }.each do | header_row |
      column_index = 0
      header_row.each do | header |
        @headers[header.text.downcase] ||= []
        (header["colspan"] ? header["colspan"].to_i : 1).times do
          @headers[header.text.downcase].push column_index

          column_index += 1
        end
      end
    end
  end

  def parse_row_headers
    all("#{@element} > tbody > tr").each_with_index{ |r,i| @row_headers[r.find("td:first-child").text.downcase] = i }
  end

  def get_cells row_name, columns_array
    columns = columns_array.map{|c| @headers[c.downcase] ? @headers[c.downcase] : [] }.inject(:&)
    row = @row_headers[row_name.downcase]
    raise "Could not find row: %s in row headers: %s" % [row_name.downcase, @row_headers] if row.nil?

    temp = []
    columns.each do |column_index|
      temp.push @table_body[row][column_index]
    end

    raise "Unable to find any matching data with row: %s and columns: %s" % [row_name.to_s, columns_array.to_s] if temp.empty?
    temp.length == 1 ? temp.first : temp
  end

  def row number
    @table_body[number]
  end

  def column number
    @headers.inject([]) { |sum,h| h[1].include?(number) ? sum.push(h[0]) : sum} + @table_body.map {|r| r[number]}
  end

  def width
    row(0).length
  end

  def height
    column(0).length
  end

  def [] number
    @table_body.map {|r| r[number]}
  end
end