cuke_modeler 0.4.1 → 1.0.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 (252) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -17
  3. data/.travis.yml +1 -1
  4. data/Gemfile +4 -0
  5. data/History.rdoc +71 -3
  6. data/LICENSE.txt +22 -22
  7. data/README.md +24 -10
  8. data/Rakefile +2 -12
  9. data/cuke_modeler.gemspec +1 -1
  10. data/features/analysis/test_comparison.feature +37 -122
  11. data/features/modeling/background_modeling.feature +77 -0
  12. data/features/modeling/background_output.feature +42 -0
  13. data/features/modeling/cell_modeling.feature +23 -0
  14. data/features/modeling/cell_output.feature +22 -0
  15. data/features/modeling/directory_modeling.feature +65 -0
  16. data/features/modeling/directory_output.feature +12 -0
  17. data/features/modeling/doc_string_modeling.feature +61 -0
  18. data/features/modeling/doc_string_output.feature +32 -0
  19. data/features/modeling/example_modeling.feature +125 -0
  20. data/features/modeling/example_output.feature +39 -0
  21. data/features/modeling/feature_file_modeling.feature +40 -0
  22. data/features/modeling/feature_file_output.feature +12 -0
  23. data/features/modeling/feature_modeling.feature +109 -0
  24. data/features/modeling/feature_output.feature +104 -0
  25. data/features/modeling/model_output.feature +22 -0
  26. data/features/modeling/model_structure.feature +48 -0
  27. data/features/modeling/outline_modeling.feature +144 -0
  28. data/features/modeling/outline_output.feature +69 -0
  29. data/features/modeling/row_modeling.feature +48 -0
  30. data/features/modeling/row_output.feature +22 -0
  31. data/features/modeling/scenario_modeling.feature +118 -0
  32. data/features/modeling/scenario_output.feature +45 -0
  33. data/features/modeling/step_modeling.feature +84 -0
  34. data/features/modeling/step_output.feature +29 -0
  35. data/features/modeling/table_modeling.feature +50 -0
  36. data/features/modeling/table_output.feature +24 -0
  37. data/features/modeling/tag_modeling.feature +43 -0
  38. data/features/modeling/tag_output.feature +22 -0
  39. data/features/step_definitions/action_steps.rb +11 -1
  40. data/features/step_definitions/background_steps.rb +1 -85
  41. data/features/step_definitions/directory_steps.rb +2 -48
  42. data/features/step_definitions/doc_string_steps.rb +1 -67
  43. data/features/step_definitions/feature_file_steps.rb +2 -37
  44. data/features/step_definitions/feature_steps.rb +4 -100
  45. data/features/step_definitions/modeling_steps.rb +44 -0
  46. data/features/step_definitions/setup_steps.rb +19 -41
  47. data/features/step_definitions/step_steps.rb +2 -166
  48. data/features/step_definitions/table_steps.rb +1 -58
  49. data/features/step_definitions/tag_steps.rb +2 -72
  50. data/features/step_definitions/verification_steps.rb +152 -4
  51. data/features/support/env.rb +4 -6
  52. data/gemfiles/{gherkin.gemfile → gherkin2.gemfile} +4 -0
  53. data/gemfiles/gherkin3.gemfile +4 -0
  54. data/gemfiles/gherkin4.gemfile +4 -0
  55. data/lib/cuke_modeler.rb +24 -22
  56. data/lib/cuke_modeler/adapters/gherkin_2_adapter.rb +103 -31
  57. data/lib/cuke_modeler/adapters/gherkin_3_adapter.rb +103 -40
  58. data/lib/cuke_modeler/adapters/gherkin_4_adapter.rb +111 -50
  59. data/lib/cuke_modeler/containing.rb +255 -4
  60. data/lib/cuke_modeler/described.rb +28 -0
  61. data/lib/cuke_modeler/models/background.rb +66 -0
  62. data/lib/cuke_modeler/models/cell.rb +48 -0
  63. data/lib/cuke_modeler/models/directory.rb +95 -0
  64. data/lib/cuke_modeler/models/doc_string.rb +59 -0
  65. data/lib/cuke_modeler/models/example.rb +167 -0
  66. data/lib/cuke_modeler/models/feature.rb +106 -0
  67. data/lib/cuke_modeler/models/feature_file.rb +64 -0
  68. data/lib/cuke_modeler/models/model.rb +32 -0
  69. data/lib/cuke_modeler/models/outline.rb +79 -0
  70. data/lib/cuke_modeler/models/row.rb +49 -0
  71. data/lib/cuke_modeler/models/scenario.rb +69 -0
  72. data/lib/cuke_modeler/models/step.rb +68 -0
  73. data/lib/cuke_modeler/models/table.rb +67 -0
  74. data/lib/cuke_modeler/models/tag.rb +46 -0
  75. data/lib/cuke_modeler/named.rb +19 -0
  76. data/lib/cuke_modeler/nested.rb +22 -15
  77. data/lib/cuke_modeler/parsed.rb +11 -0
  78. data/lib/cuke_modeler/parsing.rb +66 -83
  79. data/lib/cuke_modeler/sourceable.rb +3 -11
  80. data/lib/cuke_modeler/stepped.rb +24 -0
  81. data/lib/cuke_modeler/taggable.rb +6 -29
  82. data/lib/cuke_modeler/version.rb +2 -1
  83. data/spec/integration/background_integration_spec.rb +332 -7
  84. data/spec/integration/cell_integration_spec.rb +321 -0
  85. data/spec/integration/directory_integration_spec.rb +175 -9
  86. data/spec/integration/doc_string_integration_spec.rb +318 -7
  87. data/spec/integration/example_integration_spec.rb +602 -19
  88. data/spec/integration/feature_file_integration_spec.rb +98 -3
  89. data/spec/integration/feature_integration_spec.rb +445 -27
  90. data/spec/integration/gherkin_2_adapter_spec.rb +122 -0
  91. data/spec/integration/gherkin_3_adapter_spec.rb +125 -0
  92. data/spec/integration/gherkin_4_adapter_spec.rb +123 -0
  93. data/spec/integration/model_integration_spec.rb +15 -0
  94. data/spec/integration/nested_integration_spec.rb +91 -0
  95. data/spec/integration/outline_integration_spec.rb +485 -12
  96. data/spec/integration/parsing_integration_spec.rb +85 -0
  97. data/spec/integration/row_integration_spec.rb +221 -18
  98. data/spec/integration/scenario_integration_spec.rb +368 -14
  99. data/spec/integration/shared/models_integration_specs.rb +18 -0
  100. data/spec/integration/step_integration_spec.rb +328 -77
  101. data/spec/integration/table_integration_spec.rb +242 -20
  102. data/spec/integration/tag_integration_spec.rb +178 -13
  103. data/spec/spec_helper.rb +32 -18
  104. data/spec/unit/background_unit_spec.rb +24 -44
  105. data/spec/unit/cell_unit_spec.rb +73 -0
  106. data/spec/unit/described_unit_spec.rb +23 -0
  107. data/spec/unit/directory_unit_spec.rb +52 -62
  108. data/spec/unit/doc_string_unit_spec.rb +47 -100
  109. data/spec/unit/example_unit_spec.rb +50 -296
  110. data/spec/unit/feature_file_unit_spec.rb +53 -52
  111. data/spec/unit/feature_unit_spec.rb +39 -83
  112. data/spec/unit/model_unit_spec.rb +15 -0
  113. data/spec/unit/named_unit_spec.rb +23 -0
  114. data/spec/unit/nested_unit_spec.rb +24 -21
  115. data/spec/unit/outline_unit_spec.rb +46 -69
  116. data/spec/unit/parsed_unit_spec.rb +27 -0
  117. data/spec/unit/parsing_unit_spec.rb +2 -70
  118. data/spec/unit/row_unit_spec.rb +22 -51
  119. data/spec/unit/scenario_unit_spec.rb +27 -59
  120. data/spec/unit/{bare_bones_unit_specs.rb → shared/bare_bones_models_unit_specs.rb} +2 -2
  121. data/spec/unit/shared/containing_models_unit_specs.rb +18 -0
  122. data/spec/unit/shared/described_models_unit_specs.rb +38 -0
  123. data/spec/unit/shared/models_unit_specs.rb +15 -0
  124. data/spec/unit/shared/named_models_unit_specs.rb +39 -0
  125. data/spec/unit/shared/nested_models_unit_specs.rb +51 -0
  126. data/spec/unit/shared/parsed_models_unit_specs.rb +39 -0
  127. data/spec/unit/shared/prepopulated_models_unit_specs.rb +18 -0
  128. data/spec/unit/shared/sourced_models_unit_specs.rb +39 -0
  129. data/spec/unit/shared/stepped_models_unit_specs.rb +46 -0
  130. data/spec/unit/shared/stringifiable_models_unit_specs.rb +18 -0
  131. data/spec/unit/shared/tagged_models_unit_specs.rb +72 -0
  132. data/spec/unit/sourceable_unit_spec.rb +12 -4
  133. data/spec/unit/step_unit_spec.rb +40 -231
  134. data/spec/unit/stepped_unit_spec.rb +23 -0
  135. data/spec/unit/table_unit_spec.rb +27 -89
  136. data/spec/unit/tag_unit_spec.rb +30 -53
  137. data/spec/unit/taggable_unit_spec.rb +26 -42
  138. data/todo.txt +32 -0
  139. metadata +135 -217
  140. data/features/analysis/test_manipulation.feature +0 -37
  141. data/features/modeling/gherkin/background_modeling.feature +0 -65
  142. data/features/modeling/gherkin/background_output.feature +0 -131
  143. data/features/modeling/gherkin/directory_modeling.feature +0 -110
  144. data/features/modeling/gherkin/directory_output.feature +0 -14
  145. data/features/modeling/gherkin/doc_string_modeling.feature +0 -53
  146. data/features/modeling/gherkin/doc_string_output.feature +0 -72
  147. data/features/modeling/gherkin/example_modeling.feature +0 -101
  148. data/features/modeling/gherkin/example_output.feature +0 -193
  149. data/features/modeling/gherkin/feature_file_modeling.feature +0 -54
  150. data/features/modeling/gherkin/feature_file_output.feature +0 -14
  151. data/features/modeling/gherkin/feature_modeling.feature +0 -154
  152. data/features/modeling/gherkin/feature_output.feature +0 -245
  153. data/features/modeling/gherkin/outline_modeling.feature +0 -90
  154. data/features/modeling/gherkin/outline_output.feature +0 -198
  155. data/features/modeling/gherkin/row_modeling.feature +0 -68
  156. data/features/modeling/gherkin/row_output.feature +0 -28
  157. data/features/modeling/gherkin/scenario_modeling.feature +0 -79
  158. data/features/modeling/gherkin/scenario_output.feature +0 -148
  159. data/features/modeling/gherkin/step_modeling.feature +0 -75
  160. data/features/modeling/gherkin/step_output.feature +0 -53
  161. data/features/modeling/gherkin/table_modeling.feature +0 -42
  162. data/features/modeling/gherkin/table_output.feature +0 -43
  163. data/features/modeling/gherkin/table_row_modeling.feature +0 -57
  164. data/features/modeling/gherkin/table_row_output.feature +0 -28
  165. data/features/modeling/gherkin/tag_modeling.feature +0 -48
  166. data/features/modeling/gherkin/tag_output.feature +0 -17
  167. data/features/modeling/gherkin3/background_modeling.feature +0 -64
  168. data/features/modeling/gherkin3/background_output.feature +0 -131
  169. data/features/modeling/gherkin3/directory_modeling.feature +0 -110
  170. data/features/modeling/gherkin3/directory_output.feature +0 -14
  171. data/features/modeling/gherkin3/doc_string_modeling.feature +0 -53
  172. data/features/modeling/gherkin3/doc_string_output.feature +0 -72
  173. data/features/modeling/gherkin3/example_modeling.feature +0 -100
  174. data/features/modeling/gherkin3/example_output.feature +0 -207
  175. data/features/modeling/gherkin3/feature_file_modeling.feature +0 -54
  176. data/features/modeling/gherkin3/feature_file_output.feature +0 -14
  177. data/features/modeling/gherkin3/feature_modeling.feature +0 -155
  178. data/features/modeling/gherkin3/feature_output.feature +0 -249
  179. data/features/modeling/gherkin3/outline_modeling.feature +0 -89
  180. data/features/modeling/gherkin3/outline_output.feature +0 -255
  181. data/features/modeling/gherkin3/row_modeling.feature +0 -68
  182. data/features/modeling/gherkin3/row_output.feature +0 -28
  183. data/features/modeling/gherkin3/scenario_modeling.feature +0 -78
  184. data/features/modeling/gherkin3/scenario_output.feature +0 -148
  185. data/features/modeling/gherkin3/step_modeling.feature +0 -75
  186. data/features/modeling/gherkin3/step_output.feature +0 -53
  187. data/features/modeling/gherkin3/table_modeling.feature +0 -42
  188. data/features/modeling/gherkin3/table_output.feature +0 -43
  189. data/features/modeling/gherkin3/table_row_modeling.feature +0 -57
  190. data/features/modeling/gherkin3/table_row_output.feature +0 -28
  191. data/features/modeling/gherkin3/tag_modeling.feature +0 -49
  192. data/features/modeling/gherkin3/tag_output.feature +0 -17
  193. data/features/modeling/gherkin4/background_modeling.feature +0 -64
  194. data/features/modeling/gherkin4/background_output.feature +0 -131
  195. data/features/modeling/gherkin4/directory_modeling.feature +0 -110
  196. data/features/modeling/gherkin4/directory_output.feature +0 -14
  197. data/features/modeling/gherkin4/doc_string_modeling.feature +0 -53
  198. data/features/modeling/gherkin4/doc_string_output.feature +0 -72
  199. data/features/modeling/gherkin4/example_modeling.feature +0 -100
  200. data/features/modeling/gherkin4/example_output.feature +0 -193
  201. data/features/modeling/gherkin4/feature_file_modeling.feature +0 -54
  202. data/features/modeling/gherkin4/feature_file_output.feature +0 -14
  203. data/features/modeling/gherkin4/feature_modeling.feature +0 -153
  204. data/features/modeling/gherkin4/feature_output.feature +0 -245
  205. data/features/modeling/gherkin4/outline_modeling.feature +0 -89
  206. data/features/modeling/gherkin4/outline_output.feature +0 -198
  207. data/features/modeling/gherkin4/row_modeling.feature +0 -68
  208. data/features/modeling/gherkin4/row_output.feature +0 -28
  209. data/features/modeling/gherkin4/scenario_modeling.feature +0 -78
  210. data/features/modeling/gherkin4/scenario_output.feature +0 -148
  211. data/features/modeling/gherkin4/step_modeling.feature +0 -75
  212. data/features/modeling/gherkin4/step_output.feature +0 -53
  213. data/features/modeling/gherkin4/table_modeling.feature +0 -42
  214. data/features/modeling/gherkin4/table_output.feature +0 -43
  215. data/features/modeling/gherkin4/table_row_modeling.feature +0 -57
  216. data/features/modeling/gherkin4/table_row_output.feature +0 -28
  217. data/features/modeling/gherkin4/tag_modeling.feature +0 -48
  218. data/features/modeling/gherkin4/tag_output.feature +0 -17
  219. data/features/step_definitions/outline_steps.rb +0 -258
  220. data/features/step_definitions/test_steps.rb +0 -123
  221. data/lib/cuke_modeler/background.rb +0 -38
  222. data/lib/cuke_modeler/directory.rb +0 -83
  223. data/lib/cuke_modeler/doc_string.rb +0 -87
  224. data/lib/cuke_modeler/example.rb +0 -195
  225. data/lib/cuke_modeler/feature.rb +0 -147
  226. data/lib/cuke_modeler/feature_element.rb +0 -73
  227. data/lib/cuke_modeler/feature_file.rb +0 -77
  228. data/lib/cuke_modeler/outline.rb +0 -68
  229. data/lib/cuke_modeler/raw.rb +0 -20
  230. data/lib/cuke_modeler/row.rb +0 -64
  231. data/lib/cuke_modeler/scenario.rb +0 -45
  232. data/lib/cuke_modeler/step.rb +0 -216
  233. data/lib/cuke_modeler/table.rb +0 -90
  234. data/lib/cuke_modeler/table_row.rb +0 -64
  235. data/lib/cuke_modeler/tag.rb +0 -62
  236. data/lib/cuke_modeler/test_element.rb +0 -79
  237. data/lib/cuke_modeler/world.rb +0 -113
  238. data/spec/integration/table_row_integration_spec.rb +0 -76
  239. data/spec/integration/world_integration_spec.rb +0 -14
  240. data/spec/unit/containing_element_unit_specs.rb +0 -18
  241. data/spec/unit/feature_element_unit_spec.rb +0 -19
  242. data/spec/unit/feature_element_unit_specs.rb +0 -52
  243. data/spec/unit/nested_element_unit_specs.rb +0 -39
  244. data/spec/unit/prepopulated_unit_specs.rb +0 -14
  245. data/spec/unit/raw_element_unit_specs.rb +0 -27
  246. data/spec/unit/raw_unit_spec.rb +0 -28
  247. data/spec/unit/sourced_element_unit_specs.rb +0 -18
  248. data/spec/unit/table_row_unit_spec.rb +0 -102
  249. data/spec/unit/tagged_element_unit_specs.rb +0 -67
  250. data/spec/unit/test_element_unit_spec.rb +0 -54
  251. data/spec/unit/test_element_unit_specs.rb +0 -34
  252. data/spec/unit/world_unit_spec.rb +0 -140
@@ -0,0 +1,67 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a step's table.
4
+
5
+ class Table < Model
6
+
7
+ include Parsed
8
+ include Sourceable
9
+
10
+
11
+ # The row models that make up the table
12
+ attr_accessor :rows
13
+
14
+
15
+ # Creates a new Table object and, if *source_text* is provided, populates
16
+ # the object.
17
+ def initialize(source_text = nil)
18
+ @rows = []
19
+
20
+ super(source_text)
21
+
22
+ if source_text
23
+ parsed_table_data = parse_source(source_text)
24
+ populate_table(self, parsed_table_data)
25
+ end
26
+ end
27
+
28
+ # Returns the model objects that belong to this model.
29
+ def children
30
+ rows
31
+ end
32
+
33
+ # Returns a string representation of this model. For a table model,
34
+ # this will be Gherkin text that is equivalent to the table being modeled.
35
+ def to_s
36
+ rows.empty? ? '' : rows.collect { |row| row_output_string(row) }.join("\n")
37
+ end
38
+
39
+
40
+ private
41
+
42
+
43
+ def parse_source(source_text)
44
+ base_file_string = "Feature:\nScenario:\n* step\n"
45
+ source_text = base_file_string + source_text
46
+
47
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
48
+
49
+ parsed_file.first['elements'].first['steps'].first['table']
50
+ end
51
+
52
+ def row_output_string(row)
53
+ row_text = '|'
54
+
55
+ row.cells.count.times do |count|
56
+ row_text << " #{row.cells[count].to_s.ljust(determine_buffer_size(count))} |"
57
+ end
58
+
59
+ row_text
60
+ end
61
+
62
+ def determine_buffer_size(index)
63
+ rows.collect { |row| row.cells[index].to_s.length }.max || 0
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,46 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a tag.
4
+
5
+ class Tag < Model
6
+
7
+ include Parsed
8
+ include Sourceable
9
+
10
+
11
+ # The name of the tag
12
+ attr_accessor :name
13
+
14
+
15
+ # Creates a new Tag object and, if *source_text* is provided, populates the
16
+ # object.
17
+ def initialize(source_text = nil)
18
+ super(source_text)
19
+
20
+ if source_text
21
+ parsed_tag_data = parse_source(source_text)
22
+ populate_tag(self, parsed_tag_data)
23
+ end
24
+ end
25
+
26
+ # Returns a string representation of this model. For a tag model,
27
+ # this will be Gherkin text that is equivalent to the tag being modeled.
28
+ def to_s
29
+ name || ''
30
+ end
31
+
32
+
33
+ private
34
+
35
+
36
+ def parse_source(source_text)
37
+ base_file_string = "\nFeature: Fake feature to parse"
38
+ source_text = source_text + base_file_string
39
+
40
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
41
+
42
+ parsed_file.first['tags'].first
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by models that represent an element that has a name.
4
+
5
+ module Named
6
+
7
+ # The name of the element
8
+ attr_accessor :name
9
+
10
+
11
+ private
12
+
13
+
14
+ def name_output_string
15
+ (name.nil? || name.empty?) ? '' : " #{name}"
16
+ end
17
+
18
+ end
19
+ end
@@ -1,32 +1,39 @@
1
1
  module CukeModeler
2
2
 
3
- # A mix-in module containing methods used by elements that are nested inside
4
- # of other elements.
3
+ # A mix-in module containing methods used by models that are nested inside
4
+ # of other models.
5
5
 
6
6
  module Nested
7
7
 
8
- # The parent object that contains *self*
9
- attr_accessor :parent_element
8
+ # The parent model that contains this model
9
+ attr_accessor :parent_model
10
10
 
11
11
 
12
- # Returns the ancestor of *self* that matches the given type.
12
+ # Returns the ancestor model of this model that matches the given type.
13
13
  def get_ancestor(ancestor_type)
14
- ancestor = self.parent_element
15
- target_type = {:directory => Directory,
16
- :feature_file => FeatureFile,
17
- :feature => Feature,
18
- :test => TestElement,
19
- :step => Step,
20
- :table => Table,
21
- :example => Example
14
+ target_type = {:directory => [Directory],
15
+ :feature_file => [FeatureFile],
16
+ :feature => [Feature],
17
+ :test => [Scenario, Outline, Background],
18
+ :background => [Background],
19
+ :scenario => [Scenario],
20
+ :outline => [Outline],
21
+ :step => [Step],
22
+ :table => [Table],
23
+ :example => [Example],
24
+ :row => [Row]
22
25
  }[ancestor_type]
23
26
 
24
27
  raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_type.nil?
25
28
 
26
- until ancestor.is_a?(target_type) || ancestor.nil?
27
- ancestor = ancestor.parent_element
29
+
30
+ ancestor = self.parent_model
31
+
32
+ until target_type.include?(ancestor.class) || ancestor.nil?
33
+ ancestor = ancestor.parent_model
28
34
  end
29
35
 
36
+
30
37
  ancestor
31
38
  end
32
39
 
@@ -0,0 +1,11 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by models that are parsed from source text.
4
+
5
+ module Parsed
6
+
7
+ # The parsing data for this element that was generated by the parsing engine (i.e. the *gherkin* gem)
8
+ attr_accessor :parsing_data
9
+
10
+ end
11
+ end
@@ -1,113 +1,96 @@
1
- # The 'gherkin' gem loads differently depending across versions. Try the old one first and then the new one
2
- begin
3
- require 'gherkin'
4
- rescue LoadError => e
5
- require 'gherkin/parser'
6
- end
7
-
8
- # Parsing will be with an 'adapter' appropriate to the version of the 'gherkin' gem that has been activated
9
- case
10
- when Gem.loaded_specs['gherkin'].version.version[/^4/]
11
-
12
- require 'gherkin/parser'
13
- require 'cuke_modeler/adapters/gherkin_4_adapter'
14
-
15
-
16
- module CukeModeler
17
-
18
- module Parsing
19
- class << self
1
+ module CukeModeler
20
2
 
21
- def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
22
- raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
3
+ # A module providing source text parsing functionality.
23
4
 
24
- begin
25
- parsed_result = Gherkin::Parser.new.parse(source_text)
26
- rescue => e
27
- raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
28
- end
5
+ module Parsing
29
6
 
30
- adapted_result = CukeModeler::Gherkin4Adapter.new.adapt(parsed_result)
31
7
 
32
- adapted_result
33
- end
34
- end
35
- end
8
+ # Have to at least load some version of the gem before which version of the gem has been loaded can
9
+ # be determined and the rest of the needed files can be loaded. Try the old one first and then the
10
+ # new one.
11
+ begin
12
+ require 'gherkin'
13
+ rescue LoadError
14
+ require 'gherkin/parser'
36
15
  end
37
16
 
38
- when Gem.loaded_specs['gherkin'].version.version[/^3/]
39
-
40
- require 'gherkin/parser'
41
- require 'cuke_modeler/adapters/gherkin_3_adapter'
42
-
43
-
44
- module CukeModeler
45
-
46
- module Parsing
47
- class << self
48
17
 
49
- def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
50
- raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
18
+ # The *gherkin* gem loads differently and has different grammar rules across major versions. Parsing
19
+ # will be done with an 'adapter' appropriate to the version of the *gherkin* gem that has been activated.
51
20
 
52
- begin
53
- parsed_result = Gherkin::Parser.new.parse(source_text)
54
- rescue => e
55
- raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
56
- end
21
+ case
22
+ when Gem.loaded_specs['gherkin'].version.version[/^4/]
23
+ require 'gherkin/parser'
24
+ require 'cuke_modeler/adapters/gherkin_4_adapter'
57
25
 
58
- adapted_result = CukeModeler::Gherkin3Adapter.new.adapt(parsed_result)
59
26
 
60
- adapted_result
61
- end
27
+ # todo - make these methods private?
28
+ def self.parsing_method(source_text, _filename)
29
+ Gherkin::Parser.new.parse(source_text)
62
30
  end
63
- end
64
- end
65
31
 
66
- else
32
+ def self.adapter_class
33
+ CukeModeler::Gherkin4Adapter
34
+ end
67
35
 
68
- require 'stringio'
69
- require 'gherkin/formatter/json_formatter'
70
- require 'gherkin'
71
- require 'json'
72
- require 'multi_json'
73
- require 'cuke_modeler/adapters/gherkin_2_adapter'
36
+ when Gem.loaded_specs['gherkin'].version.version[/^3/]
37
+ require 'gherkin/parser'
38
+ require 'cuke_modeler/adapters/gherkin_3_adapter'
74
39
 
75
40
 
76
- module CukeModeler
41
+ def self.parsing_method(source_text, _filename)
42
+ Gherkin::Parser.new.parse(source_text)
43
+ end
77
44
 
78
- # A module providing source text parsing functionality.
45
+ def self.adapter_class
46
+ CukeModeler::Gherkin3Adapter
47
+ end
79
48
 
80
- module Parsing
49
+ else # Assume version 2.x
50
+ require 'stringio'
51
+ require 'gherkin/formatter/json_formatter'
52
+ require 'gherkin'
53
+ require 'json'
54
+ require 'multi_json'
55
+ require 'cuke_modeler/adapters/gherkin_2_adapter'
56
+
57
+
58
+ def self.parsing_method(source_text, filename)
59
+ io = StringIO.new
60
+ formatter = Gherkin::Formatter::JSONFormatter.new(io)
61
+ parser = Gherkin::Parser::Parser.new(formatter)
62
+ parser.parse(source_text, filename, 0)
63
+ formatter.done
64
+ MultiJson.load(io.string)
65
+ end
81
66
 
82
- class << self
67
+ def self.adapter_class
68
+ CukeModeler::Gherkin2Adapter
69
+ end
83
70
 
84
- # Parses the Cucumber feature given in *source_text* and returns an array
85
- # containing the hash representation of its logical structure.
86
- def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
87
- raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
71
+ end
88
72
 
89
- io = StringIO.new
90
- formatter = Gherkin::Formatter::JSONFormatter.new(io)
91
- parser = Gherkin::Parser::Parser.new(formatter)
92
73
 
93
- begin
94
- parser.parse(source_text, filename, 0)
95
- rescue => e
96
- raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
97
- end
74
+ class << self
98
75
 
99
- formatter.done
76
+ # Parses the Cucumber feature given in *source_text* and returns an array
77
+ # containing the hash representation of its logical structure.
78
+ def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
79
+ raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}") unless source_text.is_a?(String)
100
80
 
101
81
 
102
- parsed_result = MultiJson.load(io.string)
103
- adapted_result = CukeModeler::Gherkin2Adapter.new.adapt(parsed_result)
82
+ begin
83
+ parsed_result = parsing_method(source_text, filename)
84
+ rescue => e
85
+ raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
86
+ end
104
87
 
105
- adapted_result
106
- end
88
+ adapted_result = adapter_class.new.adapt(parsed_result)
107
89
 
108
- end
109
90
 
91
+ adapted_result
110
92
  end
111
- end
112
93
 
94
+ end
95
+ end
113
96
  end
@@ -1,20 +1,12 @@
1
1
  module CukeModeler
2
2
 
3
- # A mix-in module containing methods used by elements that know their
4
- # source code line.
3
+ # A mix-in module containing methods used by models that know from which line of
4
+ # source code they originate.
5
5
 
6
6
  module Sourceable
7
7
 
8
8
  # The line number where the element began in the source code
9
- attr_reader :source_line
10
-
11
-
12
- private
13
-
14
-
15
- def populate_element_source_line(parsed_element)
16
- @source_line = parsed_element['line']
17
- end
9
+ attr_accessor :source_line
18
10
 
19
11
  end
20
12
  end
@@ -0,0 +1,24 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by models that represent an element that has steps.
4
+
5
+ module Stepped
6
+
7
+
8
+ # The step models contained by this model
9
+ attr_accessor :steps
10
+
11
+
12
+ private
13
+
14
+
15
+ def steps_output_string
16
+ steps.collect { |step| indented_step_text(step) }.join("\n")
17
+ end
18
+
19
+ def indented_step_text(step)
20
+ step.to_s.split("\n").collect { |line| " #{line}" }.join("\n")
21
+ end
22
+
23
+ end
24
+ end
@@ -1,53 +1,30 @@
1
1
  module CukeModeler
