cuke_modeler 0.4.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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