cuke_modeler 2.1.0 → 3.4.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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +53 -1
  3. data/README.md +14 -16
  4. data/cuke_modeler.gemspec +33 -21
  5. data/lib/cuke_modeler.rb +2 -1
  6. data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +13 -0
  7. data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +13 -0
  8. data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +13 -0
  9. data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +13 -0
  10. data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +13 -0
  11. data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +13 -0
  12. data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +356 -4
  13. data/lib/cuke_modeler/containing.rb +41 -89
  14. data/lib/cuke_modeler/described.rb +40 -1
  15. data/lib/cuke_modeler/models/background.rb +12 -12
  16. data/lib/cuke_modeler/models/cell.rb +14 -8
  17. data/lib/cuke_modeler/models/comment.rb +6 -6
  18. data/lib/cuke_modeler/models/directory.rb +14 -18
  19. data/lib/cuke_modeler/models/doc_string.rb +11 -8
  20. data/lib/cuke_modeler/models/example.rb +64 -46
  21. data/lib/cuke_modeler/models/feature.rb +38 -20
  22. data/lib/cuke_modeler/models/feature_file.rb +6 -8
  23. data/lib/cuke_modeler/models/model.rb +2 -1
  24. data/lib/cuke_modeler/models/outline.rb +20 -15
  25. data/lib/cuke_modeler/models/row.rb +11 -8
  26. data/lib/cuke_modeler/models/rule.rb +101 -0
  27. data/lib/cuke_modeler/models/scenario.rb +18 -13
  28. data/lib/cuke_modeler/models/step.rb +41 -19
  29. data/lib/cuke_modeler/models/table.rb +10 -7
  30. data/lib/cuke_modeler/models/tag.rb +10 -6
  31. data/lib/cuke_modeler/named.rb +5 -1
  32. data/lib/cuke_modeler/nested.rb +22 -18
  33. data/lib/cuke_modeler/parsed.rb +8 -0
  34. data/lib/cuke_modeler/parsing.rb +55 -74
  35. data/lib/cuke_modeler/sourceable.rb +8 -0
  36. data/lib/cuke_modeler/stepped.rb +8 -0
  37. data/lib/cuke_modeler/taggable.rb +9 -1
  38. data/lib/cuke_modeler/version.rb +1 -1
  39. data/testing/cucumber/features/modeling/feature_modeling.feature +28 -7
  40. data/testing/cucumber/features/modeling/feature_output.feature +45 -23
  41. data/testing/cucumber/features/modeling/rule_modeling.feature +108 -0
  42. data/testing/cucumber/features/modeling/rule_output.feature +111 -0
  43. metadata +68 -161
  44. data/.gitignore +0 -18
  45. data/.simplecov +0 -7
  46. data/.travis.yml +0 -81
  47. data/Gemfile +0 -44
  48. data/Rakefile +0 -73
  49. data/appveyor.yml +0 -88
  50. data/lib/cuke_modeler/adapters/gherkin_2_adapter.rb +0 -274
  51. data/lib/cuke_modeler/adapters/gherkin_3_adapter.rb +0 -297
  52. data/lib/cuke_modeler/adapters/gherkin_4_adapter.rb +0 -309
  53. data/lib/cuke_modeler/adapters/gherkin_5_adapter.rb +0 -12
  54. data/lib/cuke_modeler/adapters/gherkin_6_adapter.rb +0 -310
  55. data/lib/cuke_modeler/adapters/gherkin_7_adapter.rb +0 -307
  56. data/lib/cuke_modeler/adapters/gherkin_8_adapter.rb +0 -12
  57. data/testing/cucumber/step_definitions/action_steps.rb +0 -13
  58. data/testing/cucumber/step_definitions/background_steps.rb +0 -1
  59. data/testing/cucumber/step_definitions/directory_steps.rb +0 -6
  60. data/testing/cucumber/step_definitions/doc_string_steps.rb +0 -1
  61. data/testing/cucumber/step_definitions/feature_file_steps.rb +0 -16
  62. data/testing/cucumber/step_definitions/feature_steps.rb +0 -7
  63. data/testing/cucumber/step_definitions/modeling_steps.rb +0 -49
  64. data/testing/cucumber/step_definitions/setup_steps.rb +0 -32
  65. data/testing/cucumber/step_definitions/step_steps.rb +0 -3
  66. data/testing/cucumber/step_definitions/table_steps.rb +0 -1
  67. data/testing/cucumber/step_definitions/tag_steps.rb +0 -3
  68. data/testing/cucumber/step_definitions/verification_steps.rb +0 -181
  69. data/testing/cucumber/support/env.rb +0 -30
  70. data/testing/dialect_helper.rb +0 -48
  71. data/testing/file_helper.rb +0 -47
  72. data/testing/gemfiles/gherkin2.gemfile +0 -33
  73. data/testing/gemfiles/gherkin3.gemfile +0 -26
  74. data/testing/gemfiles/gherkin4.gemfile +0 -27
  75. data/testing/gemfiles/gherkin5.gemfile +0 -27
  76. data/testing/gemfiles/gherkin6.gemfile +0 -10
  77. data/testing/gemfiles/gherkin7.gemfile +0 -9
  78. data/testing/gemfiles/gherkin8.gemfile +0 -9
  79. data/testing/gemfiles/gherkin9.gemfile +0 -9
  80. data/testing/helper_methods.rb +0 -23
  81. data/testing/rspec/spec/integration/adapters/gherkin_2_adapter_spec.rb +0 -166
  82. data/testing/rspec/spec/integration/adapters/gherkin_3_adapter_spec.rb +0 -166
  83. data/testing/rspec/spec/integration/adapters/gherkin_4_adapter_spec.rb +0 -165
  84. data/testing/rspec/spec/integration/adapters/gherkin_5_adapter_spec.rb +0 -165
  85. data/testing/rspec/spec/integration/adapters/gherkin_6_adapter_spec.rb +0 -159
  86. data/testing/rspec/spec/integration/adapters/gherkin_7_adapter_spec.rb +0 -162
  87. data/testing/rspec/spec/integration/adapters/gherkin_8_adapter_spec.rb +0 -162
  88. data/testing/rspec/spec/integration/adapters/gherkin_9_adapter_spec.rb +0 -162
  89. data/testing/rspec/spec/integration/models/background_integration_spec.rb +0 -438
  90. data/testing/rspec/spec/integration/models/cell_integration_spec.rb +0 -338
  91. data/testing/rspec/spec/integration/models/comment_integration_spec.rb +0 -180
  92. data/testing/rspec/spec/integration/models/directory_integration_spec.rb +0 -218
  93. data/testing/rspec/spec/integration/models/doc_string_integration_spec.rb +0 -398
  94. data/testing/rspec/spec/integration/models/example_integration_spec.rb +0 -753
  95. data/testing/rspec/spec/integration/models/feature_file_integration_spec.rb +0 -276
  96. data/testing/rspec/spec/integration/models/feature_integration_spec.rb +0 -655
  97. data/testing/rspec/spec/integration/models/model_integration_spec.rb +0 -15
  98. data/testing/rspec/spec/integration/models/outline_integration_spec.rb +0 -619
  99. data/testing/rspec/spec/integration/models/row_integration_spec.rb +0 -303
  100. data/testing/rspec/spec/integration/models/scenario_integration_spec.rb +0 -475
  101. data/testing/rspec/spec/integration/models/step_integration_spec.rb +0 -573
  102. data/testing/rspec/spec/integration/models/table_integration_spec.rb +0 -333
  103. data/testing/rspec/spec/integration/models/tag_integration_spec.rb +0 -271
  104. data/testing/rspec/spec/integration/nested_integration_spec.rb +0 -91
  105. data/testing/rspec/spec/integration/parsing_integration_spec.rb +0 -143
  106. data/testing/rspec/spec/integration/shared/models_integration_specs.rb +0 -18
  107. data/testing/rspec/spec/spec_helper.rb +0 -129
  108. data/testing/rspec/spec/unit/cuke_modeler_unit_spec.rb +0 -25
  109. data/testing/rspec/spec/unit/described_unit_spec.rb +0 -23
  110. data/testing/rspec/spec/unit/models/background_unit_spec.rb +0 -83
  111. data/testing/rspec/spec/unit/models/cell_unit_spec.rb +0 -68
  112. data/testing/rspec/spec/unit/models/comment_unit_spec.rb +0 -68
  113. data/testing/rspec/spec/unit/models/directory_unit_spec.rb +0 -127
  114. data/testing/rspec/spec/unit/models/doc_string_unit_spec.rb +0 -100
  115. data/testing/rspec/spec/unit/models/example_unit_spec.rb +0 -133
  116. data/testing/rspec/spec/unit/models/feature_file_unit_spec.rb +0 -125
  117. data/testing/rspec/spec/unit/models/feature_unit_spec.rb +0 -157
  118. data/testing/rspec/spec/unit/models/model_unit_spec.rb +0 -15
  119. data/testing/rspec/spec/unit/models/outline_unit_spec.rb +0 -117
  120. data/testing/rspec/spec/unit/models/row_unit_spec.rb +0 -68
  121. data/testing/rspec/spec/unit/models/scenario_unit_spec.rb +0 -86
  122. data/testing/rspec/spec/unit/models/step_unit_spec.rb +0 -109
  123. data/testing/rspec/spec/unit/models/table_unit_spec.rb +0 -77
  124. data/testing/rspec/spec/unit/models/tag_unit_spec.rb +0 -68
  125. data/testing/rspec/spec/unit/named_unit_spec.rb +0 -23
  126. data/testing/rspec/spec/unit/nested_unit_spec.rb +0 -43
  127. data/testing/rspec/spec/unit/parsed_unit_spec.rb +0 -27
  128. data/testing/rspec/spec/unit/parsing_unit_spec.rb +0 -54
  129. data/testing/rspec/spec/unit/shared/bare_bones_models_unit_specs.rb +0 -14
  130. data/testing/rspec/spec/unit/shared/containing_models_unit_specs.rb +0 -127
  131. data/testing/rspec/spec/unit/shared/described_models_unit_specs.rb +0 -38
  132. data/testing/rspec/spec/unit/shared/keyworded_models_unit_specs.rb +0 -58
  133. data/testing/rspec/spec/unit/shared/models_unit_specs.rb +0 -15
  134. data/testing/rspec/spec/unit/shared/named_models_unit_specs.rb +0 -39
  135. data/testing/rspec/spec/unit/shared/nested_models_unit_specs.rb +0 -51
  136. data/testing/rspec/spec/unit/shared/parsed_models_unit_specs.rb +0 -39
  137. data/testing/rspec/spec/unit/shared/prepopulated_models_unit_specs.rb +0 -18
  138. data/testing/rspec/spec/unit/shared/sourced_models_unit_specs.rb +0 -39
  139. data/testing/rspec/spec/unit/shared/stepped_models_unit_specs.rb +0 -46
  140. data/testing/rspec/spec/unit/shared/stringifiable_models_unit_specs.rb +0 -18
  141. data/testing/rspec/spec/unit/shared/tagged_models_unit_specs.rb +0 -72
  142. data/testing/rspec/spec/unit/sourceable_unit_spec.rb +0 -27
  143. data/testing/rspec/spec/unit/stepped_unit_spec.rb +0 -23
  144. data/testing/rspec/spec/unit/taggable_unit_spec.rb +0 -69
  145. data/testing/test_languages.json +0 -45
  146. data/todo.txt +0 -25
@@ -20,10 +20,10 @@ module CukeModeler
20
20
 
21
21
  super(source_text)
22
22
 
23
- if source_text
24
- parsed_table_data = parse_source(source_text)
25
- populate_table(self, parsed_table_data)
26
- end
23
+ return unless source_text
24
+
25
+ parsed_table_data = parse_source(source_text)
26
+ populate_table(self, parsed_table_data)
27
27
  end
28
28
 
29
29
  # Returns the model objects that belong to this model.
@@ -42,12 +42,15 @@ module CukeModeler
42
42
 
43
43
 
44
44
  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"
45
+ base_file_string = "# language: #{Parsing.dialect}
46
+ #{dialect_feature_keyword}:
47
+ #{dialect_scenario_keyword}:
48
+ #{dialect_step_keyword} step\n"
46
49
  source_text = base_file_string + source_text
47
50
 
48
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
51
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
49
52
 
50
- parsed_file.first['feature']['elements'].first['steps'].first['table']
53
+ parsed_file['feature']['elements'].first['steps'].first['table']
51
54
  end
52
55
 
53
56
  def row_output_string(row)
@@ -18,10 +18,10 @@ module CukeModeler
18
18
  def initialize(source_text = nil)
19
19
  super(source_text)
20
20
 
21
- if source_text
22
- parsed_tag_data = parse_source(source_text)
23
- populate_tag(self, parsed_tag_data)
24
- end
21
+ return unless source_text
22
+
23
+ parsed_tag_data = parse_source(source_text)
24
+ populate_tag(self, parsed_tag_data)
25
25
  end
26
26
 
27
27
  # Returns a string representation of this model. For a tag model,
@@ -38,9 +38,13 @@ module CukeModeler
38
38
  base_file_string = "\n#{dialect_feature_keyword}: Fake feature to parse"
39
39
  source_text = "# language: #{Parsing.dialect}\n" + source_text + base_file_string
40
40
 
41
- parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
41
+ parsed_file = Parsing.parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
42
+
43
+ parsed_file['feature']['tags'].first
44
+ end
42
45
 
43
- parsed_file.first['feature']['tags'].first
46
+ def populate_name(model, parsed_model_data)
47
+ model.name = parsed_model_data['name']
44
48
  end
45
49
 
46
50
  end
@@ -13,7 +13,11 @@ module CukeModeler
13
13
 
14
14
 
15
15
  def name_output_string
16
- (name.nil? || name.empty?) ? '' : " #{name}"
16
+ name.nil? || name.empty? ? '' : " #{name}"
17
+ end
18
+
19
+ def populate_name(model, parsed_model_data)
20
+ model.name = parsed_model_data['name']
17
21
  end
18
22
 
19
23
  end
@@ -12,30 +12,34 @@ module CukeModeler
12
12
 
13
13
  # Returns the ancestor model of this model that matches the given type.
14
14
  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]
15
+ target_classes = classes_for_type(ancestor_type)
27
16
 
28
- raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_type.nil?
17
+ raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_classes.nil?
29
18
 
19
+ ancestor = parent_model
20
+ ancestor = ancestor.parent_model until target_classes.include?(ancestor.class) || ancestor.nil?
30
21
 
31
- ancestor = self.parent_model
22
+ ancestor
23
+ end
32
24
 
33
- until target_type.include?(ancestor.class) || ancestor.nil?
34
- ancestor = ancestor.parent_model
35
- end
36
25
 
26
+ private
37
27
 
38
- ancestor
28
+
29
+ def classes_for_type(type)
30
+ {
31
+ directory: [Directory],
32
+ feature_file: [FeatureFile],
33
+ feature: [Feature],
34
+ test: [Scenario, Outline, Background],
35
+ background: [Background],
36
+ scenario: [Scenario],
37
+ outline: [Outline],
38
+ step: [Step],
39
+ table: [Table],
40
+ example: [Example],
41
+ row: [Row]
42
+ }[type]
39
43
  end
40
44
 
41
45
  end
@@ -8,5 +8,13 @@ module CukeModeler
8
8
  # The parsing data for this element that was generated by the parsing engine (i.e. the *gherkin* gem)
9
9
  attr_accessor :parsing_data
10
10
 
11
+
12
+ private
13
+
14
+
15
+ def populate_parsing_data(model, parsed_model_data)
16
+ model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
17
+ end
18
+
11
19
  end
12
20
  end
@@ -1,39 +1,24 @@
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 2.x, 8.x, 9.x
6
- require 'gherkin'
7
- rescue LoadError
8
- begin
9
- require 'gherkin/parser'
10
- rescue LoadError
11
- # Gherkin 6.x, 7.x
12
- require 'gherkin/gherkin'
13
- end
14
- end
2
+ # be determined and the rest of the needed files can be loaded.
3
+ require 'gherkin'
15
4
 
16
5
 
17
- # The *gherkin* gem loads differently and has different grammar rules across major versions. Parsing
18
- # will be done with an 'adapter' appropriate to the version of the *gherkin* gem that has been activated.
6
+ # The *cucumber-gherkin* gem loads differently and has different grammar rules across major versions. Parsing
7
+ # will be done with an 'adapter' appropriate to the version of the *cucumber-gherkin* gem that has been activated.
19
8
 
20
- gherkin_version = Gem.loaded_specs['gherkin'].version.version
9
+ gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
21
10
  gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
22
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
23
15
  case gherkin_major_version
24
- when 6, 7, 8, 9
25
- require 'gherkin/dialect'
26
- when 3, 4, 5
27
- require 'gherkin/parser'
28
- when 2
29
- require 'stringio'
30
- require 'gherkin/formatter/json_formatter'
31
- require 'gherkin'
32
- require 'json'
33
- require 'multi_json'
16
+ when 9, 10, 11, 12, 13, 14, 15
17
+ # Currently nothing else to load beyond the entry point to the gem
34
18
  else
35
19
  raise("Unknown Gherkin version: '#{gherkin_version}'")
36
20
  end
21
+ # rubocop:enable Lint/EmptyWhen
37
22
 
38
23
  require "cuke_modeler/adapters/gherkin_#{gherkin_major_version}_adapter"
39
24
 
@@ -57,20 +42,19 @@ module CukeModeler
57
42
 
58
43
  # The dialects currently known by the gherkin gem
59
44
  def dialects
60
- unless @dialects
61
- @dialects = Gem.loaded_specs['gherkin'].version.version[/^2\./] ? Gherkin::I18n::LANGUAGES : Gherkin::DIALECTS
62
- end
63
-
64
- @dialects
45
+ @dialects ||= Gherkin::DIALECTS
65
46
  end
66
47
 
67
- # Parses the Cucumber feature given in *source_text* and returns an array
68
- # containing the hash representation of its logical structure.
48
+ # Parses the Cucumber feature given in *source_text* and returns a hash representation of
49
+ # its logical structure. This is a standardized AST that should remain consistent across
50
+ # different versions of `cucumber-gherkin`
69
51
  def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
70
- raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}") unless source_text.is_a?(String)
52
+ unless source_text.is_a?(String)
53
+ raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}")
54
+ end
71
55
 
72
56
  begin
73
- parsed_result = parsing_method(source_text, filename)
57
+ parsed_result = parsing_method(source_text.encode('UTF-8'), filename)
74
58
  rescue => e
75
59
  raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
76
60
  end
@@ -79,77 +63,73 @@ module CukeModeler
79
63
  end
80
64
 
81
65
 
82
- gherkin_version = Gem.loaded_specs['gherkin'].version.version
66
+ gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
83
67
  gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
84
68
 
69
+ # Previous versions of the gem had more variation between their parsing methods and so it was more
70
+ # understandable to have different methods instead of a single method with lots of conditional statements
71
+ # inside of it, so I'm leaving this here in case it changes again
72
+ # rubocop:disable Lint/DuplicateMethods
85
73
  case gherkin_major_version
86
- when 9
74
+ when 13, 14, 15
75
+ # TODO: make these methods private?
87
76
  # NOT A PART OF THE PUBLIC API
88
77
  # The method to use for parsing Gherkin text
89
78
  def parsing_method(source_text, filename)
90
- messages = Gherkin.from_source(filename, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
79
+ messages = Gherkin.from_source(filename,
80
+ source_text,
81
+ { include_gherkin_document: true })
82
+ .to_a.map(&:to_hash)
91
83
 
92
- potential_error_message = messages.find { |message| message[:attachment] }
84
+ error_message = messages.find { |message| message[:parse_error] }
93
85
  gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
94
86
 
95
- if potential_error_message
96
- raise potential_error_message[:attachment][:data] if potential_error_message[:attachment][:data] =~ /expected.*got/
97
- end
87
+ raise error_message[:parse_error][:message] if error_message
98
88
 
99
89
  gherkin_ast_message[:gherkin_document]
100
90
  end
101
- when 8
91
+ when 12
92
+ # TODO: make these methods private?
102
93
  # NOT A PART OF THE PUBLIC API
103
94
  # The method to use for parsing Gherkin text
104
95
  def parsing_method(source_text, filename)
105
- messages = Gherkin.from_source(filename, source_text, { :include_gherkin_document => true }).to_a.map(&:to_hash)
96
+ messages = Gherkin.from_source(filename,
97
+ source_text,
98
+ { include_gherkin_document: true })
99
+ .to_a.map(&:to_hash)
106
100
 
107
101
  potential_error_message = messages.find { |message| message[:attachment] }
108
- gherkin_ast_message = messages.find { |message| message[:gherkinDocument] }
102
+ gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
109
103
 
110
- if potential_error_message
111
- raise potential_error_message[:attachment][:data] if potential_error_message[:attachment][:data] =~ /expected.*got/
104
+ if potential_error_message && potential_error_message[:attachment][:body] =~ /expected.*got/
105
+ raise potential_error_message[:attachment][:body]
112
106
  end
113
107
 
114
- gherkin_ast_message[:gherkinDocument]
108
+ gherkin_ast_message[:gherkin_document]
115
109
  end
116
- when 6, 7
110
+ when 9, 10, 11
111
+ # TODO: make these methods private?
117
112
  # NOT A PART OF THE PUBLIC API
118
113
  # The method to use for parsing Gherkin text
119
114
  def parsing_method(source_text, filename)
120
- messages = Gherkin::Gherkin.from_source(filename, source_text).to_a.map(&:to_hash)
115
+ messages = Gherkin.from_source(filename,
116
+ source_text,
117
+ { include_gherkin_document: true })
118
+ .to_a.map(&:to_hash)
121
119
 
122
120
  potential_error_message = messages.find { |message| message[:attachment] }
123
- gherkin_ast_message = messages.find { |message| message[:gherkinDocument] }
121
+ gherkin_ast_message = messages.find { |message| message[:gherkin_document] }
124
122
 
125
- if potential_error_message
126
- raise potential_error_message[:attachment][:data] if potential_error_message[:attachment][:data] =~ /expected.*got/
123
+ if potential_error_message && potential_error_message[:attachment][:text] =~ /expected.*got/
124
+ raise potential_error_message[:attachment][:text]
127
125
  end
128
126
 
129
- gherkin_ast_message[:gherkinDocument]
130
- end
131
- when 3, 4, 5
132
- # todo - make these methods private?
133
- # NOT A PART OF THE PUBLIC API
134
- # The method to use for parsing Gherkin text
135
- # 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
136
- def parsing_method(source_text, _filename)
137
- Gherkin::Parser.new.parse(source_text)
138
- end
139
- when 2
140
- # NOT A PART OF THE PUBLIC API
141
- # The method to use for parsing Gherkin text
142
- def parsing_method(source_text, filename)
143
- io = StringIO.new
144
- formatter = Gherkin::Formatter::JSONFormatter.new(io)
145
- parser = Gherkin::Parser::Parser.new(formatter)
146
- parser.parse(source_text, filename, 0)
147
- formatter.done
148
- MultiJson.load(io.string)
127
+ gherkin_ast_message[:gherkin_document]
149
128
  end
150
129
  else
151
130
  raise("Unknown Gherkin version: '#{gherkin_version}'")
152
131
  end
132
+ # rubocop:enable Lint/DuplicateMethods
153
133
 
154
134
  # NOT A PART OF THE PUBLIC API
155
135
  # The adapter to use when converting an AST to a standard internal shape
@@ -172,7 +152,8 @@ module CukeModeler
172
152
  end
173
153
 
174
154
  def dialect_outline_keyword
175
- get_word(Parsing.dialects[Parsing.dialect]['scenarioOutline'] || Parsing.dialects[Parsing.dialect]['scenario_outline'])
155
+ get_word(Parsing.dialects[Parsing.dialect]['scenarioOutline'] ||
156
+ Parsing.dialects[Parsing.dialect]['scenario_outline'])
176
157
  end
177
158
 
178
159
  def dialect_step_keyword
@@ -9,5 +9,13 @@ module CukeModeler
9
9
  # The line number where the element began in the source code
10
10
  attr_accessor :source_line
11
11
 
12
+
13
+ private
14
+
15
+
16
+ def populate_source_line(model, parsed_model_data)
17
+ model.source_line = parsed_model_data['line']
18
+ end
19
+
12
20
  end
13
21
  end
@@ -21,5 +21,13 @@ module CukeModeler
21
21
  step.to_s.split("\n").collect { |line| " #{line}" }.join("\n")
22
22
  end
23
23
 
24
+ def populate_steps(model, parsed_model_data)
25
+ return unless parsed_model_data['steps']
26
+
27
+ parsed_model_data['steps'].each do |step_data|
28
+ model.steps << build_child_model(Step, step_data)
29
+ end
30
+ end
31
+
24
32
  end
25
33
  end
@@ -25,7 +25,15 @@ module CukeModeler
25
25
 
26
26
 
27
27
  def tag_output_string
28
- tags.collect { |tag| tag.name }.join(' ')
28
+ tags.map(&:name).join(' ')
29
+ end
30
+
31
+ def populate_tags(model, parsed_model_data)
32
+ return unless parsed_model_data['tags']
33
+
34
+ parsed_model_data['tags'].each do |tag|
35
+ model.tags << build_child_model(Tag, tag)
36
+ end
29
37
  end
30
38
 
31
39
  end
@@ -1,4 +1,4 @@
1
1
  module CukeModeler
2
2
  # The gem version
3
- VERSION = '2.1.0'
3
+ VERSION = '3.4.0'.freeze
4
4
  end
@@ -1,6 +1,8 @@
1
1
  Feature: Feature modeling
2
2
 
3
- Feature models are the top level element of the gherkin portion of the model tree. They expose several attributes of the feature that they represent, as well as containing models for any background, scenarios, or outlines that are present in that feature.
3
+ Feature models are the top level element of the Gherkin portion of the model tree. They expose several attributes of the
4
+ feature that they represent, as well as containing models for any background, scenarios, or outlines that are present in
5
+ that feature.
4
6
 
5
7
 
6
8
  Background:
@@ -29,11 +31,18 @@ Feature models are the top level element of the gherkin portion of the model tre
29
31
  Scenario: Scenario 2
30
32
  * a step
31
33
 
32
- Scenario Outline: Outline 2
33
- * a step
34
- Examples:
35
- | param |
36
- | value |
34
+ Rule: a rule
35
+
36
+ Scenario: Scenario 3
37
+ * a step
38
+
39
+ Rule: another rule
40
+
41
+ Scenario Outline: Outline 2
42
+ * a step
43
+ Examples:
44
+ | param |
45
+ | value |
37
46
  """
38
47
  And a feature model based on that gherkin
39
48
  """
@@ -75,7 +84,18 @@ Feature models are the top level element of the gherkin portion of the model tre
75
84
  """
76
85
  Then the model returns a model for the background "The background"
77
86
 
87
+ Scenario: Modeling a feature's rules
88
+ When the feature's rules are requested
89
+ """
90
+ @model.rules
91
+ """
92
+ Then the model returns models for the following rules:
93
+ | a rule |
94
+ | another rule |
95
+
78
96
  Scenario: Modeling a feature's scenarios
97
+ Note: Scenarios under a Rule keyword are included in the corresponding Rule model instead of the Feature model
98
+
79
99
  When the feature's scenarios are requested
80
100
  """
81
101
  @model.scenarios
@@ -85,13 +105,14 @@ Feature models are the top level element of the gherkin portion of the model tre
85
105
  | Scenario 2 |
86
106
 
87
107
  Scenario: Modeling a feature's outlines
108
+ Note: Outlines under a Rule keyword are included in the corresponding Rule model instead of the Feature model
109
+
88
110
  When the feature's outlines are requested
89
111
  """
90
112
  @model.outlines
91
113
  """
92
114
  Then the model returns models for the following outlines:
93
115
  | Outline 1 |
94
- | Outline 2 |
95
116
 
96
117
  Scenario: Modeling a feature's tags
97
118