macros4cuke 0.3.17 → 0.3.18

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.3.18 / 2013-05-21
2
+ * [FEATURE] Support for sub-steps having multiline text arguments (docstring).
3
+ * [CHANGE] Method MacroStep#expand passes also built-in arguments to template engine.
4
+ * [CHANGE] Method MacroStep#validate_phrase_args does not apply validations on built-in arguments.
5
+ * [CHANGE] File `macro-step_spec.rb`: Added one example to test the insertion of triple quotes.
6
+ * [NEW] File `multiline.feature` added in examples/features/ folder.
7
+ * [CHANGE] File `README.md`: Added section 'Sub-steps with multiline text argument'
8
+
1
9
  ## 0.3.17 / 2013-05-20
2
10
  * [CHANGE] File `README.md`: Added dynamic dependencies badge (Gemnasium).
3
11
 
data/README.md CHANGED
@@ -236,7 +236,7 @@ The next example is based on one of the demo feature files:
236
236
  """
237
237
  ```
238
238
 
239
- This step can be used like this:
239
+ This step can be used like this:
240
240
  ```cucumber
241
241
  When I [enter my address as follows]:"
242
242
  |lastname|Doe|
@@ -272,13 +272,13 @@ Taking again a previous example of a -partial- macro-step definition:
272
272
  """
273
273
  ```
274
274
 
275
- The following step invokation is invalid:
275
+ The following step invokation is invalid:
276
276
  ```cucumber
277
277
  When I [travel from "San Francisco" to via "Las Vegas"]
278
278
  ```
279
279
 
280
280
  The issue is: the destination value is missing, Macros4Cuke won't be able to find a step with that syntax.
281
- The next invokation is syntactically correct for Macros4Cuke:
281
+ The next invokation is syntactically correct for Macros4Cuke:
282
282
  ```cucumber
283
283
  When I [travel from "San Francisco" to "" via "Las Vegas"]
