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
@@ -1,16 +1,24 @@
1
1
  module CukeModeler
2
- class Gherkin4Adapter
3
2
 
3
+ # An adapter that can convert the output of version 4.x of the *gherkin* gem into input that is consumable by this gem.
4
+
5
+ class Gherkin4Adapter
4
6
 
7
+ # Adapts the given AST into the shape that this gem expects
5
8
  def adapt(parsed_ast)
6
9
  adapt_feature!(parsed_ast[:feature]) if parsed_ast[:feature]
7
10
 
8
11
  [parsed_ast[:feature]].compact
9
12
  end
10
13
 
14
+ # Adapts the AST sub-tree that is rooted at the given feature node.
11
15
  def adapt_feature!(parsed_feature)
12
16
  # Saving off the original data
13
- parsed_feature['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_feature))
17
+ parsed_feature['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_feature))
18
+
19
+ # Removing parsed data for child elements in order to avoid duplicating data
20
+ parsed_feature['cuke_modeler_parsing_data'][:tags] = nil
21
+ parsed_feature['cuke_modeler_parsing_data'][:children] = nil
14
22
 
15
23
  parsed_feature['name'] = parsed_feature.delete(:name)
16
24
  parsed_feature['description'] = parsed_feature.delete(:description) || ''
@@ -27,21 +35,13 @@ module CukeModeler
27
35
  parsed_feature['tags'].concat(parsed_feature.delete(:tags))
28
36
  end
29
37
 
30
- def adapt_child_elements!(parsed_children)
31
- return if parsed_children.empty?
32
-
33
- if parsed_children.first[:type] == :Background
34
- adapt_background!(parsed_children.first)
35
-
36
- remaining_children = parsed_children[1..-1]
37
- end
38
-
39
- adapt_tests!(remaining_children || parsed_children)
40
- end
41
-
38
+ # Adapts the AST sub-tree that is rooted at the given background node.
42
39
  def adapt_background!(parsed_background)
43
40
  # Saving off the original data
44
- parsed_background['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_background))
41
+ parsed_background['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_background))
42
+
43
+ # Removing parsed data for child elements in order to avoid duplicating data
44
+ parsed_background['cuke_modeler_parsing_data'][:steps] = nil
45
45
 
46
46
  parsed_background['keyword'] = parsed_background.delete(:type).to_s
47
47
  parsed_background['name'] = parsed_background.delete(:name)
@@ -55,32 +55,12 @@ module CukeModeler
55
55
  parsed_background['steps'].concat(parsed_background.delete(:steps))
56
56
  end
57
57
 
58
- def adapt_tests!(parsed_tests)
59
- return unless parsed_tests
60
-
61
- parsed_tests.each do |test|
62
- adapt_test!(test)
63
- end
64
- end
65
-
66
- def adapt_test!(parsed_test)
67
- # Saving off the original data
68
- parsed_test['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_test))
69
-
70
- parsed_test['keyword'] = parsed_test.delete(:type).to_s
71
-
72
- case parsed_test['keyword']
73
- when 'Scenario'
74
- adapt_scenario!(parsed_test)
75
- when 'ScenarioOutline'
76
- parsed_test['keyword'] = 'Scenario Outline'
77
- adapt_outline!(parsed_test)
78
- else
79
- raise(ArgumentError, "Unknown test type: #{parsed_test['keyword']}")
80
- end
81
- end
82
-
58
+ # Adapts the AST sub-tree that is rooted at the given scenario node.
83
59
  def adapt_scenario!(parsed_test)
60
+ # Removing parsed data for child elements in order to avoid duplicating data
61
+ parsed_test['cuke_modeler_parsing_data'][:tags] = nil
62
+ parsed_test['cuke_modeler_parsing_data'][:steps] = nil
63
+
84
64
  parsed_test['name'] = parsed_test.delete(:name)
85
65
  parsed_test['description'] = parsed_test.delete(:description) || ''
86
66
  parsed_test['line'] = parsed_test.delete(:location)[:line]
@@ -98,7 +78,13 @@ module CukeModeler
98
78
  parsed_test['steps'].concat(parsed_test.delete(:steps))
99
79
  end
100
80
 
81
+ # Adapts the AST sub-tree that is rooted at the given outline node.
101
82
  def adapt_outline!(parsed_test)
83
+ # Removing parsed data for child elements in order to avoid duplicating data
84
+ parsed_test['cuke_modeler_parsing_data'][:tags] = nil
85
+ parsed_test['cuke_modeler_parsing_data'][:steps] = nil
86
+ parsed_test['cuke_modeler_parsing_data'][:examples] = nil
87
+
102
88
  parsed_test['name'] = parsed_test.delete(:name)
103
89
  parsed_test['description'] = parsed_test.delete(:description) || ''
104
90
  parsed_test['line'] = parsed_test.delete(:location)[:line]
@@ -122,9 +108,15 @@ module CukeModeler
122
108
  parsed_test['examples'].concat(parsed_test.delete(:examples))
123
109
  end
124
110
 
111
+ # Adapts the AST sub-tree that is rooted at the given example node.
125
112
  def adapt_example!(parsed_example)
126
113
  # Saving off the original data
127
- parsed_example['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_example))
114
+ parsed_example['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_example))
115
+
116
+ # Removing parsed data for child elements in order to avoid duplicating data
117
+ parsed_example['cuke_modeler_parsing_data'][:tags] = nil
118
+ parsed_example['cuke_modeler_parsing_data'][:tableHeader] = nil
119
+ parsed_example['cuke_modeler_parsing_data'][:tableBody] = nil
128
120
 
129
121
  parsed_example['name'] = parsed_example.delete(:name)
130
122
  parsed_example['line'] = parsed_example.delete(:location)[:line]
@@ -133,7 +125,8 @@ module CukeModeler
133
125
  parsed_example['rows'] = []
134
126
 
135
127
  if parsed_example[:tableHeader]
136
- parsed_example['rows'] << adapt_table_row!(parsed_example.delete(:tableHeader))
128
+ adapt_table_row!(parsed_example[:tableHeader])
129
+ parsed_example['rows'] << parsed_example.delete(:tableHeader)
137
130
  end
138
131
 
139
132
  if parsed_example[:tableBody]
@@ -152,17 +145,22 @@ module CukeModeler
152
145
  parsed_example['tags'].concat(parsed_example.delete(:tags))
153
146
  end
154
147
 
148
+ # Adapts the AST sub-tree that is rooted at the given tag node.
155
149
  def adapt_tag!(parsed_tag)
156
150
  # Saving off the original data
157
- parsed_tag['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_tag))
151
+ parsed_tag['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_tag))
158
152
 
159
153
  parsed_tag['name'] = parsed_tag.delete(:name)
160
154
  parsed_tag['line'] = parsed_tag.delete(:location)[:line]
161
155
  end
162
156
 
157
+ # Adapts the AST sub-tree that is rooted at the given step node.
163
158
  def adapt_step!(parsed_step)
164
159
  # Saving off the original data
165
- parsed_step['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_step))
160
+ parsed_step['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_step))
161
+
162
+ # Removing parsed data for child elements in order to avoid duplicating data
163
+ parsed_step['cuke_modeler_parsing_data'][:argument] = nil
166
164
 
167
165
  parsed_step['keyword'] = parsed_step.delete(:keyword)
168
166
  parsed_step['name'] = parsed_step.delete(:text)
@@ -178,42 +176,105 @@ module CukeModeler
178
176
  parsed_step['doc_string'] = parsed_step.delete(:argument)
179
177
  when :DataTable
180
178
  adapt_step_table!(step_argument)
181
- parsed_step['rows'] = parsed_step.delete(:argument)
179
+ parsed_step['table'] = parsed_step.delete(:argument)
182
180
  else
183
181
  raise(ArgumentError, "Unknown step argument type: #{step_argument[:type]}")
184
182
  end
185
183
  end
186
184
  end
187
185
 
186
+ # Adapts the AST sub-tree that is rooted at the given doc string node.
188
187
  def adapt_doc_string!(parsed_doc_string)
189
188
  # Saving off the original data
190
- parsed_doc_string['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_doc_string))
189
+ parsed_doc_string['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_doc_string))
191
190
 
192
191
  parsed_doc_string['value'] = parsed_doc_string.delete(:content)
193
192
  parsed_doc_string['content_type'] = parsed_doc_string.delete(:contentType)
193
+ parsed_doc_string['line'] = parsed_doc_string.delete(:location)[:line]
194
194
  end
195
195
 
196
+ # Adapts the AST sub-tree that is rooted at the given table node.
196
197
  def adapt_step_table!(parsed_step_table)
197
198
  # Saving off the original data
198
- parsed_step_table['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_step_table))
199
+ parsed_step_table['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_step_table))
200
+
201
+ # Removing parsed data for child elements in order to avoid duplicating data
202
+ parsed_step_table['cuke_modeler_parsing_data'][:rows] = nil
199
203
 
200
204
  parsed_step_table['rows'] = []
201
205
  parsed_step_table[:rows].each do |row|
202
206
  adapt_table_row!(row)
203
207
  end
204
208
  parsed_step_table['rows'].concat(parsed_step_table.delete(:rows))
209
+ parsed_step_table['line'] = parsed_step_table.delete(:location)[:line]
205
210
  end
206
211
 
212
+ # Adapts the AST sub-tree that is rooted at the given row node.
207
213
  def adapt_table_row!(parsed_table_row)
208
214
  # Saving off the original data
209
- parsed_table_row['cuke_modeler_raw_adapter_output'] = Marshal::load(Marshal.dump(parsed_table_row))
215
+ parsed_table_row['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_table_row))
216
+
217
+ # Removing parsed data for child elements in order to avoid duplicating data which the child elements will themselves include
218
+ parsed_table_row['cuke_modeler_parsing_data'][:cells] = nil
219
+
210
220
 
211
221
  parsed_table_row['line'] = parsed_table_row.delete(:location)[:line]
212
222
 
213
- parsed_table_row['cells'] = parsed_table_row.delete(:cells).collect { |cell| cell[:value] }
223
+ parsed_table_row['cells'] = []
224
+ parsed_table_row[:cells].each do |row|
225
+ adapt_table_cell!(row)
226
+ end
227
+ parsed_table_row['cells'].concat(parsed_table_row.delete(:cells))
228
+ end
229
+
230
+ # Adapts the AST sub-tree that is rooted at the given cell node.
231
+ def adapt_table_cell!(parsed_cell)
232
+ # Saving off the original data
233
+ parsed_cell['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_cell))
234
+
235
+ parsed_cell['value'] = parsed_cell.delete(:value)
236
+ parsed_cell['line'] = parsed_cell.delete(:location)[:line]
237
+ end
238
+
239
+
240
+ private
241
+
214
242
 
243
+ def adapt_child_elements!(parsed_children)
244
+ return if parsed_children.empty?
245
+
246
+ if parsed_children.first[:type] == :Background
247
+ adapt_background!(parsed_children.first)
248
+
249
+ remaining_children = parsed_children[1..-1]
250
+ end
251
+
252
+ adapt_tests!(remaining_children || parsed_children)
253
+ end
215
254
 
216
- parsed_table_row
255
+ def adapt_tests!(parsed_tests)
256
+ return unless parsed_tests
257
+
258
+ parsed_tests.each do |test|
259
+ adapt_test!(test)
260
+ end
261
+ end
262
+
263
+ def adapt_test!(parsed_test)
264
+ # Saving off the original data
265
+ parsed_test['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_test))
266
+
267
+ parsed_test['keyword'] = parsed_test.delete(:type).to_s
268
+
269
+ case parsed_test['keyword']
270
+ when 'Scenario'
271
+ adapt_scenario!(parsed_test)
272
+ when 'ScenarioOutline'
273
+ parsed_test['keyword'] = 'Scenario Outline'
274
+ adapt_outline!(parsed_test)
275
+ else
276
+ raise(ArgumentError, "Unknown test type: #{parsed_test['keyword']}")
277
+ end
217
278
  end
218
279
 
219
280
  end
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # A mix-in module containing methods used by models that contain other models.
3
4
 
4
5
  module Containing
5
6
 
@@ -7,11 +8,261 @@ module CukeModeler
7
8
  private
8
9
 
9
10
 
10
- def build_child_element(clazz, element_data)
11
- element = clazz.new(element_data)
12
- element.parent_element = self
11
+ def build_child_model(clazz, model_data)
12
+ model = clazz.new
13
13
 
14
- element
14
+ tiny_class = clazz.name.match(/::(\w+)/)[1].downcase
15
+ model.send("populate_#{tiny_class}", model, model_data)
16
+
17
+ model.parent_model = self
18
+
19
+
20
+ model
21
+ end
22
+
23
+ def populate_scenario(scenario_object, parsed_scenario_data)
24
+ populate_parsing_data(scenario_object, parsed_scenario_data)
25
+ populate_source_line(scenario_object, parsed_scenario_data)
26
+ populate_name(scenario_object, parsed_scenario_data)
27
+ populate_description(scenario_object, parsed_scenario_data)
28
+ populate_steps(scenario_object, parsed_scenario_data)
29
+ populate_tags(scenario_object, parsed_scenario_data)
30
+ end
31
+
32
+ def populate_outline(outline_object, parsed_outline_data)
33
+ populate_parsing_data(outline_object, parsed_outline_data)
34
+ populate_source_line(outline_object, parsed_outline_data)
35
+ populate_name(outline_object, parsed_outline_data)
36
+ populate_description(outline_object, parsed_outline_data)
37
+ populate_steps(outline_object, parsed_outline_data)
38
+ populate_tags(outline_object, parsed_outline_data)
39
+ populate_outline_examples(outline_object, parsed_outline_data['examples']) if parsed_outline_data['examples']
40
+ end
41
+
42
+ def populate_background(background_object, parsed_background_data)
43
+ populate_parsing_data(background_object, parsed_background_data)
44
+ populate_name(background_object, parsed_background_data)
45
+ populate_description(background_object, parsed_background_data)
46
+ populate_source_line(background_object, parsed_background_data)
47
+ populate_steps(background_object, parsed_background_data)
48
+ end
49
+
50
+ def populate_step(step_object, parsed_step_data)
51
+ populate_text(step_object, parsed_step_data)
52
+ populate_block(step_object, parsed_step_data)
53
+ populate_keyword(step_object, parsed_step_data)
54
+ populate_source_line(step_object, parsed_step_data)
55
+ populate_parsing_data(step_object, parsed_step_data)
56
+ end
57
+
58
+ def populate_block(step_object, parsed_step_data)
59
+ case
60
+ when parsed_step_data['table']
61
+ step_object.block = build_child_model(Table, parsed_step_data['table'])
62
+ when parsed_step_data['doc_string']
63
+ step_object.block = build_child_model(DocString, parsed_step_data['doc_string'])
64
+ else
65
+ step_object.block = nil
66
+ end
67
+ end
68
+
69
+ def populate_table(table_object, parsed_table_data)
70
+ populate_row_models(table_object, parsed_table_data)
71
+ populate_parsing_data(table_object, parsed_table_data)
72
+ populate_source_line(table_object, parsed_table_data)
73
+ end
74
+
75
+ def populate_tablerow(row_object, parsed_row_data)
76
+ populate_source_line(row_object, parsed_row_data)
77
+ populate_row_cells(row_object, parsed_row_data)
78
+ populate_parsing_data(row_object, parsed_row_data)
79
+ end
80
+
81
+ def populate_cell(cell_object, parsed_cell_data)
82
+ populate_cell_value(cell_object, parsed_cell_data)
83
+ populate_source_line(cell_object, parsed_cell_data)
84
+ populate_parsing_data(cell_object, parsed_cell_data)
85
+ end
86
+
87
+ def populate_docstring(doc_string_object, parsed_doc_string_data)
88
+ populate_content_type(doc_string_object, parsed_doc_string_data)
89
+ populate_content(doc_string_object, parsed_doc_string_data)
90
+ populate_parsing_data(doc_string_object, parsed_doc_string_data)
91
+ populate_source_line(doc_string_object, parsed_doc_string_data)
92
+ end
93
+
94
+ def populate_example(example_object, parsed_example_data)
95
+ populate_parsing_data(example_object, parsed_example_data)
96
+ populate_source_line(example_object, parsed_example_data)
97
+ populate_name(example_object, parsed_example_data)
98
+ populate_description(example_object, parsed_example_data)
99
+ populate_tags(example_object, parsed_example_data)
100
+ populate_example_rows(example_object, parsed_example_data)
101
+ end
102
+
103
+ def populate_row(row_object, parsed_row_data)
104
+ populate_source_line(row_object, parsed_row_data)
105
+ populate_row_cells(row_object, parsed_row_data)
106
+ populate_parsing_data(row_object, parsed_row_data)
107
+ end
108
+
109
+ def populate_feature(feature_object, parsed_feature_data)
110
+ populate_parsing_data(feature_object, parsed_feature_data)
111
+ populate_source_line(feature_object, parsed_feature_data)
112
+ populate_name(feature_object, parsed_feature_data)
113
+ populate_description(feature_object, parsed_feature_data)
114
+ populate_tags(feature_object, parsed_feature_data)
115
+ populate_children(feature_object, parsed_feature_data)
116
+ end
117
+
118
+ def populate_directory(directory_object, processed_directory_data)
119
+ directory_object.path = processed_directory_data['path']
120
+
121
+ processed_directory_data['directories'].each do |directory_data|
122
+ directory_object.directories << build_child_model(Directory, directory_data)
123
+ end
124
+
125
+ processed_directory_data['feature_files'].each do |feature_file_data|
126
+ directory_object.feature_files << build_child_model(FeatureFile, feature_file_data)
127
+ end
128
+ end
129
+
130
+ def populate_featurefile(feature_file_object, processed_feature_file_data)
131
+ feature_file_object.path = processed_feature_file_data['path']
132
+
133
+ feature_file_object.feature = build_child_model(Feature, processed_feature_file_data['feature']) unless processed_feature_file_data['feature'].nil?
134
+ end
135
+
136
+ def populate_tag(tag_object, processed_tag_data)
137
+ populate_name(tag_object, processed_tag_data)
138
+ populate_parsing_data(tag_object, processed_tag_data)
139
+ populate_source_line(tag_object, processed_tag_data)
140
+ end
141
+
142
+ def populate_text(step_model, parsed_step_data)
143
+ step_model.text = parsed_step_data['name']
144
+ end
145
+
146
+ def populate_keyword(step_model, parsed_step_data)
147
+ step_model.keyword = parsed_step_data['keyword'].strip
148
+ end
149
+
150
+ def populate_row_models(table_model, parsed_table_data)
151
+ parsed_table_data['rows'].each do |row_data|
152
+ table_model.rows << build_child_model(Row, row_data)
153
+ end
154
+ end
155
+
156
+ def populate_row_cells(row_model, parsed_row_data)
157
+ parsed_row_data['cells'].each do |cell_data|
158
+ row_model.cells << build_child_model(Cell, cell_data)
159
+ end
160
+ end
161
+
162
+ def populate_cell_value(cell_model, parsed_cell_data)
163
+ cell_model.value = parsed_cell_data['value']
164
+ end
165
+
166
+ def populate_content_type(doc_string_model, parsed_doc_string_data)
167
+ doc_string_model.content_type = parsed_doc_string_data['content_type'] == "" ? nil : parsed_doc_string_data['content_type']
168
+ end
169
+
170
+ def populate_content(doc_string_model, parsed_doc_string_data)
171
+ doc_string_model.content = parsed_doc_string_data['value']
172
+ end
173
+
174
+ def populate_outline_examples(outline_model, parsed_examples)
175
+ parsed_examples.each do |example_data|
176
+ outline_model.examples << build_child_model(Example, example_data)
177
+ end
178
+ end
179
+
180
+ def populate_example_rows(example_model, parsed_example_data)
181
+ parsed_example_data['rows'].each do |row_data|
182
+ example_model.rows << build_child_model(Row, row_data)
183
+ end
184
+ end
185
+
186
+ def populate_children(feature_model, parsed_feature_data)
187
+ elements = parsed_feature_data['elements']
188
+
189
+ if elements
190
+ elements.each do |element|
191
+ case element['keyword']
192
+ when 'Scenario'
193
+ feature_model.tests << build_child_model(Scenario, element)
194
+ when 'Scenario Outline'
195
+ feature_model.tests << build_child_model(Outline, element)
196
+ when 'Background'
197
+ feature_model.background = build_child_model(Background, element)
198
+ else
199
+ raise(ArgumentError, "Unknown keyword: #{element['keyword']}")
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def populate_parsing_data(model, parsed_model_data)
206
+ model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
207
+ end
208
+
209
+ def populate_source_line(model, parsed_model_data)
210
+ model.source_line = parsed_model_data['line']
211
+ end
212
+
213
+ def populate_name(model, parsed_model_data)
214
+ model.name = parsed_model_data['name']
215
+ end
216
+
217
+ def populate_description(model, parsed_model_data)
218
+ model.description = trimmed_description(parsed_model_data['description'])
219
+ end
220
+
221
+ def trimmed_description(description)
222
+ description = description.split("\n")
223
+
224
+ trim_leading_blank_lines(description)
225
+ trim_trailing_blank_lines(description)
226
+ trim_leading_spaces(description)
227
+ trim_trailing_spaces(description)
228
+
229
+ description.join("\n")
230
+ end
231
+
232
+ def trim_leading_blank_lines(description)
233
+ description.replace(description.drop_while { |line| line !~ /\S/ })
234
+ end
235
+
236
+ def trim_trailing_blank_lines(description)
237
+ # Nothing to do. Already done by the parser but leaving this here in case that changes in future versions.
238
+ end
239
+
240
+ def trim_leading_spaces(description)
241
+ non_blank_lines = description.select { |line| line =~ /\S/ }
242
+
243
+ fewest_spaces = non_blank_lines.collect { |line| line[/^\s*/].length }.min || 0
244
+
245
+ description.each { |line| line.slice!(0..(fewest_spaces - 1)) } if fewest_spaces > 0
246
+ end
247
+
248
+ def trim_trailing_spaces(description)
249
+ description.map! { |line| line.rstrip }
250
+ end
251
+
252
+ def populate_tags(model, parsed_model_data)
253
+ if parsed_model_data['tags']
254
+ parsed_model_data['tags'].each do |tag|
255
+ model.tags << build_child_model(Tag, tag)
256
+ end
257
+ end
258
+ end
259
+
260
+ def populate_steps(model, parsed_model_data)
261
+ if parsed_model_data['steps']
262
+ parsed_model_data['steps'].each do |step_data|
263
+ model.steps << build_child_model(Step, step_data)
264
+ end
265
+ end
15
266
  end
16
267
 
17
268
  end