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 +1 -1
- data/cuke-patterns.gemspec +8 -5
- data/features/apply_pattern.feature +8 -0
- data/features/apply_pattern_steps.rb +9 -0
- data/features/pattern_generator.feature +13 -0
- data/features/simple_patterns.feature +40 -0
- data/features/step_definitions/pattern_generator_steps.rb +18 -0
- data/features/step_definitions/simple_pattern_steps.rb +17 -26
- data/lib/cuke-patterns.rb +1 -0
- data/lib/cuke-patterns/rb_dsl_ext.rb +8 -4
- data/lib/cuke-patterns/rb_language_ext.rb +42 -5
- data/lib/cuke-patterns/rb_world_ext.rb +15 -0
- metadata +9 -6
- data/features/no_regressions_in_normal_cukes.feature +0 -9
- data/features/simple_cuke_patterns.feature +0 -16
- data/features/step_definitions/no_regression_steps.rb +0 -6
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/cuke-patterns.gemspec
CHANGED
@@ -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.
|
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-
|
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/
|
27
|
-
"features/
|
28
|
-
"features/
|
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,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 "
|
2
|
-
|
1
|
+
When "I assign :ivar_name to :value" do |ivar, value|
|
2
|
+
instance_variable_set(ivar, value)
|
3
3
|
end
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
Then ":ivar should be equal to :value" do |ivar, value|
|
6
|
+
ivar.should == value
|
7
7
|
end
|
8
8
|
|
9
|
-
Then "
|
10
|
-
|
9
|
+
Then ":ivar should be a :class" do |ivar, klass|
|
10
|
+
ivar.should be_kind_of(klass)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
13
|
+
Pattern /a|an/
|
14
|
+
Pattern /is|are/
|
16
15
|
|
17
|
-
Pattern :class, /([A-Z][
|
18
|
-
|
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 :
|
22
|
-
|
22
|
+
Pattern :ivar, /(@\w+)/ do |ivar_name|
|
23
|
+
instance_variable_get(ivar_name)
|
23
24
|
end
|
24
25
|
|
25
|
-
Pattern :
|
26
|
-
list.split(/ *(?:,|and) */).map{|number| number.to_i}
|
27
|
-
end
|
26
|
+
Pattern :ivar_name, /(@\w+)/
|
28
27
|
|
29
|
-
|
30
|
-
|
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
@@ -1,8 +1,12 @@
|
|
1
1
|
module CukePatterns
|
2
2
|
module RbDslExt
|
3
3
|
|
4
|
-
def
|
5
|
-
@rb_language.
|
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(
|
19
|
-
Cucumber::RbSupport::RbDsl.register_rb_cuke_pattern(
|
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 ||=
|
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
|
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
|
46
|
-
name = ":#{name}" if name.is_a?(Symbol)
|
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 =
|
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
|
-
-
|
9
|
-
version: 0.1.
|
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-
|
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/
|
38
|
-
- features/
|
39
|
-
- features/
|
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]
|