284
284
  ```
@@ -290,6 +290,47 @@ For any argument that can receive a value through a data table, three situations
290
290
  2. A row for that argument and an empty text value are specified at invokation. The argument is bound to an empty text.
291
291
  3. There is no row for that argument. The argument is unbound (nil) but is rendered as an empty text.
292
292
 
293
+ ## Sub-steps with multiline text argument ##
294
+ - __Question__: is it possible to define a macro-step with a sub-step that itself
295
+ uses a multiline text argument (also called a docstring)?
296
+ - __Answer__: Yes but there is a catch.
297
+
298
+ Consider the following attempt of a macro-step definition:
299
+ ```cucumber
300
+ Given I define the step "* I [make a long journey]" to mean:
301
+ """
302
+ When I visit the cities:
303
+ """
304
+ Amsterdam
305
+ Brussels
306
+ Copenhagen
307
+ """
308
+ """
309
+ ```
310
+
311
+ This will result in an error. The issue is caused by the nesting of triple quotes:
312
+ Cucumber simply doesn't allow this. In fact, the error is reported by [Gherkin](https://github.com/cucumber/gherkin),
313
+ a component used by Cucumber.
314
+ As Gherkin has other [issues](https://github.com/cucumber/gherkin/issues/124) with docstrings, we
315
+ need a workaround today until the fixes are applied.
316
+ The workaround is the following:
317
+ - There exists in Macros4Cuke a predefined sub-step argument called __\<quotes\>__ and its value
318
+ is set to a triple quote sequence """.
319
+ - Use it everywhere you want to place nested triple quotes.
320
+
321
+ Thus to make the previous example work, one must change it like follows:
322
+ ```cucumber
323
+ Given I define the step "* I [make a long journey]" to mean:
324
+ """
325
+ When I visit the cities:
326
+ <quotes>
327
+ Amsterdam
328
+ Brussels
329
+ Copenhagen
330
+ <quotes>
331
+ """
332
+ ```
333
+
293
334
 
294
335
  ## Conditional sections in substeps. ##
295
336
  To make the macros more flexible, it is possible to define conditional sections in the substep sequence.
@@ -377,7 +418,7 @@ This last argument becomes important in the context of user acceptance testing,
377
418
  every tester is also Rubyist is -alas!- far from the truth.
378
419
 
379
420
 
380
- Macros with Cucumber is highly debated topic, so it is always wise to know what other people say about it:
421
+ Macros with Cucumber is highly debated topic, so it is good to know what other people say about it:
381
422
  [Support for Macros] (https://github.com/cucumber/gherkin/issues/178)
382
423
  [Substeps - macro request for the nth time] (http://grokbase.com/t/gg/cukes/133ey063b8/cucumber-substeps-macro-request-for-the-nth-time)
383
424
 
@@ -0,0 +1,30 @@
1
+ # File: multiline.feature
2
+
3
+ Feature: Show how multiline text inside macros
4
+ As a Cuke user
5
+ So that I enjoy writing scenario.
6
+
7
+
8
+ Scenario: Using a step with multiline text argument
9
+ When I visit the cities:
10
+ """
11
+ Amsterdam
12
+ Brussels
13
+ Copenhagen
14
+ """
15
+
16
+ Scenario: Definition of macro-step having a substep with multiline text
17
+ Given I define the step "* I [make a long journey from <origin> to <destination>]" to mean:
18
+ """
19
+ When I visit the cities:
20
+ <quotes>
21
+ <origin>
22
+ Amsterdam
23
+ Brussels
24
+ Copenhagen
25
+ <destination>
26
+ <quotes>
27
+ """
28
+
29
+ # Now use it...
30
+ When I [make a long journey from "London" to "Oslo"]
@@ -7,15 +7,23 @@ When(/^I leave '(.*)'$/) do |city|
7
7
  end
8
8
 
9
9
 
10
- When(/^I visit (.+)$/) do |city|
10
+ When(/^I visit (\S+)$/) do |city|
11
11
  show "I visit #{city}"
12
12
  end
13
13
 
14
14
 
15
+ # This step uses a multiline text argument
16
+ When(/^I visit the cities:$/) do |cities_raw|
17
+ cities = cities_raw.split(/\r\n?|\n/)
18
+ cities.each { |city| show "I visit #{city}" }
19
+ end
20
+
21
+
15
22
  When(/^I arrive in (.+)$/) do |city|
16
23
  show "I arrive in #{city}"
17
24
  end
18
25
 
26
+
19
27
  When(/^I type \"([^"]*)\"$/) do |text|
20
28
  show text
21
29
  end
@@ -4,7 +4,7 @@
4
4
 
5
5
  module Macros4Cuke # Module used as a namespace
6
6
  # The version number of the gem.
7
- Version = '0.3.17'
7
+ Version = '0.3.18'
8
8
 
9
9
  # Brief description of the gem.
10
10
  Description = "Macros for Cucumber"
@@ -16,6 +16,11 @@ module Macros4Cuke # Module used as a namespace
16
16
  # The actual values bound to these arguments
17
17
  # are passed to the sub-steps at execution time.
18
18
  class MacroStep
19
+ # The set of predefined macro argument constant values.
20
+ BuiltinParameters = {
21
+ 'quotes' => '"""'
22
+ }
23
+
19
24
  # A template engine that expands the sub-steps upon request.
20
25
  attr_reader(:renderer)
21
26
 
@@ -28,7 +33,6 @@ class MacroStep
28
33
  # The list of macro argument names (as appearing in the substeps
29
34
  # and in the macro phrase).
30
35
  attr_reader(:args)
31
-
32
36
 
33
37
  # Constructor.
34
38
  # @param aMacroPhrase[String] The text from the macro step definition
@@ -110,11 +114,15 @@ class MacroStep
110
114
  # Render the steps from the template, given the values
111
115
  # taken by the parameters
112
116
  # @param aPhrase [String] an instance of the macro phrase.
113
- # @param rawData [Array or nil] An Array with coupples of the form:
117
+ # @param rawData [Array or nil] An Array with couples of the form:
114
118
  # [macro argument name, a value].
115
119
  # Multiple rows with same argument name are acceptable.
116
120
  def expand(aPhrase, rawData)
117
121
  params = validate_params(aPhrase, rawData)
122
+
123
+ # Add built-in constants if necessary.
124
+ params = BuiltinParameters.merge(params)
125
+
118
126
  return renderer.render(nil, params)
119
127
  end
120
128
 
@@ -132,7 +140,6 @@ private
132
140
  quoted_values.each_with_index do |val, index|
133
141
  macro_parameters[phrase_args[index]] = val
134
142
  end
135
-
136
143
 
137
144
  unless rawData.nil?
138
145
  rawData.each do |(a_key, value)|
@@ -153,7 +160,7 @@ private
153
160
  end
154
161
 
155
162
 
156
-
163
+
157
164
 
158
165
  # Retrieve from the macro phrase, all the text between <..> or double quotes.
159
166
  # Returns an array. Each of its elements corresponds to quoted text.
@@ -180,7 +187,7 @@ private
180
187
 
181
188
  return args
182
189
  end
183
-
190
+
184
191
  # Return the substeps text after some transformation
185
192
  # [theSubstepsSource] The source text of the steps
186
193
  # to be expanded upon macro invokation.
@@ -208,8 +215,9 @@ private
208
215
  # and the macro-step does not use data table.
209
216
  unless use_table?
210
217
  substepsVars.each do |substep_arg|
211
- unless thePhraseArgs.include? substep_arg
212
- raise UnreachableSubstepArgument.new(substep_arg)
218
+ unless (thePhraseArgs.include?(substep_arg) ||
219
+ BuiltinParameters.include?(substep_arg))
220
+ raise UnreachableSubstepArgument.new(substep_arg)
213
221
  end
214
222
  end
215
223
  end
@@ -166,9 +166,8 @@ public
166
166
  end # class
167
167
 
168
168
 
169
- # Represents a section in a template, that is,
170
- # a set of template elements for which its rendition depends
171
- # on the (in)existence of an actual value bound to the variable name.
169
+ # A specialized section in a template for which its rendition
170
+ # depends on the (in)existence of an actual value bound to the variable name.
172
171
  class ConditionalSection < Section
173
172
  # A boolean that indicates whether the rendition condition is
174
173
  # the existence of a value for the variable (true)
@@ -94,7 +94,7 @@ SNIPPET
94
94
 
95
95
  text.should == expectation
96
96
  end
97
-
97
+
98
98
  it "should un-escape the double-quotes for phrase arguments" do
99
99
  specific_phrase = %q|enter my credentials as "quotable\""|
100
100
  text = subject.expand(specific_phrase, [ %w(password no-secret) ])
@@ -109,7 +109,7 @@ SNIPPET
109
109
  text.should == expectation
110
110
  end
111
111
 
112
-
112
+
113
113
  it "should complain when an unknown variable is used" do
114
114
  # Error case: there is no macro argument called <unknown>
115
115
  error_message = "Unknown macro-step argument 'unknown'."
@@ -118,6 +118,25 @@ SNIPPET
118
118
  UnknownArgumentError, error_message)
119
119
  end
120
120
 
121
+
122
+ it "should expand built-in variables" do
123
+ phrase = "do nothing useful"
124
+ substeps = <<-SNIPPET
125
+ Given I travel through:
126
+ <quotes>
127
+ London
128
+ Paris
129
+ San Francisco
130
+ <quotes>
131
+ SNIPPET
132
+
133
+ instance = MacroStep.new(phrase, substeps, true)
134
+ actual = instance.expand(phrase, [])
135
+ expected = substeps.gsub(/<quotes>/, '"""')
136
+ actual.should == expected
137
+ end
138
+
139
+
121
140
  end # context
122
141
 
123
142
  end # describe
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: macros4cuke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.17
4
+ version: 0.3.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-20 00:00:00.000000000 Z
12
+ date: 2013-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber
@@ -104,6 +104,7 @@ files:
104
104
  - lib/macros4cuke/templating/engine.rb
105
105
  - examples/demo/cucumber.yml
106
106
  - examples/demo/features/basic.feature
107
+ - examples/demo/features/multiline.feature
107
108
  - examples/demo/features/step_definitions/step_defs.rb
108
109
  - examples/demo/features/step_definitions/use_macro_steps.rb
109
110
  - examples/demo/features/support/env.rb