Created
March 29, 2017 07:06
-
-
Save hoasung01/96ba3cc095562894b2f282e9ece84594 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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