Skip to content

Instantly share code, notes, and snippets.

@hoasung01
Created March 29, 2017 07:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hoasung01/96ba3cc095562894b2f282e9ece84594 to your computer and use it in GitHub Desktop.
Save hoasung01/96ba3cc095562894b2f282e9ece84594 to your computer and use it in GitHub Desktop.
module TableHelpers
module ArrayMethods
def find_row(expected_row)
find_index do |row|
expected_row.all? do |expected_column|
first_column = row.find_index do |column|
content = normalize_content(column.content)
expected_content = normalize_content(expected_column)
matching_parts = expected_content.split(/\s*\*\s*/, -1).collect { |part| Regexp.escape(part) }
matching_expression = /\A#{matching_parts.join(".*")}\z/
content =~ matching_expression
end
if first_column.nil?
false
else
row = row[(first_column + 1)..-1]
true
end
end
end
end
# Only cross-Ruby way to get a character for its UTF-16 (hex) representation
def character(code)
[code.to_i(16)].pack('U*')
end
def normalize_content(content)
shy = character("00ad") # soft hyphen
nbsp = character("00a0") # non-breaking space
zwsp = character("200b") # zero-width space
content = content.gsub(/[#{shy}#{zwsp}]/, '')
content = content.gsub(/[\r\n\t#{nbsp}]+/, ' ')
content = content.gsub(/ {2,}/, ' ')
content = content.strip
content
end
end
rspec = defined?(RSpec) ? RSpec : Spec
rspec::Matchers.define :contain_table do |*args|
match do |tables|
@last_unmatched_row = nil
@extra_rows = nil
@best_rows_matched = -1
options = args.extract_options!
expected_table = args.first
tables.any? do |table|
skipped_rows = []
rows_matched = 0
match = expected_table.all? do |expected_row|
if @best_rows_matched < rows_matched
@last_unmatched_row = expected_row
@best_rows_matched = rows_matched
end
table.extend ArrayMethods
first_row = table.find_row(expected_row)
if first_row.nil?
false
else
rows_matched += 1
if options[:unordered]
table.delete_at(first_row)
else
skipped_rows += table[0...first_row]
table = table[(first_row + 1)..-1]
end
true
end
end
remaining_rows = skipped_rows + table
if match and options[:exactly] and not remaining_rows.empty?
@extra_rows = remaining_rows
match = false
end
match
end
end
failure_message do
if @extra_rows
"Found the following extra row: #{@extra_rows.first.collect(&:content).collect(&:squish).inspect}"
elsif @last_unmatched_row
"Could not find the following row: #{@last_unmatched_row.inspect}"
else
"Could not find a table"
end
end
failure_message_when_negated do
"Found the complete table: #{args.first.inspect}."
end
end
def parse_table(table)
if table.is_a?(String)
# multiline string. split it assuming a format like cucumber tables have.
table.split(/\n/).collect do |line|
line.gsub!(/\t|\s/, '')
line.sub!(/^\|/, '')
line.sub!(/\|$/, '')
line.split(/\s*\|\s*/)
end
else
table.raw
end
end
end
RSpec.configure do |config|
config.include TableHelpers
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment