cuke_modeler 3.2.0 → 3.7.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 +48 -3
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/cuke_modeler.gemspec +35 -16
- data/lib/cuke_modeler.rb +1 -2
- 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 +13 -0
- data/lib/cuke_modeler/adapters/gherkin_16_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_17_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -243
- data/lib/cuke_modeler/containing.rb +47 -90
- data/lib/cuke_modeler/described.rb +40 -2
- data/lib/cuke_modeler/models/background.rb +11 -12
- data/lib/cuke_modeler/models/cell.rb +13 -8
- data/lib/cuke_modeler/models/comment.rb +5 -6
- data/lib/cuke_modeler/models/directory.rb +13 -18
- data/lib/cuke_modeler/models/doc_string.rb +10 -8
- data/lib/cuke_modeler/models/example.rb +63 -46
- data/lib/cuke_modeler/models/feature.rb +23 -17
- data/lib/cuke_modeler/models/feature_file.rb +5 -8
- data/lib/cuke_modeler/models/model.rb +2 -3
- data/lib/cuke_modeler/models/outline.rb +19 -15
- data/lib/cuke_modeler/models/row.rb +15 -8
- data/lib/cuke_modeler/models/rule.rb +11 -10
- data/lib/cuke_modeler/models/scenario.rb +17 -13
- data/lib/cuke_modeler/models/step.rb +40 -19
- data/lib/cuke_modeler/models/table.rb +9 -7
- data/lib/cuke_modeler/models/tag.rb +9 -6
- data/lib/cuke_modeler/named.rb +5 -2
- data/lib/cuke_modeler/nested.rb +22 -19
- data/lib/cuke_modeler/parsed.rb +8 -1
- data/lib/cuke_modeler/parsing.rb +38 -29
- data/lib/cuke_modeler/sourceable.rb +8 -1
- data/lib/cuke_modeler/stepped.rb +8 -1
- data/lib/cuke_modeler/taggable.rb +9 -2
- data/lib/cuke_modeler/version.rb +1 -1
- metadata +91 -36
@@ -1,7 +1,6 @@
|
|
1
1
|
module CukeModeler
|
2
2
|
|
3
3
|
# A class modeling a rule in a Cucumber suite.
|
4
|
-
|
5
4
|
class Rule < Model
|
6
5
|
|
7
6
|
include Parsing
|
@@ -28,17 +27,19 @@ module CukeModeler
|
|
28
27
|
|
29
28
|
super(source_text)
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
return unless source_text
|
31
|
+
|
32
|
+
parsed_rule_data = parse_source(source_text)
|
33
|
+
populate_rule(self, parsed_rule_data)
|
35
34
|
end
|
36
35
|
|
37
36
|
# Returns *true* if the rule contains a background, *false* otherwise.
|
38
|
-
def
|
37
|
+
def background?
|
39
38
|
!@background.nil?
|
40
39
|
end
|
41
40
|
|
41
|
+
alias has_background? background?
|
42
|
+
|
42
43
|
# Returns the scenario models contained in the rule.
|
43
44
|
def scenarios
|
44
45
|
@tests.select { |test| test.is_a? Scenario }
|
@@ -63,9 +64,9 @@ module CukeModeler
|
|
63
64
|
text = ''
|
64
65
|
|
65
66
|
text << "#{@keyword}:#{name_output_string}"
|
66
|
-
text << "\n"
|
67
|
-
text << "\n\n"
|
68
|
-
text << "\n\n"
|
67
|
+
text << "\n#{description_output_string}" unless no_description_to_output?
|
68
|
+
text << "\n\n#{background_output_string}" if background
|
69
|
+
text << "\n\n#{tests_output_string}" unless tests.empty?
|
69
70
|
|
70
71
|
text
|
71
72
|
end
|
@@ -78,7 +79,7 @@ module CukeModeler
|
|
78
79
|
base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n"
|
79
80
|
source_text = base_file_string + source_text
|
80
81
|
|
81
|
-
parsed_file = Parsing
|
82
|
+
parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_rule.feature')
|
82
83
|
|
83
84
|
parsed_file['feature']['elements'].first
|
84
85
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CukeModeler
|
2
2
|
|
3
3
|
# A class modeling an individual scenario of a Cucumber suite.
|
4
|
-
|
5
4
|
class Scenario < Model
|
6
5
|
|
7
6
|
include Parsing
|
@@ -25,17 +24,17 @@ module CukeModeler
|
|
25
24
|
|
26
25
|
super(source_text)
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
return unless source_text
|
28
|
+
|
29
|
+
parsed_scenario_data = parse_source(source_text)
|
30
|
+
populate_scenario(self, parsed_scenario_data)
|
32
31
|
end
|
33
32
|
|
34
33
|
# Returns *true* if the two models have equivalent steps and *false* otherwise.
|
35
|
-
def ==(
|
36
|
-
return false unless
|
34
|
+
def ==(other)
|
35
|
+
return false unless other.respond_to?(:steps)
|
37
36
|
|
38
|
-
steps ==
|
37
|
+
steps == other.steps
|
39
38
|
end
|
40
39
|
|
41
40
|
# Returns the model objects that belong to this model.
|
@@ -43,20 +42,25 @@ module CukeModeler
|
|
43
42
|
steps + tags
|
44
43
|
end
|
45
44
|
|
45
|
+
# Building strings just isn't pretty
|
46
|
+
# rubocop:disable Metrics/AbcSize
|
47
|
+
|
46
48
|
# Returns a string representation of this model. For a scenario model,
|
47
49
|
# this will be Gherkin text that is equivalent to the scenario being modeled.
|
48
50
|
def to_s
|
49
51
|
text = ''
|
50
52
|
|
51
|
-
text << tag_output_string
|
53
|
+
text << "#{tag_output_string}\n" unless tags.empty?
|
52
54
|
text << "#{@keyword}:#{name_output_string}"
|
53
|
-
text << "\n"
|
54
|
-
text << "\n" unless
|
55
|
-
text << "\n"
|
55
|
+
text << "\n#{description_output_string}" unless no_description_to_output?
|
56
|
+
text << "\n" unless steps.empty? || no_description_to_output?
|
57
|
+
text << "\n#{steps_output_string}" unless steps.empty?
|
56
58
|
|
57
59
|
text
|
58
60
|
end
|
59
61
|
|
62
|
+
# rubocop:enable Metrics/AbcSize
|
63
|
+
|
60
64
|
|
61
65
|
private
|
62
66
|
|
@@ -65,7 +69,7 @@ module CukeModeler
|
|
65
69
|
base_file_string = "# language: #{Parsing.dialect}\n#{dialect_feature_keyword}: Fake feature to parse\n"
|
66
70
|
source_text = base_file_string + source_text
|
67
71
|
|
68
|
-
parsed_file = Parsing
|
72
|
+
parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_scenario.feature')
|
69
73
|
|
70
74
|
parsed_file['feature']['elements'].first
|
71
75
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CukeModeler
|
2
2
|
|
3
3
|
# A class modeling a single step of a background, scenario, or outline.
|
4
|
-
|
5
4
|
class Step < Model
|
6
5
|
|
7
6
|
include Sourceable
|
@@ -24,20 +23,20 @@ module CukeModeler
|
|
24
23
|
def initialize(source_text = nil)
|
25
24
|
super(source_text)
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
return unless source_text
|
27
|
+
|
28
|
+
parsed_step_data = parse_source(source_text)
|
29
|
+
populate_step(self, parsed_step_data)
|
31
30
|
end
|
32
31
|
|
33
32
|
# Returns *true* if the two steps have the same base text (i.e. minus any keyword,
|
34
33
|
# table, or doc string and *false* otherwise.
|
35
|
-
def ==(
|
36
|
-
return false unless
|
34
|
+
def ==(other)
|
35
|
+
return false unless other.is_a?(CukeModeler::Step)
|
37
36
|
|
38
|
-
text_matches?(
|
39
|
-
|
40
|
-
|
37
|
+
text_matches?(other) &&
|
38
|
+
table_matches?(other) &&
|
39
|
+
doc_string_matches?(other)
|
41
40
|
end
|
42
41
|
|
43
42
|
# Returns the model objects that belong to this model.
|
@@ -49,7 +48,7 @@ module CukeModeler
|
|
49
48
|
# this will be Gherkin text that is equivalent to the step being modeled.
|
50
49
|
def to_s
|
51
50
|
text = "#{keyword} #{self.text}"
|
52
|
-
text << "\n
|
51
|
+
text << "\n#{block.to_s.split("\n").collect { |line| " #{line}" }.join("\n")}" if block
|
53
52
|
|
54
53
|
text
|
55
54
|
end
|
@@ -59,10 +58,12 @@ module CukeModeler
|
|
59
58
|
|
60
59
|
|
61
60
|
def parse_source(source_text)
|
62
|
-
base_file_string = "# language: #{Parsing.dialect}
|
61
|
+
base_file_string = "# language: #{Parsing.dialect}
|
62
|
+
#{dialect_feature_keyword}: Fake feature to parse
|
63
|
+
#{dialect_scenario_keyword}:\n"
|
63
64
|
source_text = base_file_string + source_text
|
64
65
|
|
65
|
-
parsed_file = Parsing
|
66
|
+
parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_step.feature')
|
66
67
|
|
67
68
|
parsed_file['feature']['elements'].first['steps'].first
|
68
69
|
end
|
@@ -72,18 +73,18 @@ module CukeModeler
|
|
72
73
|
end
|
73
74
|
|
74
75
|
def table_matches?(other_step)
|
75
|
-
return false if
|
76
|
-
return true
|
76
|
+
return false if only_one_step_has_table?(other_step)
|
77
|
+
return true if neither_step_has_table?(other_step)
|
77
78
|
|
78
|
-
first_step_values
|
79
|
+
first_step_values = block.rows.collect { |table_row| table_row.cells.map(&:value) }
|
79
80
|
second_step_values = other_step.block.rows.collect { |table_row| table_row.cells.map(&:value) }
|
80
81
|
|
81
82
|
first_step_values == second_step_values
|
82
83
|
end
|
83
84
|
|
84
85
|
def doc_string_matches?(other_step)
|
85
|
-
return false if
|
86
|
-
return true
|
86
|
+
return false if only_one_step_has_doc_string?(other_step)
|
87
|
+
return true if neither_step_has_doc_string?(other_step)
|
87
88
|
|
88
89
|
first_content = block.content
|
89
90
|
first_content_type = block.content_type
|
@@ -91,7 +92,27 @@ module CukeModeler
|
|
91
92
|
second_content_type = other_step.block.content_type
|
92
93
|
|
93
94
|
(first_content == second_content) &&
|
94
|
-
|
95
|
+
(first_content_type == second_content_type)
|
96
|
+
end
|
97
|
+
|
98
|
+
def only_one_step_has_table?(other_step)
|
99
|
+
(!block.is_a?(CukeModeler::Table) || !other_step.block.is_a?(CukeModeler::Table)) &&
|
100
|
+
(block.is_a?(CukeModeler::Table) || other_step.block.is_a?(CukeModeler::Table))
|
101
|
+
end
|
102
|
+
|
103
|
+
def neither_step_has_table?(other_step)
|
104
|
+
!block.is_a?(CukeModeler::Table) &&
|
105
|
+
!other_step.block.is_a?(CukeModeler::Table)
|
106
|
+
end
|
107
|
+
|
108
|
+
def only_one_step_has_doc_string?(other_step)
|
109
|
+
(!block.is_a?(CukeModeler::DocString) || !other_step.block.is_a?(CukeModeler::DocString)) &&
|
110
|
+
(block.is_a?(CukeModeler::DocString) || other_step.block.is_a?(CukeModeler::DocString))
|
111
|
+
end
|
112
|
+
|
113
|
+
def neither_step_has_doc_string?(other_step)
|
114
|
+
!block.is_a?(CukeModeler::DocString) &&
|
115
|
+
!other_step.block.is_a?(CukeModeler::DocString)
|
95
116
|
end
|
96
117
|
|
97
118
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CukeModeler
|
2
2
|
|
3
3
|
# A class modeling a step's table.
|
4
|
-
|
5
4
|
class Table < Model
|
6
5
|
|
7
6
|
include Parsing
|
@@ -20,10 +19,10 @@ module CukeModeler
|
|
20
19
|
|
21
20
|
super(source_text)
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
return unless source_text
|
23
|
+
|
24
|
+
parsed_table_data = parse_source(source_text)
|
25
|
+
populate_table(self, parsed_table_data)
|
27
26
|
end
|
28
27
|
|
29
28
|
# Returns the model objects that belong to this model.
|
@@ -42,10 +41,13 @@ module CukeModeler
|
|
42
41
|
|
43
42
|
|
44
43
|
def parse_source(source_text)
|
45
|
-
base_file_string = "# language: #{Parsing.dialect}
|
44
|
+
base_file_string = "# language: #{Parsing.dialect}
|
45
|
+
#{dialect_feature_keyword}:
|
46
|
+
#{dialect_scenario_keyword}:
|
47
|
+
#{dialect_step_keyword} step\n"
|
46
48
|
source_text = base_file_string + source_text
|
47
49
|
|
48
|
-
parsed_file = Parsing
|
50
|
+
parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
|
49
51
|
|
50
52
|
parsed_file['feature']['elements'].first['steps'].first['table']
|
51
53
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CukeModeler
|
2
2
|
|
3
3
|
# A class modeling a tag.
|
4
|
-
|
5
4
|
class Tag < Model
|
6
5
|
|
7
6
|
include Parsing
|
@@ -18,10 +17,10 @@ module CukeModeler
|
|
18
17
|
def initialize(source_text = nil)
|
19
18
|
super(source_text)
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
return unless source_text
|
21
|
+
|
22
|
+
parsed_tag_data = parse_source(source_text)
|
23
|
+
populate_tag(self, parsed_tag_data)
|
25
24
|
end
|
26
25
|
|
27
26
|
# Returns a string representation of this model. For a tag model,
|
@@ -38,10 +37,14 @@ module CukeModeler
|
|
38
37
|
base_file_string = "\n#{dialect_feature_keyword}: Fake feature to parse"
|
39
38
|
source_text = "# language: #{Parsing.dialect}\n" + source_text + base_file_string
|
40
39
|
|
41
|
-
parsed_file = Parsing
|
40
|
+
parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
|
42
41
|
|
43
42
|
parsed_file['feature']['tags'].first
|
44
43
|
end
|
45
44
|
|
45
|
+
def populate_name(model, parsed_model_data)
|
46
|
+
model.name = parsed_model_data['name']
|
47
|
+
end
|
48
|
+
|
46
49
|
end
|
47
50
|
end
|
data/lib/cuke_modeler/named.rb
CHANGED
@@ -2,7 +2,6 @@ module CukeModeler
|
|
2
2
|
|
3
3
|
# NOT A PART OF THE PUBLIC API
|
4
4
|
# A mix-in module containing methods used by models that represent an element that has a name.
|
5
|
-
|
6
5
|
module Named
|
7
6
|
|
8
7
|
# The name of the element
|
@@ -13,7 +12,11 @@ module CukeModeler
|
|
13
12
|
|
14
13
|
|
15
14
|
def name_output_string
|
16
|
-
|
15
|
+
name.nil? || name.empty? ? '' : " #{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def populate_name(model, parsed_model_data)
|
19
|
+
model.name = parsed_model_data['name']
|
17
20
|
end
|
18
21
|
|
19
22
|
end
|
data/lib/cuke_modeler/nested.rb
CHANGED
@@ -3,7 +3,6 @@ module CukeModeler
|
|
3
3
|
# NOT A PART OF THE PUBLIC API
|
4
4
|
# A mix-in module containing methods used by models that are nested inside
|
5
5
|
# of other models.
|
6
|
-
|
7
6
|
module Nested
|
8
7
|
|
9
8
|
# The parent model that contains this model
|
@@ -12,30 +11,34 @@ module CukeModeler
|
|
12
11
|
|
13
12
|
# Returns the ancestor model of this model that matches the given type.
|
14
13
|
def get_ancestor(ancestor_type)
|
15
|
-
|
16
|
-
:feature_file => [FeatureFile],
|
17
|
-
:feature => [Feature],
|
18
|
-
:test => [Scenario, Outline, Background],
|
19
|
-
:background => [Background],
|
20
|
-
:scenario => [Scenario],
|
21
|
-
:outline => [Outline],
|
22
|
-
:step => [Step],
|
23
|
-
:table => [Table],
|
24
|
-
:example => [Example],
|
25
|
-
:row => [Row]
|
26
|
-
}[ancestor_type]
|
14
|
+
target_classes = classes_for_type(ancestor_type)
|
27
15
|
|
28
|
-
raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if
|
16
|
+
raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_classes.nil?
|
29
17
|
|
18
|
+
ancestor = parent_model
|
19
|
+
ancestor = ancestor.parent_model until target_classes.include?(ancestor.class) || ancestor.nil?
|
30
20
|
|
31
|
-
ancestor
|
21
|
+
ancestor
|
22
|
+
end
|
32
23
|
|
33
|
-
until target_type.include?(ancestor.class) || ancestor.nil?
|
34
|
-
ancestor = ancestor.parent_model
|
35
|
-
end
|
36
24
|
|
25
|
+
private
|
37
26
|
|
38
|
-
|
27
|
+
|
28
|
+
def classes_for_type(type)
|
29
|
+
{
|
30
|
+
directory: [Directory],
|
31
|
+
feature_file: [FeatureFile],
|
32
|
+
feature: [Feature],
|
33
|
+
test: [Scenario, Outline, Background],
|
34
|
+
background: [Background],
|
35
|
+
scenario: [Scenario],
|
36
|
+
outline: [Outline],
|
37
|
+
step: [Step],
|
38
|
+
table: [Table],
|
39
|
+
example: [Example],
|
40
|
+
row: [Row]
|
41
|
+
}[type]
|
39
42
|
end
|
40
43
|
|
41
44
|
end
|
data/lib/cuke_modeler/parsed.rb
CHANGED
@@ -2,11 +2,18 @@ module CukeModeler
|
|
2
2
|
|
3
3
|
# NOT A PART OF THE PUBLIC API
|
4
4
|
# A mix-in module containing methods used by models that are parsed from source text.
|
5
|
-
|
6
5
|
module Parsed
|
7
6
|
|
8
7
|
# The parsing data for this element that was generated by the parsing engine (i.e. the *gherkin* gem)
|
9
8
|
attr_accessor :parsing_data
|
10
9
|
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
|
14
|
+
def populate_parsing_data(model, parsed_model_data)
|
15
|
+
model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
|
16
|
+
end
|
17
|
+
|
11
18
|
end
|
12
19
|
end
|
data/lib/cuke_modeler/parsing.rb
CHANGED
@@ -1,13 +1,6 @@
|
|
1
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.
|
3
|
-
|
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
|
2
|
+
# be determined and the rest of the needed files can be loaded.
|
3
|
+
require 'gherkin'
|
11
4
|
|
12
5
|
|
13
6
|
# The *cucumber-gherkin* gem loads differently and has different grammar rules across major versions. Parsing
|
@@ -16,12 +9,16 @@ end
|
|
16
9
|
gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
|
17
10
|
gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
|
18
11
|
|
12
|
+
# Previous versions of the gem did not use the conventional entry point, so I'm leaving this here in case it
|
13
|
+
# changes again
|
14
|
+
# rubocop:disable Lint/EmptyWhen
|
19
15
|
case gherkin_major_version
|
20
|
-
when 9, 10, 11, 12, 13, 14
|
16
|
+
when 9, 10, 11, 12, 13, 14, 15, 16, 17
|
21
17
|
# Currently nothing else to load beyond the entry point to the gem
|
22
18
|
else
|
23
19
|
raise("Unknown Gherkin version: '#{gherkin_version}'")
|
24
20
|
end
|
21
|
+
# rubocop:enable Lint/EmptyWhen
|
25
22
|
|
26
23
|
require "cuke_modeler/adapters/gherkin_#{gherkin_major_version}_adapter"
|
27
24
|
|
@@ -29,7 +26,6 @@ require "cuke_modeler/adapters/gherkin_#{gherkin_major_version}_adapter"
|
|
29
26
|
module CukeModeler
|
30
27
|
|
31
28
|
# A module providing source text parsing functionality.
|
32
|
-
|
33
29
|
module Parsing
|
34
30
|
|
35
31
|
class << self
|
@@ -45,18 +41,16 @@ module CukeModeler
|
|
45
41
|
|
46
42
|
# The dialects currently known by the gherkin gem
|
47
43
|
def dialects
|
48
|
-
|
49
|
-
@dialects = Gherkin::DIALECTS
|
50
|
-
end
|
51
|
-
|
52
|
-
@dialects
|
44
|
+
@dialects ||= Gherkin::DIALECTS
|
53
45
|
end
|
54
46
|
|
55
47
|
# Parses the Cucumber feature given in *source_text* and returns a hash representation of
|
56
48
|
# its logical structure. This is a standardized AST that should remain consistent across
|
57
49
|
# different versions of `cucumber-gherkin`
|
58
50
|
def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
|
59
|
-
|
51
|
+
unless source_text.is_a?(String)
|
52
|
+
raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}")
|
53
|
+
end
|
60
54
|
|
61
55
|
begin
|
62
56
|
parsed_result = parsing_method(source_text.encode('UTF-8'), filename)
|
@@ -71,13 +65,20 @@ module CukeModeler
|
|
71
65
|
gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
|
72
66
|
gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
|
73
67
|
|
68
|
+
# Previous versions of the gem had more variation between their parsing methods and so it was more
|
69
|
+
# understandable to have different methods instead of a single method with lots of conditional statements
|
70
|
+
# inside of it, so I'm leaving this here in case it changes again
|
71
|
+
# rubocop:disable Lint/DuplicateMethods
|
74
72
|
case gherkin_major_version
|
75
|
-
when 13, 14
|
76
|
-
#
|
73
|
+
when 13, 14, 15, 16, 17
|
74
|
+
# TODO: make these methods private?
|
77
75
|
# NOT A PART OF THE PUBLIC API
|
78
76
|
# The method to use for parsing Gherkin text
|
79
77
|
def parsing_method(source_text, filename)
|
80
|
-
messages = Gherkin.from_source(filename,
|
78
|
+
messages = Gherkin.from_source(filename,
|
79
|
+
source_text,
|
80
|
+
{ include_gherkin_document: true })
|
81
|
+
.to_a.map(&:to_hash)
|
81
82
|
|
82
83
|
error_message = messages.find { |message| message[:parse_error] }
|
83
84
|
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
@@ -87,33 +88,39 @@ module CukeModeler
|
|
87
88
|
gherkin_ast_message[:gherkin_document]
|
88
89
|
end
|
89
90
|
when 12
|
90
|
-
#
|
91
|
+
# TODO: make these methods private?
|
91
92
|
# NOT A PART OF THE PUBLIC API
|
92
93
|
# The method to use for parsing Gherkin text
|
93
94
|
def parsing_method(source_text, filename)
|
94
|
-
messages = Gherkin.from_source(filename,
|
95
|
+
messages = Gherkin.from_source(filename,
|
96
|
+
source_text,
|
97
|
+
{ include_gherkin_document: true })
|
98
|
+
.to_a.map(&:to_hash)
|
95
99
|
|
96
100
|
potential_error_message = messages.find { |message| message[:attachment] }
|
97
101
|
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
98
102
|
|
99
|
-
if potential_error_message
|
100
|
-
raise potential_error_message[:attachment][:body]
|
103
|
+
if potential_error_message && potential_error_message[:attachment][:body] =~ /expected.*got/
|
104
|
+
raise potential_error_message[:attachment][:body]
|
101
105
|
end
|
102
106
|
|
103
107
|
gherkin_ast_message[:gherkin_document]
|
104
108
|
end
|
105
109
|
when 9, 10, 11
|
106
|
-
#
|
110
|
+
# TODO: make these methods private?
|
107
111
|
# NOT A PART OF THE PUBLIC API
|
108
112
|
# The method to use for parsing Gherkin text
|
109
113
|
def parsing_method(source_text, filename)
|
110
|
-
messages = Gherkin.from_source(filename,
|
114
|
+
messages = Gherkin.from_source(filename,
|
115
|
+
source_text,
|
116
|
+
{ include_gherkin_document: true })
|
117
|
+
.to_a.map(&:to_hash)
|
111
118
|
|
112
119
|
potential_error_message = messages.find { |message| message[:attachment] }
|
113
120
|
gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
|
114
121
|
|
115
|
-
if potential_error_message
|
116
|
-
raise potential_error_message[:attachment][:text]
|
122
|
+
if potential_error_message && potential_error_message[:attachment][:text] =~ /expected.*got/
|
123
|
+
raise potential_error_message[:attachment][:text]
|
117
124
|
end
|
118
125
|
|
119
126
|
gherkin_ast_message[:gherkin_document]
|
@@ -121,6 +128,7 @@ module CukeModeler
|
|
121
128
|
else
|
122
129
|
raise("Unknown Gherkin version: '#{gherkin_version}'")
|
123
130
|
end
|
131
|
+
# rubocop:enable Lint/DuplicateMethods
|
124
132
|
|
125
133
|
# NOT A PART OF THE PUBLIC API
|
126
134
|
# The adapter to use when converting an AST to a standard internal shape
|
@@ -143,7 +151,8 @@ module CukeModeler
|
|
143
151
|
end
|
144
152
|
|
145
153
|
def dialect_outline_keyword
|
146
|
-
get_word(Parsing.dialects[Parsing.dialect]['scenarioOutline'] ||
|
154
|
+
get_word(Parsing.dialects[Parsing.dialect]['scenarioOutline'] ||
|
155
|
+
Parsing.dialects[Parsing.dialect]['scenario_outline'])
|
147
156
|
end
|
148
157
|
|
149
158
|
def dialect_step_keyword
|