Skip to content

Commit

Permalink
Merge e9023a6 into 13c621d
Browse files Browse the repository at this point in the history
  • Loading branch information
roschaefer committed Apr 11, 2015
2 parents 13c621d + e9023a6 commit 61266c0
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 28 deletions.
48 changes: 20 additions & 28 deletions lib/cucumber/multiline_argument/data_table.rb
Expand Up @@ -336,7 +336,7 @@ def diff!(other_table, options={})
convert_columns!

original_width = cell_matrix[0].length
other_table_cell_matrix = pad!(other_table.cell_matrix)
@cell_matrix, other_table_cell_matrix = pad_and_match(@cell_matrix, other_table.cell_matrix)
padded_width = cell_matrix[0].length

missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
Expand Down Expand Up @@ -556,44 +556,36 @@ def clear_cache! #:nodoc:
@hashes = @rows_hash = @col_names = @rows = @columns = nil
end

# Pads our own cell_matrix and returns a cell matrix of same
# column width that can be used for diffing
def pad!(other_cell_matrix) #:nodoc:
# Pads two cell matrices to same column width and matches columns according to header value.
# The first cell matrix is the reference matrix with the second matrix matched against it.
def pad_and_match(a_cell_matrix, other_cell_matrix) #:nodoc:
clear_cache!
cols = cell_matrix.transpose
unmapped_cols = other_cell_matrix.transpose
cols = a_cell_matrix.transpose
unmatched_cols = other_cell_matrix.transpose

mapped_cols = []

cols.each_with_index do |col, col_index|
header = col[0]
candidate_cols, unmapped_cols = unmapped_cols.partition do |other_col|
other_col[0] == header
end
raise "More than one column has the header #{header}" if candidate_cols.size > 2
header_values = cols.map(&:first)
matched_cols = []

other_padded_col = if candidate_cols.size == 1
# Found a matching column
candidate_cols[0]
header_values.each_with_index do |v, i|
mapped_index = unmatched_cols.index{|unmapped_col| unmapped_col.first == v}
if (mapped_index)
matched_cols << unmatched_cols.delete_at(mapped_index)
else
mark_as_missing(cols[col_index])
(0...other_cell_matrix.length).map do |row|
val = row == 0 ? header.value : nil
SurplusCell.new(val, self, -1)
end
mark_as_missing(cols[i])
empty_col = other_cell_matrix.collect {SurplusCell.new(nil, self, -1)}
empty_col.first.value = v
matched_cols << empty_col
end
mapped_cols.insert(col_index, other_padded_col)
end

unmapped_cols.each_with_index do |col, col_index|
empty_col = (0...cell_matrix.length).map do |row|
SurplusCell.new(nil, self, -1)
end

empty_col = cell_matrix.collect {SurplusCell.new(nil, self, -1)}
unmatched_cols.each do
cols << empty_col
end

@cell_matrix = cols.transpose
(mapped_cols + unmapped_cols).transpose
return cols.transpose, (matched_cols + unmatched_cols).transpose
end

def ensure_table(table_or_array) #:nodoc:
Expand Down
74 changes: 74 additions & 0 deletions spec/cucumber/multiline_argument/data_table_spec.rb
Expand Up @@ -316,6 +316,80 @@ module MultilineArgument
}
end

context "in case of duplicate header values" do
it "raises no error for two identical tables" do
t = DataTable.from(%{
|a|a|c|
|d|e|f|
|g|h|i|
})
t.diff!(t.dup)
expect( t.to_s(:indent => 12, :color => false) ).to eq %{
| a | a | c |
| d | e | f |
| g | h | i |
}
end

it "detects a diff in one cell" do
t1 = DataTable.from(%{
|a|a|c|
|d|e|f|
|g|h|i|
})
t2 = DataTable.from(%{
|a|a|c|
|d|oops|f|
|g|h|i|
})
expect{ t1.diff!(t2) }.to raise_error
expect( t1.to_s(:indent => 12, :color => false) ).to eq %{
| a | a | c |
| (-) d | (-) e | (-) f |
| (+) d | (+) oops | (+) f |
| g | h | i |
}
end

it "detects missing columns" do
t1 = DataTable.from(%{
|a|a|b|c|
|d|d|e|f|
|g|g|h|i|
})
t2 = DataTable.from(%{
|a|b|c|
|d|e|f|
|g|h|i|
})
expect{ t1.diff!(t2) }.to raise_error
expect( t1.to_s(:indent => 12, :color => false) ).to eq %{
| a | (-) a | b | c |
| d | (-) d | e | f |
| g | (-) g | h | i |
}
end

it "detects surplus columns" do
t1 = DataTable.from(%{
|a|b|c|
|d|e|f|
|g|h|i|
})
t2 = DataTable.from(%{
|a|b|a|c|
|d|e|d|f|
|g|h|g|i|
})
expect{ t1.diff!(t2, :surplus_col => true) }.to raise_error
expect( t1.to_s(:indent => 12, :color => false) ).to eq %{
| a | b | c | (+) a |
| d | e | f | (+) d |
| g | h | i | (+) g |
}
end
end

it "should inspect missing and surplus cells" do
t1 = DataTable.from([
['name', 'male', 'lastname', 'swedish'],
Expand Down

0 comments on commit 61266c0

Please sign in to comment.