cuke-patterns 0.1.3 → 0.1.4

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cuke-patterns}
8
- s.version = "0.1.3"
8
+ s.version = "0.1.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brendan Baldwin"]
12
- s.date = %q{2010-08-16}
12
+ s.date = %q{2010-08-18}
13
13
  s.description = %q{Makes cucumber step definitions more focused, understandable, searchable and awesomeable.}
14
14
  s.email = %q{brendan@usergenic.com}
15
15
  s.extra_rdoc_files = [
@@ -23,14 +23,17 @@ Gem::Specification.new do |s|
23
23
  "Rakefile",
24
24
  "VERSION",
25
25
  "cuke-patterns.gemspec",
26
- "features/no_regressions_in_normal_cukes.feature",
27
- "features/simple_cuke_patterns.feature",
28
- "features/step_definitions/no_regression_steps.rb",
26
+ "features/apply_pattern.feature",
27
+ "features/apply_pattern_steps.rb",
28
+ "features/pattern_generator.feature",
29
+ "features/simple_patterns.feature",
30
+ "features/step_definitions/pattern_generator_steps.rb",
29
31
  "features/step_definitions/simple_pattern_steps.rb",
30
32
  "features/support/env.rb",
31
33
  "lib/cuke-patterns.rb",
32
34
  "lib/cuke-patterns/rb_dsl_ext.rb",
33
35
  "lib/cuke-patterns/rb_language_ext.rb",
36
+ "lib/cuke-patterns/rb_world_ext.rb",
34
37
  "lib/cuke-patterns/step_mother_ext.rb"
35
38
  ]
36
39
  s.homepage = %q{http://github.com/brendan/cuke-patterns}
@@ -0,0 +1,8 @@
1
+ Feature: Apply Pattern
2
+
3
+ Patterns can be called from within other Patterns.
4
+
5
+ Scenario: A list pattern
6
+ When @x contains 1, "potato", 2.0 and "potato"
7
+ Then @x should be equal to [1, "potato", 2.0, "potato"]
8
+ And @x should be an Array
@@ -0,0 +1,9 @@
1
+ When ":ivar_name contains :list" do |ivar, array|
2
+ instance_variable_set(ivar, array)
3
+ end
4
+
5
+ Pattern :list, /(.+(?:,| and ).+)/ do |list|
6
+ list.split(/ *(?:,|and) */).map do |item|
7
+ Pattern :value, item
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ Feature: Pattern Generator
2
+
3
+ Sometimes its nice to be able to have a catch-all like Ruby's method_missing
4
+ so we can do more dynamic things. A PatternGenerator works like this, taking
5
+ a string of word characters representing a "word" or ":symbol" and then
6
+ returns a regexp and optional conversion proc. If it returns neither, we
7
+ move on to the next defined Pattern Generator.
8
+
9
+ Scenario: singular/plural form agnosticizer
10
+ When I eat 1 apple
11
+ And I eat 2 apples
12
+ Then I should have eaten 3 apples
13
+
@@ -0,0 +1,40 @@
1
+ Feature: Simple Patterns
2
+ These are some examples of very simple but useful patterns.
3
+
4
+ Scenario: :fixnum
5
+ When I assign @x to 1
6
+ Then @x should be equal to 1
7
+ And @x should be a Fixnum
8
+
9
+ Scenario: :fixnum (negative)
10
+ When I assign @x to -1
11
+ Then @x should be equal to -1
12
+ And @x should be a Fixnum
13
+
14
+ Scenario: :float
15
+ When I assign @x to 2.0
16
+ Then @x should be equal to 2.0
17
+ And @x should be a Float
18
+
19
+ Scenario: :float (negative)
20
+ When I assign @x to -2.0
21
+ Then @x should be equal to -2.0
22
+ And @x should be a Float
23
+
24
+ Scenario: :hash
25
+ When I assign @x to {'a'=>'b','c'=>'d'}
26
+ Then @x should be equal to {'a'=>'b','c'=>'d'}
27
+ And @x should be a Hash
28
+
29
+ Scenario: :array
30
+ When I assign @x to [1,2,3]
31
+ Then @x should be equal to [1,2,3]
32
+ And @x should be an Array
33
+
34
+ Scenario: :string
35
+ When I assign @x to "aww yeah"
36
+ Then @x should be equal to "aww yeah"
37
+ And @x should be a String
38
+
39
+
40
+
@@ -0,0 +1,18 @@
1
+ When "I eat :value apples" do |count|
2
+ @apples_consumed ||= 0
3
+ @apples_consumed += count
4
+ end
5
+
6
+ Then "I should have eaten :value apples" do |count|
7
+ @apples_consumed.should == count
8
+ end
9
+
10
+ # This pattern generator doesn't do *real* pluralize/singularize;
11
+ # it's just a demonstration of the concept. Here I strip and append
12
+ # an 's' onto the word passed in and construct a regexp that looks
13
+ # for all forms rather naively.
14
+ PatternGenerator do |word|
15
+ base_plural_singular = [word, word+'s', word.sub(/s$/,'')].uniq
16
+ base_plural_singular.map! {|w| Regexp.escape(w)}
17
+ Regexp.new(base_plural_singular.join('|'))
18
+ end
@@ -1,39 +1,30 @@
1
- When "@x is :integer" do |integer|
2
- @x = integer
1
+ When "I assign :ivar_name to :value" do |ivar, value|
2
+ instance_variable_set(ivar, value)
3
3
  end
4
4
 
5
- When "@x contains :list_of_integers" do |list|
6
- @x = list
5
+ Then ":ivar should be equal to :value" do |ivar, value|
6
+ ivar.should == value
7
7
  end
8
8
 
9
- Then "@x should be a :class" do |klass|
10
- @x.class.should == klass
9
+ Then ":ivar should be a :class" do |ivar, klass|
10
+ ivar.should be_kind_of(klass)
11
11
  end
12
12
 
13
- Then /^@x should evaluate to (.*)$/ do |expression|
14
- @x.should == eval(expression)
15
- end
13
+ Pattern /a|an/
14
+ Pattern /is|are/
16
15
 
17
- Pattern :class, /([A-Z][a-z]+)/ do |class_name|
18
- Object.const_get(class_name)
16
+ Pattern :class, /([A-Z]\w*(?:::[A-Z]\w*)*)/ do |class_name|
17
+ class_name.split(/::/).inject(Object) do |klass, subname|
18
+ klass.const_get(subname)
19
+ end
19
20
  end
20
21
 
21
- Pattern :integer, /(-?\d+)/ do |number|
22
- number.to_i
22
+ Pattern :ivar, /(@\w+)/ do |ivar_name|
23
+ instance_variable_get(ivar_name)
23
24
  end
24
25
 
25
- Pattern :list_of_integers, /(-?\d+(?: *(?:,|and) *-?\d+)*)/ do |list|
26
- list.split(/ *(?:,|and) */).map{|number| number.to_i}
27
- end
26
+ Pattern :ivar_name, /(@\w+)/
28
27
 
29
- PatternGenerator do |key|
30
- %w[a an].include?(key) and /a|an/
28
+ Pattern :value, /(.*)/ do |expression|
29
+ eval(expression)
31
30
  end
32
-
33
- ## This PatternGenerator would enable automatic singularize/pluralize of ALL words
34
- ## so you don't have to resort to regexp construction for steps just do deal with
35
- ## pluralization related nonsense.
36
- #
37
- # PatternGenerator do |key|
38
- # Regexp.new([Regexp.escape(key.singularize), Regexp.escape(key.pluralize)].join('|'))
39
- # end
data/lib/cuke-patterns.rb CHANGED
@@ -3,5 +3,6 @@ end
3
3
 
4
4
  require 'cuke-patterns/rb_dsl_ext'
5
5
  require 'cuke-patterns/rb_language_ext'
6
+ require 'cuke-patterns/rb_world_ext'
6
7
  require 'cuke-patterns/step_mother_ext'
7
8
 
@@ -1,8 +1,12 @@
1
1
  module CukePatterns
2
2
  module RbDslExt
3
3
 
4
- def register_rb_cuke_pattern(name, regexp, &proc)
5
- @rb_language.register_rb_cuke_pattern(name, regexp, &proc)
4
+ def apply_rb_cuke_pattern(name, string)
5
+ @rb_language.apply_rb_cuke_pattern(name, string)
6
+ end
7
+
8
+ def register_rb_cuke_pattern(*args, &proc)
9
+ @rb_language.register_rb_cuke_pattern(*args, &proc)
6
10
  end
7
11
 
8
12
  def register_rb_cuke_pattern_generator(&proc)
@@ -15,8 +19,8 @@ end
15
19
  Cucumber::RbSupport::RbDsl.module_eval do
16
20
  extend CukePatterns::RbDslExt
17
21
 
18
- def Pattern(name, regexp, &proc)
19
- Cucumber::RbSupport::RbDsl.register_rb_cuke_pattern(name, regexp, &proc)
22
+ def Pattern(*args, &proc)
23
+ Cucumber::RbSupport::RbDsl.register_rb_cuke_pattern(*args, &proc)
20
24
  end
21
25
 
22
26
  def PatternGenerator(&proc)
@@ -25,7 +25,7 @@ module CukePatterns
25
25
  end
26
26
 
27
27
  def cuke_patterns
28
- @cuke_patterns ||= Hash.new {|hash, key| default_cuke_pattern(key)}
28
+ @cuke_patterns ||= {}
29
29
  end
30
30
 
31
31
  # Hook this method to automatically generate regexp matches for words in step
@@ -33,7 +33,7 @@ module CukePatterns
33
33
  def default_cuke_pattern(key)
34
34
  default_cuke_pattern_generators.each do |generator|
35
35
  regexp, proc = generator[key]
36
- return [regexp, proc] if regexp
36
+ return regexp, proc if regexp
37
37
  end
38
38
  return nil
39
39
  end
@@ -42,8 +42,45 @@ module CukePatterns
42
42
  @default_cuke_pattern_generators ||= []
43
43
  end
44
44
 
45
- def register_rb_cuke_pattern(name, regexp, &conversion_proc)
46
- name = ":#{name}" if name.is_a?(Symbol) # so :user becomes ':user'
45
+ def apply_rb_cuke_pattern(name, string)
46
+ name = ":#{name}" if name.is_a?(Symbol)
47
+ regexp, proc = lookup_cuke_pattern(name)
48
+ match = regexp.match(string)
49
+ raise "Pattern #{regexp.to_s} does not match #{string.inspect}" unless match
50
+ return instance_exec(*match.captures, &proc) if proc
51
+ return match.to_s
52
+ end
53
+
54
+ def lookup_cuke_pattern(name)
55
+ keys, regexp, proc = [], nil, nil
56
+ cuke_patterns.each do |key, value|
57
+ if key === name
58
+ keys << key
59
+ regexp, proc = value
60
+ end
61
+ end
62
+ return default_cuke_pattern(name) if keys.empty?
63
+ return regexp, proc if keys.length == 1
64
+ raise "Ambiguous Pattern for #{name.inspect}: #{keys.inspect}"
65
+ end
66
+
67
+ def register_rb_cuke_pattern(*args, &conversion_proc)
68
+ if args.length == 1
69
+ if args.first.is_a?(Hash)
70
+ args.first.each do |key, value|
71
+ register_rb_cuke_pattern(key, value, &conversion_proc)
72
+ end
73
+ return
74
+ else
75
+ # We wrap the key form of the regexp in begin/end
76
+ # so that we match only whole tokens when doing lookup
77
+ name = Regexp.new("^(?:#{args.first})$")
78
+ regexp = args.first
79
+ end
80
+ elsif args.length == 2
81
+ name, regexp = args
82
+ name = ":#{name}" if name.is_a?(Symbol) # so :user becomes ':user'
83
+ end
47
84
 
48
85
  if conversion_proc
49
86
  # Count the capturing '(' characters to get the pattern arity
@@ -83,7 +120,7 @@ module CukePatterns
83
120
  # Split the string by non-alphanumeric, underscore or leading-colon characters
84
121
  matcher.scan(/(:?\w+)|([^:\w]+|:)/) do |candidate, non_candidate|
85
122
 
86
- regexp, conversion_proc = cuke_patterns[candidate] if candidate
123
+ regexp, conversion_proc = lookup_cuke_pattern(candidate) if candidate
87
124
 
88
125
  if non_candidate or not regexp
89
126
  matcher_regexp << Regexp.escape(candidate || non_candidate)
@@ -0,0 +1,15 @@
1
+ module CukePatterns
2
+
3
+ module RbWorldExt
4
+
5
+ def Pattern(name, string)
6
+ Cucumber::RbSupport::RbDsl.apply_rb_cuke_pattern(name, string)
7
+ end
8
+
9
+ end
10
+
11
+ end
12
+
13
+ Cucumber::RbSupport::RbWorld.module_eval do
14
+ include CukePatterns::RbWorldExt
15
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 3
9
- version: 0.1.3
8
+ - 4
9
+ version: 0.1.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Brendan Baldwin
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-16 00:00:00 -07:00
17
+ date: 2010-08-18 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -34,14 +34,17 @@ files:
34
34
  - Rakefile
35
35
  - VERSION
36
36
  - cuke-patterns.gemspec
37
- - features/no_regressions_in_normal_cukes.feature
38
- - features/simple_cuke_patterns.feature
39
- - features/step_definitions/no_regression_steps.rb
37
+ - features/apply_pattern.feature
38
+ - features/apply_pattern_steps.rb
39
+ - features/pattern_generator.feature
40
+ - features/simple_patterns.feature
41
+ - features/step_definitions/pattern_generator_steps.rb
40
42
  - features/step_definitions/simple_pattern_steps.rb
41
43
  - features/support/env.rb
42
44
  - lib/cuke-patterns.rb
43
45
  - lib/cuke-patterns/rb_dsl_ext.rb
44
46
  - lib/cuke-patterns/rb_language_ext.rb
47
+ - lib/cuke-patterns/rb_world_ext.rb
45
48
  - lib/cuke-patterns/step_mother_ext.rb
46
49
  has_rdoc: true
47
50
  homepage: http://github.com/brendan/cuke-patterns
@@ -1,9 +0,0 @@
1
- Feature: No regressions in normal cukes
2
- In order for anyone to want to use this cuke-patterns gem
3
- As a developer of cuke-patterns
4
- I want to ensure this doesn't screw anything up
5
-
6
- Scenario: Simple regexp matched scenario
7
- Given a typical given step
8
- When a typical when step
9
- Then a typical then step
@@ -1,16 +0,0 @@
1
- Feature: Simple Cuke Patterns
2
-
3
- Scenario: Transform string of digits into Fixnum
4
- When @x is 1234
5
- Then @x should be a Fixnum
6
- And @x should evaluate to 1234
7
-
8
- Scenario: Transform digits with negative sign into Fixnum
9
- When @x is -1234
10
- Then @x should be a Fixnum
11
- And @x should evaluate to -1234
12
-
13
- Scenario: Transform a list to an array of Fixnums
14
- When @x contains 1, 2, 3 and 4
15
- Then @x should be an Array
16
- And @x should evaluate to [1, 2, 3, 4]
@@ -1,6 +0,0 @@
1
- Given /^a typical given step$/ do
2
- end
3
- When /^a typical when step$/ do
4
- end
5
- Then /^a typical then step$/ do
6
- end