cuke_modeler 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -1
  3. data/cuke_modeler.gemspec +23 -14
  4. data/lib/cuke_modeler.rb +1 -1
  5. data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +2 -1
  6. data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +2 -1
  7. data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +2 -1
  8. data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +2 -1
  9. data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +2 -1
  10. data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +2 -1
  11. data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -242
  12. data/lib/cuke_modeler/containing.rb +31 -89
  13. data/lib/cuke_modeler/described.rb +40 -1
  14. data/lib/cuke_modeler/models/background.rb +11 -11
  15. data/lib/cuke_modeler/models/cell.rb +13 -7
  16. data/lib/cuke_modeler/models/comment.rb +5 -5
  17. data/lib/cuke_modeler/models/directory.rb +13 -17
  18. data/lib/cuke_modeler/models/doc_string.rb +10 -7
  19. data/lib/cuke_modeler/models/example.rb +63 -45
  20. data/lib/cuke_modeler/models/feature.rb +23 -16
  21. data/lib/cuke_modeler/models/feature_file.rb +5 -7
  22. data/lib/cuke_modeler/models/model.rb +2 -1
  23. data/lib/cuke_modeler/models/outline.rb +19 -14
  24. data/lib/cuke_modeler/models/row.rb +10 -7
  25. data/lib/cuke_modeler/models/rule.rb +11 -9
  26. data/lib/cuke_modeler/models/scenario.rb +17 -12
  27. data/lib/cuke_modeler/models/step.rb +40 -18
  28. data/lib/cuke_modeler/models/table.rb +9 -6
  29. data/lib/cuke_modeler/models/tag.rb +9 -5
  30. data/lib/cuke_modeler/named.rb +5 -1
  31. data/lib/cuke_modeler/nested.rb +22 -18
  32. data/lib/cuke_modeler/parsed.rb +8 -0
  33. data/lib/cuke_modeler/parsing.rb +36 -26
  34. data/lib/cuke_modeler/sourceable.rb +8 -0
  35. data/lib/cuke_modeler/stepped.rb +8 -0
  36. data/lib/cuke_modeler/taggable.rb +9 -1
  37. data/lib/cuke_modeler/version.rb +1 -1
  38. metadata +53 -33
@@ -1,3 +1,6 @@
1
+ # It's the module that has functionality for every possible model type. So, yes, it's long.
2
+ # rubocop:disable Metrics/ModuleLength
3
+
1
4
  module CukeModeler
2
5
 
3
6
  # NOT A PART OF THE PUBLIC API
@@ -74,14 +77,11 @@ module CukeModeler
74
77
  end
75
78
 
76
79
  def populate_block(step_object, parsed_step_data)
77
- case
78
- when parsed_step_data['table']
79
- step_object.block = build_child_model(Table, parsed_step_data['table'])
80
- when parsed_step_data['doc_string']
81
- step_object.block = build_child_model(DocString, parsed_step_data['doc_string'])
82
- else
83
- step_object.block = nil
84
- end
80
+ step_object.block = if parsed_step_data['table']
81
+ build_child_model(Table, parsed_step_data['table'])
82
+ elsif parsed_step_data['doc_string']
83
+ build_child_model(DocString, parsed_step_data['doc_string'])
84
+ end
85
85
  end
86
86
 
87
87
  def populate_table(table_object, parsed_table_data)
@@ -154,7 +154,9 @@ module CukeModeler
154
154
  populate_parsing_data(feature_file_object, processed_feature_file_data)
155
155
  feature_file_object.path = processed_feature_file_data['path']
156
156
 
157
- feature_file_object.feature = build_child_model(Feature, processed_feature_file_data['feature']) unless processed_feature_file_data['feature'].nil?
157
+ if processed_feature_file_data['feature']
158
+ feature_file_object.feature = build_child_model(Feature, processed_feature_file_data['feature'])
159
+ end
158
160
 
159
161
  processed_feature_file_data['comments'].each do |comment_data|
160
162
  feature_file_object.comments << build_child_model(Comment, comment_data)
@@ -202,7 +204,7 @@ module CukeModeler
202
204
  end
203
205
 
204
206
  def populate_content_type(doc_string_model, parsed_doc_string_data)
205
- doc_string_model.content_type = parsed_doc_string_data['content_type'] == "" ? nil : parsed_doc_string_data['content_type']
207
+ doc_string_model.content_type = parsed_doc_string_data['content_type']
206
208
  end
207
209
 
208
210
  def populate_content(doc_string_model, parsed_doc_string_data)
@@ -221,89 +223,29 @@ module CukeModeler
221
223
  end
222
224
  end
223
225
 
224
- def populate_children(model, parsed_feature_data)
225
- elements = parsed_feature_data['elements']
226
-
227
- if elements
228
- elements.each do |element|
229
- case element['type']
230
- when 'Scenario', 'scenario'
231
- model.tests << build_child_model(Scenario, element)
232
- when 'ScenarioOutline', 'scenario_outline'
233
- model.tests << build_child_model(Outline, element)
234
- when 'Background', 'background'
235
- model.background = build_child_model(Background, element)
236
- when 'Rule'
237
- model.rules << build_child_model(Rule, element)
238
- else
239
- raise(ArgumentError, "Unknown element type: #{element['type']}")
240
- end
241
- end
242
- end
243
- end
244
-
245
- def populate_parsing_data(model, parsed_model_data)
246
- model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
247
- end
248
-
249
- def populate_source_line(model, parsed_model_data)
250
- model.source_line = parsed_model_data['line']
251
- end
252
-
253
- def populate_name(model, parsed_model_data)
254
- model.name = parsed_model_data['name']
255
- end
256
-
257
- def populate_description(model, parsed_model_data)
258
- model.description = trimmed_description(parsed_model_data['description'])
259
- end
260
-
261
- def trimmed_description(description)
262
- description = description.split("\n")
263
-
264
- trim_leading_blank_lines(description)
265
- trim_trailing_blank_lines(description)
266
- trim_leading_spaces(description)
267
- trim_trailing_spaces(description)
268
-
269
- description.join("\n")
270
- end
271
-
272
- def trim_leading_blank_lines(description)
273
- description.replace(description.drop_while { |line| line !~ /\S/ })
274
- end
226
+ # It's not getting better any time soon
227
+ # rubocop:disable Metrics/AbcSize
275
228
 
276
- def trim_trailing_blank_lines(description)
277
- # Nothing to do. Already done by the parser but leaving this here in case that changes in future versions.
278
- end
279
-
280
- def trim_leading_spaces(description)
281
- non_blank_lines = description.select { |line| line =~ /\S/ }
282
-
283
- fewest_spaces = non_blank_lines.collect { |line| line[/^\s*/].length }.min || 0
284
-
285
- description.each { |line| line.slice!(0..(fewest_spaces - 1)) } if fewest_spaces > 0
286
- end
287
-
288
- def trim_trailing_spaces(description)
289
- description.map! { |line| line.rstrip }
290
- end
291
-
292
- def populate_tags(model, parsed_model_data)
293
- if parsed_model_data['tags']
294
- parsed_model_data['tags'].each do |tag|
295
- model.tags << build_child_model(Tag, tag)
296
- end
297
- end
298
- end
299
-
300
- def populate_steps(model, parsed_model_data)
301
- if parsed_model_data['steps']
302
- parsed_model_data['steps'].each do |step_data|
303
- model.steps << build_child_model(Step, step_data)
229
+ def populate_children(model, parsed_feature_data)
230
+ return unless parsed_feature_data['elements']
231
+
232
+ parsed_feature_data['elements'].each do |element|
233
+ case element['type']
234
+ when 'Scenario', 'scenario'
235
+ model.tests << build_child_model(Scenario, element)
236
+ when 'ScenarioOutline', 'scenario_outline'
237
+ model.tests << build_child_model(Outline, element)
238
+ when 'Background', 'background'
239
+ model.background = build_child_model(Background, element)
240
+ when 'Rule'
241
+ model.rules << build_child_model(Rule, element)
242
+ else
243
+ raise(ArgumentError, "Unknown element type: #{element['type']}")
304
244
  end
305
245
  end
306
246
  end
247
+ # rubocop:enable Metrics/AbcSize
307
248
 
308
249
  end
309
250
  end
251
+ # rubocop:enable Metrics/ModuleLength
@@ -19,11 +19,50 @@ module CukeModeler
19
19
  description_lines = description.split("\n")
20
20
 
21
21
  text << "\n" if description_lines.first =~ /\S/
22
- text << description_lines.collect { |line| "#{line}" }.join("\n")
22
+ text << description_lines.join("\n")
23
23
  end
24
24
 
25
25
  text
26
26
  end
27
27
 
28
+ def no_description_to_output?
29
+ description.nil? || description.empty?
30
+ end
31
+
32
+ def populate_description(model, parsed_model_data)
33
+ model.description = trimmed_description(parsed_model_data['description'])
34
+ end
35
+
36
+ def trimmed_description(description)
37
+ description = description.split("\n")
38
+
39
+ trim_leading_blank_lines(description)
40
+ trim_trailing_blank_lines(description)
41
+ trim_leading_spaces(description)
42
+ trim_trailing_spaces(description)
43
+
44
+ description.join("\n")
45
+ end
46
+
47
+ def trim_leading_blank_lines(description)
48
+ description.replace(description.drop_while { |line| line !~ /\S/ })
49
+ end
50
+
51
+ def trim_trailing_blank_lines(_description)
52
+ # Nothing to do. Already done by the parser but leaving this here in case that changes in future versions.
53
+ end
54
+
55
+ def trim_leading_spaces(description)
56
+ non_blank_lines = description.select { |line| line =~ /\S/ }
57
+
58
+ fewest_spaces = non_blank_lines.collect { |line| line[/^\s*/].length }.min || 0
59
+
60
+ description.each { |line| line.slice!(0..(fewest_spaces - 1)) } if fewest_spaces.positive?
61
+ end
62
+
63
+ def trim_trailing_spaces(description)
64
+ description.map!(&:rstrip)
65
+ end
66
+
28
67
  end
29
68
  end
@@ -23,17 +23,17 @@ module CukeModeler
23
23
 
24
24
  super(source_text)
25
25
 
26
- if source_text
27
- parsed_background_data = parse_source(source_text)
28
- populate_background(self, parsed_background_data)
29
- end
26
+ return unless source_text
27
+
28
+ parsed_background_data = parse_source(source_text)
29
+ populate_background(self, parsed_background_data)
30
30
  end
31
31
 
32
32
  # Returns *true* if the two models have equivalent steps and *false* otherwise.
33
- def ==(other_model)
34
- return false unless other_model.respond_to?(:steps)
33
+ def ==(other)
34
+ return false unless other.respond_to?(:steps)
35
35
 
36
- steps == other_model.steps
36
+ steps == other.steps
37
37
  end
38
38
 
39
39
  # Returns the model objects that belong to this model.
@@ -47,9 +47,9 @@ module CukeModeler
47
47
  text = ''
48
48
 
49
49
  text << "#{@keyword}:#{name_output_string}"
50
- text << "\n" + description_output_string unless (description.nil? || description.empty?)
51
- text << "\n" unless (steps.empty? || description.nil? || description.empty?)
52
- text << "\n" + steps_output_string unless steps.empty?
50
+ text << "\n#{description_output_string}" unless no_description_to_output?
51
+ text << "\n" unless steps.empty? || no_description_to_output?
52
+ text << "\n#{steps_output_string}" unless steps.empty?
53
53
 
54
54
  text
55
55
  end
@@ -62,7 +62,7 @@ module CukeModeler
62
62
  base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n"
63
63
  source_text = base_file_string + source_text
64
64
 
65
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_background.feature')
65
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_background.feature')
66
66
 
67
67
  parsed_file['feature']['elements'].first
68
68
  end
@@ -18,10 +18,10 @@ module CukeModeler
18
18
  def initialize(source_text = nil)
19
19
  super(source_text)
20
20
 
21
- if source_text
22
- parsed_cell_data = parse_source(source_text)
23
- populate_cell(self, parsed_cell_data)
24
- end
21
+ return unless source_text
22
+
23
+ parsed_cell_data = parse_source(source_text)
24
+ populate_cell(self, parsed_cell_data)
25
25
  end
26
26
 
27
27
  # Returns a string representation of this model. For a cell model,
@@ -35,14 +35,20 @@ module CukeModeler
35
35
  private
36
36
 
37
37
 
38
+ # It's only considered complex because of how deeply nested cells are in the tree. It's not REALLY complex.
39
+ # rubocop:disable Metrics/AbcSize
38
40
  def parse_source(source_text)
39
- base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n#{dialect_scenario_keyword}:\n#{dialect_step_keyword} fake step\n"
40
- source_text = base_file_string + '|' + source_text + '|'
41
+ base_file_string = "# language: #{Parsing.dialect}
42
+ #{dialect_feature_keyword}: Fake feature to parse
43
+ #{dialect_scenario_keyword}:
44
+ #{dialect_step_keyword} fake step\n"
45
+ source_text = "#{base_file_string}|#{source_text}|"
41
46
 
42
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_cell.feature')
47
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_cell.feature')
43
48
 
44
49
  parsed_file['feature']['elements'].first['steps'].first['table']['rows'].first['cells'].first
45
50
  end
51
+ # rubocop:enable Metrics/AbcSize
46
52
 
47
53
  end
48
54
 
@@ -18,10 +18,10 @@ module CukeModeler
18
18
  def initialize(source_text = nil)
19
19
  super(source_text)
20
20
 
21
- if source_text
22
- parsed_comment_data = parse_source(source_text)
23
- populate_comment(self, parsed_comment_data)
24
- end
21
+ return unless source_text
22
+
23
+ parsed_comment_data = parse_source(source_text)
24
+ populate_comment(self, parsed_comment_data)
25
25
  end
26
26
 
27
27
  # Returns a string representation of this model. For a comment model,
@@ -38,7 +38,7 @@ module CukeModeler
38
38
  base_file_string = "\n#{dialect_feature_keyword}: Fake feature to parse"
39
39
  source_text = "# language: #{Parsing.dialect}\n" + source_text + base_file_string
40
40
 
41
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_comment.feature')
41
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_comment.feature')
42
42
 
43
43
  parsed_file['comments'].last
44
44
  end
@@ -24,12 +24,11 @@ module CukeModeler
24
24
 
25
25
  super(directory_path)
26
26
 
27
- if directory_path
28
- raise(ArgumentError, "Unknown directory: #{directory_path.inspect}") unless File.exists?(directory_path)
27
+ return unless directory_path
28
+ raise(ArgumentError, "Unknown directory: #{directory_path.inspect}") unless File.exist?(directory_path)
29
29
 
30
- processed_directory_data = process_directory(directory_path)
31
- populate_directory(self, processed_directory_data)
32
- end
30
+ processed_directory_data = process_directory(directory_path)
31
+ populate_directory(self, processed_directory_data)
33
32
  end
34
33
 
35
34
  # Returns the name of the modeled directory.
@@ -53,10 +52,9 @@ module CukeModeler
53
52
 
54
53
 
55
54
  def process_directory(directory_path)
56
- directory_data = {'path' => directory_path,
57
- 'directories' => [],
58
- 'feature_files' => []
59
- }
55
+ directory_data = { 'path' => directory_path,
56
+ 'directories' => [],
57
+ 'feature_files' => [] }
60
58
 
61
59
  entries = Dir.entries(directory_path)
62
60
  entries.delete '.'
@@ -65,13 +63,11 @@ module CukeModeler
65
63
  entries.each do |entry|
66
64
  entry = "#{directory_path}/#{entry}"
67
65
 
68
- case
69
- when File.directory?(entry)
70
- directory_data['directories'] << process_directory(entry)
71
- when entry =~ /\.feature$/
72
- directory_data['feature_files'] << process_feature_file(entry)
73
- else
74
- # Ignore anything that isn't a directory or a feature file
66
+ # Ignore anything that isn't a directory or a feature file
67
+ if File.directory?(entry)
68
+ directory_data['directories'] << process_directory(entry)
69
+ elsif entry =~ /\.feature$/
70
+ directory_data['feature_files'] << process_feature_file(entry)
75
71
  end
76
72
  end
77
73
 
@@ -82,7 +78,7 @@ module CukeModeler
82
78
  def process_feature_file(file_path)
83
79
  source_text = IO.read(file_path)
84
80
 
85
- feature_file_data = Parsing::parse_text(source_text, file_path)
81
+ feature_file_data = Parsing.parse_text(source_text, file_path)
86
82
  feature_file_data = feature_file_data.merge({ 'path' => file_path })
87
83
 
88
84
  feature_file_data
@@ -21,10 +21,10 @@ module CukeModeler
21
21
  def initialize(source_text = nil)
22
22
  super(source_text)
23
23
 
24
- if source_text
25
- parsed_doc_string_data = parse_source(source_text)
26
- populate_docstring(self, parsed_doc_string_data)
27
- end
24
+ return unless source_text
25
+
26
+ parsed_doc_string_data = parse_source(source_text)
27
+ populate_docstring(self, parsed_doc_string_data)
28
28
  end
29
29
 
30
30
  # Returns a string representation of this model. For a doc string model,
@@ -40,10 +40,13 @@ module CukeModeler
40
40
 
41
41
 
42
42
  def parse_source(source_text)
43
- base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}:\n#{dialect_scenario_keyword}:\n#{dialect_step_keyword} step\n"
43
+ base_file_string = "# language: #{Parsing.dialect}
44
+ #{dialect_feature_keyword}:
45
+ #{dialect_scenario_keyword}:
46
+ #{dialect_step_keyword} step\n"
44
47
  source_text = base_file_string + source_text
45
48
 
46
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_doc_string.feature')
49
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_doc_string.feature')
47
50
 
48
51
  parsed_file['feature']['elements'].first['steps'].first['doc_string']
49
52
  end
@@ -53,7 +56,7 @@ module CukeModeler
53
56
  end
54
57
 
55
58
  def content_output_string
56
- (content.nil? || content.empty?) ? '' : content.gsub('"""', '\"\"\"') + "\n"
59
+ content.nil? || content.empty? ? '' : content.gsub('"""', '\"\"\"') + "\n"
57
60
  end
58
61
 
59
62
  end
@@ -1,3 +1,6 @@
1
+ # I'll take extra class length due to extra helper methods over having fewer but more complex methods
2
+ # rubocop:disable Metrics/ClassLength
3
+
1
4
  module CukeModeler
2
5
 
3
6
  # A class modeling an example table of an outline.
@@ -27,10 +30,10 @@ module CukeModeler
27
30
 
28
31
  super(source_text)
29
32
 
30
- if source_text
31
- parsed_example_data = parse_source(source_text)
32
- populate_example(self, parsed_example_data)
33
- end
33
+ return unless source_text
34
+
35
+ parsed_example_data = parse_source(source_text)
36
+ populate_example(self, parsed_example_data)
34
37
  end
35
38
 
36
39
  # Adds a row to the example table. The row can be given as a Hash of
@@ -40,42 +43,39 @@ module CukeModeler
40
43
  raise('Cannot add a row. No parameters have been set.') if rows.empty?
41
44
 
42
45
  # A quick 'deep clone' so that the input isn't modified
43
- row = Marshal::load(Marshal.dump(row))
44
-
45
- case
46
- when row.is_a?(Array)
47
- # 'stringify' input
48
- row.collect! { |value| value.to_s }
49
-
50
- @rows << Row.new("|#{row.join('|')}|")
51
- when row.is_a?(Hash)
52
- # 'stringify' input
53
- row = row.inject({}) { |hash, (key, value)| hash[key.to_s] = value.to_s; hash }
54
-
55
- @rows << Row.new("|#{ordered_row_values(row).join('|')}|")
56
- else
57
- raise(ArgumentError, "Can only add row from a Hash or an Array but received #{row.class}")
58
- end
46
+ row = Marshal.load(Marshal.dump(row))
47
+
48
+ values = if row.is_a?(Array)
49
+ row
50
+ elsif row.is_a?(Hash)
51
+ # There is no guarantee that the user built up their hash with the keys in the same order as
52
+ # the parameter row and so the values have to be ordered by us. Additionally, the hash needs
53
+ # to have string keys in order for #order_row_values to work
54
+ ordered_row_values(stringify_keys(row))
55
+ else
56
+ raise(ArgumentError, "Can only add row from a Hash or an Array but received #{row.class}")
57
+ end
58
+
59
+ @rows << Row.new("|#{values.join('|')}|")
59
60
  end
60
61
 
61
62
  # Removes a row from the example table. The row can be given as a Hash of
62
63
  # parameters and their corresponding values or as an Array of values
63
64
  # which will be assigned in order.
64
65
  def remove_row(row_removed)
65
- return unless argument_rows
66
-
67
- case
68
- when row_removed.is_a?(Array)
69
- location = argument_rows.index { |row| row.cells.collect { |cell| cell.value } == row_removed.collect { |value| value.strip } }
70
- when row_removed.is_a?(Hash)
71
- # Note: the hash value order has to be manually calculated because Ruby 1.8.7 does not have ordered
72
- # hash keys. Alternatively, the hash may have simply been built up 'willy nilly' by the user instead
73
- # of being built up in order according to the parameter order.
74
- location = argument_rows.index { |row| row.cells.collect { |cell| cell.value } == ordered_row_values(row_removed.each_value { |value| value.strip! }) }
75
- else
76
- raise(ArgumentError, "Can only remove row from a Hash or an Array but received #{row_removed.class}")
77
- end
78
-
66
+ return if argument_rows.empty?
67
+
68
+ values = if row_removed.is_a?(Array)
69
+ row_removed
70
+ elsif row_removed.is_a?(Hash)
71
+ # There is no guarantee that the user built up their hash with the keys in the same order as
72
+ # the parameter row and so the values have to be ordered by us.
73
+ ordered_row_values(row_removed)
74
+ else
75
+ raise(ArgumentError, "Can only remove row from a Hash or an Array but received #{row_removed.class}")
76
+ end
77
+
78
+ location = index_for_values(values.map(&:to_s).map(&:strip))
79
79
  @rows.delete_at(location + 1) if location
80
80
  end
81
81
 
@@ -91,7 +91,7 @@ module CukeModeler
91
91
 
92
92
  # Returns the parameters of the example table
93
93
  def parameters
94
- parameter_row ? parameter_row.cells.collect { |cell| cell.value } : []
94
+ parameter_row ? parameter_row.cells.map(&:value) : []
95
95
  end
96
96
 
97
97
  # Returns the model objects that belong to this model.
@@ -99,30 +99,38 @@ module CukeModeler
99
99
  rows + tags
100
100
  end
101
101
 
102
+ # Building strings just isn't pretty
103
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
104
+
102
105
  # Returns a string representation of this model. For an example model,
103
106
  # this will be Gherkin text that is equivalent to the example being modeled.
104
107
  def to_s
105
108
  text = ''
106
109
 
107
- text << tag_output_string + "\n" unless tags.empty?
110
+ text << "#{tag_output_string}\n" unless tags.empty?
108
111
  text << "#{@keyword}:#{name_output_string}"
109
- text << "\n" + description_output_string unless (description.nil? || description.empty?)
110
- text << "\n" unless (rows.empty? || description.nil? || description.empty?)
111
- text << "\n" + parameters_output_string if parameter_row
112
- text << "\n" + rows_output_string unless argument_rows.empty?
112
+ text << "\n#{description_output_string}" unless no_description_to_output?
113
+ text << "\n" unless rows.empty? || no_description_to_output?
114
+ text << "\n#{parameters_output_string}" if parameter_row
115
+ text << "\n#{rows_output_string}" unless argument_rows.empty?
113
116
 
114
117
  text
115
118
  end
116
119
 
120
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
121
+
117
122
 
118
123
  private
119
124
 
120
125
 
121
126
  def parse_source(source_text)
122
- base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n#{dialect_outline_keyword}:\n#{dialect_step_keyword} fake step\n"
127
+ base_file_string = "# language: #{Parsing.dialect}
128
+ #{dialect_feature_keyword}: Fake feature to parse
129
+ #{dialect_outline_keyword}:
130
+ #{dialect_step_keyword} fake step\n"
123
131
  source_text = base_file_string + source_text
124
132
 
125
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_example.feature')
133
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_example.feature')
126
134
 
127
135
  parsed_file['feature']['elements'].first['examples'].first
128
136
  end
@@ -135,7 +143,7 @@ module CukeModeler
135
143
  text = ''
136
144
 
137
145
  unless parameter_row.nil?
138
- text << " |"
146
+ text << ' |'
139
147
  parameter_row.cells.count.times { |index| text << " #{string_for(parameter_row.cells, index)} |" }
140
148
  end
141
149
 
@@ -148,7 +156,7 @@ module CukeModeler
148
156
  unless argument_rows.empty?
149
157
 
150
158
  argument_rows.each do |row|
151
- text << " |"
159
+ text << ' |'
152
160
  row.cells.count.times { |index| text << " #{string_for(row.cells, index)} |" }
153
161
  text << "\n"
154
162
  end
@@ -164,8 +172,18 @@ module CukeModeler
164
172
  end
165
173
 
166
174
  def ordered_row_values(row_hash)
167
- parameter_row.cells.collect { |cell| cell.value }.collect { |parameter| row_hash[parameter] }
175
+ parameter_row.cells.map(&:value).collect { |parameter| row_hash[parameter] }
176
+ end
177
+
178
+ def stringify_keys(hash)
179
+ hash.each_with_object({}) { |(key, value), new_hash| new_hash[key.to_s] = value }
180
+ end
181
+
182
+ def index_for_values(values)
183
+ argument_rows.index { |row| row.cells.map(&:value) == values }
168
184
  end
169
185
 
170
186
  end
171
187
  end
188
+
189
+ # rubocop:enable Metrics/ClassLength