Skip to content

Instantly share code, notes, and snippets.

@pcreux
Created January 23, 2012 10:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcreux/1662281 to your computer and use it in GitHub Desktop.
Save pcreux/1662281 to your computer and use it in GitHub Desktop.
Cucumber step to match tables
module TableMatchHelper
# @param table [Array[Array]]
# @param expected_table [Array[Array[String]]]
# The expected_table values are String. They are converted to
# Regexp when they start and end with a '/'
# Example:
#
# assert_table_match(
# [["Name", "Date"], ["Philippe", "Feb 08"]],
# [["Name", "Date"], ["Philippe", "/\w{3} \d{2}/"]]
# )
def assert_tables_match(table, expected_table)
expected_table.each_index do |row_index|
expected_table[row_index].each_index do |column_index|
expected_cell = expected_table[row_index][column_index]
cell = table.try(:[], row_index).try(:[], column_index)
begin
assert_cells_match(cell, expected_cell)
rescue
puts "Cell at line #{row_index} and column #{column_index}: #{cell.inspect} does not match #{expected_cell.inspect}"
puts "Expecting:"
table.each { |row| puts row.inspect }
puts "to match:"
expected_table.each { |row| puts row.inspect }
raise $!
end
end
end
end
def assert_cells_match(cell, expected_cell)
if expected_cell[0].chr == '/' && expected_cell[-1].chr == '/'
cell.should match(Regexp.new(expected_cell[1..-2]))
else
cell.should == expected_cell
end
end
end # module TableMatchHelper
# Usage:
# I should see the following "invoices" table:
# | Invoice # | Date | Total Amount |
# | /\d+/ | 27/01/12 | $30.00 |
# | /\d+/ | 12/02/12 | $25.00 |
Then /^I should see the following "([^"]*)" table:$/ do |table_id, expected_table|
expected_table = expected_table.raw
table = Nokogiri::HTML(page.body).css("table##{table_id}").map do |table|
table.css("tr").map do |tr|
tr.css('th, td').map do |td|
td.text
end
end
end[0]
assert_tables_match(table, expected_table)
end
# I should see the CSV:
# | Invoice # | Date | Total Amount |
# | /\d+/ | 27/01/12 | $30.00 |
# | /\d+/ | 12/02/12 | $25.00 |
Then /^I should see the CSV:$/ do |table|
csv = CSV.parse(page.body)
table.raw
assert_tables_match(csv, table.raw)
end
@jmgarnier
Copy link

Then /^I should see the following "([^"]*)" table$/ do |table_id, expected_table|
  expected_table.diff!(table_at(table_id).to_a)
end

def table_at(selector)
  Nokogiri::HTML(page.body).css(selector).map do |table|
    table.css('tr').map do |tr|
      tr.css('th, td').map { |td| td.text }
    end
  end[0].reject(&:empty?)
end

@pcreux
Copy link
Author

pcreux commented Jan 23, 2012

@21croissants That's cool! css > xpath. I gonna use yours!

@jesperronn
Copy link

@21croissants, Your solution is very simple. However, it does not normalize whitespace (which is REALLY helpful when my TDs contain newlines. I modified the line to remove line breaks and normalize whitespace.

Notice I am appending .gsub(/\s+/,' ').strip to the td.text

def table_at(selector)
   Nokogiri::HTML(page.body).css(selector).map do |table|
    table.css('tr').map do |tr|
      tr.css('th, td').map { |td| td.text.gsub(/\s+/,' ').strip }
    end
   end[0].reject(&:empty?)
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment