cuke_modeler 2.1.0 → 3.4.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +53 -1
- data/README.md +14 -16
- data/cuke_modeler.gemspec +33 -21
- data/lib/cuke_modeler.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +356 -4
- data/lib/cuke_modeler/containing.rb +41 -89
- data/lib/cuke_modeler/described.rb +40 -1
- data/lib/cuke_modeler/models/background.rb +12 -12
- data/lib/cuke_modeler/models/cell.rb +14 -8
- data/lib/cuke_modeler/models/comment.rb +6 -6
- data/lib/cuke_modeler/models/directory.rb +14 -18
- data/lib/cuke_modeler/models/doc_string.rb +11 -8
- data/lib/cuke_modeler/models/example.rb +64 -46
- data/lib/cuke_modeler/models/feature.rb +38 -20
- data/lib/cuke_modeler/models/feature_file.rb +6 -8
- data/lib/cuke_modeler/models/model.rb +2 -1
- data/lib/cuke_modeler/models/outline.rb +20 -15
- data/lib/cuke_modeler/models/row.rb +11 -8
- data/lib/cuke_modeler/models/rule.rb +101 -0
- data/lib/cuke_modeler/models/scenario.rb +18 -13
- data/lib/cuke_modeler/models/step.rb +41 -19
- data/lib/cuke_modeler/models/table.rb +10 -7
- data/lib/cuke_modeler/models/tag.rb +10 -6
- 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 +55 -74
- 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
- data/testing/cucumber/features/modeling/feature_modeling.feature +28 -7
- data/testing/cucumber/features/modeling/feature_output.feature +45 -23
- data/testing/cucumber/features/modeling/rule_modeling.feature +108 -0
- data/testing/cucumber/features/modeling/rule_output.feature +111 -0
- metadata +68 -161
- data/.gitignore +0 -18
- data/.simplecov +0 -7
- data/.travis.yml +0 -81
- data/Gemfile +0 -44
- data/Rakefile +0 -73
- data/appveyor.yml +0 -88
- data/lib/cuke_modeler/adapters/gherkin_2_adapter.rb +0 -274
- data/lib/cuke_modeler/adapters/gherkin_3_adapter.rb +0 -297
- data/lib/cuke_modeler/adapters/gherkin_4_adapter.rb +0 -309
- data/lib/cuke_modeler/adapters/gherkin_5_adapter.rb +0 -12
- data/lib/cuke_modeler/adapters/gherkin_6_adapter.rb +0 -310
- data/lib/cuke_modeler/adapters/gherkin_7_adapter.rb +0 -307
- data/lib/cuke_modeler/adapters/gherkin_8_adapter.rb +0 -12
- data/testing/cucumber/step_definitions/action_steps.rb +0 -13
- data/testing/cucumber/step_definitions/background_steps.rb +0 -1
- data/testing/cucumber/step_definitions/directory_steps.rb +0 -6
- data/testing/cucumber/step_definitions/doc_string_steps.rb +0 -1
- data/testing/cucumber/step_definitions/feature_file_steps.rb +0 -16
- data/testing/cucumber/step_definitions/feature_steps.rb +0 -7
- data/testing/cucumber/step_definitions/modeling_steps.rb +0 -49
- data/testing/cucumber/step_definitions/setup_steps.rb +0 -32
- data/testing/cucumber/step_definitions/step_steps.rb +0 -3
- data/testing/cucumber/step_definitions/table_steps.rb +0 -1
- data/testing/cucumber/step_definitions/tag_steps.rb +0 -3
- data/testing/cucumber/step_definitions/verification_steps.rb +0 -181
- data/testing/cucumber/support/env.rb +0 -30
- data/testing/dialect_helper.rb +0 -48
- data/testing/file_helper.rb +0 -47
- data/testing/gemfiles/gherkin2.gemfile +0 -33
- data/testing/gemfiles/gherkin3.gemfile +0 -26
- data/testing/gemfiles/gherkin4.gemfile +0 -27
- data/testing/gemfiles/gherkin5.gemfile +0 -27
- data/testing/gemfiles/gherkin6.gemfile +0 -10
- data/testing/gemfiles/gherkin7.gemfile +0 -9
- data/testing/gemfiles/gherkin8.gemfile +0 -9
- data/testing/gemfiles/gherkin9.gemfile +0 -9
- data/testing/helper_methods.rb +0 -23
- data/testing/rspec/spec/integration/adapters/gherkin_2_adapter_spec.rb +0 -166
- data/testing/rspec/spec/integration/adapters/gherkin_3_adapter_spec.rb +0 -166
- data/testing/rspec/spec/integration/adapters/gherkin_4_adapter_spec.rb +0 -165
- data/testing/rspec/spec/integration/adapters/gherkin_5_adapter_spec.rb +0 -165
- data/testing/rspec/spec/integration/adapters/gherkin_6_adapter_spec.rb +0 -159
- data/testing/rspec/spec/integration/adapters/gherkin_7_adapter_spec.rb +0 -162
- data/testing/rspec/spec/integration/adapters/gherkin_8_adapter_spec.rb +0 -162
- data/testing/rspec/spec/integration/adapters/gherkin_9_adapter_spec.rb +0 -162
- data/testing/rspec/spec/integration/models/background_integration_spec.rb +0 -438
- data/testing/rspec/spec/integration/models/cell_integration_spec.rb +0 -338
- data/testing/rspec/spec/integration/models/comment_integration_spec.rb +0 -180
- data/testing/rspec/spec/integration/models/directory_integration_spec.rb +0 -218
- data/testing/rspec/spec/integration/models/doc_string_integration_spec.rb +0 -398
- data/testing/rspec/spec/integration/models/example_integration_spec.rb +0 -753
- data/testing/rspec/spec/integration/models/feature_file_integration_spec.rb +0 -276
- data/testing/rspec/spec/integration/models/feature_integration_spec.rb +0 -655
- data/testing/rspec/spec/integration/models/model_integration_spec.rb +0 -15
- data/testing/rspec/spec/integration/models/outline_integration_spec.rb +0 -619
- data/testing/rspec/spec/integration/models/row_integration_spec.rb +0 -303
- data/testing/rspec/spec/integration/models/scenario_integration_spec.rb +0 -475
- data/testing/rspec/spec/integration/models/step_integration_spec.rb +0 -573
- data/testing/rspec/spec/integration/models/table_integration_spec.rb +0 -333
- data/testing/rspec/spec/integration/models/tag_integration_spec.rb +0 -271
- data/testing/rspec/spec/integration/nested_integration_spec.rb +0 -91
- data/testing/rspec/spec/integration/parsing_integration_spec.rb +0 -143
- data/testing/rspec/spec/integration/shared/models_integration_specs.rb +0 -18
- data/testing/rspec/spec/spec_helper.rb +0 -129
- data/testing/rspec/spec/unit/cuke_modeler_unit_spec.rb +0 -25
- data/testing/rspec/spec/unit/described_unit_spec.rb +0 -23
- data/testing/rspec/spec/unit/models/background_unit_spec.rb +0 -83
- data/testing/rspec/spec/unit/models/cell_unit_spec.rb +0 -68
- data/testing/rspec/spec/unit/models/comment_unit_spec.rb +0 -68
- data/testing/rspec/spec/unit/models/directory_unit_spec.rb +0 -127
- data/testing/rspec/spec/unit/models/doc_string_unit_spec.rb +0 -100
- data/testing/rspec/spec/unit/models/example_unit_spec.rb +0 -133
- data/testing/rspec/spec/unit/models/feature_file_unit_spec.rb +0 -125
- data/testing/rspec/spec/unit/models/feature_unit_spec.rb +0 -157
- data/testing/rspec/spec/unit/models/model_unit_spec.rb +0 -15
- data/testing/rspec/spec/unit/models/outline_unit_spec.rb +0 -117
- data/testing/rspec/spec/unit/models/row_unit_spec.rb +0 -68
- data/testing/rspec/spec/unit/models/scenario_unit_spec.rb +0 -86
- data/testing/rspec/spec/unit/models/step_unit_spec.rb +0 -109
- data/testing/rspec/spec/unit/models/table_unit_spec.rb +0 -77
- data/testing/rspec/spec/unit/models/tag_unit_spec.rb +0 -68
- data/testing/rspec/spec/unit/named_unit_spec.rb +0 -23
- data/testing/rspec/spec/unit/nested_unit_spec.rb +0 -43
- data/testing/rspec/spec/unit/parsed_unit_spec.rb +0 -27
- data/testing/rspec/spec/unit/parsing_unit_spec.rb +0 -54
- data/testing/rspec/spec/unit/shared/bare_bones_models_unit_specs.rb +0 -14
- data/testing/rspec/spec/unit/shared/containing_models_unit_specs.rb +0 -127
- data/testing/rspec/spec/unit/shared/described_models_unit_specs.rb +0 -38
- data/testing/rspec/spec/unit/shared/keyworded_models_unit_specs.rb +0 -58
- data/testing/rspec/spec/unit/shared/models_unit_specs.rb +0 -15
- data/testing/rspec/spec/unit/shared/named_models_unit_specs.rb +0 -39
- data/testing/rspec/spec/unit/shared/nested_models_unit_specs.rb +0 -51
- data/testing/rspec/spec/unit/shared/parsed_models_unit_specs.rb +0 -39
- data/testing/rspec/spec/unit/shared/prepopulated_models_unit_specs.rb +0 -18
- data/testing/rspec/spec/unit/shared/sourced_models_unit_specs.rb +0 -39
- data/testing/rspec/spec/unit/shared/stepped_models_unit_specs.rb +0 -46
- data/testing/rspec/spec/unit/shared/stringifiable_models_unit_specs.rb +0 -18
- data/testing/rspec/spec/unit/shared/tagged_models_unit_specs.rb +0 -72
- data/testing/rspec/spec/unit/sourceable_unit_spec.rb +0 -27
- data/testing/rspec/spec/unit/stepped_unit_spec.rb +0 -23
- data/testing/rspec/spec/unit/taggable_unit_spec.rb +0 -69
- data/testing/test_languages.json +0 -45
- data/todo.txt +0 -25
@@ -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
|
@@ -32,7 +35,6 @@ module CukeModeler
|
|
32
35
|
|
33
36
|
model.parent_model = self
|
34
37
|
|
35
|
-
|
36
38
|
model
|
37
39
|
end
|
38
40
|
|
@@ -75,14 +77,11 @@ module CukeModeler
|
|
75
77
|
end
|
76
78
|
|
77
79
|
def populate_block(step_object, parsed_step_data)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
else
|
84
|
-
step_object.block = nil
|
85
|
-
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
|
86
85
|
end
|
87
86
|
|
88
87
|
def populate_table(table_object, parsed_table_data)
|
@@ -130,6 +129,15 @@ module CukeModeler
|
|
130
129
|
populate_children(feature_object, parsed_feature_data)
|
131
130
|
end
|
132
131
|
|
132
|
+
def populate_rule(rule_object, parsed_rule_data)
|
133
|
+
populate_parsing_data(rule_object, parsed_rule_data)
|
134
|
+
populate_source_line(rule_object, parsed_rule_data)
|
135
|
+
populate_keyword(rule_object, parsed_rule_data)
|
136
|
+
populate_name(rule_object, parsed_rule_data)
|
137
|
+
populate_description(rule_object, parsed_rule_data)
|
138
|
+
populate_children(rule_object, parsed_rule_data)
|
139
|
+
end
|
140
|
+
|
133
141
|
def populate_directory(directory_object, processed_directory_data)
|
134
142
|
directory_object.path = processed_directory_data['path']
|
135
143
|
|
@@ -146,7 +154,9 @@ module CukeModeler
|
|
146
154
|
populate_parsing_data(feature_file_object, processed_feature_file_data)
|
147
155
|
feature_file_object.path = processed_feature_file_data['path']
|
148
156
|
|
149
|
-
|
157
|
+
if processed_feature_file_data['feature']
|
158
|
+
feature_file_object.feature = build_child_model(Feature, processed_feature_file_data['feature'])
|
159
|
+
end
|
150
160
|
|
151
161
|
processed_feature_file_data['comments'].each do |comment_data|
|
152
162
|
feature_file_object.comments << build_child_model(Comment, comment_data)
|
@@ -194,7 +204,7 @@ module CukeModeler
|
|
194
204
|
end
|
195
205
|
|
196
206
|
def populate_content_type(doc_string_model, parsed_doc_string_data)
|
197
|
-
doc_string_model.content_type = parsed_doc_string_data['content_type']
|
207
|
+
doc_string_model.content_type = parsed_doc_string_data['content_type']
|
198
208
|
end
|
199
209
|
|
200
210
|
def populate_content(doc_string_model, parsed_doc_string_data)
|
@@ -213,87 +223,29 @@ module CukeModeler
|
|
213
223
|
end
|
214
224
|
end
|
215
225
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
def populate_parsing_data(model, parsed_model_data)
|
236
|
-
model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
|
237
|
-
end
|
238
|
-
|
239
|
-
def populate_source_line(model, parsed_model_data)
|
240
|
-
model.source_line = parsed_model_data['line']
|
241
|
-
end
|
242
|
-
|
243
|
-
def populate_name(model, parsed_model_data)
|
244
|
-
model.name = parsed_model_data['name']
|
245
|
-
end
|
246
|
-
|
247
|
-
def populate_description(model, parsed_model_data)
|
248
|
-
model.description = trimmed_description(parsed_model_data['description'])
|
249
|
-
end
|
250
|
-
|
251
|
-
def trimmed_description(description)
|
252
|
-
description = description.split("\n")
|
253
|
-
|
254
|
-
trim_leading_blank_lines(description)
|
255
|
-
trim_trailing_blank_lines(description)
|
256
|
-
trim_leading_spaces(description)
|
257
|
-
trim_trailing_spaces(description)
|
258
|
-
|
259
|
-
description.join("\n")
|
260
|
-
end
|
261
|
-
|
262
|
-
def trim_leading_blank_lines(description)
|
263
|
-
description.replace(description.drop_while { |line| line !~ /\S/ })
|
264
|
-
end
|
265
|
-
|
266
|
-
def trim_trailing_blank_lines(description)
|
267
|
-
# Nothing to do. Already done by the parser but leaving this here in case that changes in future versions.
|
268
|
-
end
|
269
|
-
|
270
|
-
def trim_leading_spaces(description)
|
271
|
-
non_blank_lines = description.select { |line| line =~ /\S/ }
|
272
|
-
|
273
|
-
fewest_spaces = non_blank_lines.collect { |line| line[/^\s*/].length }.min || 0
|
274
|
-
|
275
|
-
description.each { |line| line.slice!(0..(fewest_spaces - 1)) } if fewest_spaces > 0
|
276
|
-
end
|
277
|
-
|
278
|
-
def trim_trailing_spaces(description)
|
279
|
-
description.map! { |line| line.rstrip }
|
280
|
-
end
|
281
|
-
|
282
|
-
def populate_tags(model, parsed_model_data)
|
283
|
-
if parsed_model_data['tags']
|
284
|
-
parsed_model_data['tags'].each do |tag|
|
285
|
-
model.tags << build_child_model(Tag, tag)
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def populate_steps(model, parsed_model_data)
|
291
|
-
if parsed_model_data['steps']
|
292
|
-
parsed_model_data['steps'].each do |step_data|
|
293
|
-
model.steps << build_child_model(Step, step_data)
|
226
|
+
# It's not getting better any time soon
|
227
|
+
# rubocop:disable Metrics/AbcSize
|
228
|
+
|
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']}")
|
294
244
|
end
|
295
245
|
end
|
296
246
|
end
|
247
|
+
# rubocop:enable Metrics/AbcSize
|
297
248
|
|
298
249
|
end
|
299
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,9 +62,9 @@ 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
|
-
parsed_file
|
67
|
+
parsed_file['feature']['elements'].first
|
68
68
|
end
|
69
69
|
|
70
70
|
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
|
-
parsed_file
|
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,9 +38,9 @@ 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
|
-
parsed_file
|
43
|
+
parsed_file['comments'].last
|
44
44
|
end
|
45
45
|
|
46
46
|
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,8 +78,8 @@ 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
|
86
|
-
feature_file_data = feature_file_data.merge({'path' => file_path})
|
81
|
+
feature_file_data = Parsing.parse_text(source_text, file_path)
|
82
|
+
feature_file_data = feature_file_data.merge({ 'path' => file_path })
|
87
83
|
|
88
84
|
feature_file_data
|
89
85
|
end
|
@@ -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,12 +40,15 @@ 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
|
-
parsed_file
|
51
|
+
parsed_file['feature']['elements'].first['steps'].first['doc_string']
|
49
52
|
end
|
50
53
|
|
51
54
|
def content_type_output_string
|
@@ -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,32 +99,40 @@ 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
|
-
parsed_file
|
135
|
+
parsed_file['feature']['elements'].first['examples'].first
|
128
136
|
end
|
129
137
|
|
130
138
|
def determine_buffer_size(index)
|
@@ -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
|