macros4cuke 0.0.02 → 0.1.00

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.
@@ -4,14 +4,12 @@ Feature: Show the use of a basic macro
4
4
  As a Cuke user
5
5
  So that I enjoy writing scenario.
6
6
 
7
- # The background section is THE good place to define your macros.
8
- # Since the steps from this section are pre-pended to the steps of every scenario (outline),
9
- # the macros will be available to every scenario in the feature file.
10
- Background:
7
+
8
+ Scenario: Definition of a simple macro-step
11
9
  # The next step creates a macro(-step)
12
- # The syntax of the new macro-step is specified between the < ... > delimiters.
10
+ # The syntax of the new macro-step is specified between double quotes.
13
11
  # The steps to execute when the macro is used/invoked are listed in the multiline triple quotes arguments.
14
- Given I define the step <When I [log in]> to mean:
12
+ Given I define the step "When I [log in]" to mean:
15
13
  """
16
14
  Given I landed in the homepage
17
15
  When I click "Sign in"
@@ -4,15 +4,13 @@ Feature: Show the use of a basic macro with one argument
4
4
  As a Cuke user
5
5
  So that I enjoy writing scenario.
6
6
 
7
- # The background section is THE good place to define your macros.
8
- # Since the steps from this section are pre-pended to the steps of every scenario (outline),
9
- # the macros will be available to every scenario in the feature file.
10
- Background:
7
+
8
+ Scenario: Creating a basic scenario with one argument
11
9
  # The next step creates a macro(-step)
12
- # The syntax of the new macro-step is specified between the < ... > delimiters.
10
+ # The syntax of the new macro-step is specified between the double quotes.
13
11
  # The steps to execute when the macro is used/invoked are listed in the multiline triple quotes arguments.
14
12
  # The macro argument is put between double(triple) curly braces {{...}} as required by the Mustache template library.
15
- Given I define the step <When I [log in as {{userid}}]> to mean:
13
+ Given I define the step "When I [log in as {{userid}}]" to mean:
16
14
  """
17
15
  Given I landed in the homepage
18
16
  When I click "Sign in"
@@ -4,15 +4,12 @@ Feature: Show the use of a basic macro with multiple arguments
4
4
  As a Cuke user
5
5
  So that I enjoy writing scenario.
6
6
 
7
- # The background section is THE good place to define your macros.
8
- # Since the steps from this section are pre-pended to the steps of every scenario (outline),
9
- # the macros will be available to every scenario in the feature file.
10
- Background:
11
- # The next step creates a macro(-step)
12
- # The syntax of the new macro-step is specified between the < ... > delimiters.
7
+
8
+ Scenario: defining basic macro with multiple arguments
9
+ # The next step creates a macro(-step)double quotes.
13
10
  # The steps to execute when the macro is used/invoked are listed in the multiline triple quotes arguments.
14
11
  # The macro argument is put between double(triple) curly braces {{...}} as required by the Mustache template library.
15
- Given I define the step <When I [enter my userid {{userid}} and password {{password}}]> to mean:
12
+ Given I define the step "When I [enter my userid {{userid}} and password {{password}}]" to mean:
16
13
  """
17
14
  Given I landed in the homepage
18
15
  When I click "Sign in"
@@ -36,7 +33,7 @@ Invoked step: ... I click "Submit"
36
33
  """
37
34
 
