cucumber-cucumber-expressions 8.3.1 → 19.0.0
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.
- checksums.yaml +4 -4
- data/LICENSE +2 -2
- data/lib/cucumber/cucumber_expressions/argument.rb +8 -4
- data/lib/cucumber/cucumber_expressions/ast.rb +166 -0
- data/lib/cucumber/cucumber_expressions/combinatorial_generated_expression_factory.rb +6 -13
- data/lib/cucumber/cucumber_expressions/cucumber_expression.rb +82 -80
- data/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +14 -26
- data/lib/cucumber/cucumber_expressions/cucumber_expression_parser.rb +203 -0
- data/lib/cucumber/cucumber_expressions/cucumber_expression_tokenizer.rb +90 -0
- data/lib/cucumber/cucumber_expressions/errors.rb +205 -13
- data/lib/cucumber/cucumber_expressions/expression_factory.rb +24 -0
- data/lib/cucumber/cucumber_expressions/generated_expression.rb +2 -0
- data/lib/cucumber/cucumber_expressions/group.rb +7 -1
- data/lib/cucumber/cucumber_expressions/group_builder.rb +9 -2
- data/lib/cucumber/cucumber_expressions/parameter_type.rb +14 -21
- data/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb +11 -9
- data/lib/cucumber/cucumber_expressions/parameter_type_registry.rb +28 -16
- data/lib/cucumber/cucumber_expressions/regular_expression.rb +3 -2
- data/lib/cucumber/cucumber_expressions/tree_regexp.rb +54 -46
- metadata +76 -77
- data/.github/ISSUE_TEMPLATE.md +0 -5
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -5
- data/.rspec +0 -1
- data/.rsync +0 -4
- data/.subrepo +0 -1
- data/Gemfile +0 -3
- data/Makefile +0 -1
- data/README.md +0 -5
- data/Rakefile +0 -27
- data/cucumber-cucumber-expressions.gemspec +0 -33
- data/default.mk +0 -70
- data/examples.txt +0 -31
- data/scripts/update-gemspec +0 -32
- data/spec/capture_warnings.rb +0 -74
- data/spec/coverage.rb +0 -7
- data/spec/cucumber/cucumber_expressions/argument_spec.rb +0 -17
- data/spec/cucumber/cucumber_expressions/combinatorial_generated_expression_factory_test.rb +0 -43
- data/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb +0 -231
- data/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb +0 -57
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +0 -212
- data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +0 -202
- data/spec/cucumber/cucumber_expressions/expression_examples_spec.rb +0 -30
- data/spec/cucumber/cucumber_expressions/parameter_type_registry_spec.rb +0 -86
- data/spec/cucumber/cucumber_expressions/parameter_type_spec.rb +0 -15
- data/spec/cucumber/cucumber_expressions/regular_expression_spec.rb +0 -80
- data/spec/cucumber/cucumber_expressions/tree_regexp_spec.rb +0 -133
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/cucumber_expression'
|
|
2
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
3
|
-
|
|
4
|
-
module Cucumber
|
|
5
|
-
module CucumberExpressions
|
|
6
|
-
describe CucumberExpression do
|
|
7
|
-
it "documents match arguments" do
|
|
8
|
-
parameter_registry = ParameterTypeRegistry.new
|
|
9
|
-
|
|
10
|
-
### [capture-match-arguments]
|
|
11
|
-
expr = "I have {int} cuke(s)"
|
|
12
|
-
expression = CucumberExpression.new(expr, parameter_registry)
|
|
13
|
-
args = expression.match("I have 7 cukes")
|
|
14
|
-
expect(args[0].value(nil)).to eq(7)
|
|
15
|
-
### [capture-match-arguments]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "matches word" do
|
|
19
|
-
expect(match("three {word} mice", "three blind mice")).to eq(['blind'])
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it('matches double quoted string') do
|
|
23
|
-
expect(match('three {string} mice', 'three "blind" mice')).to eq(['blind'])
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it('matches multiple double quoted strings') do
|
|
27
|
-
expect(match('three {string} and {string} mice', 'three "blind" and "crippled" mice')).to eq(['blind', 'crippled'])
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it('matches single quoted string') do
|
|
31
|
-
expect(match('three {string} mice', "three 'blind' mice")).to eq(['blind'])
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it('matches multiple single quoted strings') do
|
|
35
|
-
expect(match('three {string} and {string} mice', "three 'blind' and 'crippled' mice")).to eq(['blind', 'crippled'])
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it('does not match misquoted string') do
|
|
39
|
-
expect(match('three {string} mice', 'three "blind\' mice')).to eq(nil)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it('matches single quoted string with double quotes') do
|
|
43
|
-
expect(match('three {string} mice', 'three \'"blind"\' mice')).to eq(['"blind"'])
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it('matches double quoted string with single quotes') do
|
|
47
|
-
expect(match('three {string} mice', 'three "\'blind\'" mice')).to eq(["'blind'"])
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it('matches double quoted string with escaped double quote') do
|
|
51
|
-
expect(match('three {string} mice', 'three "bl\\"nd" mice')).to eq(['bl"nd'])
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it('matches single quoted string with escaped single quote') do
|
|
55
|
-
expect(match('three {string} mice', "three 'bl\\'nd' mice")).to eq(["bl'nd"])
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it('matches single quoted empty string as empty string') do
|
|
59
|
-
expect(match('three {string} mice', "three '' mice")).to eq([''])
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it('matches double quoted empty string as empty string') do
|
|
63
|
-
expect(match('three {string} mice', 'three "" mice')).to eq([''])
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it('matches single quoted empty string as empty string, along with other strings') do
|
|
67
|
-
expect(match('three {string} and {string} mice', "three '' and 'handsome' mice")).to eq(['', 'handsome'])
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it('matches double quoted empty string as empty string, along with other strings') do
|
|
71
|
-
expect(match('three {string} and {string} mice', 'three "" and "handsome" mice')).to eq(['', 'handsome'])
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it 'matches escaped parentheses' do
|
|
75
|
-
expect(match('three \\(exceptionally) {string} mice', 'three (exceptionally) "blind" mice')).to eq(['blind'])
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "matches escaped slash" do
|
|
79
|
-
expect(match("12\\/2020", "12/2020")).to eq([])
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "matches int" do
|
|
83
|
-
expect(match("{int}", "22")).to eq([22])
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "doesn't match float as int" do
|
|
87
|
-
expect(match("{int}", "1.22")).to be_nil
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it "matches int as float" do
|
|
91
|
-
expect(match("{float}", "0")).to eq([0.0])
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it "matches float" do
|
|
95
|
-
expect(match("{float}", "")).to eq(nil)
|
|
96
|
-
expect(match("{float}", ".")).to eq(nil)
|
|
97
|
-
expect(match("{float}", ",")).to eq(nil)
|
|
98
|
-
expect(match("{float}", "-")).to eq(nil)
|
|
99
|
-
expect(match("{float}", "E")).to eq(nil)
|
|
100
|
-
expect(match("{float}", "1,")).to eq(nil)
|
|
101
|
-
expect(match("{float}", ",1")).to eq(nil)
|
|
102
|
-
expect(match("{float}", "1.")).to eq(nil)
|
|
103
|
-
|
|
104
|
-
expect(match("{float}", "1")).to eq([1])
|
|
105
|
-
expect(match("{float}", "-1")).to eq([-1])
|
|
106
|
-
expect(match("{float}", "1.1")).to eq([1.1])
|
|
107
|
-
expect(match("{float}", "1,000")).to eq(nil)
|
|
108
|
-
expect(match("{float}", "1,000,0")).to eq(nil)
|
|
109
|
-
expect(match("{float}", "1,000.1")).to eq(nil)
|
|
110
|
-
expect(match("{float}", "1,000,10")).to eq(nil)
|
|
111
|
-
expect(match("{float}", "1,0.1")).to eq(nil)
|
|
112
|
-
expect(match("{float}", "1,000,000.1")).to eq(nil)
|
|
113
|
-
expect(match("{float}", "-1.1")).to eq([-1.1])
|
|
114
|
-
|
|
115
|
-
expect(match("{float}", ".1")).to eq([0.1])
|
|
116
|
-
expect(match("{float}", "-.1")).to eq([-0.1])
|
|
117
|
-
expect(match("{float}", "-.1000001")).to eq([-0.1000001])
|
|
118
|
-
expect(match("{float}", "1E1")).to eq([10.0])
|
|
119
|
-
expect(match("{float}", ".1E1")).to eq([1])
|
|
120
|
-
expect(match("{float}", "E1")).to eq(nil)
|
|
121
|
-
expect(match("{float}", "-.1E-1")).to eq([-0.01])
|
|
122
|
-
expect(match("{float}", "-.1E-2")).to eq([-0.001])
|
|
123
|
-
expect(match("{float}", "-.1E+1")).to eq([-1])
|
|
124
|
-
expect(match("{float}", "-.1E+2")).to eq([-10])
|
|
125
|
-
expect(match("{float}", "-.1E1")).to eq([-1])
|
|
126
|
-
expect(match("{float}", "-.1E2")).to eq([-10])
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
it "matches anonymous" do
|
|
130
|
-
expect(match("{}", "0.22")).to eq(["0.22"])
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
'[]()$.|?*+'.split('').each do |char|
|
|
134
|
-
it "does not allow parameter type with #{char}" do
|
|
135
|
-
expect {match("{#{char}string}", "something")}.to raise_error("Illegal character '#{char}' in parameter name {#{char}string}")
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
it "throws unknown parameter type" do
|
|
140
|
-
expect {match("{unknown}", "something")}.to raise_error('Undefined parameter type {unknown}')
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "does not allow optional parameter types" do
|
|
144
|
-
expect {match("({int})", "3")}.to raise_error('Parameter types cannot be optional: ({int})')
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
it "does allow escaped optional parameter types" do
|
|
148
|
-
expect(match("\\({int})", "(3)")).to eq([3])
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "does not allow text/parameter type alternation" do
|
|
152
|
-
expect {match("x/{int}", "3")}.to raise_error('Parameter types cannot be alternative: x/{int}')
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "does not allow parameter type/text alternation" do
|
|
156
|
-
expect {match("{int}/x", "3")}.to raise_error('Parameter types cannot be alternative: {int}/x')
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
it "exposes source" do
|
|
160
|
-
expr = "I have {int} cuke(s)"
|
|
161
|
-
expect(CucumberExpression.new(expr, ParameterTypeRegistry.new).source).to eq(expr)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
it "delegates transform to custom object" do
|
|
165
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
|
166
|
-
parameter_type_registry.define_parameter_type(
|
|
167
|
-
ParameterType.new(
|
|
168
|
-
'widget',
|
|
169
|
-
/\w+/,
|
|
170
|
-
Object,
|
|
171
|
-
-> (s) {
|
|
172
|
-
self.create_widget(s)
|
|
173
|
-
},
|
|
174
|
-
false,
|
|
175
|
-
true
|
|
176
|
-
)
|
|
177
|
-
)
|
|
178
|
-
expression = CucumberExpression.new(
|
|
179
|
-
'I have a {widget}',
|
|
180
|
-
parameter_type_registry
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
class World
|
|
184
|
-
def create_widget(s)
|
|
185
|
-
"widget:#{s}"
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
args = expression.match("I have a bolt")
|
|
190
|
-
expect(args[0].value(World.new)).to eq('widget:bolt')
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
describe "escapes special characters" do
|
|
194
|
-
%w(\\ [ ] ^ $ . | ? * +).each do |character|
|
|
195
|
-
it "escapes #{character}" do
|
|
196
|
-
expr = "I have {int} cuke(s) and #{character}"
|
|
197
|
-
expression = CucumberExpression.new(expr, ParameterTypeRegistry.new)
|
|
198
|
-
arg1 = expression.match("I have 800 cukes and #{character}")[0]
|
|
199
|
-
expect(arg1.value(nil)).to eq(800)
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def match(expression, text)
|
|
205
|
-
cucumber_expression = CucumberExpression.new(expression, ParameterTypeRegistry.new)
|
|
206
|
-
args = cucumber_expression.match(text)
|
|
207
|
-
return nil if args.nil?
|
|
208
|
-
args.map {|arg| arg.value(nil)}
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
end
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/cucumber_expression'
|
|
2
|
-
require 'cucumber/cucumber_expressions/regular_expression'
|
|
3
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
4
|
-
|
|
5
|
-
module Cucumber
|
|
6
|
-
module CucumberExpressions
|
|
7
|
-
class Color
|
|
8
|
-
attr_reader :name
|
|
9
|
-
|
|
10
|
-
### [color-constructor]
|
|
11
|
-
def initialize(name)
|
|
12
|
-
@name = name
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
### [color-constructor]
|
|
16
|
-
|
|
17
|
-
def ==(other)
|
|
18
|
-
other.is_a?(Color) && other.name == name
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class CssColor
|
|
23
|
-
attr_reader :name
|
|
24
|
-
|
|
25
|
-
def initialize(name)
|
|
26
|
-
@name = name
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def ==(other)
|
|
30
|
-
other.is_a?(CssColor) && other.name == name
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
class Coordinate
|
|
35
|
-
attr_reader :x, :y, :z
|
|
36
|
-
|
|
37
|
-
def initialize(x, y, z)
|
|
38
|
-
@x, @y, @z = x, y, z
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def ==(other)
|
|
42
|
-
other.is_a?(Coordinate) && other.x == x && other.y == y && other.z == z
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe "Custom parameter type" do
|
|
47
|
-
before do
|
|
48
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
|
49
|
-
### [add-color-parameter-type]
|
|
50
|
-
parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
51
|
-
'color', # name
|
|
52
|
-
/red|blue|yellow/, # regexp
|
|
53
|
-
Color, # type
|
|
54
|
-
lambda {|s| Color.new(s)}, # transform
|
|
55
|
-
true, # use_for_snippets
|
|
56
|
-
false # prefer_for_regexp_match
|
|
57
|
-
))
|
|
58
|
-
### [add-color-parameter-type]
|
|
59
|
-
@parameter_type_registry = parameter_type_registry
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "throws exception for illegal character in parameter name" do
|
|
63
|
-
expect do
|
|
64
|
-
ParameterType.new(
|
|
65
|
-
'[string]',
|
|
66
|
-
/.*/,
|
|
67
|
-
String,
|
|
68
|
-
lambda {|s| s},
|
|
69
|
-
true,
|
|
70
|
-
false
|
|
71
|
-
)
|
|
72
|
-
end.to raise_error("Illegal character '[' in parameter name {[string]}")
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe CucumberExpression do
|
|
76
|
-
it "matches parameters with custom parameter type" do
|
|
77
|
-
expression = CucumberExpression.new("I have a {color} ball", @parameter_type_registry)
|
|
78
|
-
transformed_argument_value = expression.match("I have a red ball")[0].value(nil)
|
|
79
|
-
expect(transformed_argument_value).to eq(Color.new('red'))
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "matches parameters with multiple capture groups" do
|
|
83
|
-
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
84
|
-
'coordinate',
|
|
85
|
-
/(\d+),\s*(\d+),\s*(\d+)/,
|
|
86
|
-
Coordinate,
|
|
87
|
-
lambda {|x, y, z| Coordinate.new(x.to_i, y.to_i, z.to_i)},
|
|
88
|
-
true,
|
|
89
|
-
false
|
|
90
|
-
))
|
|
91
|
-
|
|
92
|
-
expression = CucumberExpression.new(
|
|
93
|
-
'A {int} thick line from {coordinate} to {coordinate}',
|
|
94
|
-
@parameter_type_registry
|
|
95
|
-
)
|
|
96
|
-
args = expression.match('A 5 thick line from 10,20,30 to 40,50,60')
|
|
97
|
-
|
|
98
|
-
thick = args[0].value(nil)
|
|
99
|
-
expect(thick).to eq(5)
|
|
100
|
-
|
|
101
|
-
from = args[1].value(nil)
|
|
102
|
-
expect(from).to eq(Coordinate.new(10, 20, 30))
|
|
103
|
-
|
|
104
|
-
to = args[2].value(nil)
|
|
105
|
-
expect(to).to eq(Coordinate.new(40, 50, 60))
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "matches parameters with custom parameter type using optional capture group" do
|
|
109
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
|
110
|
-
parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
111
|
-
'color',
|
|
112
|
-
[/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/],
|
|
113
|
-
Color,
|
|
114
|
-
lambda {|s| Color.new(s)},
|
|
115
|
-
true,
|
|
116
|
-
false
|
|
117
|
-
))
|
|
118
|
-
expression = CucumberExpression.new("I have a {color} ball", parameter_type_registry)
|
|
119
|
-
transformed_argument_value = expression.match("I have a dark red ball")[0].value(nil)
|
|
120
|
-
expect(transformed_argument_value).to eq(Color.new('dark red'))
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it "defers transformation until queried from argument" do
|
|
124
|
-
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
125
|
-
'throwing',
|
|
126
|
-
/bad/,
|
|
127
|
-
CssColor,
|
|
128
|
-
lambda {|s| raise "Can't transform [#{s}]"},
|
|
129
|
-
true,
|
|
130
|
-
false
|
|
131
|
-
))
|
|
132
|
-
expression = CucumberExpression.new("I have a {throwing} parameter", @parameter_type_registry)
|
|
133
|
-
args = expression.match("I have a bad parameter")
|
|
134
|
-
expect {args[0].value(nil)}.to raise_error("Can't transform [bad]")
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
describe "conflicting parameter type" do
|
|
138
|
-
it "is detected for type name" do
|
|
139
|
-
expect {
|
|
140
|
-
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
141
|
-
'color',
|
|
142
|
-
/.*/,
|
|
143
|
-
CssColor,
|
|
144
|
-
lambda {|s| CssColor.new(s)},
|
|
145
|
-
true,
|
|
146
|
-
false
|
|
147
|
-
))
|
|
148
|
-
}.to raise_error("There is already a parameter with name color")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "is not detected for type" do
|
|
152
|
-
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
153
|
-
'whatever',
|
|
154
|
-
/.*/,
|
|
155
|
-
Color,
|
|
156
|
-
lambda {|s| Color.new(s)},
|
|
157
|
-
false,
|
|
158
|
-
false
|
|
159
|
-
))
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
it "is not detected for regexp" do
|
|
163
|
-
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
164
|
-
'css-color',
|
|
165
|
-
/red|blue|yellow/,
|
|
166
|
-
CssColor,
|
|
167
|
-
lambda {|s| CssColor.new(s)},
|
|
168
|
-
true,
|
|
169
|
-
false
|
|
170
|
-
))
|
|
171
|
-
|
|
172
|
-
css_color = CucumberExpression.new("I have a {css-color} ball", @parameter_type_registry)
|
|
173
|
-
css_color_value = css_color.match("I have a blue ball")[0].value(nil)
|
|
174
|
-
expect(css_color_value).to eq(CssColor.new("blue"))
|
|
175
|
-
|
|
176
|
-
color = CucumberExpression.new("I have a {color} ball", @parameter_type_registry)
|
|
177
|
-
color_value = color.match("I have a blue ball")[0].value(nil)
|
|
178
|
-
expect(color_value).to eq(Color.new("blue"))
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
describe RegularExpression do
|
|
184
|
-
it "matches arguments with custom parameter type without name" do
|
|
185
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
|
186
|
-
parameter_type_registry.define_parameter_type(ParameterType.new(
|
|
187
|
-
nil,
|
|
188
|
-
/red|blue|yellow/,
|
|
189
|
-
Color,
|
|
190
|
-
lambda {|s| Color.new(s)},
|
|
191
|
-
true,
|
|
192
|
-
false
|
|
193
|
-
))
|
|
194
|
-
|
|
195
|
-
expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, parameter_type_registry)
|
|
196
|
-
value = expression.match("I have a red ball")[0].value(nil)
|
|
197
|
-
expect(value).to eq(Color.new('red'))
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/cucumber_expression'
|
|
2
|
-
require 'cucumber/cucumber_expressions/regular_expression'
|
|
3
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
4
|
-
require 'json'
|
|
5
|
-
|
|
6
|
-
module Cucumber
|
|
7
|
-
module CucumberExpressions
|
|
8
|
-
describe 'examples.txt' do
|
|
9
|
-
def match(expression_text, text)
|
|
10
|
-
expression = expression_text =~ /\/(.*)\// ?
|
|
11
|
-
RegularExpression.new(Regexp.new($1), ParameterTypeRegistry.new) :
|
|
12
|
-
CucumberExpression.new(expression_text, ParameterTypeRegistry.new)
|
|
13
|
-
|
|
14
|
-
arguments = expression.match(text)
|
|
15
|
-
return nil if arguments.nil?
|
|
16
|
-
arguments.map { |arg| arg.value(nil) }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
File.open(File.expand_path("../../../../examples.txt", __FILE__), "r:utf-8") do |io|
|
|
20
|
-
chunks = io.read.split(/^---/m)
|
|
21
|
-
chunks.each do |chunk|
|
|
22
|
-
expression_text, text, expected_args = *chunk.strip.split(/\n/m)
|
|
23
|
-
it "Works with: #{expression_text}" do
|
|
24
|
-
expect( match(expression_text, text).to_json ).to eq(expected_args)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
2
|
-
require 'cucumber/cucumber_expressions/parameter_type'
|
|
3
|
-
require 'cucumber/cucumber_expressions/errors'
|
|
4
|
-
|
|
5
|
-
module Cucumber
|
|
6
|
-
module CucumberExpressions
|
|
7
|
-
|
|
8
|
-
CAPITALISED_WORD = /[A-Z]+\w+/
|
|
9
|
-
|
|
10
|
-
class Name
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
class Person
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class Place
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe ParameterTypeRegistry do
|
|
20
|
-
before do
|
|
21
|
-
@registry = ParameterTypeRegistry.new
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it 'does not allow more than one prefer_for_regexp_match parameter type for each regexp' do
|
|
25
|
-
@registry.define_parameter_type(ParameterType.new("name", CAPITALISED_WORD, Name, lambda {|s| Name.new}, true, true))
|
|
26
|
-
@registry.define_parameter_type(ParameterType.new("person", CAPITALISED_WORD, Person, lambda {|s| Person.new}, true, false))
|
|
27
|
-
expect do
|
|
28
|
-
@registry.define_parameter_type(ParameterType.new("place", CAPITALISED_WORD, Place, lambda {|s| Place.new}, true, true))
|
|
29
|
-
end.to raise_error(
|
|
30
|
-
CucumberExpressionError,
|
|
31
|
-
"There can only be one preferential parameter type per regexp. The regexp /[A-Z]+\\w+/ is used for two preferential parameter types, {name} and {place}"
|
|
32
|
-
)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'looks up prefer_for_regexp_match parameter type by regexp' do
|
|
36
|
-
name = ParameterType.new("name", CAPITALISED_WORD, Name, lambda {|s| Name.new}, true, false)
|
|
37
|
-
person = ParameterType.new("person", CAPITALISED_WORD, Person, lambda {|s| Person.new}, true, true)
|
|
38
|
-
place = ParameterType.new("place", CAPITALISED_WORD, Place, lambda {|s| Place.new}, true, false)
|
|
39
|
-
|
|
40
|
-
@registry.define_parameter_type(name)
|
|
41
|
-
@registry.define_parameter_type(person)
|
|
42
|
-
@registry.define_parameter_type(place)
|
|
43
|
-
|
|
44
|
-
expect(@registry.lookup_by_regexp(CAPITALISED_WORD.source, /([A-Z]+\w+) and ([A-Z]+\w+)/, "Lisa and Bob")).to eq(person)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it 'throws ambiguous exception when no parameter types are prefer_for_regexp_match' do
|
|
48
|
-
name = ParameterType.new("name", CAPITALISED_WORD, Name, lambda {|s| Name.new}, true, false)
|
|
49
|
-
person = ParameterType.new("person", CAPITALISED_WORD, Person, lambda {|s| Person.new}, true, false)
|
|
50
|
-
place = ParameterType.new("place", CAPITALISED_WORD, Place, lambda {|s| Place.new}, true, false)
|
|
51
|
-
|
|
52
|
-
@registry.define_parameter_type(name)
|
|
53
|
-
@registry.define_parameter_type(person)
|
|
54
|
-
@registry.define_parameter_type(place)
|
|
55
|
-
|
|
56
|
-
expect do
|
|
57
|
-
expect(@registry.lookup_by_regexp(CAPITALISED_WORD.source, /([A-Z]+\w+) and ([A-Z]+\w+)/, "Lisa and Bob")).to eq(person)
|
|
58
|
-
end.to raise_error(
|
|
59
|
-
CucumberExpressionError,
|
|
60
|
-
"Your Regular Expression /([A-Z]+\\w+) and ([A-Z]+\\w+)/\n" +
|
|
61
|
-
"matches multiple parameter types with regexp /[A-Z]+\\w+/:\n" +
|
|
62
|
-
" {name}\n" +
|
|
63
|
-
" {person}\n" +
|
|
64
|
-
" {place}\n" +
|
|
65
|
-
"\n" +
|
|
66
|
-
"I couldn't decide which one to use. You have two options:\n" +
|
|
67
|
-
"\n" +
|
|
68
|
-
"1) Use a Cucumber Expression instead of a Regular Expression. Try one of these:\n" +
|
|
69
|
-
" {name} and {name}\n" +
|
|
70
|
-
" {name} and {person}\n" +
|
|
71
|
-
" {name} and {place}\n" +
|
|
72
|
-
" {person} and {name}\n" +
|
|
73
|
-
" {person} and {person}\n" +
|
|
74
|
-
" {person} and {place}\n" +
|
|
75
|
-
" {place} and {name}\n" +
|
|
76
|
-
" {place} and {person}\n" +
|
|
77
|
-
" {place} and {place}\n" +
|
|
78
|
-
"\n" +
|
|
79
|
-
"2) Make one of the parameter types preferential and continue to use a Regular Expression.\n" +
|
|
80
|
-
"\n"
|
|
81
|
-
)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/parameter_type'
|
|
2
|
-
|
|
3
|
-
module Cucumber
|
|
4
|
-
module CucumberExpressions
|
|
5
|
-
describe ParameterType do
|
|
6
|
-
it 'does not allow ignore flag on regexp' do
|
|
7
|
-
expect do
|
|
8
|
-
ParameterType.new("case-insensitive", /[a-z]+/i, String, lambda {|s| s}, true, true)
|
|
9
|
-
end.to raise_error(
|
|
10
|
-
CucumberExpressionError,
|
|
11
|
-
"ParameterType Regexps can't use option Regexp::IGNORECASE")
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
require 'cucumber/cucumber_expressions/regular_expression'
|
|
2
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
3
|
-
|
|
4
|
-
module Cucumber
|
|
5
|
-
module CucumberExpressions
|
|
6
|
-
describe RegularExpression do
|
|
7
|
-
it "documents match arguments" do
|
|
8
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
|
9
|
-
|
|
10
|
-
### [capture-match-arguments]
|
|
11
|
-
expr = /I have (\d+) cukes? in my (\w*) now/
|
|
12
|
-
expression = RegularExpression.new(expr, parameter_type_registry)
|
|
13
|
-
args = expression.match("I have 7 cukes in my belly now")
|
|
14
|
-
expect( args[0].value(nil) ).to eq(7)
|
|
15
|
-
expect( args[1].value(nil) ).to eq("belly")
|
|
16
|
-
### [capture-match-arguments]
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "does no transform by default" do
|
|
20
|
-
expect( match(/(\d\d)/, "22") ).to eq(["22"])
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it "does not transform anonymous" do
|
|
24
|
-
expect( match(/(.*)/, "22") ).to eq(["22"])
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it "transforms negative int" do
|
|
28
|
-
expect( match(/(-?\d+)/, "-22") ).to eq([-22])
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "transforms positive int" do
|
|
32
|
-
expect( match(/(\d+)/, "22") ).to eq([22])
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "returns nil when there is no match" do
|
|
36
|
-
expect( match(/hello/, "world") ).to be_nil
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "matches nested capture group without match" do
|
|
40
|
-
expect( match(/^a user( named "([^"]*)")?$/, 'a user') ).to eq([nil])
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "matches nested capture group with match" do
|
|
44
|
-
expect( match(/^a user( named "([^"]*)")?$/, 'a user named "Charlie"') ).to eq(['Charlie'])
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "ignores non capturing groups" do
|
|
48
|
-
expect( match(
|
|
49
|
-
/(\S+) ?(can|cannot) (?:delete|cancel) the (\d+)(?:st|nd|rd|th) (attachment|slide) ?(?:upload)?/,
|
|
50
|
-
"I can cancel the 1st slide upload")
|
|
51
|
-
).to eq(["I", "can", 1, "slide"])
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "matches capture group nested in optional one" do
|
|
55
|
-
regexp = /^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/
|
|
56
|
-
expect( match(regexp, 'a purchase') ).to eq([nil, nil])
|
|
57
|
-
expect( match(regexp, 'a purchase for $33') ).to eq([nil, 33])
|
|
58
|
-
expect( match(regexp, 'a pre buyer fee model purchase') ).to eq(['pre buyer fee model ', nil])
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it "works with escaped parenthesis" do
|
|
62
|
-
expect( match(/Across the line\(s\)/, 'Across the line(s)') ).to eq([])
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "exposes source and regexp" do
|
|
66
|
-
regexp = /I have (\d+) cukes? in my (\+) now/
|
|
67
|
-
expression = RegularExpression.new(regexp, ParameterTypeRegistry.new)
|
|
68
|
-
expect(expression.regexp).to eq(regexp)
|
|
69
|
-
expect(expression.source).to eq(regexp.source)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def match(expression, text)
|
|
73
|
-
regular_expression = RegularExpression.new(expression, ParameterTypeRegistry.new)
|
|
74
|
-
arguments = regular_expression.match(text)
|
|
75
|
-
return nil if arguments.nil?
|
|
76
|
-
arguments.map { |arg| arg.value(nil) }
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|