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,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