cuke_modeler 1.5.1 → 3.2.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 +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
|