cucumber-cucumber-expressions 16.1.2 → 17.0.2
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/.rubocop.yml +37 -0
- data/.rubocop_todo.yml +443 -0
- data/Gemfile +2 -1
- data/Rakefile +4 -17
- data/VERSION +1 -1
- data/cucumber-cucumber-expressions.gemspec +22 -17
- data/lib/cucumber/cucumber_expressions/argument.rb +7 -3
- data/lib/cucumber/cucumber_expressions/ast.rb +24 -59
- data/lib/cucumber/cucumber_expressions/combinatorial_generated_expression_factory.rb +6 -13
- data/lib/cucumber/cucumber_expressions/cucumber_expression.rb +17 -19
- data/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +11 -15
- data/lib/cucumber/cucumber_expressions/cucumber_expression_parser.rb +37 -53
- data/lib/cucumber/cucumber_expressions/cucumber_expression_tokenizer.rb +13 -18
- data/lib/cucumber/cucumber_expressions/errors.rb +121 -103
- data/lib/cucumber/cucumber_expressions/expression_factory.rb +2 -0
- data/lib/cucumber/cucumber_expressions/generated_expression.rb +2 -0
- data/lib/cucumber/cucumber_expressions/group.rb +2 -0
- data/lib/cucumber/cucumber_expressions/group_builder.rb +3 -1
- data/lib/cucumber/cucumber_expressions/parameter_type.rb +14 -26
- data/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb +9 -7
- data/lib/cucumber/cucumber_expressions/parameter_type_registry.rb +27 -22
- data/lib/cucumber/cucumber_expressions/regular_expression.rb +3 -2
- data/lib/cucumber/cucumber_expressions/tree_regexp.rb +8 -7
- data/spec/cucumber/cucumber_expressions/argument_spec.rb +4 -2
- data/spec/cucumber/cucumber_expressions/combinatorial_generated_expression_factory_spec.rb +41 -0
- data/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb +106 -103
- data/spec/cucumber/cucumber_expressions/cucumber_expression_parser_spec.rb +3 -1
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +90 -93
- data/spec/cucumber/cucumber_expressions/cucumber_expression_tokenizer_spec.rb +4 -2
- data/spec/cucumber/cucumber_expressions/cucumber_expression_transformation_spec.rb +4 -2
- data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +80 -61
- data/spec/cucumber/cucumber_expressions/expression_factory_spec.rb +3 -1
- data/spec/cucumber/cucumber_expressions/parameter_type_registry_spec.rb +44 -49
- data/spec/cucumber/cucumber_expressions/parameter_type_spec.rb +5 -2
- data/spec/cucumber/cucumber_expressions/regular_expression_spec.rb +39 -30
- data/spec/cucumber/cucumber_expressions/tree_regexp_spec.rb +49 -49
- metadata +80 -25
- data/.rspec +0 -1
- data/scripts/update-gemspec +0 -32
- data/spec/capture_warnings.rb +0 -74
- data/spec/cucumber/cucumber_expressions/combinatorial_generated_expression_factory_test.rb +0 -43
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cucumber/cucumber_expressions/parameter_type'
|
4
|
+
require 'cucumber/cucumber_expressions/combinatorial_generated_expression_factory'
|
5
|
+
|
6
|
+
describe Cucumber::CucumberExpressions::CombinatorialGeneratedExpressionFactory do
|
7
|
+
let(:klazz) { Class.new }
|
8
|
+
let(:color_parameter_type) do
|
9
|
+
Cucumber::CucumberExpressions::ParameterType.new('color', /red|blue|yellow/, klazz, ->(_) { klazz.new }, true, false)
|
10
|
+
end
|
11
|
+
let(:css_color_parameter_type) do
|
12
|
+
Cucumber::CucumberExpressions::ParameterType.new('csscolor', /red|blue|yellow/, klazz, ->(_) { klazz.new }, true, false)
|
13
|
+
end
|
14
|
+
let(:date_parameter_type) do
|
15
|
+
Cucumber::CucumberExpressions::ParameterType.new('date', /\d{4}-\d{2}-\d{2}/, klazz, ->(_) { klazz.new }, true, false)
|
16
|
+
end
|
17
|
+
let(:date_time_parameter_type) do
|
18
|
+
Cucumber::CucumberExpressions::ParameterType.new('datetime', /\d{4}-\d{2}-\d{2}/, klazz, ->(_) { klazz.new }, true, false)
|
19
|
+
end
|
20
|
+
let(:timestamp_parameter_type) do
|
21
|
+
Cucumber::CucumberExpressions::ParameterType.new('timestamp', /\d{4}-\d{2}-\d{2}/, klazz, ->(_) { klazz.new }, true, false)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'generates multiple expressions' do
|
25
|
+
parameter_type_combinations = [
|
26
|
+
[color_parameter_type, css_color_parameter_type],
|
27
|
+
[date_parameter_type, date_time_parameter_type, timestamp_parameter_type]
|
28
|
+
]
|
29
|
+
|
30
|
+
factory = described_class.new('I bought a {%s} ball on {%s}', parameter_type_combinations)
|
31
|
+
expressions = factory.generate_expressions.map { |generated_expression| generated_expression.source }
|
32
|
+
expect(expressions).to eq([
|
33
|
+
'I bought a {color} ball on {date}',
|
34
|
+
'I bought a {color} ball on {datetime}',
|
35
|
+
'I bought a {color} ball on {timestamp}',
|
36
|
+
'I bought a {csscolor} ball on {date}',
|
37
|
+
'I bought a {csscolor} ball on {datetime}',
|
38
|
+
'I bought a {csscolor} ball on {timestamp}',
|
39
|
+
])
|
40
|
+
end
|
41
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cucumber/cucumber_expressions/cucumber_expression_generator'
|
2
4
|
require 'cucumber/cucumber_expressions/cucumber_expression'
|
3
5
|
require 'cucumber/cucumber_expressions/parameter_type'
|
@@ -11,206 +13,207 @@ module Cucumber
|
|
11
13
|
|
12
14
|
before do
|
13
15
|
@parameter_type_registry = ParameterTypeRegistry.new
|
14
|
-
@generator =
|
16
|
+
@generator = described_class.new(@parameter_type_registry)
|
15
17
|
end
|
16
18
|
|
17
|
-
it
|
19
|
+
it 'documents expression generation' do
|
18
20
|
parameter_registry = ParameterTypeRegistry.new
|
19
21
|
### [generate-expression]
|
20
|
-
generator =
|
21
|
-
undefined_step_text =
|
22
|
+
generator = described_class.new(parameter_registry)
|
23
|
+
undefined_step_text = 'I have 2 cucumbers and 1.5 tomato'
|
22
24
|
generated_expression = generator.generate_expressions(undefined_step_text)[0]
|
23
|
-
expect(generated_expression.source).to eq(
|
25
|
+
expect(generated_expression.source).to eq('I have {int} cucumbers and {float} tomato')
|
24
26
|
expect(generated_expression.parameter_types[1].type).to eq(Float)
|
25
27
|
### [generate-expression]
|
26
28
|
end
|
27
29
|
|
28
|
-
it
|
29
|
-
assert_expression(
|
30
|
+
it 'generates expression for no args' do
|
31
|
+
assert_expression('hello', [], 'hello')
|
30
32
|
end
|
31
33
|
|
32
|
-
it
|
33
|
-
assert_expression(
|
34
|
-
"\\(iii)", [],
|
35
|
-
"(iii)")
|
34
|
+
it 'generates expression with escaped left parenthesis' do
|
35
|
+
assert_expression('\\(iii)', [], '(iii)')
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
39
|
-
assert_expression(
|
40
|
-
"\\{iii}", [],
|
41
|
-
"{iii}")
|
38
|
+
it 'generates expression with escaped left curly brace' do
|
39
|
+
assert_expression('\\{iii}', [], '{iii}')
|
42
40
|
end
|
43
41
|
|
44
|
-
it
|
45
|
-
assert_expression(
|
46
|
-
"The {int}\\/{int}\\/{int} hey", ["int", "int2", "int3"],
|
47
|
-
"The 1814/05/17 hey")
|
42
|
+
it 'generates expression with escaped slashes' do
|
43
|
+
assert_expression('The {int}\\/{int}\\/{int} hey', ['int', 'int2', 'int3'], 'The 1814/05/17 hey')
|
48
44
|
end
|
49
45
|
|
50
|
-
it
|
51
|
-
assert_expression(
|
52
|
-
"I have {int} cukes and {float} euro", ["int", "float"],
|
53
|
-
"I have 2 cukes and 1.5 euro")
|
46
|
+
it 'generates expression for int float arg' do
|
47
|
+
assert_expression('I have {int} cukes and {float} euro', ['int', 'float'], 'I have 2 cukes and 1.5 euro')
|
54
48
|
end
|
55
49
|
|
56
|
-
it
|
57
|
-
assert_expression(
|
58
|
-
"I like {string} and {string}", ["string", "string2"],
|
59
|
-
'I like "bangers" and \'mash\'')
|
50
|
+
it 'generates expression for strings' do
|
51
|
+
assert_expression('I like {string} and {string}', ['string', 'string2'], 'I like "bangers" and \'mash\'')
|
60
52
|
end
|
61
53
|
|
62
|
-
it
|
63
|
-
assert_expression(
|
64
|
-
"I am {int}% foobar", ["int"],
|
65
|
-
'I am 20% foobar')
|
54
|
+
it 'generates expression with % sign' do
|
55
|
+
assert_expression('I am {int}% foobar', ['int'], 'I am 20% foobar')
|
66
56
|
end
|
67
57
|
|
68
|
-
it
|
69
|
-
assert_expression(
|
70
|
-
"{int}", ["int"],
|
71
|
-
"99999")
|
58
|
+
it 'generates expression for just int' do
|
59
|
+
assert_expression('{int}', ['int'], '99999')
|
72
60
|
end
|
73
61
|
|
74
|
-
it
|
75
|
-
assert_expression(
|
76
|
-
"I have {int} cukes and {int} euro", ["int", "int2"],
|
77
|
-
"I have 2 cukes and 5 euro")
|
62
|
+
it 'numbers only second argument when builtin type is not reserved keyword' do
|
63
|
+
assert_expression('I have {int} cukes and {int} euro', ['int', 'int2'], 'I have 2 cukes and 5 euro')
|
78
64
|
end
|
79
65
|
|
80
|
-
it
|
81
|
-
@parameter_type_registry.define_parameter_type(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
66
|
+
it 'numbers only second argument when type is not reserved keyword' do
|
67
|
+
@parameter_type_registry.define_parameter_type(
|
68
|
+
ParameterType.new(
|
69
|
+
'currency',
|
70
|
+
'[A-Z]{3}',
|
71
|
+
Currency,
|
72
|
+
->(s) { Currency.new(s) },
|
73
|
+
true,
|
74
|
+
true
|
75
|
+
)
|
76
|
+
)
|
89
77
|
|
90
|
-
assert_expression(
|
91
|
-
"I have a {currency} account and a {currency} account", ["currency", "currency2"],
|
92
|
-
"I have a EUR account and a GBP account")
|
78
|
+
assert_expression('I have a {currency} account and a {currency} account', ['currency', 'currency2'], 'I have a EUR account and a GBP account')
|
93
79
|
end
|
94
80
|
|
95
|
-
it
|
96
|
-
expression = @generator.generate_expressions(
|
81
|
+
it 'exposes parameters in a generated expression' do
|
82
|
+
expression = @generator.generate_expressions('I have 2 cukes and 1.5 euro')[0]
|
97
83
|
types = expression.parameter_types.map(&:type)
|
84
|
+
|
98
85
|
expect(types).to eq([Integer, Float])
|
99
86
|
end
|
100
87
|
|
101
|
-
it
|
102
|
-
@parameter_type_registry.define_parameter_type(
|
88
|
+
it 'matches parameter types with optional capture groups' do
|
89
|
+
@parameter_type_registry.define_parameter_type(
|
90
|
+
ParameterType.new(
|
103
91
|
'optional-flight',
|
104
92
|
/(1st flight)?/,
|
105
93
|
String,
|
106
|
-
|
94
|
+
->(s) { s },
|
107
95
|
true,
|
108
96
|
false
|
109
|
-
|
110
|
-
|
97
|
+
)
|
98
|
+
)
|
99
|
+
@parameter_type_registry.define_parameter_type(
|
100
|
+
ParameterType.new(
|
111
101
|
'optional-hotel',
|
112
102
|
/(1 hotel)?/,
|
113
103
|
String,
|
114
|
-
|
104
|
+
->(s) { s },
|
115
105
|
true,
|
116
106
|
false
|
117
|
-
|
107
|
+
)
|
108
|
+
)
|
118
109
|
|
119
|
-
expression = @generator.generate_expressions(
|
110
|
+
expression = @generator.generate_expressions('I reach Stage 4: 1st flight -1 hotel')[0]
|
120
111
|
# While you would expect this to be `I reach Stage {int}: {optional-flight} -{optional-hotel}`
|
121
112
|
# the `-1` causes {int} to match just before {optional-hotel}.
|
122
|
-
|
113
|
+
|
114
|
+
expect(expression.source).to eq('I reach Stage {int}: {optional-flight} {int} hotel')
|
123
115
|
end
|
124
116
|
|
125
|
-
it
|
117
|
+
it 'generates at most 256 expressions' do
|
126
118
|
for i in 0..3
|
127
|
-
@parameter_type_registry.define_parameter_type(
|
119
|
+
@parameter_type_registry.define_parameter_type(
|
120
|
+
ParameterType.new(
|
128
121
|
"my-type-#{i}",
|
129
122
|
/([a-z] )*?[a-z]/,
|
130
123
|
String,
|
131
|
-
|
124
|
+
->(s) { s },
|
132
125
|
true,
|
133
126
|
false
|
134
|
-
|
127
|
+
)
|
128
|
+
)
|
135
129
|
end
|
136
130
|
# This would otherwise generate 4^11=4194300 expressions and consume just shy of 1.5GB.
|
137
|
-
expressions = @generator.generate_expressions(
|
131
|
+
expressions = @generator.generate_expressions('a s i m p l e s t e p')
|
132
|
+
|
138
133
|
expect(expressions.length).to eq(256)
|
139
134
|
end
|
140
135
|
|
141
|
-
it
|
142
|
-
@parameter_type_registry.define_parameter_type(
|
136
|
+
it 'prefers expression with longest non empty match' do
|
137
|
+
@parameter_type_registry.define_parameter_type(
|
138
|
+
ParameterType.new(
|
143
139
|
'zero-or-more',
|
144
140
|
/[a-z]*/,
|
145
141
|
String,
|
146
|
-
|
142
|
+
->(s) { s },
|
147
143
|
true,
|
148
144
|
false
|
149
|
-
|
150
|
-
|
145
|
+
)
|
146
|
+
)
|
147
|
+
@parameter_type_registry.define_parameter_type(
|
148
|
+
ParameterType.new(
|
151
149
|
'exactly-one',
|
152
150
|
/[a-z]/,
|
153
151
|
String,
|
154
|
-
|
152
|
+
->(s) { s },
|
155
153
|
true,
|
156
154
|
false
|
157
|
-
|
155
|
+
)
|
156
|
+
)
|
157
|
+
expressions = @generator.generate_expressions('a simple step')
|
158
158
|
|
159
|
-
expressions = @generator.generate_expressions("a simple step")
|
160
159
|
expect(expressions.length).to eq(2)
|
161
|
-
expect(expressions[0].source).to eq(
|
162
|
-
expect(expressions[1].source).to eq(
|
160
|
+
expect(expressions[0].source).to eq('{exactly-one} {zero-or-more} {zero-or-more}')
|
161
|
+
expect(expressions[1].source).to eq('{zero-or-more} {zero-or-more} {zero-or-more}')
|
163
162
|
end
|
164
163
|
|
165
|
-
context
|
164
|
+
context 'does not suggest parameter when match is' do
|
166
165
|
before do
|
167
|
-
@parameter_type_registry.define_parameter_type(
|
166
|
+
@parameter_type_registry.define_parameter_type(
|
167
|
+
ParameterType.new(
|
168
168
|
'direction',
|
169
169
|
/(up|down)/,
|
170
170
|
String,
|
171
|
-
|
171
|
+
->(s) { s },
|
172
172
|
true,
|
173
173
|
false
|
174
|
-
|
174
|
+
)
|
175
|
+
)
|
175
176
|
end
|
176
177
|
|
177
|
-
it
|
178
|
-
expect(@generator.generate_expressions(
|
179
|
-
expect(@generator.generate_expressions(
|
178
|
+
it 'at the beginning of a word' do
|
179
|
+
expect(@generator.generate_expressions('When I download a picture')[0].source).not_to eq('When I {direction}load a picture')
|
180
|
+
expect(@generator.generate_expressions('When I download a picture')[0].source).to eq('When I download a picture')
|
180
181
|
end
|
181
182
|
|
182
|
-
it
|
183
|
-
expect(@generator.generate_expressions(
|
184
|
-
expect(@generator.generate_expressions(
|
183
|
+
it 'inside a word' do
|
184
|
+
expect(@generator.generate_expressions('When I watch the muppet show')[0].source).not_to eq('When I watch the m{direction}pet show')
|
185
|
+
expect(@generator.generate_expressions('When I watch the muppet show')[0].source).to eq('When I watch the muppet show')
|
185
186
|
end
|
186
187
|
|
187
|
-
it
|
188
|
-
expect(@generator.generate_expressions(
|
189
|
-
expect(@generator.generate_expressions(
|
188
|
+
it 'at the end of a word' do
|
189
|
+
expect(@generator.generate_expressions('When I create a group')[0].source).not_to eq('When I create a gro{direction}')
|
190
|
+
expect(@generator.generate_expressions('When I create a group')[0].source).to eq('When I create a group')
|
190
191
|
end
|
191
192
|
end
|
192
193
|
|
193
|
-
context
|
194
|
+
context 'does suggest parameter when match is' do
|
194
195
|
before do
|
195
|
-
@parameter_type_registry.define_parameter_type(
|
196
|
+
@parameter_type_registry.define_parameter_type(
|
197
|
+
ParameterType.new(
|
196
198
|
'direction',
|
197
199
|
/(up|down)/,
|
198
200
|
String,
|
199
|
-
|
201
|
+
->(s) { s },
|
200
202
|
true,
|
201
203
|
false
|
202
|
-
|
204
|
+
)
|
205
|
+
)
|
203
206
|
end
|
204
207
|
|
205
|
-
it
|
206
|
-
expect(@generator.generate_expressions(
|
207
|
-
expect(@generator.generate_expressions(
|
208
|
-
expect(@generator.generate_expressions(
|
208
|
+
it 'a full word' do
|
209
|
+
expect(@generator.generate_expressions('When I go down the road')[0].source).to eq('When I go {direction} the road')
|
210
|
+
expect(@generator.generate_expressions('When I walk up the hill')[0].source).to eq('When I walk {direction} the hill')
|
211
|
+
expect(@generator.generate_expressions('up the hill, the road goes down')[0].source).to eq('{direction} the hill, the road goes {direction}')
|
209
212
|
end
|
210
213
|
|
211
214
|
it 'wrapped around punctuation characters' do
|
212
|
-
expect(@generator.generate_expressions(
|
213
|
-
expect(@generator.generate_expressions(
|
215
|
+
expect(@generator.generate_expressions('When direction is:down')[0].source).to eq('When direction is:{direction}')
|
216
|
+
expect(@generator.generate_expressions('Then direction is down.')[0].source).to eq('Then direction is {direction}.')
|
214
217
|
end
|
215
218
|
end
|
216
219
|
|
@@ -221,9 +224,9 @@ module Cucumber
|
|
221
224
|
|
222
225
|
cucumber_expression = CucumberExpression.new(generated_expression.source, @parameter_type_registry)
|
223
226
|
match = cucumber_expression.match(text)
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
+
|
228
|
+
raise "Expected text '#{text}' to match generated expression '#{generated_expression.source}'" if match.nil?
|
229
|
+
|
227
230
|
expect(match.length).to eq(expected_argument_names.length)
|
228
231
|
end
|
229
232
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'cucumber/cucumber_expressions/cucumber_expression_parser'
|
3
5
|
require 'cucumber/cucumber_expressions/errors'
|
@@ -8,7 +10,7 @@ module Cucumber
|
|
8
10
|
Dir['../testdata/cucumber-expression/parser/*.yaml'].each do |path|
|
9
11
|
expectation = YAML.load_file(path)
|
10
12
|
it "parses #{path}" do
|
11
|
-
parser =
|
13
|
+
parser = described_class.new
|
12
14
|
if expectation['exception']
|
13
15
|
expect { parser.parse(expectation['expression']) }.to raise_error(expectation['exception'])
|
14
16
|
else
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
require 'cucumber/cucumber_expressions/cucumber_expression'
|
3
5
|
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
@@ -5,18 +7,18 @@ require 'cucumber/cucumber_expressions/parameter_type_registry'
|
|
5
7
|
module Cucumber
|
6
8
|
module CucumberExpressions
|
7
9
|
describe CucumberExpression do
|
8
|
-
|
9
10
|
Dir['../testdata/cucumber-expression/matching/*.yaml'].each do |path|
|
10
11
|
expectation = YAML.load_file(path)
|
12
|
+
|
11
13
|
it "matches #{path}" do
|
12
14
|
parameter_registry = ParameterTypeRegistry.new
|
13
15
|
if expectation['exception']
|
14
16
|
expect {
|
15
|
-
cucumber_expression =
|
17
|
+
cucumber_expression = described_class.new(expectation['expression'], parameter_registry)
|
16
18
|
cucumber_expression.match(expectation['text'])
|
17
19
|
}.to raise_error(expectation['exception'])
|
18
20
|
else
|
19
|
-
cucumber_expression =
|
21
|
+
cucumber_expression = described_class.new(expectation['expression'], parameter_registry)
|
20
22
|
matches = cucumber_expression.match(expectation['text'])
|
21
23
|
values = matches.nil? ? nil : matches.map do |arg|
|
22
24
|
value = arg.value(nil)
|
@@ -36,115 +38,110 @@ module Cucumber
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
|
-
it
|
41
|
+
it 'documents match arguments' do
|
40
42
|
parameter_registry = ParameterTypeRegistry.new
|
41
43
|
|
42
44
|
### [capture-match-arguments]
|
43
|
-
expr =
|
44
|
-
expression =
|
45
|
-
args = expression.match(
|
45
|
+
expr = 'I have {int} cuke(s)'
|
46
|
+
expression = described_class.new(expr, parameter_registry)
|
47
|
+
args = expression.match('I have 7 cukes')
|
48
|
+
|
46
49
|
expect(args[0].value(nil)).to eq(7)
|
47
50
|
### [capture-match-arguments]
|
48
51
|
end
|
49
52
|
|
50
|
-
it
|
51
|
-
expect(match(
|
52
|
-
expect(match(
|
53
|
-
expect(match(
|
54
|
-
expect(match(
|
55
|
-
expect(match(
|
56
|
-
expect(match(
|
57
|
-
expect(match(
|
58
|
-
expect(match(
|
59
|
-
|
60
|
-
expect(match(
|
61
|
-
expect(match(
|
62
|
-
expect(match(
|
63
|
-
expect(match(
|
64
|
-
expect(match(
|
65
|
-
expect(match(
|
66
|
-
expect(match(
|
67
|
-
expect(match(
|
68
|
-
expect(match(
|
69
|
-
expect(match(
|
70
|
-
|
71
|
-
expect(match(
|
72
|
-
expect(match(
|
73
|
-
expect(match(
|
74
|
-
expect(match(
|
75
|
-
expect(match(
|
76
|
-
expect(match(
|
77
|
-
expect(match(
|
78
|
-
expect(match(
|
79
|
-
expect(match(
|
80
|
-
expect(match(
|
81
|
-
expect(match(
|
82
|
-
expect(match(
|
53
|
+
it 'matches float' do
|
54
|
+
expect(match('{float}', '')).to eq(nil)
|
55
|
+
expect(match('{float}', '.')).to eq(nil)
|
56
|
+
expect(match('{float}', ',')).to eq(nil)
|
57
|
+
expect(match('{float}', '-')).to eq(nil)
|
58
|
+
expect(match('{float}', 'E')).to eq(nil)
|
59
|
+
expect(match('{float}', '1,')).to eq(nil)
|
60
|
+
expect(match('{float}', ',1')).to eq(nil)
|
61
|
+
expect(match('{float}', '1.')).to eq(nil)
|
62
|
+
|
63
|
+
expect(match('{float}', '1')).to eq([1])
|
64
|
+
expect(match('{float}', '-1')).to eq([-1])
|
65
|
+
expect(match('{float}', '1.1')).to eq([1.1])
|
66
|
+
expect(match('{float}', '1,000')).to eq(nil)
|
67
|
+
expect(match('{float}', '1,000,0')).to eq(nil)
|
68
|
+
expect(match('{float}', '1,000.1')).to eq(nil)
|
69
|
+
expect(match('{float}', '1,000,10')).to eq(nil)
|
70
|
+
expect(match('{float}', '1,0.1')).to eq(nil)
|
71
|
+
expect(match('{float}', '1,000,000.1')).to eq(nil)
|
72
|
+
expect(match('{float}', '-1.1')).to eq([-1.1])
|
73
|
+
|
74
|
+
expect(match('{float}', '.1')).to eq([0.1])
|
75
|
+
expect(match('{float}', '-.1')).to eq([-0.1])
|
76
|
+
expect(match('{float}', '-.1000001')).to eq([-0.1000001])
|
77
|
+
expect(match('{float}', '1E1')).to eq([10.0])
|
78
|
+
expect(match('{float}', '.1E1')).to eq([1])
|
79
|
+
expect(match('{float}', 'E1')).to eq(nil)
|
80
|
+
expect(match('{float}', '-.1E-1')).to eq([-0.01])
|
81
|
+
expect(match('{float}', '-.1E-2')).to eq([-0.001])
|
82
|
+
expect(match('{float}', '-.1E+1')).to eq([-1])
|
83
|
+
expect(match('{float}', '-.1E+2')).to eq([-10])
|
84
|
+
expect(match('{float}', '-.1E1')).to eq([-1])
|
85
|
+
expect(match('{float}', '-.1E2')).to eq([-10])
|
83
86
|
end
|
84
87
|
|
85
|
-
it
|
86
|
-
expect(match(
|
88
|
+
it 'float with zero' do
|
89
|
+
expect(match('{float}', '0')).to eq([0.0])
|
87
90
|
end
|
88
91
|
|
89
|
-
it
|
90
|
-
expect(match(
|
92
|
+
it 'matches anonymous' do
|
93
|
+
expect(match('{}', '0.22')).to eq(['0.22'])
|
91
94
|
end
|
92
95
|
|
93
|
-
it
|
94
|
-
expr =
|
95
|
-
|
96
|
+
it 'exposes source' do
|
97
|
+
expr = 'I have {int} cuke(s)'
|
98
|
+
|
99
|
+
expect(described_class.new(expr, ParameterTypeRegistry.new).source).to eq(expr)
|
96
100
|
end
|
97
101
|
|
98
|
-
it
|
99
|
-
expr =
|
100
|
-
|
102
|
+
it 'exposes source via #to_s' do
|
103
|
+
expr = 'I have {int} cuke(s)'
|
104
|
+
|
105
|
+
expect(described_class.new(expr, ParameterTypeRegistry.new).to_s).to eq(expr.inspect)
|
101
106
|
end
|
102
107
|
|
103
|
-
it
|
108
|
+
it 'unmatched optional groups have undefined values' do
|
104
109
|
parameter_type_registry = ParameterTypeRegistry.new
|
105
110
|
parameter_type_registry.define_parameter_type(
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
true
|
115
|
-
)
|
116
|
-
)
|
117
|
-
expression = CucumberExpression.new(
|
118
|
-
'{textAndOrNumber}',
|
119
|
-
parameter_type_registry
|
111
|
+
ParameterType.new(
|
112
|
+
'textAndOrNumber',
|
113
|
+
/([A-Z]+)?(?: )?([0-9]+)?/,
|
114
|
+
Object,
|
115
|
+
->(s1, s2) { [s1, s2] },
|
116
|
+
false,
|
117
|
+
true
|
118
|
+
)
|
120
119
|
)
|
120
|
+
expression = described_class.new('{textAndOrNumber}', parameter_type_registry)
|
121
121
|
|
122
|
-
class World
|
123
|
-
end
|
122
|
+
class World; end
|
124
123
|
|
125
|
-
expect(expression.match(
|
126
|
-
expect(expression.match(
|
124
|
+
expect(expression.match('TLA')[0].value(World.new)).to eq(['TLA', nil])
|
125
|
+
expect(expression.match('123')[0].value(World.new)).to eq([nil, '123'])
|
127
126
|
end
|
128
127
|
|
129
128
|
# Ruby specific
|
130
129
|
|
131
|
-
it
|
130
|
+
it 'delegates transform to custom object' do
|
132
131
|
parameter_type_registry = ParameterTypeRegistry.new
|
133
132
|
parameter_type_registry.define_parameter_type(
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
true
|
143
|
-
)
|
133
|
+
ParameterType.new(
|
134
|
+
'widget',
|
135
|
+
/\w+/,
|
136
|
+
Object,
|
137
|
+
->(s) { self.create_widget(s) },
|
138
|
+
false,
|
139
|
+
true
|
140
|
+
)
|
144
141
|
)
|
145
|
-
expression =
|
146
|
-
|
147
|
-
|
142
|
+
expression = described_class.new(
|
143
|
+
'I have a {widget}',
|
144
|
+
parameter_type_registry
|
148
145
|
)
|
149
146
|
|
150
147
|
class World
|
@@ -153,27 +150,27 @@ module Cucumber
|
|
153
150
|
end
|
154
151
|
end
|
155
152
|
|
156
|
-
args = expression.match(
|
153
|
+
args = expression.match('I have a bolt')
|
154
|
+
|
157
155
|
expect(args[0].value(World.new)).to eq('widget:bolt')
|
158
156
|
end
|
159
157
|
|
160
|
-
it
|
158
|
+
it 'reports undefined parameter type name' do
|
161
159
|
parameter_type_registry = ParameterTypeRegistry.new
|
162
160
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
expect(e.undefined_parameter_type_name).to eq('widget')
|
170
|
-
end
|
161
|
+
described_class.new(
|
162
|
+
'I have {int} {widget}(s) in {word}',
|
163
|
+
parameter_type_registry
|
164
|
+
)
|
165
|
+
rescue UndefinedParameterTypeError => e
|
166
|
+
expect(e.undefined_parameter_type_name).to eq('widget')
|
171
167
|
end
|
172
168
|
|
173
169
|
def match(expression, text)
|
174
170
|
cucumber_expression = CucumberExpression.new(expression, ParameterTypeRegistry.new)
|
175
171
|
args = cucumber_expression.match(text)
|
176
172
|
return nil if args.nil?
|
173
|
+
|
177
174
|
args.map { |arg| arg.value(nil) }
|
178
175
|
end
|
179
176
|
end
|