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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -3
  3. data/LICENSE.txt +1 -1
  4. data/README.md +7 -7
  5. data/cuke_modeler.gemspec +35 -16
  6. data/lib/cuke_modeler.rb +1 -2
  7. data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +2 -1
  8. data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +2 -1
  9. data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +2 -1
  10. data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +2 -1
  11. data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +2 -1
  12. data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +13 -0
  13. data/lib/cuke_modeler/adapters/gherkin_16_adapter.rb +13 -0
  14. data/lib/cuke_modeler/adapters/gherkin_17_adapter.rb +13 -0
  15. data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -243
  16. data/lib/cuke_modeler/containing.rb +47 -90
  17. data/lib/cuke_modeler/described.rb +40 -2
  18. data/lib/cuke_modeler/models/background.rb +11 -12
  19. data/lib/cuke_modeler/models/cell.rb +13 -8
  20. data/lib/cuke_modeler/models/comment.rb +5 -6
  21. data/lib/cuke_modeler/models/directory.rb +13 -18
  22. data/lib/cuke_modeler/models/doc_string.rb +10 -8
  23. data/lib/cuke_modeler/models/example.rb +63 -46
  24. data/lib/cuke_modeler/models/feature.rb +23 -17
  25. data/lib/cuke_modeler/models/feature_file.rb +5 -8
  26. data/lib/cuke_modeler/models/model.rb +2 -3
  27. data/lib/cuke_modeler/models/outline.rb +19 -15
  28. data/lib/cuke_modeler/models/row.rb +15 -8
  29. data/lib/cuke_modeler/models/rule.rb +11 -10
  30. data/lib/cuke_modeler/models/scenario.rb +17 -13
  31. data/lib/cuke_modeler/models/step.rb +40 -19
  32. data/lib/cuke_modeler/models/table.rb +9 -7
  33. data/lib/cuke_modeler/models/tag.rb +9 -6
  34. data/lib/cuke_modeler/named.rb +5 -2
  35. data/lib/cuke_modeler/nested.rb +22 -19
  36. data/lib/cuke_modeler/parsed.rb +8 -1
  37. data/lib/cuke_modeler/parsing.rb +38 -29
  38. data/lib/cuke_modeler/sourceable.rb +8 -1
  39. data/lib/cuke_modeler/stepped.rb +8 -1
  40. data/lib/cuke_modeler/taggable.rb +9 -2
  41. data/lib/cuke_modeler/version.rb +1 -1
  42. 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
- if source_text
32
- parsed_rule_data = parse_source(source_text)
33
- populate_rule(self, parsed_rule_data)
34
- end
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 has_background?
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" + 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?
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::parse_text(source_text, 'cuke_modeler_stand_alone_rule.feature')
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
- if source_text
29
- parsed_scenario_data = parse_source(source_text)
30
- populate_scenario(self, parsed_scenario_data)
31
- end
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 ==(other_model)
36
- return false unless other_model.respond_to?(:steps)
34
+ def ==(other)
35
+ return false unless other.respond_to?(:steps)
37
36
 
38
- steps == other_model.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 + "\n" unless tags.empty?
53
+ text << "#{tag_output_string}\n" unless tags.empty?
52
54
  text << "#{@keyword}:#{name_output_string}"
53
- text << "\n" + description_output_string unless (description.nil? || description.empty?)
54
- text << "\n" unless (steps.empty? || description.nil? || description.empty?)
55
- text << "\n" + steps_output_string unless steps.empty?
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::parse_text(source_text, 'cuke_modeler_stand_alone_scenario.feature')
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
- if source_text
28
- parsed_step_data = parse_source(source_text)
29
- populate_step(self, parsed_step_data)
30
- end
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 ==(other_step)
36
- return false unless other_step.is_a?(CukeModeler::Step)
34
+ def ==(other)
35
+ return false unless other.is_a?(CukeModeler::Step)
37
36
 
38
- text_matches?(other_step) &&
39
- table_matches?(other_step) &&
40
- doc_string_matches?(other_step)
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" + block.to_s.split("\n").collect { |line| " #{line}" }.join("\n") if block
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}\n#{dialect_feature_keyword}: Fake feature to parse\n#{dialect_scenario_keyword}:\n"
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::parse_text(source_text, 'cuke_modeler_stand_alone_step.feature')
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 (!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)
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 = block.rows.collect { |table_row| table_row.cells.map(&:value) }
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 (!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)
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
- (first_content_type == second_content_type)
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
- if source_text
24
- parsed_table_data = parse_source(source_text)
25
- populate_table(self, parsed_table_data)
26
- end
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}\n#{dialect_feature_keyword}:\n#{dialect_scenario_keyword}:\n#{dialect_step_keyword} step\n"
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::parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
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
- if source_text
22
- parsed_tag_data = parse_source(source_text)
23
- populate_tag(self, parsed_tag_data)
24
- end
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::parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
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
@@ -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
- (name.nil? || name.empty?) ? '' : " #{name}"
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
@@ -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
- target_type = {:directory => [Directory],
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 target_type.nil?
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 = self.parent_model
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
- ancestor
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
@@ -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
@@ -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. 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
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
- unless @dialects
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
- raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}") unless source_text.is_a?(String)
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
- # todo - make these methods private?
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, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
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
- # todo - make these methods private?
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, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
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] if potential_error_message[:attachment][:body] =~ /expected.*got/
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
- # todo - make these methods private?
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, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
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] if potential_error_message[:attachment][:text] =~ /expected.*got/
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'] || Parsing.dialects[Parsing.dialect]['scenario_outline'])
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