cuke_modeler 3.2.0 → 3.7.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 +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
|