cuke_modeler 1.5.1 → 3.2.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 +60 -1
- data/LICENSE.txt +1 -1
- data/README.md +13 -15
- data/cuke_modeler.gemspec +12 -9
- data/lib/cuke_modeler.rb +1 -0
- data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +12 -0
- data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +12 -0
- data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +12 -0
- data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +12 -0
- data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +12 -0
- data/lib/cuke_modeler/adapters/{gherkin_6_adapter.rb → gherkin_9_adapter.rb} +105 -69
- data/lib/cuke_modeler/containing.rb +16 -5
- data/lib/cuke_modeler/described.rb +1 -0
- data/lib/cuke_modeler/models/background.rb +1 -1
- data/lib/cuke_modeler/models/cell.rb +1 -1
- data/lib/cuke_modeler/models/comment.rb +1 -1
- data/lib/cuke_modeler/models/directory.rb +2 -2
- data/lib/cuke_modeler/models/doc_string.rb +1 -1
- data/lib/cuke_modeler/models/example.rb +1 -1
- data/lib/cuke_modeler/models/feature.rb +16 -5
- data/lib/cuke_modeler/models/feature_file.rb +2 -2
- data/lib/cuke_modeler/models/outline.rb +1 -1
- data/lib/cuke_modeler/models/row.rb +1 -1
- data/lib/cuke_modeler/models/rule.rb +99 -0
- data/lib/cuke_modeler/models/scenario.rb +1 -1
- data/lib/cuke_modeler/models/step.rb +32 -3
- data/lib/cuke_modeler/models/table.rb +1 -1
- data/lib/cuke_modeler/models/tag.rb +1 -1
- data/lib/cuke_modeler/named.rb +1 -0
- data/lib/cuke_modeler/nested.rb +1 -0
- data/lib/cuke_modeler/parsed.rb +1 -0
- data/lib/cuke_modeler/parsing.rb +89 -102
- data/lib/cuke_modeler/sourceable.rb +1 -0
- data/lib/cuke_modeler/stepped.rb +1 -0
- data/lib/cuke_modeler/taggable.rb +1 -0
- data/lib/cuke_modeler/version.rb +1 -1
- data/testing/cucumber/features/analysis/step_comparison.feature +25 -0
- data/testing/cucumber/features/analysis/test_comparison.feature +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 +39 -140
- data/.gitignore +0 -18
- data/.simplecov +0 -7
- data/.travis.yml +0 -60
- data/Gemfile +0 -37
- data/Rakefile +0 -73
- data/appveyor.yml +0 -61
- data/lib/cuke_modeler/adapters/gherkin_2_adapter.rb +0 -273
- data/lib/cuke_modeler/adapters/gherkin_3_adapter.rb +0 -296
- data/lib/cuke_modeler/adapters/gherkin_4_adapter.rb +0 -308
- 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 -44
- 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 -173
- 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/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_6_adapter_spec.rb +0 -166
- data/testing/rspec/spec/integration/models/background_integration_spec.rb +0 -442
- data/testing/rspec/spec/integration/models/cell_integration_spec.rb +0 -335
- data/testing/rspec/spec/integration/models/comment_integration_spec.rb +0 -177
- data/testing/rspec/spec/integration/models/directory_integration_spec.rb +0 -218
- data/testing/rspec/spec/integration/models/doc_string_integration_spec.rb +0 -402
- data/testing/rspec/spec/integration/models/example_integration_spec.rb +0 -741
- data/testing/rspec/spec/integration/models/feature_file_integration_spec.rb +0 -272
- data/testing/rspec/spec/integration/models/feature_integration_spec.rb +0 -650
- data/testing/rspec/spec/integration/models/model_integration_spec.rb +0 -15
- data/testing/rspec/spec/integration/models/outline_integration_spec.rb +0 -624
- data/testing/rspec/spec/integration/models/row_integration_spec.rb +0 -291
- data/testing/rspec/spec/integration/models/scenario_integration_spec.rb +0 -479
- data/testing/rspec/spec/integration/models/step_integration_spec.rb +0 -475
- data/testing/rspec/spec/integration/models/table_integration_spec.rb +0 -337
- data/testing/rspec/spec/integration/models/tag_integration_spec.rb +0 -259
- data/testing/rspec/spec/integration/nested_integration_spec.rb +0 -91
- data/testing/rspec/spec/integration/parsing_integration_spec.rb +0 -122
- data/testing/rspec/spec/integration/shared/models_integration_specs.rb +0 -18
- data/testing/rspec/spec/spec_helper.rb +0 -125
- 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 -24
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module CukeModeler
|
|
2
2
|
|
|
3
|
+
# NOT A PART OF THE PUBLIC API
|
|
3
4
|
# A mix-in module containing methods used by models that contain other models.
|
|
4
5
|
|
|
5
6
|
module Containing
|
|
@@ -31,7 +32,6 @@ module CukeModeler
|
|
|
31
32
|
|
|
32
33
|
model.parent_model = self
|
|
33
34
|
|
|
34
|
-
|
|
35
35
|
model
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -129,6 +129,15 @@ module CukeModeler
|
|
|
129
129
|
populate_children(feature_object, parsed_feature_data)
|
|
130
130
|
end
|
|
131
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
|
+
|
|
132
141
|
def populate_directory(directory_object, processed_directory_data)
|
|
133
142
|
directory_object.path = processed_directory_data['path']
|
|
134
143
|
|
|
@@ -212,18 +221,20 @@ module CukeModeler
|
|
|
212
221
|
end
|
|
213
222
|
end
|
|
214
223
|
|
|
215
|
-
def populate_children(
|
|
224
|
+
def populate_children(model, parsed_feature_data)
|
|
216
225
|
elements = parsed_feature_data['elements']
|
|
217
226
|
|
|
218
227
|
if elements
|
|
219
228
|
elements.each do |element|
|
|
220
229
|
case element['type']
|
|
221
230
|
when 'Scenario', 'scenario'
|
|
222
|
-
|
|
231
|
+
model.tests << build_child_model(Scenario, element)
|
|
223
232
|
when 'ScenarioOutline', 'scenario_outline'
|
|
224
|
-
|
|
233
|
+
model.tests << build_child_model(Outline, element)
|
|
225
234
|
when 'Background', 'background'
|
|
226
|
-
|
|
235
|
+
model.background = build_child_model(Background, element)
|
|
236
|
+
when 'Rule'
|
|
237
|
+
model.rules << build_child_model(Rule, element)
|
|
227
238
|
else
|
|
228
239
|
raise(ArgumentError, "Unknown element type: #{element['type']}")
|
|
229
240
|
end
|
|
@@ -41,7 +41,7 @@ module CukeModeler
|
|
|
41
41
|
|
|
42
42
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_cell.feature')
|
|
43
43
|
|
|
44
|
-
parsed_file
|
|
44
|
+
parsed_file['feature']['elements'].first['steps'].first['table']['rows'].first['cells'].first
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
end
|
|
@@ -82,8 +82,8 @@ module CukeModeler
|
|
|
82
82
|
def process_feature_file(file_path)
|
|
83
83
|
source_text = IO.read(file_path)
|
|
84
84
|
|
|
85
|
-
feature_file_data = Parsing::parse_text(source_text, file_path)
|
|
86
|
-
feature_file_data = feature_file_data.merge({'path' => file_path})
|
|
85
|
+
feature_file_data = Parsing::parse_text(source_text, file_path)
|
|
86
|
+
feature_file_data = feature_file_data.merge({ 'path' => file_path })
|
|
87
87
|
|
|
88
88
|
feature_file_data
|
|
89
89
|
end
|
|
@@ -45,7 +45,7 @@ module CukeModeler
|
|
|
45
45
|
|
|
46
46
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_doc_string.feature')
|
|
47
47
|
|
|
48
|
-
parsed_file
|
|
48
|
+
parsed_file['feature']['elements'].first['steps'].first['doc_string']
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def content_type_output_string
|
|
@@ -124,7 +124,7 @@ module CukeModeler
|
|
|
124
124
|
|
|
125
125
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_example.feature')
|
|
126
126
|
|
|
127
|
-
parsed_file
|
|
127
|
+
parsed_file['feature']['elements'].first['examples'].first
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
def determine_buffer_size(index)
|
|
@@ -17,6 +17,9 @@ module CukeModeler
|
|
|
17
17
|
# The Background object contained by the Feature
|
|
18
18
|
attr_accessor :background
|
|
19
19
|
|
|
20
|
+
# The Rule objects contained by the Feature
|
|
21
|
+
attr_accessor :rules
|
|
22
|
+
|
|
20
23
|
# The Scenario and Outline objects contained by the Feature
|
|
21
24
|
attr_accessor :tests
|
|
22
25
|
|
|
@@ -25,6 +28,7 @@ module CukeModeler
|
|
|
25
28
|
# object.
|
|
26
29
|
def initialize(source_text = nil)
|
|
27
30
|
@tags = []
|
|
31
|
+
@rules = []
|
|
28
32
|
@tests = []
|
|
29
33
|
|
|
30
34
|
super(source_text)
|
|
@@ -50,6 +54,8 @@ module CukeModeler
|
|
|
50
54
|
@tests.select { |test| test.is_a? Outline }
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
# TODO: Remove this method on next major version release
|
|
58
|
+
# DEPRECATED
|
|
53
59
|
# Returns the number of test cases contained in the feature. A test case is a
|
|
54
60
|
# single set of test values, such as an individual scenario or one example row
|
|
55
61
|
# of an outline.
|
|
@@ -63,7 +69,7 @@ module CukeModeler
|
|
|
63
69
|
|
|
64
70
|
# Returns the model objects that belong to this model.
|
|
65
71
|
def children
|
|
66
|
-
models = tests + tags
|
|
72
|
+
models = rules + tests + tags
|
|
67
73
|
models << background if background
|
|
68
74
|
|
|
69
75
|
models
|
|
@@ -79,6 +85,7 @@ module CukeModeler
|
|
|
79
85
|
text << "\n" + description_output_string unless (description.nil? || description.empty?)
|
|
80
86
|
text << "\n\n" + background_output_string if background
|
|
81
87
|
text << "\n\n" + tests_output_string unless tests.empty?
|
|
88
|
+
text << "\n\n" + rules_output_string unless rules.empty?
|
|
82
89
|
|
|
83
90
|
text
|
|
84
91
|
end
|
|
@@ -90,18 +97,22 @@ module CukeModeler
|
|
|
90
97
|
def parse_source(source_text)
|
|
91
98
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_feature.feature')
|
|
92
99
|
|
|
93
|
-
parsed_file
|
|
100
|
+
parsed_file['feature']
|
|
94
101
|
end
|
|
95
102
|
|
|
96
103
|
def background_output_string
|
|
97
|
-
|
|
104
|
+
child_element_output_string(background)
|
|
98
105
|
end
|
|
99
106
|
|
|
100
107
|
def tests_output_string
|
|
101
|
-
tests.collect { |test|
|
|
108
|
+
tests.collect { |test| child_element_output_string(test) }.join("\n\n")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def rules_output_string
|
|
112
|
+
rules.collect { |rule| child_element_output_string(rule) }.join("\n\n")
|
|
102
113
|
end
|
|
103
114
|
|
|
104
|
-
def
|
|
115
|
+
def child_element_output_string(model)
|
|
105
116
|
model.to_s.split("\n").collect { |line| line.empty? ? '' : " #{line}" }.join("\n")
|
|
106
117
|
end
|
|
107
118
|
|
|
@@ -57,8 +57,8 @@ module CukeModeler
|
|
|
57
57
|
def process_feature_file(file_path)
|
|
58
58
|
source_text = IO.read(file_path)
|
|
59
59
|
|
|
60
|
-
feature_file_data = Parsing::parse_text(source_text, file_path)
|
|
61
|
-
feature_file_data = feature_file_data.merge({'path' => file_path})
|
|
60
|
+
feature_file_data = Parsing::parse_text(source_text, file_path)
|
|
61
|
+
feature_file_data = feature_file_data.merge({ 'path' => file_path })
|
|
62
62
|
|
|
63
63
|
feature_file_data
|
|
64
64
|
end
|
|
@@ -43,7 +43,7 @@ module CukeModeler
|
|
|
43
43
|
|
|
44
44
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_row.feature')
|
|
45
45
|
|
|
46
|
-
parsed_file
|
|
46
|
+
parsed_file['feature']['elements'].first['steps'].first['table']['rows'].first
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a rule in a Cucumber suite.
|
|
4
|
+
|
|
5
|
+
class Rule < Model
|
|
6
|
+
|
|
7
|
+
include Parsing
|
|
8
|
+
include Parsed
|
|
9
|
+
include Named
|
|
10
|
+
include Described
|
|
11
|
+
include Sourceable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# The keyword for the rule
|
|
15
|
+
attr_accessor :keyword
|
|
16
|
+
|
|
17
|
+
# The Background object contained by the Rule
|
|
18
|
+
attr_accessor :background
|
|
19
|
+
|
|
20
|
+
# The Scenario and Outline objects contained by the Rule
|
|
21
|
+
attr_accessor :tests
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Creates a new Rule object and, if *source_text* is provided, populates the
|
|
25
|
+
# object.
|
|
26
|
+
def initialize(source_text = nil)
|
|
27
|
+
@tests = []
|
|
28
|
+
|
|
29
|
+
super(source_text)
|
|
30
|
+
|
|
31
|
+
if source_text
|
|
32
|
+
parsed_rule_data = parse_source(source_text)
|
|
33
|
+
populate_rule(self, parsed_rule_data)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns *true* if the rule contains a background, *false* otherwise.
|
|
38
|
+
def has_background?
|
|
39
|
+
!@background.nil?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns the scenario models contained in the rule.
|
|
43
|
+
def scenarios
|
|
44
|
+
@tests.select { |test| test.is_a? Scenario }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns the outline models contained in the rule.
|
|
48
|
+
def outlines
|
|
49
|
+
@tests.select { |test| test.is_a? Outline }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns the model objects that belong to this model.
|
|
53
|
+
def children
|
|
54
|
+
models = tests
|
|
55
|
+
models << background if background
|
|
56
|
+
|
|
57
|
+
models
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns a string representation of this model. For a rule model,
|
|
61
|
+
# this will be Gherkin text that is equivalent to the rule being modeled.
|
|
62
|
+
def to_s
|
|
63
|
+
text = ''
|
|
64
|
+
|
|
65
|
+
text << "#{@keyword}:#{name_output_string}"
|
|
66
|
+
text << "\n" + description_output_string unless (description.nil? || description.empty?)
|
|
67
|
+
text << "\n\n" + background_output_string if background
|
|
68
|
+
text << "\n\n" + tests_output_string unless tests.empty?
|
|
69
|
+
|
|
70
|
+
text
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def parse_source(source_text)
|
|
78
|
+
base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n"
|
|
79
|
+
source_text = base_file_string + source_text
|
|
80
|
+
|
|
81
|
+
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_rule.feature')
|
|
82
|
+
|
|
83
|
+
parsed_file['feature']['elements'].first
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def background_output_string
|
|
87
|
+
test_output_string(background)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def tests_output_string
|
|
91
|
+
tests.collect { |test| test_output_string(test) }.join("\n\n")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_output_string(model)
|
|
95
|
+
model.to_s.split("\n").collect { |line| line.empty? ? '' : " #{line}" }.join("\n")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -33,9 +33,11 @@ module CukeModeler
|
|
|
33
33
|
# Returns *true* if the two steps have the same base text (i.e. minus any keyword,
|
|
34
34
|
# table, or doc string and *false* otherwise.
|
|
35
35
|
def ==(other_step)
|
|
36
|
-
return false unless other_step.
|
|
36
|
+
return false unless other_step.is_a?(CukeModeler::Step)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
text_matches?(other_step) &&
|
|
39
|
+
table_matches?(other_step) &&
|
|
40
|
+
doc_string_matches?(other_step)
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
# Returns the model objects that belong to this model.
|
|
@@ -62,7 +64,34 @@ module CukeModeler
|
|
|
62
64
|
|
|
63
65
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_step.feature')
|
|
64
66
|
|
|
65
|
-
parsed_file
|
|
67
|
+
parsed_file['feature']['elements'].first['steps'].first
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def text_matches?(other_step)
|
|
71
|
+
text == other_step.text
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def table_matches?(other_step)
|
|
75
|
+
return false if (!block.is_a?(CukeModeler::Table) || !other_step.block.is_a?(CukeModeler::Table)) && (block.is_a?(CukeModeler::Table) || other_step.block.is_a?(CukeModeler::Table))
|
|
76
|
+
return true unless block.is_a?(CukeModeler::Table) && other_step.block.is_a?(CukeModeler::Table)
|
|
77
|
+
|
|
78
|
+
first_step_values = block.rows.collect { |table_row| table_row.cells.map(&:value) }
|
|
79
|
+
second_step_values = other_step.block.rows.collect { |table_row| table_row.cells.map(&:value) }
|
|
80
|
+
|
|
81
|
+
first_step_values == second_step_values
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def doc_string_matches?(other_step)
|
|
85
|
+
return false if (!block.is_a?(CukeModeler::DocString) || !other_step.block.is_a?(CukeModeler::DocString)) && (block.is_a?(CukeModeler::DocString) || other_step.block.is_a?(CukeModeler::DocString))
|
|
86
|
+
return true unless block.is_a?(CukeModeler::DocString) && other_step.block.is_a?(CukeModeler::DocString)
|
|
87
|
+
|
|
88
|
+
first_content = block.content
|
|
89
|
+
first_content_type = block.content_type
|
|
90
|
+
second_content = other_step.block.content
|
|
91
|
+
second_content_type = other_step.block.content_type
|
|
92
|
+
|
|
93
|
+
(first_content == second_content) &&
|
|
94
|
+
(first_content_type == second_content_type)
|
|
66
95
|
end
|
|
67
96
|
|
|
68
97
|
end
|
|
@@ -47,7 +47,7 @@ module CukeModeler
|
|
|
47
47
|
|
|
48
48
|
parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
|
|
49
49
|
|
|
50
|
-
parsed_file
|
|
50
|
+
parsed_file['feature']['elements'].first['steps'].first['table']
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def row_output_string(row)
|
data/lib/cuke_modeler/named.rb
CHANGED
data/lib/cuke_modeler/nested.rb
CHANGED
data/lib/cuke_modeler/parsed.rb
CHANGED
data/lib/cuke_modeler/parsing.rb
CHANGED
|
@@ -1,107 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
begin
|
|
12
|
-
require 'gherkin'
|
|
13
|
-
rescue LoadError
|
|
14
|
-
begin
|
|
15
|
-
require 'gherkin/parser'
|
|
16
|
-
rescue LoadError
|
|
17
|
-
# Gherkin 6.x
|
|
18
|
-
require 'gherkin/gherkin'
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# The *gherkin* gem loads differently and has different grammar rules across major versions. Parsing
|
|
24
|
-
# will be done with an 'adapter' appropriate to the version of the *gherkin* gem that has been activated.
|
|
25
|
-
|
|
26
|
-
gherkin_version = Gem.loaded_specs['gherkin'].version.version
|
|
27
|
-
|
|
28
|
-
case gherkin_version
|
|
29
|
-
when /^6\./
|
|
30
|
-
require 'gherkin/gherkin'
|
|
31
|
-
require 'cuke_modeler/adapters/gherkin_6_adapter'
|
|
32
|
-
|
|
33
|
-
# The method to use for parsing Gherkin text
|
|
34
|
-
def self.parsing_method(source_text, filename)
|
|
35
|
-
messages = Gherkin::Gherkin.from_source(filename, source_text, {:default_dialect => CukeModeler::Parsing.dialect}).to_a
|
|
36
|
-
|
|
37
|
-
messages.map(&:to_hash).find { |message| message[:gherkinDocument] }[:gherkinDocument]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# The adapter to use when converting an AST to a standard internal shape
|
|
41
|
-
def self.adapter_class
|
|
42
|
-
CukeModeler::Gherkin6Adapter
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
when /^[54]\./
|
|
46
|
-
require 'gherkin/parser'
|
|
47
|
-
require 'cuke_modeler/adapters/gherkin_4_adapter'
|
|
1
|
+
# Have to at least load some version of the gem before which version of the gem has been loaded can
|
|
2
|
+
# be determined and the rest of the needed files can be loaded. The entry points vary across versions,
|
|
3
|
+
# so try them all until one of them works.
|
|
4
|
+
begin
|
|
5
|
+
# Gherkin 9.x
|
|
6
|
+
require 'gherkin'
|
|
7
|
+
rescue LoadError => e
|
|
8
|
+
# Add other entry points again if things change again
|
|
9
|
+
raise e
|
|
10
|
+
end
|
|
48
11
|
|
|
49
12
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
# Filename isn't used by this version of Gherkin but keeping the parameter so that the calling method only has to know one method signature
|
|
53
|
-
def self.parsing_method(source_text, _filename)
|
|
54
|
-
Gherkin::Parser.new.parse(source_text)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# The adapter to use when converting an AST to a standard internal shape
|
|
58
|
-
def self.adapter_class
|
|
59
|
-
CukeModeler::Gherkin4Adapter
|
|
60
|
-
end
|
|
13
|
+
# The *cucumber-gherkin* gem loads differently and has different grammar rules across major versions. Parsing
|
|
14
|
+
# will be done with an 'adapter' appropriate to the version of the *cucumber-gherkin* gem that has been activated.
|
|
61
15
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
require 'cuke_modeler/adapters/gherkin_3_adapter'
|
|
16
|
+
gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
|
|
17
|
+
gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
|
|
65
18
|
|
|
19
|
+
case gherkin_major_version
|
|
20
|
+
when 9, 10, 11, 12, 13, 14
|
|
21
|
+
# Currently nothing else to load beyond the entry point to the gem
|
|
22
|
+
else
|
|
23
|
+
raise("Unknown Gherkin version: '#{gherkin_version}'")
|
|
24
|
+
end
|
|
66
25
|
|
|
67
|
-
|
|
68
|
-
# Filename isn't used by this version of Gherkin but keeping the parameter so that the calling method only has to know one method signature
|
|
69
|
-
def self.parsing_method(source_text, _filename)
|
|
70
|
-
Gherkin::Parser.new.parse(source_text)
|
|
71
|
-
end
|
|
26
|
+
require "cuke_modeler/adapters/gherkin_#{gherkin_major_version}_adapter"
|
|
72
27
|
|
|
73
|
-
# The adapter to use when converting an AST to a standard internal shape
|
|
74
|
-
def self.adapter_class
|
|
75
|
-
CukeModeler::Gherkin3Adapter
|
|
76
|
-
end
|
|
77
|
-
when /^2\./
|
|
78
|
-
require 'stringio'
|
|
79
|
-
require 'gherkin/formatter/json_formatter'
|
|
80
|
-
require 'gherkin'
|
|
81
|
-
require 'json'
|
|
82
|
-
require 'multi_json'
|
|
83
|
-
require 'cuke_modeler/adapters/gherkin_2_adapter'
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
# The method to use for parsing Gherkin text
|
|
87
|
-
def self.parsing_method(source_text, filename)
|
|
88
|
-
io = StringIO.new
|
|
89
|
-
formatter = Gherkin::Formatter::JSONFormatter.new(io)
|
|
90
|
-
parser = Gherkin::Parser::Parser.new(formatter)
|
|
91
|
-
parser.parse(source_text, filename, 0)
|
|
92
|
-
formatter.done
|
|
93
|
-
MultiJson.load(io.string)
|
|
94
|
-
end
|
|
95
28
|
|
|
96
|
-
|
|
97
|
-
def self.adapter_class
|
|
98
|
-
CukeModeler::Gherkin2Adapter
|
|
99
|
-
end
|
|
29
|
+
module CukeModeler
|
|
100
30
|
|
|
101
|
-
|
|
102
|
-
raise("Unknown Gherkin version: '#{gherkin_version}'")
|
|
103
|
-
end
|
|
31
|
+
# A module providing source text parsing functionality.
|
|
104
32
|
|
|
33
|
+
module Parsing
|
|
105
34
|
|
|
106
35
|
class << self
|
|
107
36
|
|
|
@@ -117,28 +46,86 @@ module CukeModeler
|
|
|
117
46
|
# The dialects currently known by the gherkin gem
|
|
118
47
|
def dialects
|
|
119
48
|
unless @dialects
|
|
120
|
-
@dialects =
|
|
49
|
+
@dialects = Gherkin::DIALECTS
|
|
121
50
|
end
|
|
122
51
|
|
|
123
52
|
@dialects
|
|
124
53
|
end
|
|
125
54
|
|
|
126
|
-
# Parses the Cucumber feature given in *source_text* and returns
|
|
127
|
-
#
|
|
55
|
+
# Parses the Cucumber feature given in *source_text* and returns a hash representation of
|
|
56
|
+
# its logical structure. This is a standardized AST that should remain consistent across
|
|
57
|
+
# different versions of `cucumber-gherkin`
|
|
128
58
|
def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
|
|
129
59
|
raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}") unless source_text.is_a?(String)
|
|
130
60
|
|
|
131
|
-
|
|
132
61
|
begin
|
|
133
|
-
parsed_result = parsing_method(source_text, filename)
|
|
62
|
+
parsed_result = parsing_method(source_text.encode('UTF-8'), filename)
|
|
134
63
|
rescue => e
|
|
135
64
|
raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
|
|
136
65
|
end
|
|
137
66
|
|
|
138
|
-
|
|
67
|
+
adapter_class.new.adapt(parsed_result)
|
|
68
|
+
end
|
|
69
|
+
|
|
139
70
|
|
|
71
|
+
gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
|
|
72
|
+
gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
|
|
73
|
+
|
|
74
|
+
case gherkin_major_version
|
|
75
|
+
when 13, 14
|
|
76
|
+
# todo - make these methods private?
|
|
77
|
+
# NOT A PART OF THE PUBLIC API
|
|
78
|
+
# The method to use for parsing Gherkin text
|
|
79
|
+
def parsing_method(source_text, filename)
|
|
80
|
+
messages = Gherkin.from_source(filename, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
|
|
81
|
+
|
|
82
|
+
error_message = messages.find { |message| message[:parse_error] }
|
|
83
|
+
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
|
84
|
+
|
|
85
|
+
raise error_message[:parse_error][:message] if error_message
|
|
86
|
+
|
|
87
|
+
gherkin_ast_message[:gherkin_document]
|
|
88
|
+
end
|
|
89
|
+
when 12
|
|
90
|
+
# todo - make these methods private?
|
|
91
|
+
# NOT A PART OF THE PUBLIC API
|
|
92
|
+
# The method to use for parsing Gherkin text
|
|
93
|
+
def parsing_method(source_text, filename)
|
|
94
|
+
messages = Gherkin.from_source(filename, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
|
|
95
|
+
|
|
96
|
+
potential_error_message = messages.find { |message| message[:attachment] }
|
|
97
|
+
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
|
98
|
+
|
|
99
|
+
if potential_error_message
|
|
100
|
+
raise potential_error_message[:attachment][:body] if potential_error_message[:attachment][:body] =~ /expected.*got/
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
gherkin_ast_message[:gherkin_document]
|
|
104
|
+
end
|
|
105
|
+
when 9, 10, 11
|
|
106
|
+
# todo - make these methods private?
|
|
107
|
+
# NOT A PART OF THE PUBLIC API
|
|
108
|
+
# The method to use for parsing Gherkin text
|
|
109
|
+
def parsing_method(source_text, filename)
|
|
110
|
+
messages = Gherkin.from_source(filename, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
|
|
111
|
+
|
|
112
|
+
potential_error_message = messages.find { |message| message[:attachment] }
|
|
113
|
+
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
|
114
|
+
|
|
115
|
+
if potential_error_message
|
|
116
|
+
raise potential_error_message[:attachment][:text] if potential_error_message[:attachment][:text] =~ /expected.*got/
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
gherkin_ast_message[:gherkin_document]
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
raise("Unknown Gherkin version: '#{gherkin_version}'")
|
|
123
|
+
end
|
|
140
124
|
|
|
141
|
-
|
|
125
|
+
# NOT A PART OF THE PUBLIC API
|
|
126
|
+
# The adapter to use when converting an AST to a standard internal shape
|
|
127
|
+
define_method('adapter_class') do
|
|
128
|
+
CukeModeler.const_get("Gherkin#{gherkin_major_version}Adapter")
|
|
142
129
|
end
|
|
143
130
|
|
|
144
131
|
end
|