2
2
 
3
- # A mix-in module containing methods used by elements that can be tagged.
3
+ # A mix-in module containing methods used by models that represent an element that can be tagged.
4
4
 
5
5
  module Taggable
6
6
 
7
- # The tags which are directly assigned to the element
7
+ # The models for tags which are directly assigned to the element
8
8
  attr_accessor :tags
9
9
 
10
- # The tag elements belonging to the element
11
- attr_accessor :tag_elements
12
10
 
13
-
14
- # Returns the tags which are indirectly assigned to the element (i.e. they
11
+ # Returns the models for tags which are indirectly assigned to the element (i.e. they
15
12
  # have been inherited from a parent element).
16
13
  def applied_tags
17
- @parent_element.respond_to?(:all_tags) ? @parent_element.all_tags : []
18
- end
19
-
20
- # Returns the tags elements which are indirectly assigned to the element
21
- # (i.e. they have been inherited from a parent element).
22
- def applied_tag_elements
23
- @parent_element.respond_to?(:all_tag_elements) ? @parent_element.all_tag_elements : []
14
+ parent_model.respond_to?(:all_tags) ? parent_model.all_tags : []
24
15
  end
25
16
 
26
- # Returns all of the tags which are applicable to the element.
17
+ # Returns models for all of the tags which are applicable to the element.
27
18
  def all_tags
28
19
  applied_tags + @tags
29
20
  end
30
21
 
31
- # Returns all of the tag elements which are applicable to the element.
32
- def all_tag_elements
33
- applied_tag_elements + @tag_elements
34
- end
35
-
36
22
 
37
23
  private
38
24
 
39
25
 
40
- def populate_element_tags(parsed_element)
41
- if parsed_element['tags']
42
- parsed_element['tags'].each do |tag|
43
- @tags << tag['name']
44
- @tag_elements << build_child_element(Tag, tag)
45
- end
46
- end
47
- end
48
-
49
26
  def tag_output_string
50
- tag_elements.collect { |tag| tag.name }.join(' ')
27
+ tags.collect { |tag| tag.name }.join(' ')
51
28
  end
52
29
 
53
30
  end