38
35
  Scenario: A macro invoking another macro (YES, it's possible!)
39
- Given I define the step <When I [enter my credentials]> to mean:
36
+ Given I define the step "When I [enter my credentials]" to mean:
40
37
  """
41
38
  {{! Notice that the next step is invoking the first macro above}}
42
39
  When I [enter my userid "guest" and password "unguessable"]
@@ -4,15 +4,13 @@ Feature: Show the use of a macro with multiple arguments in a table
4
4
  As a Cuke user
5
5
  So that I enjoy writing scenario.
6
6
 
7
- # The background section is THE good place to define your macros.
8
- # Since the steps from this section are pre-pended to the steps of every scenario (outline),
9
- # the macros will be available to every scenario in the feature file.
10
- Background:
7
+
8
+ Scenario: Defining a macro to be used with multiple arguments in a table
11
9
  # The next step creates a macro(-step)
12
- # The syntax of the new macro-step is specified between the < ... > delimiters.
10
+ # The syntax of the new macro-step is specified between double quotes.
13
11
  # The steps to execute when the macro is used/invoked are listed in the multiline triple quotes arguments.
14
12
  # The macro argument is put between double(triple) curly braces {{...}} as required by the Mustache template library.
15
- Given I define the step <When I [enter my credentials as]:> to mean:
13
+ Given I define the step "When I [enter my credentials as]:" to mean:
16
14
  """
17
15
  Given I landed in the homepage
18
16
  When I click "Sign in"
@@ -36,7 +36,6 @@ end # module
36
36
  World { Macros4Cuke::TracingWorld.new }
37
37
 
38
38
 
39
-
40
39
  # Macros4Cuke step two: extend the world object with the mix-in module
41
40
  # that adds the support for macros in Cucumber.
42
41
  World(Macros4Cuke::MacroStepSupport)
data/lib/macro_steps.rb CHANGED
@@ -3,69 +3,44 @@
3
3
 
4
4
 
5
5
 
6
- =begin This step is used to define a macro-step
7
- Example:
8
- Given I define the step <When I [create the following {{contactType}} contact]:> to mean:
9
- """
10
- # In the next step we use triple curly brace in order to get un-escaped text
11
- When I select "<type>" from "type"
12
- When I fill in "name" with "{{{name}}}"
13
- And I fill in "companyName" with "{{companyName}}"
14
- And I fill in "companyName2" with "{{companyName2}}"
15
- """
16
- =end
17
- Given(/^I define the step <When I \[([^\]]+\]:?)> to mean:$/) do |macro_phrase, template|
6
+ # This step is used to define a macro-step
7
+ # Example:
8
+ # Given I define the step "When I [log in as {{userid}}]" to mean:
9
+ # """
10
+ # Given I landed in the homepage
11
+ # When I click "Sign in"
12
+ # And I fill in "Username" with "{{userid}}"
13
+ # And I fill in "Password" with "unguessable"
14
+ # And I click "Submit"
15
+ # """
16
+
17
+ Given(/^I define the step "When I \[([^\]]+\]:?)" to mean:$/) do |macro_phrase, template|
18
18
  add_macro(macro_phrase, template)
19
19
  end
20
20
 
21
- =begin This step is used to invoke a simple macro-step
21
+ # This step is used to invoke a simple macro-step
22
22
  # Example:
23
- # Here we define a simple macro-step
24
- Given I define the step <When I [fly from {{origin}} to {{destination}} via {{waypoint}}]> to mean:
25
- """
26
- When I display the text "Departure: {{origin}}."
27
- When I display the text "Stop at: {{waypoint}}."
28
- When I display the text "Destination {{destination}}."
29
- """
30
- =end
23
+ # When I [log in as "guest"]
24
+ #
31
25
  When(/^I \[([^\]]+\])$/) do |macro_phrase|
32
- macro = find_macro(macro_phrase)
33
- raise StandardError, "Undefined macro step for '[#{macro_phrase}'." if macro.nil?
34
-
35
- # Retrieve macro argument names and their associated value from the table
36
- params = macro.validate_params(macro_phrase, nil)
37
-
38
- # Render the steps
39
- rendered_steps = macro.expand(params)
40
-
41
- # Execute the steps
42
- steps(rendered_steps)
26
+ invoke_macro(macro_phrase) # This will call the macro with the given phrase
43
27
  end
44
28
 
45
29
 
46
30
  # This step is used to invoke a macro-step with a table argument.
47
31
  # Example:
48
- # When I [create the following "Registrant" contact]:
49
- # |name|John Doe|
50
- # |city|Gotham City|
51
- # |street| Main street|
52
- # |street3| Small street|
32
+ # When I [enter my credentials as]:
33
+ # |userid |guest |
34
+ # |password|unguessable|
53
35
  When(/^I \[([^\]]+\]:)$/) do |macro_phrase, table_argument|
54
- macro = find_macro(macro_phrase)
55
- raise StandardError, "Undefined macro step for '#{macro_phrase}'." if macro.nil?
56
-
36
+ # Ensure that the second argument is of the correct type
57
37
  unless table_argument.kind_of?(Cucumber::Ast::Table)
58
- raise StandardError, "This step must have a table as an argument."
38
+ raise StandardError, "This step must have a data table as an argument."
59
39
  end
60
40
 
61
- # Retrieve macro argument names and their associated value from the table
62
- params = macro.validate_params(macro_phrase, table_argument.rows_hash())
63
-
64
- # Render the steps
65
- rendered_steps = macro.expand(params)
66
-
67
- # Execute the steps
68
- steps(rendered_steps)
41
+ # This will call the macro with the given phrase.
42
+ # The second argument consists of a hash with pairs of the kind: argument name => actual value
43
+ invoke_macro(macro_phrase, table_argument.rows_hash())
69
44
  end
70
45
 
71
46
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Macros4Cuke # Module used as a namespace
5
5
  # This constant keeps the current version of the gem.
6
- Version = '0.0.02'
6
+ Version = '0.1.00'
7
7
 
8
8
  Description = "Macros for Cucumber"
9
9
 
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8 -- You should see a paragraph character: §
2
+ # File: exceptions.rb
3
+
4
+ module Macros4Cuke # Module used as a namespace
5
+
6
+ # Base class for any exception explicitly raised in the Macros4Cuke methods.
7
+ class Macros4CukeError < StandardError
8
+ end # class
9
+
10
+ # Raised when one attempts to define a new macro
11
+ # that has the same phrase as an existing macro.
12
+ class DuplicateMacroError < Macros4CukeError
13
+ def initialize(aPhrase)
14
+ super("A macro-step with phrase '[#{aPhrase}' already exist.")
15
+ end
16
+ end # class
17
+
18
+
19
+
20
+ # Raised when one invokes a macro-step with an unknown phrase.
21
+ class UnknownMacroError < Macros4CukeError
22
+ def initialize(aPhrase)
23
+ super("Unknown macro-step with phrase: '[#{aPhrase}'.")
24
+ end
25
+ end # class
26
+
27
+
28
+
29
+ # Raised when one invokes a macro-step with an argument
30
+ # that has an unknown name.
31
+ class UnknownArgumentError < Macros4CukeError
32
+ def initialize(argName)
33
+ super("Unknown macro argument #{argName}.")
34
+ end
35
+ end # class
36
+
37
+
38
+ # Raised when Macros4Cuke encountered an issue
39
+ # that it can't handle properly.
40
+ class InternalError < Macros4CukeError
41
+ end # class
42
+
43
+
44
+ end # module
45
+
46
+ # End of file
@@ -0,0 +1,81 @@
1
+ # File: macro-collection.rb
2
+ # Purpose: Implementation of the MacroCollection class.
3
+
4
+ require 'singleton' # We'll use the Singleton design pattern for this class.
5
+ require_relative "macro-step"
6
+
7
+ module Macros4Cuke # Module used as a namespace
8
+
9
+ # Represents a container of macros.
10
+ # It gather all the macros encountered by Cucumber while "executing" the feature files.
11
+ class MacroCollection
12
+ include Singleton # Use the Singleton design pattern.
13
+
14
+ # A Hash with pairs of the form: phrase => MacroStep object
15
+ attr_reader(:macro_steps)
16
+
17
+ # Init the pool if it was not done yet.
18
+ def init()
19
+ @macro_steps = {} if @macro_steps.nil?
20
+ end
21
+
22
+ public
23
+ # Return true iff the host has a macro with the given key.
24
+ def has_macro?(aPhrase, mode)
25
+ key = MacroStep::macro_key(aPhrase, mode)
26
+ return @macro_steps.include? key
27
+ end
28
+
29
+
30
+ # Add a new macro.
31
+ # Pre-condition: there is no existing macro with the same key.
32
+ # [aPhrase] The text that is enclosed between the square brackets.
33
+ # [aTemplate] A text that consists of a sequence of Cucumber steps.
34
+ # These steps
35
+ def add_macro(aPhrase, aTemplate)
36
+ new_macro = MacroStep.new(aPhrase, aTemplate)
37
+
38
+ # Prevent collision of macros (macros with same phrase).
39
+ # This can occur if a macro was defined in a background section.
40
+ # An exception is raised if the phrase syntax of both macros are the
41
+ if find_macro(aPhrase)
42
+ pp find_macro(aPhrase)
43
+ raise DuplicateMacroError.new(aPhrase)
44
+ end
45
+
46
+ @macro_steps[new_macro.name] = new_macro
47
+
48
+ end
49
+
50
+ # Render the steps associated to the macro with given phrase
51
+ # and (optionally) given a table of values.
52
+ # Return the rendered steps as a text.
53
+ # [aPhrase] an instance of the macro phrase.
54
+ # [rawData] An Array of couples.
55
+ # Each couple is of the form: argument name, a value.
56
+ # Multiple rows with same argument name are acceptable.
57
+ def render_steps(aPhrase, rawData = nil)
58
+
59
+ macro = find_macro(aPhrase)
60
+ raise UnknownMacroError.new(aPhrase) if macro.nil?
61
+
62
+ # Retrieve macro argument names and their associated value from the table
63
+ params = macro.validate_params(aPhrase, rawData)
64
+
65
+ # Render the steps
66
+ rendered_steps = macro.expand(params)
67
+
68
+ end
69
+
70
+ private
71
+ # Retrieve the macro, given a phrase.
72
+ def find_macro(aMacroPhrase)
73
+ return @macro_steps[MacroStep::macro_key(aMacroPhrase, :invokation)]
74
+ end
75
+
76
+ end # class
77
+
78
+ end # module
79
+
80
+
81
+ # End of file
@@ -1,46 +1,48 @@
1
1
  # File: macro-step-support.rb
