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,15 +1,193 @@
1
1
  require 'spec_helper'
2
2
 
3
- SimpleCov.command_name('Example') unless RUBY_VERSION.to_s < '1.9.0'
4
3
 
5
4
  describe 'Example, Integration' do
6
5
 
7
6
  let(:clazz) { CukeModeler::Example }
7
+ let(:example) { clazz.new }
8
8
 
9
9
 
10
+ describe 'common behavior' do
11
+
12
+ it_should_behave_like 'a model, integration'
13
+
14
+ end
15
+
10
16
  describe 'unique behavior' do
11
17
 
12
- it 'properly sets its child elements' do
18
+ it 'can be instantiated with the minimum viable Gherkin', :gherkin4 => true do
19
+ source = ['Examples:']
20
+ source = source.join("\n")
21
+
22
+ expect { @model = clazz.new(source) }.to_not raise_error
23
+ end
24
+
25
+ it 'can be instantiated with the minimum viable Gherkin', :gherkin3 => true do
26
+ source = ['Examples:',
27
+ '|param|',
28
+ '|value|']
29
+ source = source.join("\n")
30
+
31
+ expect { @model = clazz.new(source) }.to_not raise_error
32
+ end
33
+
34
+ it 'can be instantiated with the minimum viable Gherkin', :gherkin2 => true do
35
+ source = ['Examples:',
36
+ '|param|']
37
+ source = source.join("\n")
38
+
39
+ expect { @model = clazz.new(source) }.to_not raise_error
40
+ end
41
+
42
+ it 'stores the original data generated by the parsing adapter', :gherkin4 => true do
43
+ example = clazz.new("@tag\nExamples: test example\ndescription\n|param|\n|value|")
44
+ data = example.parsing_data
45
+
46
+ expect(data.keys).to match_array([:type, :tags, :location, :keyword, :name, :tableHeader, :tableBody, :description])
47
+ expect(data[:type]).to eq(:Examples)
48
+ end
49
+
50
+ it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
51
+ example = clazz.new("@tag\nExamples: test example\ndescription\n|param|\n|value|")
52
+ data = example.parsing_data
53
+
54
+ expect(data.keys).to match_array([:type, :tags, :location, :keyword, :name, :tableHeader, :tableBody, :description])
55
+ expect(data[:type]).to eq(:Examples)
56
+ end
57
+
58
+ it 'stores the original data generated by the parsing adapter', :gherkin2 => true do
59
+ example = clazz.new("@tag\nExamples: test example\ndescription\n|param|\n|value|")
60
+ data = example.parsing_data
61
+
62
+ expect(data.keys).to match_array(['keyword', 'name', 'line', 'description', 'id', 'rows', 'tags'])
63
+ expect(data['keyword']).to eq('Examples')
64
+ end
65
+
66
+ it 'provides a descriptive filename when being parsed from stand alone text' do
67
+ source = 'bad example text'
68
+
69
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_example\.feature'/)
70
+ end
71
+
72
+ it 'trims whitespace from its source description' do
73
+ source = ['Examples:',
74
+ ' ',
75
+ ' description line 1',
76
+ '',
77
+ ' description line 2',
78
+ ' description line 3 ',
79
+ '',
80
+ '',
81
+ '',
82
+ '|param|',
83
+ '|value|']
84
+ source = source.join("\n")
85
+
86
+ example = clazz.new(source)
87
+ description = example.description.split("\n")
88
+
89
+ expect(description).to eq([' description line 1',
90
+ '',
91
+ 'description line 2',
92
+ ' description line 3'])
93
+ end
94
+
95
+
96
+ describe 'model population' do
97
+
98
+ context 'from source text' do
99
+
100
+ it "models the example's source line" do
101
+ source_text = "Feature:
102
+
103
+ Scenario Outline:
104
+ * step
105
+ Examples:
106
+ | param |
107
+ | value |"
108
+ example = CukeModeler::Feature.new(source_text).tests.first.examples.first
109
+
110
+ expect(example.source_line).to eq(5)
111
+ end
112
+
113
+
114
+ context 'a filled example' do
115
+
116
+ let(:source_text) { "@tag1 @tag2 @tag3
117
+ Examples: test example
118
+
119
+ Some example description.
120
+
121
+ Some more.
122
+ Even more.
123
+
124
+ | param |
125
+ | value |" }
126
+ let(:example) { clazz.new(source_text) }
127
+
128
+
129
+ it "models the example's name" do
130
+ expect(example.name).to eq('test example')
131
+ end
132
+
133
+ it "models the example's description" do
134
+ description = example.description.split("\n")
135
+
136
+ expect(description).to eq([' Some example description.',
137
+ '',
138
+ 'Some more.',
139
+ ' Even more.'])
140
+ end
141
+
142
+ it "models the example's rows" do
143
+ row_cell_values = example.rows.collect { |row| row.cells.collect { |cell| cell.value } }
144
+
145
+ expect(row_cell_values).to eq([['param'], ['value']])
146
+ end
147
+
148
+ it "models the example's tags" do
149
+ tag_names = example.tags.collect { |tag| tag.name }
150
+
151
+ expect(tag_names).to eq(['@tag1', '@tag2', '@tag3'])
152
+ end
153
+
154
+ it "models the example's parameters" do
155
+ expect(example.parameters).to eq(['param'])
156
+ end
157
+
158
+ end
159
+
160
+ # gherkin 2.x/3.x does not accept incomplete examples
161
+ context 'an empty example', :gherkin2 => false, :gherkin3 => false do
162
+
163
+ let(:source_text) { 'Examples:' }
164
+ let(:example) { clazz.new(source_text) }
165
+
166
+
167
+ it "models the example's name" do
168
+ expect(example.name).to eq('')
169
+ end
170
+
171
+ it "models the example's description" do
172
+ expect(example.description).to eq('')
173
+ end
174
+
175
+ it "models the example's rows" do
176
+ expect(example.rows).to eq([])
177
+ end
178
+
179
+ it "models the example's tags" do
180
+ expect(example.tags).to eq([])
181
+ end
182
+
183
+ end
184
+
185
+ end
186
+
187
+ end
188
+
189
+
190
+ it 'properly sets its child models' do
13
191
  source = ['@a_tag',
14
192
  'Examples:',
15
193
  ' | param |',
@@ -17,14 +195,224 @@ describe 'Example, Integration' do
17
195
  source = source.join("\n")
18
196
 
19
197
  example = clazz.new(source)
20
- rows = example.row_elements
21
- tag = example.tag_elements.first
198
+ rows = example.rows
199
+ tag = example.tags.first
200
+
201
+ expect(rows[0].parent_model).to equal(example)
202
+ expect(rows[1].parent_model).to equal(example)
203
+ expect(tag.parent_model).to equal(example)
204
+ end
205
+
206
+ it 'does not include the parameter row when accessing argument rows' do
207
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|"
208
+ example = clazz.new(source)
209
+
210
+ rows = example.argument_rows
211
+ row_cell_values = rows.collect { |row| row.cells.collect { |cell| cell.value } }
212
+
213
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', 'value4']])
214
+ end
215
+
216
+ it 'does not include argument rows when accessing the parameter row' do
217
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|"
218
+ example = clazz.new(source)
219
+
220
+ row = example.parameter_row
221
+ row_cell_values = row.cells.collect { |cell| cell.value }
222
+
223
+ expect(row_cell_values).to eq(['param1', 'param2'])
224
+ end
225
+
226
+
227
+ describe 'adding rows' do
228
+
229
+ it 'can add a new row as a hash, string values' do
230
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
231
+ example = clazz.new(source)
232
+
233
+ new_row = {'param1' => 'value3', 'param2' => 'value4'}
234
+ example.add_row(new_row)
235
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
236
+
237
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', 'value4']])
238
+ end
239
+
240
+ it 'can add a new row as a hash, non-string values' do
241
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
242
+ example = clazz.new(source)
243
+
244
+ new_row = {:param1 => 'value3', 'param2' => 4}
245
+ example.add_row(new_row)
246
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
247
+
248
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', '4']])
249
+ end
250
+
251
+ it 'can add a new row as a hash, random key order' do
252
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
253
+ example = clazz.new(source)
254
+
255
+ new_row = {'param2' => 'value4', 'param1' => 'value3'}
256
+ example.add_row(new_row)
257
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
258
+
259
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', 'value4']])
260
+ end
261
+
262
+ it 'can add a new row as an array, string values' do
263
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
264
+ example = clazz.new(source)
265
+
266
+ new_row = ['value3', 'value4']
267
+ example.add_row(new_row)
268
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
269
+
270
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', 'value4']])
271
+ end
272
+
273
+ it 'can add a new row as an array, non-string values' do
274
+ source = "Examples:\n|param1|param2|param3|\n|value1|value2|value3|"
275
+ example = clazz.new(source)
276
+
277
+ new_row = [:value4, 5, 'value6']
278
+ example.add_row(new_row)
279
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
280
+
281
+ expect(row_cell_values).to eq([['value1', 'value2', 'value3'], ['value4', '5', 'value6']])
282
+ end
283
+
284
+ it 'can only use a Hash or an Array to add a new row' do
285
+ source = "Examples:\n|param|\n|value|"
286
+ example = clazz.new(source)
287
+
288
+ expect { example.add_row({}) }.to_not raise_error
289
+ expect { example.add_row([]) }.to_not raise_error
290
+ expect { example.add_row(:a_row) }.to raise_error(ArgumentError)
291
+ end
292
+
293
+ it 'trims whitespace from added rows' do
294
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
295
+ example = clazz.new(source)
296
+
297
+ hash_row = {'param1' => 'value3 ', 'param2' => ' value4'}
298
+ array_row = ['value5', ' value6 ']
299
+ example.add_row(hash_row)
300
+ example.add_row(array_row)
301
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
302
+
303
+ expect(row_cell_values).to eq([['value1', 'value2'], ['value3', 'value4'], ['value5', 'value6']])
304
+ end
305
+
306
+ it 'will complain if a row is added and no parameters have been set' do
307
+ example = clazz.new
308
+ example.rows = []
309
+
310
+ new_row = ['value1', 'value2']
311
+ expect { example.add_row(new_row) }.to raise_error('Cannot add a row. No parameters have been set.')
312
+
313
+ new_row = {'param1' => 'value1', 'param2' => 'value2'}
314
+ expect { example.add_row(new_row) }.to raise_error('Cannot add a row. No parameters have been set.')
315
+ end
316
+
317
+ it 'does not modify its row input' do
318
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
319
+ example = clazz.new(source)
320
+
321
+ array_row = ['value1'.freeze, 'value2'.freeze].freeze
322
+ expect { example.add_row(array_row) }.to_not raise_error
323
+
324
+ hash_row = {'param1'.freeze => 'value1'.freeze, 'param2'.freeze => 'value2'.freeze}.freeze
325
+ expect { example.add_row(hash_row) }.to_not raise_error
326
+ end
22
327
 
23
- expect(rows[0].parent_element).to equal(example)
24
- expect(rows[1].parent_element).to equal(example)
25
- expect(tag.parent_element).to equal(example)
26
328
  end
27
329
 
330
+
331
+ describe 'removing rows' do
332
+
333
+ it 'can remove an existing row as a hash' do
334
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|"
335
+ example = clazz.new(source)
336
+
337
+ old_row = {'param1' => 'value3', 'param2' => 'value4'}
338
+ example.remove_row(old_row)
339
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
340
+
341
+ expect(row_cell_values).to eq([['value1', 'value2']])
342
+ end
343
+
344
+ it 'can remove an existing row as a hash, random key order' do
345
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|"
346
+ example = clazz.new(source)
347
+
348
+ old_row = {'param2' => 'value4', 'param1' => 'value3'}
349
+ example.remove_row(old_row)
350
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
351
+
352
+ expect(row_cell_values).to eq([['value1', 'value2']])
353
+ end
354
+
355
+ it 'can remove an existing row as an array' do
356
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|"
357
+ example = clazz.new(source)
358
+
359
+ old_row = ['value3', 'value4']
360
+ example.remove_row(old_row)
361
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
362
+
363
+ expect(row_cell_values).to eq([['value1', 'value2']])
364
+ end
365
+
366
+ it 'can only use a Hash or an Array to remove an existing row' do
367
+ expect { example.remove_row({}) }.to_not raise_error
368
+ expect { example.remove_row([]) }.to_not raise_error
369
+ expect { example.remove_row(:a_row) }.to raise_error(ArgumentError)
370
+ end
371
+
372
+ it 'trims whitespace from removed rows' do
373
+ source = "Examples:\n|param1|param2|\n|value1|value2|\n|value3|value4|\n|value5|value6|"
374
+ example = clazz.new(source)
375
+
376
+ # These will affect different rows
377
+ hash_row = {'param1' => 'value3 ', 'param2' => ' value4'}
378
+ array_row = ['value5', ' value6 ']
379
+
380
+ example.remove_row(hash_row)
381
+ example.remove_row(array_row)
382
+ row_cell_values = example.argument_rows.collect { |row| row.cells.collect { |cell| cell.value } }
383
+
384
+ expect(row_cell_values).to eq([['value1', 'value2']])
385
+ end
386
+
387
+ it 'can gracefully remove a row from an example that has no rows' do
388
+ example = clazz.new
389
+ example.rows = []
390
+
391
+ expect { example.remove_row({}) }.to_not raise_error
392
+ expect { example.remove_row([]) }.to_not raise_error
393
+ end
394
+
395
+ it 'will not remove the parameter row' do
396
+ source = "Examples:\n|param1|param2|\n|value1|value2|"
397
+ example = clazz.new(source)
398
+
399
+ hash_row = {'param1' => 'param1 ', 'param2' => ' param2'}
400
+ array_row = ['param1', ' param2 ']
401
+
402
+ example.remove_row(hash_row)
403
+ row_cell_values = example.rows.collect { |row| row.cells.collect { |cell| cell.value } }
404
+
405
+ expect(row_cell_values).to eq([['param1', 'param2'], ['value1', 'value2']])
406
+
407
+ example.remove_row(array_row)
408
+ row_cell_values = example.rows.collect { |row| row.cells.collect { |cell| cell.value } }
409
+
410
+ expect(row_cell_values).to eq([['param1', 'param2'], ['value1', 'value2']])
411
+ end
412
+
413
+ end
414
+
415
+
28
416
  describe 'getting ancestors' do
29
417
 
30
418
  before(:each) do
@@ -42,7 +430,7 @@ describe 'Example, Integration' do
42
430
  end
43
431
 
44
432
  let(:directory) { CukeModeler::Directory.new(@default_file_directory) }
45
- let(:example) { directory.feature_files.first.features.first.tests.first.examples.first }
433
+ let(:example) { directory.feature_files.first.feature.tests.first.examples.first }
46
434
 
47
435
 
48
436
  it 'can get its directory' do
@@ -60,13 +448,34 @@ describe 'Example, Integration' do
60
448
  it 'can get its feature' do
61
449
  ancestor = example.get_ancestor(:feature)
62
450
 
63
- expect(ancestor).to equal(directory.feature_files.first.features.first)
451
+ expect(ancestor).to equal(directory.feature_files.first.feature)
64
452
  end
65
453
 
66
- it 'can get its test' do
67
- ancestor = example.get_ancestor(:test)
454
+ context 'an example that is part of an outline' do
455
+
456
+ before(:each) do
457
+ source = 'Feature: Test feature
458
+
459
+ Scenario Outline: Test outline
460
+ * a step
461
+ Examples:
462
+ | param |
463
+ | value |'
464
+
465
+ file_path = "#{@default_file_directory}/step_test_file.feature"
466
+ File.open(file_path, 'w') { |file| file.write(source) }
467
+ end
468
+
469
+ let(:directory) { CukeModeler::Directory.new(@default_file_directory) }
470
+ let(:example) { directory.feature_files.first.feature.tests.first.examples.first }
471
+
472
+
473
+ it 'can get its outline' do
474
+ ancestor = example.get_ancestor(:outline)
475
+
476
+ expect(ancestor).to equal(directory.feature_files.first.feature.tests.first)
477
+ end
68
478
 
69
- expect(ancestor).to equal(directory.feature_files.first.features.first.tests.first)
70
479
  end
71
480
 
72
481
  it 'returns nil if it does not have the requested type of ancestor' do
@@ -77,22 +486,196 @@ describe 'Example, Integration' do
77
486
 
78
487
  end
79
488
 
80
- describe 'example output edge cases' do
81
489
 
82
- context 'a new example object' do
490
+ describe 'example output' do
491
+
492
+ it 'can be remade from its own output' do
493
+ source = ['@tag1 @tag2 @tag3',
494
+ 'Examples: with everything it could have',
495
+ '',
496
+ 'Some description.',
497
+ 'Some more description.',
498
+ '',
499
+ ' | param1 | param2 |',
500
+ ' | value1 | value2 |',
501
+ ' | value3 | value4 |']
502
+ source = source.join("\n")
503
+ example = clazz.new(source)
504
+
505
+ example_output = example.to_s
506
+ remade_example_output = clazz.new(example_output).to_s
507
+
508
+ expect(remade_example_output).to eq(example_output)
509
+ end
510
+
511
+
512
+ # This behavior should already be taken care of by the cell object's output method, but
513
+ # the example object has to adjust that output in order to properly buffer column width
514
+ # and it is possible that during that process it messes up the cell's output.
515
+
516
+ it 'can correctly output a row that has special characters in it' do
517
+ source = ['Examples:',
518
+ ' | param with \| |',
519
+ ' | a value with \| and \\\\ |',
520
+ ' | a value with \\\\ |']
521
+ source = source.join("\n")
522
+ example = clazz.new(source)
523
+
524
+ example_output = example.to_s.split("\n")
525
+
526
+ expect(example_output).to eq(['Examples:',
527
+ ' | param with \| |',
528
+ ' | a value with \| and \\\\ |',
529
+ ' | a value with \\\\ |'])
530
+ end
531
+
532
+
533
+ context 'from source text' do
534
+
535
+ # gherkin 2.x/3.x does not accept incomplete examples
536
+ it 'can output an empty example', :gherkin2 => false, :gherkin3 => false do
537
+ source = ['Examples:']
538
+ source = source.join("\n")
539
+ example = clazz.new(source)
540
+
541
+ example_output = example.to_s.split("\n")
542
+
543
+ expect(example_output).to eq(['Examples:'])
544
+ end
545
+
546
+ # gherkin 2.x/3.x does not accept incomplete examples
547
+ it 'can output an example that has a name', :gherkin2 => false, :gherkin3 => false do
548
+ source = ['Examples: test example']
549
+ source = source.join("\n")
550
+ example = clazz.new(source)
551
+
552
+ example_output = example.to_s.split("\n")
553
+
554
+ expect(example_output).to eq(['Examples: test example'])
555
+ end
556
+
557
+ # gherkin 2.x/3.x does not accept incomplete examples
558
+ it 'can output an example that has a description', :gherkin2 => false, :gherkin3 => false do
559
+ source = ['Examples:',
560
+ 'Some description.',
561
+ 'Some more description.']
562
+ source = source.join("\n")
563
+ example = clazz.new(source)
564
+
565
+ example_output = example.to_s.split("\n")
566
+
567
+ expect(example_output).to eq(['Examples:',
568
+ '',
569
+ 'Some description.',
570
+ 'Some more description.'])
571
+ end
572
+
573
+
574
+ # gherkin 3.x does not accept incomplete examples
575
+ it 'can output an example that has a single row', :gherkin3 => false do
576
+ source = ['Examples:',
577
+ '|param1|param2|']
578
+ source = source.join("\n")
579
+ example = clazz.new(source)
580
+
581
+ example_output = example.to_s.split("\n")
582
+
583
+ expect(example_output).to eq(['Examples:',
584
+ ' | param1 | param2 |'])
585
+ end
586
+
587
+ it 'can output an example that has multiple rows' do
588
+ source = ['Examples:',
589
+ '|param1|param2|',
590
+ '|value1|value2|',
591
+ '|value3|value4|']
592
+ source = source.join("\n")
593
+ example = clazz.new(source)
594
+
595
+ example_output = example.to_s.split("\n")
596
+
597
+ expect(example_output).to eq(['Examples:',
598
+ ' | param1 | param2 |',
599
+ ' | value1 | value2 |',
600
+ ' | value3 | value4 |'])
601
+ end
602
+
603
+ it 'can output an example that has tags' do
604
+ source = ['@tag1',
605
+ '@tag2 @tag3',
606
+ 'Examples:',
607
+ '|param1|param2|',
608
+ '|value1|value2|',
609
+ '|value3|value4|']
610
+ source = source.join("\n")
611
+ example = clazz.new(source)
612
+
613
+ example_output = example.to_s.split("\n")
614
+
615
+ expect(example_output).to eq(['@tag1 @tag2 @tag3',
616
+ 'Examples:',
617
+ ' | param1 | param2 |',
618
+ ' | value1 | value2 |',
619
+ ' | value3 | value4 |'])
620
+ end
621
+
622
+ it 'can output an example that has everything' do
623
+ source = ['@tag1',
624
+ '@tag2 @tag3',
625
+ 'Examples: with everything it could have',
626
+ 'Some description.',
627
+ 'Some more description.',
628
+ '|param1|param2|',
629
+ '|value1|value2|',
630
+ '|value3|value4|']
631
+ source = source.join("\n")
632
+ example = clazz.new(source)
633
+
634
+ example_output = example.to_s.split("\n")
635
+
636
+ expect(example_output).to eq(['@tag1 @tag2 @tag3',
637
+ 'Examples: with everything it could have',
638
+ '',
639
+ 'Some description.',
640
+ 'Some more description.',
641
+ '',
642
+ ' | param1 | param2 |',
643
+ ' | value1 | value2 |',
644
+ ' | value3 | value4 |'])
645
+ end
646
+
647
+ it 'buffers row cells based on the longest value in a column' do
648
+ source = ['Examples:',
649
+ '|parameter 1| x|',
650
+ '|y|value 1|',
651
+ '|a|b|']
652
+ source = source.join("\n")
653
+ example = clazz.new(source)
654
+
655
+ example_output = example.to_s.split("\n")
656
+
657
+ expect(example_output).to eq(['Examples:',
658
+ ' | parameter 1 | x |',
659
+ ' | y | value 1 |',
660
+ ' | a | b |'])
661
+ end
662
+
663
+ end
664
+
665
+
666
+ context 'from abstract instantiation' do
83
667
 
84
668
  let(:example) { clazz.new }
85
669
 
86
670
 
87
- it 'can output an example that has only tag elements' do
88
- example.tag_elements = [CukeModeler::Tag.new]
671
+ it 'can output an example that has only tags' do
672
+ example.tags = [CukeModeler::Tag.new]
89
673
 
90
674
  expect { example.to_s }.to_not raise_error
91
675
  end
92
676
 
93
- #todo - remove once Hash rows are no longer supported
94
- it 'can output an example that has only row elements' do
95
- example.row_elements = [CukeModeler::Row.new]
677
+ it 'can output an example that has only rows' do
678
+ example.rows = [CukeModeler::Row.new]
96
679
 
97
680
  expect { example.to_s }.to_not raise_error
98
681
  end