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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/cuke_modeler.gemspec +23 -14
- data/lib/cuke_modeler.rb +1 -1
- data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -242
- data/lib/cuke_modeler/containing.rb +31 -89
- data/lib/cuke_modeler/described.rb +40 -1
- data/lib/cuke_modeler/models/background.rb +11 -11
- data/lib/cuke_modeler/models/cell.rb +13 -7
- data/lib/cuke_modeler/models/comment.rb +5 -5
- data/lib/cuke_modeler/models/directory.rb +13 -17
- data/lib/cuke_modeler/models/doc_string.rb +10 -7
- data/lib/cuke_modeler/models/example.rb +63 -45
- data/lib/cuke_modeler/models/feature.rb +23 -16
- data/lib/cuke_modeler/models/feature_file.rb +5 -7
- data/lib/cuke_modeler/models/model.rb +2 -1
- data/lib/cuke_modeler/models/outline.rb +19 -14
- data/lib/cuke_modeler/models/row.rb +10 -7
- data/lib/cuke_modeler/models/rule.rb +11 -9
- data/lib/cuke_modeler/models/scenario.rb +17 -12
- data/lib/cuke_modeler/models/step.rb +40 -18
- data/lib/cuke_modeler/models/table.rb +9 -6
- data/lib/cuke_modeler/models/tag.rb +9 -5
- data/lib/cuke_modeler/named.rb +5 -1
- data/lib/cuke_modeler/nested.rb +22 -18
- data/lib/cuke_modeler/parsed.rb +8 -0
- data/lib/cuke_modeler/parsing.rb +36 -26
- data/lib/cuke_modeler/sourceable.rb +8 -0
- data/lib/cuke_modeler/stepped.rb +8 -0
- data/lib/cuke_modeler/taggable.rb +9 -1
- data/lib/cuke_modeler/version.rb +1 -1
- 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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
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']
|
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
|
-
|
225
|
-
|
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
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
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.
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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 ==(
|
34
|
-
return false unless
|
33
|
+
def ==(other)
|
34
|
+
return false unless other.respond_to?(:steps)
|
35
35
|
|
36
|
-
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"
|
51
|
-
text << "\n" unless
|
52
|
-
text << "\n"
|
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
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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}
|
40
|
-
|
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
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
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
|
-
|
28
|
-
|
27
|
+
return unless directory_path
|
28
|
+
raise(ArgumentError, "Unknown directory: #{directory_path.inspect}") unless File.exist?(directory_path)
|
29
29
|
|
30
|
-
|
31
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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}
|
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
|
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
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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.
|
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
|
110
|
+
text << "#{tag_output_string}\n" unless tags.empty?
|
108
111
|
text << "#{@keyword}:#{name_output_string}"
|
109
|
-
text << "\n"
|
110
|
-
text << "\n" unless
|
111
|
-
text << "\n"
|
112
|
-
text << "\n"
|
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}
|
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
|
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.
|
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
|