2
2
 
3
- require_relative "macro-step"
3
+ require_relative "exceptions"
4
+ require_relative "macro-collection"
4
5
 
5
6
  module Macros4Cuke # Module used as a namespace
6
7
 
7
- # Mix-in module that should be extending World objects of Cucumber.
8
- # Synopsis (in env.rb):
9
- module MacroStepSupport
8
+ # Mix-in module that should be extending World objects in Cucumber.
9
+ # Synopsis (in env.rb):
10
+ # require 'macros4cuke'
11
+ # ...
12
+ # World(Macros4Cuke::MacroStepSupport) # Extend the world object with this module.
13
+ #
14
+ module MacroStepSupport
10
15
 
11
16
  # Callback invoked when a World object is extend(ed) with this module.
12
17
  def self.extended(world)
13
- # Add & initialize an instance variable for macro support.
14
- world.clear_macro_steps()
18
+ # Add & initialize an instance variable for macro support.
19
+ MacroCollection::instance.init()
15
20
  end
16
21
 
17
-
22
+
18
23
  public
19
- # Remove all macro steps
20
- def clear_macro_steps()
21
- @macro_steps = {}
22
- end
23
-
24
- # Return true iff the host has a macro with the given key.
25
- def has_macro?(aMacroPhrase, mode)
26
- key = MacroStep::macro_key(aMacroPhrase, mode)
27
- return @macro_steps.include? key
28
- end
29
-
24
+
30
25
  # Add a new macro.
31
26
  # Pre-condition: there is no existing macro with the same key.
27
+ # [aPhrase] The text that is enclosed between the square brackets.
28
+ # [aTemplate] A text that consists of a sequence of Cucumber steps.
29
+ # These steps
32
30
  def add_macro(aPhrase, aTemplate)
33
- if has_macro?(aPhrase, :definition)
34
- raise StandardError, "Macro step for '[#{aPhrase}' already exist."
35
- else
36
- new_macro = MacroStep.new(aPhrase, aTemplate)
37
- @macro_steps[new_macro.name] = new_macro
38
- end
31
+ MacroCollection::instance.add_macro(aPhrase, aTemplate)
39
32
  end
33
+
40
34
 
41
- # Retrieve the macro, given a phrase.
42
- def find_macro(aMacroPhrase)
43
- return @macro_steps[MacroStep::macro_key(aMacroPhrase, :invokation)]
35
+ # Invoke a macro with given phrase and (optionally) a table of values
36
+ # [aPhrase] an instance of the macro phrase.
37
+ # [rawData] An Array of couples.
38
+ # Each couple is of the form: argument name, a value.
39
+ # Multiple rows with same argument name are acceptable.
40
+ def invoke_macro(aPhrase, rawData = nil)
41
+ # Generate a text rendition of the step to be executed.
42
+ rendered_steps = MacroCollection::instance.render_steps(aPhrase, rawData)
43
+
44
+ # Execute the steps
45
+ steps(rendered_steps)
44
46
  end
45
47
 
46
48
  end # module
@@ -5,7 +5,8 @@ require 'mustache' # Load the Mustache template library
5
5
 
6
6
  module Macros4Cuke # Module used as a namespace
7
7
 
8
- # In essence, a macro step object represents a Cucumber step that stands for a sequence of steps.
8
+ # In essence, a macro step object represents a Cucumber step that is itself
9
+ # an aggregation of lower-level Cucumber steps.
9
10
  class MacroStep
10
11
  # A Mustache instance that expands the steps upon request.
11
12
  attr_reader(:renderer)
@@ -18,6 +19,7 @@ class MacroStep
18
19
 
19
20
  # The list of macro argument names (as appearing in the Mustache template and in the macro phrase).
20
21
  attr_reader(:args)
