macros4cuke 0.2.18 → 0.2.19

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.19 / 2013-05-06
2
+ * [CHANGE] Added validation of macro argument names in new `Engine::parse_tag` method.
3
+ * [CHANGE] InvalidCharError exception added.
4
+ * [CHANGE] File `engine_spec.rb`: Added one RSpec example for an invalid argument name.
5
+ * [CHANGE] File `README.md`: added a new section on naming macro arguments.
6
+
1
7
  ## 0.2.18 / 2013-05-06
2
8
  * [CHANGE] Amended spec files and added a new demo feature. SimpleCov code coverage raised to more than 97%.
3
9
  * [CHANGE] Macro-step arguments can be multivalued (experimental)
data/README.md CHANGED
@@ -245,6 +245,14 @@ Here are few observations worth noticing:
245
245
  the value "Main Street, 22".
246
246
  - Data rows don't have to follow strictly the order of the arguments in the sub-step sequence.
247
247
 
248
+ ## Naming macro-step arguments ##
249
+ In line with most computer languages, Macros4Cuke accepts argument names containing alphanumeric characters and
250
+ underscores.
251
+ In fact, the only characters that are not allowed in argument names are the following punctuation or delimiting
252
+ signs:
253
+ __\!"'\#$%\&\*\+\-/,\.\:\;\=\?\(\)\<\>\[\]\{\}\\\^\`\|\~__
254
+
255
+
248
256
  ## With great power comes great responsibility. ##
249
257
  _Stan Lee_
250
258
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Macros4Cuke # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.2.18'
6
+ Version = '0.2.19'
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = "Macros for Cucumber"
@@ -1,4 +1,4 @@
1
- # encoding: utf-8 -- You should see a paragraph character: §
1
+ # encoding: utf-8 -- You should see a paragraph character: §
2
2
  # File: exceptions.rb
3
3
 
4
4
  module Macros4Cuke # Module used as a namespace
@@ -8,7 +8,7 @@ module Macros4Cuke # Module used as a namespace
8
8
  class Macros4CukeError < StandardError
9
9
  end # class
10
10
 
11
- # Raised when one attempts to define a new macro
11
+ # Raised when one attempts to define a new macro
12
12
  # that has the same phrase as an existing macro.
13
13
  class DuplicateMacroError < Macros4CukeError
14
14
  def initialize(aPhrase)
@@ -44,7 +44,15 @@ class EmptyArgumentError < Macros4CukeError
44
44
  end # class
45
45
 
46
46
 
47
- # Raised when one invokes a macro-step with an unknown phrase.
47
+ # Raised when an argument name contains invalid characters.
48
+ class InvalidCharError < Macros4CukeError
49
+ def initialize(aText, aWrongChar)
50
+ super("The invalid sign '#{aWrongChar}' occurs in the argument/tag '#{aText}'.")
51
+ end
52
+ end # class
53
+
54
+
55
+ # Raised when one invokes a macro-step with an unknown phrase.
48
56
  class UnknownMacroError < Macros4CukeError
49
57
  def initialize(aPhrase)
50
58
  super("Unknown macro-step with phrase: '#{aPhrase}'.")
@@ -54,7 +62,7 @@ end # class
54
62
 
55
63
 
56
64
  # Raised when one invokes a macro-step with an argument
57
- # that has an unknown name.
65
+ # that has an unknown name.
58
66
  class UnknownArgumentError < Macros4CukeError
59
67
  def initialize(argName)
60
68
  super("Unknown macro-step argument '#{argName}'.")
@@ -101,6 +101,15 @@ end # class
101
101
  # while Mustache use !{{...}} delimiters),
102
102
  # - Feature files are meant to be simple, so should the template engine be.
103
103
  class Engine
104
+ # The regular expression that matches any punctuation sign or delimiter that is forbidden between chevrons <...> template tags.
105
+ DisallowedSigns = begin
106
+ forbidden = '!"#' + "$%&'()*+,-./:;<=>?[\\]^`{|}~" # Used concatenation (+) to work around Ruby bug!
107
+ all_escaped = []
108
+ forbidden.each_char() { |ch| all_escaped << Regexp.escape(ch) }
109
+ pattern = all_escaped.join("|")
110
+ Regexp.new(pattern)
111
+ end
112
+
104
113
  # The original text of the template is kept here.
