cucumber 0.3.11 → 0.3.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +101 -0
- data/Manifest.txt +14 -5
- data/config/hoe.rb +1 -2
- data/cucumber.yml +1 -0
- data/examples/i18n/ar/Rakefile +1 -1
- data/examples/i18n/ar/features/addition.feature +1 -0
- data/examples/i18n/bg/Rakefile +1 -1
- data/examples/i18n/bg/features/addition.feature +1 -0
- data/examples/i18n/bg/features/consecutive_calculations.feature +1 -0
- data/examples/i18n/bg/features/division.feature +1 -0
- data/examples/i18n/cat/Rakefile +1 -1
- data/examples/i18n/cat/features/suma.feature +1 -0
- data/examples/i18n/da/Rakefile +1 -1
- data/examples/i18n/da/features/summering.feature +1 -0
- data/examples/i18n/de/Rakefile +1 -1
- data/examples/i18n/de/features/addition.feature +1 -0
- data/examples/i18n/de/features/division.feature +1 -0
- data/examples/i18n/en-lol/features/stuffing.feature +1 -1
- data/examples/i18n/en/Rakefile +1 -1
- data/examples/i18n/en/features/addition.feature +1 -0
- data/examples/i18n/en/features/division.feature +1 -0
- data/examples/i18n/es/Rakefile +1 -1
- data/examples/i18n/es/features/adicion.feature +1 -0
- data/examples/i18n/et/Rakefile +1 -1
- data/examples/i18n/et/features/jagamine.feature +1 -0
- data/examples/i18n/et/features/liitmine.feature +1 -0
- data/examples/i18n/fi/Rakefile +1 -1
- data/examples/i18n/fi/features/jakolasku.feature +1 -0
- data/examples/i18n/fr/Rakefile +1 -1
- data/examples/i18n/fr/features/addition.feature +2 -1
- data/examples/i18n/he/Rakefile +1 -1
- data/examples/i18n/he/features/addition.feature +1 -0
- data/examples/i18n/he/features/division.feature +1 -0
- data/examples/i18n/hu/Rakefile +1 -1
- data/examples/i18n/hu/features/addition.feature +1 -0
- data/examples/i18n/hu/features/division.feature +1 -0
- data/examples/i18n/id/Rakefile +1 -1
- data/examples/i18n/id/features/addition.feature +1 -0
- data/examples/i18n/id/features/division.feature +1 -0
- data/examples/i18n/it/Rakefile +1 -1
- data/examples/i18n/it/features/somma.feature +1 -0
- data/examples/i18n/ja/Rakefile +1 -1
- data/examples/i18n/ja/features/addition.feature +1 -0
- data/examples/i18n/ja/features/division.feature +1 -0
- data/examples/i18n/ko/Rakefile +1 -1
- data/examples/i18n/ko/features/addition.feature +6 -5
- data/examples/i18n/ko/features/division.feature +1 -0
- data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/lt/Rakefile +1 -1
- data/examples/i18n/lt/features/addition.feature +1 -0
- data/examples/i18n/lt/features/division.feature +1 -0
- data/examples/i18n/lv/Rakefile +1 -1
- data/examples/i18n/lv/features/addition.feature +1 -0
- data/examples/i18n/lv/features/division.feature +1 -0
- data/examples/i18n/no/Rakefile +1 -1
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +1 -1
- data/examples/i18n/no/features/summering.feature +1 -0
- data/examples/i18n/pl/Rakefile +1 -1
- data/examples/i18n/pl/features/addition.feature +1 -0
- data/examples/i18n/pl/features/division.feature +1 -0
- data/examples/i18n/pt/Rakefile +1 -1
- data/examples/i18n/pt/features/adicao.feature +1 -0
- data/examples/i18n/ro/Rakefile +1 -1
- data/examples/i18n/ro/features/suma.feature +1 -0
- data/examples/i18n/ru/Rakefile +1 -1
- data/examples/i18n/ru/features/addition.feature +1 -0
- data/examples/i18n/ru/features/consecutive_calculations.feature +1 -0
- data/examples/i18n/ru/features/division.feature +1 -0
- data/examples/i18n/se/Rakefile +1 -1
- data/examples/i18n/se/features/summering.feature +1 -0
- data/examples/i18n/sk/Rakefile +1 -1
- data/examples/i18n/sk/features/addition.feature +1 -0
- data/examples/i18n/sk/features/division.feature +1 -0
- data/examples/i18n/zh-CN/features/addition.feature +1 -0
- data/examples/i18n/zh-TW/features/addition.feature +1 -0
- data/examples/i18n/zh-TW/features/division.feature +1 -0
- data/examples/self_test/features/support/env.rb +2 -1
- data/examples/sinatra/features/step_definitions/add_steps.rb +1 -1
- data/examples/sinatra/features/support/env.rb +13 -5
- data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
- data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
- data/examples/tickets/features/step_definitons/tickets_steps.rb +15 -0
- data/examples/tickets/features/table_diffing.feature +13 -0
- data/features/after_block_exceptions.feature +4 -1
- data/features/after_step_block_exceptions.feature +4 -1
- data/features/background.feature +6 -0
- data/features/bug_371.feature +32 -0
- data/features/cucumber_cli.feature +11 -1
- data/features/cucumber_cli_diff_disabled.feature +9 -2
- data/features/drb_server_integration.feature +28 -5
- data/features/expand.feature +2 -1
- data/features/html_formatter/a.html +129 -1614
- data/features/junit_formatter.feature +4 -4
- data/features/language_from_header.feature +30 -0
- data/features/rake_task.feature +28 -0
- data/features/step_definitions/cucumber_steps.rb +2 -2
- data/features/steps_formatter.feature +25 -0
- data/features/support/env.rb +13 -5
- data/features/table_diffing.feature +45 -0
- data/features/unicode_table.feature +35 -0
- data/features/work_in_progress.feature +3 -0
- data/gem_tasks/sass.rake +4 -0
- data/lib/cucumber.rb +0 -57
- data/lib/cucumber/ast/comment.rb +1 -1
- data/lib/cucumber/ast/feature.rb +2 -2
- data/lib/cucumber/ast/feature_element.rb +4 -0
- data/lib/cucumber/ast/outline_table.rb +2 -1
- data/lib/cucumber/ast/py_string.rb +0 -1
- data/lib/cucumber/ast/scenario.rb +5 -3
- data/lib/cucumber/ast/scenario_outline.rb +6 -1
- data/lib/cucumber/ast/step.rb +8 -1
- data/lib/cucumber/ast/step_invocation.rb +6 -1
- data/lib/cucumber/ast/table.rb +287 -49
- data/lib/cucumber/ast/visitor.rb +2 -1
- data/lib/cucumber/cli/configuration.rb +45 -28
- data/lib/cucumber/cli/drb_client.rb +8 -9
- data/lib/cucumber/cli/language_help_formatter.rb +9 -7
- data/lib/cucumber/cli/main.rb +8 -9
- data/lib/cucumber/feature_file.rb +53 -0
- data/lib/cucumber/filter.rb +50 -0
- data/lib/cucumber/formatter/console.rb +12 -0
- data/lib/cucumber/formatter/cucumber.css +106 -48
- data/lib/cucumber/formatter/cucumber.sass +121 -31
- data/lib/cucumber/formatter/html.rb +6 -5
- data/lib/cucumber/formatter/junit.rb +3 -6
- data/lib/cucumber/formatter/pretty.rb +22 -9
- data/lib/cucumber/formatter/profile.rb +1 -1
- data/lib/cucumber/formatter/progress.rb +1 -1
- data/lib/cucumber/formatter/steps.rb +49 -0
- data/lib/cucumber/languages.yml +3 -3
- data/lib/cucumber/parser.rb +1 -33
- data/lib/cucumber/parser/feature.rb +39 -16
- data/lib/cucumber/parser/feature.tt +1 -3
- data/lib/cucumber/parser/i18n.tt +30 -23
- data/lib/cucumber/parser/i18n/language.rb +83 -0
- data/lib/cucumber/parser/treetop_ext.rb +12 -83
- data/lib/cucumber/platform.rb +6 -0
- data/lib/cucumber/rake/task.rb +6 -0
- data/lib/cucumber/step_definition.rb +6 -0
- data/lib/cucumber/step_match.rb +1 -1
- data/lib/cucumber/step_mother.rb +3 -3
- data/lib/cucumber/version.rb +1 -1
- data/lib/cucumber/webrat/table_locator.rb +66 -0
- data/rails_generators/cucumber/templates/cucumber.rake +4 -0
- data/rails_generators/cucumber/templates/env.rb +1 -0
- data/rails_generators/cucumber/templates/spork_env.rb +1 -1
- data/rails_generators/cucumber/templates/webrat_steps.rb +17 -0
- data/rails_generators/feature/templates/feature.erb +1 -1
- data/rails_generators/feature/templates/steps.erb +2 -8
- data/spec/cucumber/ast/step_collection_spec.rb +5 -4
- data/spec/cucumber/ast/table_spec.rb +145 -0
- data/spec/cucumber/cli/configuration_spec.rb +55 -9
- data/spec/cucumber/cli/drb_client_spec.rb +5 -4
- data/spec/cucumber/cli/main_spec.rb +9 -12
- data/spec/cucumber/formatter/progress_spec.rb +2 -2
- data/spec/cucumber/parser/feature_parser_spec.rb +11 -9
- data/spec/cucumber/parser/table_parser_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- metadata +21 -20
- data/spec/cucumber/formatter/html/cucumber.css +0 -37
- data/spec/cucumber/formatter/html/cucumber.js +0 -13
- data/spec/cucumber/formatter/html/index.html +0 -45
- data/spec/cucumber/formatter/html/jquery-1.3.min.js +0 -19
- data/spec/cucumber/formatter/html/jquery.uitableedit.js +0 -100
|
@@ -88,7 +88,8 @@ module Cucumber
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def actual_keyword
|
|
91
|
-
|
|
91
|
+
repeat_keywords = [language.but_keywords, language.and_keywords].flatten
|
|
92
|
+
if repeat_keywords.index(@step.keyword) && previous
|
|
92
93
|
previous.actual_keyword
|
|
93
94
|
else
|
|
94
95
|
keyword
|
|
@@ -123,6 +124,10 @@ module Cucumber
|
|
|
123
124
|
@step.backtrace_line
|
|
124
125
|
end
|
|
125
126
|
|
|
127
|
+
def language
|
|
128
|
+
@step.language
|
|
129
|
+
end
|
|
130
|
+
|
|
126
131
|
def to_sexp
|
|
127
132
|
[:step_invocation, @step.line, @step.keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
|
|
128
133
|
end
|
data/lib/cucumber/ast/table.rb
CHANGED
|
@@ -7,7 +7,9 @@ module Cucumber
|
|
|
7
7
|
#
|
|
8
8
|
# This gets parsed into a Table holding the values <tt>[['a', 'b'], ['c', 'd']]</tt>
|
|
9
9
|
#
|
|
10
|
-
class Table
|
|
10
|
+
class Table
|
|
11
|
+
include Enumerable
|
|
12
|
+
|
|
11
13
|
NULL_CONVERSIONS = Hash.new(lambda{ |cell_value| cell_value }).freeze
|
|
12
14
|
|
|
13
15
|
attr_accessor :file
|
|
@@ -16,18 +18,19 @@ module Cucumber
|
|
|
16
18
|
"table"
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
def initialize(raw,
|
|
20
|
-
# Verify that it's square
|
|
21
|
-
raw.transpose
|
|
22
|
-
@raw = raw
|
|
21
|
+
def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup)
|
|
23
22
|
@cells_class = Cells
|
|
24
23
|
@cell_class = Cell
|
|
25
|
-
|
|
24
|
+
|
|
25
|
+
# Verify that it's square
|
|
26
|
+
transposed = raw.transpose
|
|
27
|
+
create_cell_matrix(raw)
|
|
28
|
+
@conversion_procs = conversion_procs
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
# Creates a copy of this table, inheriting the column mappings.
|
|
29
32
|
def dup
|
|
30
|
-
self.class.new(
|
|
33
|
+
self.class.new(raw.dup, @conversion_procs.dup)
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
# Returns a new, transposed table. Example:
|
|
@@ -42,7 +45,7 @@ module Cucumber
|
|
|
42
45
|
# | 4 | 2 |
|
|
43
46
|
#
|
|
44
47
|
def transpose
|
|
45
|
-
self.class.new(
|
|
48
|
+
self.class.new(raw.transpose, @conversion_procs.dup)
|
|
46
49
|
end
|
|
47
50
|
|
|
48
51
|
# Converts this table into an Array of Hash where the keys of each
|
|
@@ -62,7 +65,7 @@ module Cucumber
|
|
|
62
65
|
def hashes
|
|
63
66
|
@hashes ||= cells_rows[1..-1].map do |row|
|
|
64
67
|
row.to_hash
|
|
65
|
-
end
|
|
68
|
+
end.freeze
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
# Converts this table into a Hash where the first column is
|
|
@@ -78,8 +81,9 @@ module Cucumber
|
|
|
78
81
|
# The table must be exactly two columns wide
|
|
79
82
|
#
|
|
80
83
|
def rows_hash
|
|
84
|
+
return @rows_hash if @rows_hash
|
|
81
85
|
verify_table_width(2)
|
|
82
|
-
@rows_hash = self.transpose.hashes[0]
|
|
86
|
+
@rows_hash = self.transpose.hashes[0].freeze
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
# Gets the raw data of this table. For example, a Table built from
|
|
@@ -88,17 +92,21 @@ module Cucumber
|
|
|
88
92
|
# | a | b |
|
|
89
93
|
# | c | d |
|
|
90
94
|
#
|
|
91
|
-
#
|
|
95
|
+
# gets converted into the following:
|
|
92
96
|
#
|
|
93
97
|
# [['a', 'b], ['c', 'd']]
|
|
94
98
|
#
|
|
95
99
|
def raw
|
|
96
|
-
|
|
100
|
+
cell_matrix.map do |row|
|
|
101
|
+
row.map do |cell|
|
|
102
|
+
cell.value
|
|
103
|
+
end
|
|
104
|
+
end
|
|
97
105
|
end
|
|
98
106
|
|
|
99
107
|
# Same as #raw, but skips the first (header) row
|
|
100
108
|
def rows
|
|
101
|
-
|
|
109
|
+
raw[1..-1]
|
|
102
110
|
end
|
|
103
111
|
|
|
104
112
|
def each_cells_row(&proc)
|
|
@@ -117,7 +125,7 @@ module Cucumber
|
|
|
117
125
|
[:table, *cells_rows.map{|row| row.to_sexp}]
|
|
118
126
|
end
|
|
119
127
|
|
|
120
|
-
#
|
|
128
|
+
# Redefines the table headers. This makes it
|
|
121
129
|
# possible to use prettier header names in the features. Example:
|
|
122
130
|
#
|
|
123
131
|
# | Phone Number | Address |
|
|
@@ -130,6 +138,18 @@ module Cucumber
|
|
|
130
138
|
# hashes = mapped_table.hashes
|
|
131
139
|
# # => [{:phone => '123456', :address => 'xyz'}, {:phone => '345678', :address => 'abc'}]
|
|
132
140
|
#
|
|
141
|
+
def map_headers!(mappings)
|
|
142
|
+
header_cells = cell_matrix[0]
|
|
143
|
+
mappings.each_pair do |pre, post|
|
|
144
|
+
header_cell = header_cells.detect{|cell| cell.value == pre}
|
|
145
|
+
header_cell.value = post
|
|
146
|
+
if @conversion_procs.has_key?(pre)
|
|
147
|
+
@conversion_procs[post] = @conversion_procs.delete(pre)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Returns a new Table where the headers are redefined. See #map_headers!
|
|
133
153
|
def map_headers(mappings)
|
|
134
154
|
table = self.dup
|
|
135
155
|
table.map_headers!(mappings)
|
|
@@ -153,11 +173,110 @@ module Cucumber
|
|
|
153
173
|
@conversion_procs[column_name] = conversion_proc
|
|
154
174
|
end
|
|
155
175
|
|
|
176
|
+
# Compares +other_table+ to self. If +other_table+ contains columns
|
|
177
|
+
# and/or rows that are not in self, new columns/rows are added at the
|
|
178
|
+
# relevant positions, marking the cells in those rows/columns as
|
|
179
|
+
# <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
|
|
180
|
+
# rows that are present in self, these are marked as <tt>missing</tt>.
|
|
181
|
+
#
|
|
182
|
+
# <tt>surplus</tt> and <tt>missing</tt> cells are recognised by formatters
|
|
183
|
+
# and displayed so that it's easy to read the differences.
|
|
184
|
+
#
|
|
185
|
+
# Cells that are different, but <em>look</em> identical (for example the
|
|
186
|
+
# boolean true and the string "true") are converted to their Object#inspect
|
|
187
|
+
# representation and preceded with (i) - to make it easier to identify
|
|
188
|
+
# where the difference actually is.
|
|
189
|
+
#
|
|
190
|
+
# Since all tables that are passed to StepDefinitions always have String
|
|
191
|
+
# objects in their cells, you may want to use #map_column! before calling
|
|
192
|
+
# #diff!
|
|
193
|
+
#
|
|
194
|
+
# An exception is raised if there are missing rows or columns, or
|
|
195
|
+
# surplus rows. An error is <em>not</em> raised for surplus columns.
|
|
196
|
+
# Whether to raise or not raise can be changed by setting values in
|
|
197
|
+
# +options+ to true or false:
|
|
198
|
+
#
|
|
199
|
+
# * <tt>missing_row</tt>: Raise on missing rows (defaults to true)
|
|
200
|
+
# * <tt>surplus_row</tt>: Raise on surplus rows (defaults to true)
|
|
201
|
+
# * <tt>missing_col</tt>: Raise on missing columns (defaults to true)
|
|
202
|
+
# * <tt>surplus_col</tt>: Raise on surplus columns (defaults to false)
|
|
203
|
+
#
|
|
204
|
+
# The +other_table+ argument can be another Table, an Array of Array or
|
|
205
|
+
# an Array of Hash (similar to the structure returned by #hashes).
|
|
206
|
+
#
|
|
207
|
+
# Calling this method is particularly useful in <tt>Then</tt> steps that take
|
|
208
|
+
# a Table argument, if you want to compare that table to some actual values.
|
|
209
|
+
#
|
|
210
|
+
def diff!(other_table, options={})
|
|
211
|
+
options = {:missing_row => true, :surplus_row => true, :missing_col => true, :surplus_col => false}.merge(options)
|
|
212
|
+
|
|
213
|
+
other_table = ensure_table(other_table)
|
|
214
|
+
ensure_green!
|
|
215
|
+
|
|
216
|
+
original_width = cell_matrix[0].length
|
|
217
|
+
other_table_cell_matrix = pad!(other_table.cell_matrix)
|
|
218
|
+
padded_width = cell_matrix[0].length
|
|
219
|
+
|
|
220
|
+
missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
|
|
221
|
+
surplus_col = padded_width > original_width
|
|
222
|
+
|
|
223
|
+
require_diff_lcs
|
|
224
|
+
cell_matrix.extend(Diff::LCS)
|
|
225
|
+
convert_columns!
|
|
226
|
+
changes = cell_matrix.diff(other_table_cell_matrix).flatten
|
|
227
|
+
|
|
228
|
+
inserted = 0
|
|
229
|
+
missing = 0
|
|
230
|
+
|
|
231
|
+
row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
|
|
232
|
+
|
|
233
|
+
last_change = nil
|
|
234
|
+
missing_row_pos = nil
|
|
235
|
+
insert_row_pos = nil
|
|
236
|
+
|
|
237
|
+
changes.each do |change|
|
|
238
|
+
if(change.action == '-')
|
|
239
|
+
missing_row_pos = change.position + inserted
|
|
240
|
+
cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
|
|
241
|
+
row_indices.insert(missing_row_pos, nil)
|
|
242
|
+
missing += 1
|
|
243
|
+
else # '+'
|
|
244
|
+
insert_row_pos = change.position + missing
|
|
245
|
+
inserted_row = change.element
|
|
246
|
+
inserted_row.each{|cell| cell.status = :comment}
|
|
247
|
+
cell_matrix.insert(insert_row_pos, inserted_row)
|
|
248
|
+
row_indices[insert_row_pos] = nil
|
|
249
|
+
inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
|
|
250
|
+
inserted += 1
|
|
251
|
+
end
|
|
252
|
+
last_change = change
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
other_table_cell_matrix.each_with_index do |other_row, i|
|
|
256
|
+
row_index = row_indices.index(i)
|
|
257
|
+
row = cell_matrix[row_index] if row_index
|
|
258
|
+
if row
|
|
259
|
+
(original_width..padded_width).each do |col_index|
|
|
260
|
+
surplus_cell = other_row[col_index]
|
|
261
|
+
row[col_index].value = surplus_cell.value if row[col_index]
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
clear_cache!
|
|
267
|
+
should_raise =
|
|
268
|
+
missing_row_pos && options[:missing_row] ||
|
|
269
|
+
insert_row_pos && options[:surplus_row] ||
|
|
270
|
+
missing_col && options[:missing_col] ||
|
|
271
|
+
surplus_col && options[:surplus_col]
|
|
272
|
+
raise 'Tables were not identical' if should_raise
|
|
273
|
+
end
|
|
274
|
+
|
|
156
275
|
def to_hash(cells) #:nodoc:
|
|
157
276
|
hash = Hash.new do |hash, key|
|
|
158
277
|
hash[key.to_s] if key.is_a?(Symbol)
|
|
159
278
|
end
|
|
160
|
-
|
|
279
|
+
raw[0].each_with_index do |column_name, column_index|
|
|
161
280
|
value = @conversion_procs[column_name].call(cells.value(column_index))
|
|
162
281
|
hash[column_name] = value
|
|
163
282
|
end
|
|
@@ -169,11 +288,11 @@ module Cucumber
|
|
|
169
288
|
end
|
|
170
289
|
|
|
171
290
|
def verify_column(column_name)
|
|
172
|
-
raise %{The column named "#{column_name}" does not exist} unless
|
|
291
|
+
raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
|
|
173
292
|
end
|
|
174
293
|
|
|
175
294
|
def verify_table_width(width)
|
|
176
|
-
raise %{The table must have exactly #{width} columns} unless
|
|
295
|
+
raise %{The table must have exactly #{width} columns} unless raw[0].size == width
|
|
177
296
|
end
|
|
178
297
|
|
|
179
298
|
def arguments_replaced(arguments) #:nodoc:
|
|
@@ -202,47 +321,158 @@ module Cucumber
|
|
|
202
321
|
end
|
|
203
322
|
|
|
204
323
|
def headers
|
|
205
|
-
|
|
324
|
+
raw.first
|
|
206
325
|
end
|
|
207
326
|
|
|
208
327
|
def header_cell(col)
|
|
209
328
|
cells_rows[0][col]
|
|
210
329
|
end
|
|
211
330
|
|
|
331
|
+
def cell_matrix
|
|
332
|
+
@cell_matrix
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def col_width(col)
|
|
336
|
+
columns[col].__send__(:width)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def to_s(options = {})
|
|
340
|
+
options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
|
|
341
|
+
io = StringIO.new
|
|
342
|
+
|
|
343
|
+
c = Term::ANSIColor.coloring?
|
|
344
|
+
Term::ANSIColor.coloring = options[:color]
|
|
345
|
+
f = Formatter::Pretty.new(nil, io, options)
|
|
346
|
+
f.instance_variable_set('@indent', options[:indent])
|
|
347
|
+
f.visit_multiline_arg(self)
|
|
348
|
+
Term::ANSIColor.coloring = c
|
|
349
|
+
|
|
350
|
+
io.rewind
|
|
351
|
+
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
|
352
|
+
s
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
private
|
|
356
|
+
|
|
357
|
+
TO_S_PREFIXES = Hash.new(' ')
|
|
358
|
+
TO_S_PREFIXES[:comment] = ['(+) ']
|
|
359
|
+
TO_S_PREFIXES[:undefined] = ['(-) ']
|
|
360
|
+
|
|
212
361
|
protected
|
|
213
362
|
|
|
214
|
-
def
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
363
|
+
def inspect_rows(missing_row, inserted_row)
|
|
364
|
+
missing_row.each_with_index do |missing_cell, col|
|
|
365
|
+
inserted_cell = inserted_row[col]
|
|
366
|
+
if(missing_cell.value != inserted_cell.value && (missing_cell.value.to_s == inserted_cell.value.to_s))
|
|
367
|
+
missing_cell.inspect!
|
|
368
|
+
inserted_cell.inspect!
|
|
220
369
|
end
|
|
221
370
|
end
|
|
222
371
|
end
|
|
223
372
|
|
|
224
|
-
|
|
373
|
+
def create_cell_matrix(raw)
|
|
374
|
+
@cell_matrix = raw.map do |raw_row|
|
|
375
|
+
line = raw_row.line rescue -1
|
|
376
|
+
raw_row.map do |raw_cell|
|
|
377
|
+
new_cell(raw_cell, line)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
225
381
|
|
|
226
|
-
def
|
|
227
|
-
|
|
382
|
+
def convert_columns!
|
|
383
|
+
cell_matrix.transpose.each do |col|
|
|
384
|
+
conversion_proc = @conversion_procs[col[0].value]
|
|
385
|
+
col[1..-1].each do |cell|
|
|
386
|
+
cell.value = conversion_proc.call(cell.value)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def require_diff_lcs
|
|
392
|
+
begin
|
|
393
|
+
require 'diff/lcs'
|
|
394
|
+
rescue LoadError => e
|
|
395
|
+
e.message << "\n Please gem install diff-lcs\n"
|
|
396
|
+
raise e
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def clear_cache!
|
|
401
|
+
@hashes = @rows_hash = @rows = @columns = nil
|
|
228
402
|
end
|
|
229
403
|
|
|
230
404
|
def columns
|
|
231
405
|
@columns ||= cell_matrix.transpose.map do |cell_row|
|
|
232
406
|
@cells_class.new(self, cell_row)
|
|
233
|
-
end
|
|
407
|
+
end.freeze
|
|
234
408
|
end
|
|
235
409
|
|
|
236
|
-
def
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
410
|
+
def new_cell(raw_cell, line)
|
|
411
|
+
@cell_class.new(raw_cell, self, line)
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Pads our own cell_matrix and returns a cell matrix of same
|
|
415
|
+
# column width that can be used for diffing
|
|
416
|
+
def pad!(other_cell_matrix)
|
|
417
|
+
clear_cache!
|
|
418
|
+
cols = cell_matrix.transpose
|
|
419
|
+
unmapped_cols = other_cell_matrix.transpose
|
|
420
|
+
|
|
421
|
+
mapped_cols = []
|
|
422
|
+
|
|
423
|
+
cols.each_with_index do |col, col_index|
|
|
424
|
+
header = col[0]
|
|
425
|
+
candidate_cols, unmapped_cols = unmapped_cols.partition do |other_col|
|
|
426
|
+
other_col[0] == header
|
|
245
427
|
end
|
|
428
|
+
raise "More than one column has the header #{header}" if candidate_cols.size > 2
|
|
429
|
+
|
|
430
|
+
other_padded_col = if candidate_cols.size == 1
|
|
431
|
+
# Found a matching column
|
|
432
|
+
candidate_cols[0]
|
|
433
|
+
else
|
|
434
|
+
mark_as_missing(cols[col_index])
|
|
435
|
+
(0...other_cell_matrix.length).map do |row|
|
|
436
|
+
val = row == 0 ? header.value : nil
|
|
437
|
+
SurplusCell.new(val, self, -1)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
mapped_cols.insert(col_index, other_padded_col)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
unmapped_cols.each_with_index do |col, col_index|
|
|
444
|
+
empty_col = (0...cell_matrix.length).map do |row|
|
|
445
|
+
SurplusCell.new(nil, self, -1)
|
|
446
|
+
end
|
|
447
|
+
cols << empty_col
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
@cell_matrix = cols.transpose
|
|
451
|
+
(mapped_cols + unmapped_cols).transpose
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def ensure_table(table_or_array)
|
|
455
|
+
return table_or_array if Table === table_or_array
|
|
456
|
+
table_or_array = hashes_to_array(table_or_array) if Hash === table_or_array[0]
|
|
457
|
+
Table.new(table_or_array)
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def hashes_to_array(hashes)
|
|
461
|
+
header = hashes[0].keys
|
|
462
|
+
[header] + hashes.map{|hash| header.map{|key| hash[key]}}
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def ensure_green!
|
|
466
|
+
each_cell{|cell| cell.status = :passed}
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def each_cell(&proc)
|
|
470
|
+
cell_matrix.each{|row| row.each(&proc)}
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def mark_as_missing(col)
|
|
474
|
+
col.each do |cell|
|
|
475
|
+
cell.status = :undefined
|
|
246
476
|
end
|
|
247
477
|
end
|
|
248
478
|
|
|
@@ -268,7 +498,7 @@ module Cucumber
|
|
|
268
498
|
end
|
|
269
499
|
|
|
270
500
|
def to_hash #:nodoc:
|
|
271
|
-
@to_hash ||= @table.to_hash(self)
|
|
501
|
+
@to_hash ||= @table.to_hash(self).freeze
|
|
272
502
|
end
|
|
273
503
|
|
|
274
504
|
def value(n) #:nodoc:
|
|
@@ -303,30 +533,38 @@ module Cucumber
|
|
|
303
533
|
end
|
|
304
534
|
|
|
305
535
|
class Cell
|
|
306
|
-
attr_reader :
|
|
307
|
-
|
|
536
|
+
attr_reader :line, :table
|
|
537
|
+
attr_accessor :status, :value
|
|
308
538
|
|
|
309
|
-
def initialize(value, table,
|
|
310
|
-
@value, @table, @
|
|
539
|
+
def initialize(value, table, line)
|
|
540
|
+
@value, @table, @line = value, table, line
|
|
311
541
|
end
|
|
312
542
|
|
|
313
543
|
def accept(visitor)
|
|
314
|
-
visitor.visit_table_cell_value(
|
|
544
|
+
visitor.visit_table_cell_value(value, status)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def inspect!
|
|
548
|
+
@value = "(i) #{value.inspect}"
|
|
315
549
|
end
|
|
316
550
|
|
|
317
|
-
def
|
|
318
|
-
|
|
551
|
+
def ==(o)
|
|
552
|
+
SurplusCell === o || value == o.value
|
|
319
553
|
end
|
|
320
554
|
|
|
321
555
|
# For testing only
|
|
322
556
|
def to_sexp #:nodoc:
|
|
323
557
|
[:cell, @value]
|
|
324
558
|
end
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
class SurplusCell < Cell
|
|
562
|
+
def status
|
|
563
|
+
:comment
|
|
564
|
+
end
|
|
325
565
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
def col_width
|
|
329
|
-
@col_width ||= @table.__send__(:col_width, @col)
|
|
566
|
+
def ==(o)
|
|
567
|
+
true
|
|
330
568
|
end
|
|
331
569
|
end
|
|
332
570
|
end
|