22
+
21
23
 
22
24
  # Constructor.
23
25
  # [aMacroPhrase]
@@ -106,7 +108,7 @@ class MacroStep
106
108
 
107
109
  unless rawData.nil?
108
110
  rawData.each do |(key, value)|
109
- raise StandardError,"Unknown macro argument #{key}." unless @args.include? key
111
+ raise UnknownArgumentError.new(key) unless @args.include? key
110
112
  if macro_parameters.include? key
111
113
  if macro_parameters[key].kind_of?(Array)
112
114
  macro_parameters[key] << value
@@ -122,6 +124,7 @@ class MacroStep
122
124
  return macro_parameters
123
125
  end
124
126
 
127
+
125
128
 
126
129
  private
127
130
  # Retrieve from the macro phrase, all the text between "mustaches" or double quotes.
@@ -140,7 +143,7 @@ private
140
143
  when :invokation
141
144
  /"([^"]*)"/
142
145
  else
143
- raise Standard, "Internal error: Unknown mode argument #{mode}"
146
+ raise InternalError, "Internal error: Unknown mode argument #{mode}"
144
147
  end
145
148
  raw_result = aMacroPhrase.scan(pattern)
146
149
  return raw_result.flatten.compact
@@ -152,7 +155,7 @@ private
152
155
  def add_tags_multi(tokens)
153
156
  first_token = tokens.shift
154
157
  unless first_token == :multi
155
- raise StandardError, "Expecting a :multi token instead of a #{first_token}"
158
+ raise InternalError, "Expecting a :multi token instead of a #{first_token}"
156
159
  end
157
160
 
158
161
  tokens.each do |an_opcode|
@@ -166,7 +169,7 @@ private
166
169
  when String
167
170
  #Do nothing...
168
171
  else
169
- raise StandardError, "Unknown Mustache token type #{an_opcode.first}"
172
+ raise InternalError, "Unknown Mustache token type #{an_opcode.first}"
170
173
  end
171
174
  end
172
175
  end
@@ -178,8 +181,8 @@ private
178
181
  case mustache_opcode[0]
179
182
  when :etag
180
183
  triplet = mustache_opcode[1]
181
- raise StandardError, "expected 'mustache' token instead of '#{triplet[0]}'" unless triplet[0] == :mustache
182
- raise StandardError, "expected 'fetch' token instead of '#{triplet[1]}'" unless triplet[1] == :fetch
184
+ raise InternalError, "expected 'mustache' token instead of '#{triplet[0]}'" unless triplet[0] == :mustache
185
+ raise InternalError, "expected 'fetch' token instead of '#{triplet[1]}'" unless triplet[1] == :fetch
183
186
  @args << triplet.last
184
187
 
185
188
  when :fetch
@@ -189,7 +192,7 @@ private
189
192
  add_tags_section(mustache_opcode)
190
193
 
191
194
  else
192
- raise StandardError, "Unknown Mustache token type #{mustache_opcode.first}"
195
+ raise InternalError, "Unknown Mustache token type #{mustache_opcode.first}"
193
196
  end
194
197
  end
195
198
 
@@ -208,7 +211,7 @@ private
208
211
  when String
209
212
  return
210
213
  else
211
- raise StandardError, "Unknown Mustache token type #{op.first}"
214
+ raise InternalError, "Unknown Mustache token type #{op.first}"
212
215
  end
213
216
  end
214
217
  end
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.0.02
4
+ version: 0.1.00
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-04-21 00:00:00.000000000 Z
12
+ date: 2013-04-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -60,8 +60,8 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  description: ! "\tMacros4Cuke is a lightweight library that adds a macro facility
63
- your Cucumber scenarios.\n In short, you will be able to create new steps that
64
- will replace a sequence of lower-level steps. \n"
63
+ your Cucumber scenarios.\n In short, you can create new steps that replace a sequence
64
+ of lower-level steps. \n"
65
65
  email: famished.tiger@yahoo.com
66
66
  executables: []
67
67
  extensions: []
@@ -74,6 +74,8 @@ files:
74
74
  - lib/macros4cuke.rb
75
75
  - lib/macro_steps.rb
76
76
  - lib/macros4cuke/constants.rb
77
+ - lib/macros4cuke/exceptions.rb
78
+ - lib/macros4cuke/macro-collection.rb
77
79
  - lib/macros4cuke/macro-step-support.rb
78
80
  - lib/macros4cuke/macro-step.rb
79
81
  - features/demo01.feature