105
114
  attr_reader(:source)
106
115
 
@@ -140,7 +149,6 @@ public
140
149
  return @variables
141
150
  end
142
151
 
143
-
144
152
  # Class method. Parse the given line text into a raw representation.
145
153
  # @return [Array] Couples of the form:
146
154
  # [:static, text] or [:dynamic, tag text]
@@ -211,7 +219,7 @@ private
211
219
  end
212
220
 
213
221
 
214
- # [aCouple] a two-element array of the form: [kind, text]
222
+ # @param aCouple [Array] a two-element array of the form: [kind, text]
215
223
  # Where kind must be one of :static, :dynamic
216
224
  def compile_couple(aCouple)
217
225
  (kind, text) = aCouple
@@ -221,14 +229,24 @@ private
221
229
  StaticText.new(text)
222
230
 
223
231
  when :dynamic
224
- Placeholder.new(text)
232
+ parse_tag(text)
225
233
  else
226
234
  raise StandardError, "Internal error: Don't know template element of kind #{kind}"
227
235
  end
228
-
236
+
229
237
  return result
230
238
  end
231
239
 
240
+ # Parse the contents of a tag entry.
241
+ # @param aText [String] The text that is enclosed between chevrons.
242
+ def parse_tag(aText)
243
+ # Disallow punctuation and delimiter signs in tags.
244
+ matching = DisallowedSigns.match(aText)
245
+ raise InvalidCharError.new(aText, matching[0]) if matching
246
+
247
+ return Placeholder.new(aText)
248
+ end
249
+
232
250
  end # class
233
251
 
234
252
  end # module
@@ -4,6 +4,7 @@
4
4
  require_relative '../../spec_helper'
5
5
  require_relative '../../../lib/macros4cuke/templating/engine' # Load the class under test
6
6
 
7
+
7
8
  module Macros4Cuke
8
9
 
9
10
  module Templating # Open this namespace to get rid of module qualifier prefixes
@@ -171,9 +172,14 @@ SNIPPET
171
172
  text_w_empty_arg = sample_template.sub(/userid/, '')
172
173
  error_message = %Q|An empty or blank argument occurred in 'And I fill in "Username" with "<>"'.|
173
174
  lambda { Engine.new text_w_empty_arg }.should raise_error(Macros4Cuke::EmptyArgumentError, error_message)
175
+ end
174
176
 
177
+ it "should complain when a placeholder contains an invalid character" do
178
+ text_w_empty_arg = sample_template.sub(/userid/, 'user%id')
179
+ error_message = "The invalid sign '%' occurs in the argument/tag 'user%id'."
180
+ lambda { Engine.new text_w_empty_arg }.should raise_error(Macros4Cuke::InvalidCharError, error_message)
175
181
  end
176
- end
182
+ end # context
177
183
 
178
184
  context "Provided services" do
179
185
 
@@ -208,7 +214,7 @@ SNIPPET
208
214
  SNIPPET
209
215
 
210
216
  rendered_text.should == expected
211
-
217
+
212
218
  # Case of an actual that's not a String
213
219
  locals = {'userid' => "johndoe", "password" => 12345678 }
214
220
  rendered_text = subject.render(Object.new, locals)
@@ -220,8 +226,8 @@ SNIPPET
220
226
  And I click "Sign in"
221
227
  SNIPPET
222
228
 
223
- rendered_text.should == expected
224
-
229
+ rendered_text.should == expected
230
+
225
231
 
226
232
  # Place actual value in context object
227
233
  Context = Struct.new(:userid, :password)
@@ -236,7 +242,7 @@ SNIPPET
236
242
  SNIPPET
237
243
 
238
244
  rendered_text.should == expected
239
-
245
+
240
246
 
241
247
  # Case of an empty source template text
242
248
  instance = Engine.new ''
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.2.18
4
+ version: 0.2.19
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-06 00:00:00.000000000 Z
12
+ date: 2013-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber