cucumber-cucumber-expressions 10.3.0 → 11.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/.rsync +1 -0
- data/VERSION +1 -1
- data/cucumber-cucumber-expressions.gemspec +1 -1
- data/examples.txt +5 -1
- data/lib/cucumber/cucumber_expressions/ast.rb +201 -0
- data/lib/cucumber/cucumber_expressions/cucumber_expression.rb +80 -76
- data/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +4 -8
- data/lib/cucumber/cucumber_expressions/cucumber_expression_parser.rb +219 -0
- data/lib/cucumber/cucumber_expressions/cucumber_expression_tokenizer.rb +95 -0
- data/lib/cucumber/cucumber_expressions/errors.rb +175 -4
- data/lib/cucumber/cucumber_expressions/parameter_type.rb +12 -7
- data/spec/cucumber/cucumber_expressions/cucumber_expression_parser_spec.rb +24 -0
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +62 -140
- data/spec/cucumber/cucumber_expressions/cucumber_expression_tokenizer_spec.rb +24 -0
- data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +1 -1
- data/spec/cucumber/cucumber_expressions/expression_examples_spec.rb +1 -1
- data/spec/cucumber/cucumber_expressions/expression_factory_spec.rb +0 -4
- data/testdata/ast/alternation-followed-by-optional.yaml +17 -0
- data/testdata/ast/alternation-phrase.yaml +16 -0
- data/testdata/ast/alternation-with-parameter.yaml +27 -0
- data/testdata/ast/alternation-with-unused-end-optional.yaml +15 -0
- data/testdata/ast/alternation-with-unused-start-optional.yaml +8 -0
- data/testdata/ast/alternation-with-white-space.yaml +12 -0
- data/testdata/ast/alternation.yaml +12 -0
- data/testdata/ast/anonymous-parameter.yaml +5 -0
- data/testdata/ast/closing-brace.yaml +5 -0
- data/testdata/ast/closing-parenthesis.yaml +5 -0
- data/testdata/ast/empty-alternation.yaml +8 -0
- data/testdata/ast/empty-alternations.yaml +9 -0
- data/testdata/ast/empty-string.yaml +3 -0
- data/testdata/ast/escaped-alternation.yaml +5 -0
- data/testdata/ast/escaped-backslash.yaml +5 -0
- data/testdata/ast/escaped-opening-parenthesis.yaml +5 -0
- data/testdata/ast/escaped-optional-followed-by-optional.yaml +15 -0
- data/testdata/ast/escaped-optional-phrase.yaml +10 -0
- data/testdata/ast/escaped-optional.yaml +7 -0
- data/testdata/ast/opening-brace.yaml +8 -0
- data/testdata/ast/opening-parenthesis.yaml +8 -0
- data/testdata/ast/optional-containing-nested-optional.yaml +15 -0
- data/testdata/ast/optional-phrase.yaml +12 -0
- data/testdata/ast/optional.yaml +7 -0
- data/testdata/ast/parameter.yaml +7 -0
- data/testdata/ast/phrase.yaml +9 -0
- data/testdata/ast/unfinished-parameter.yaml +8 -0
- data/testdata/expression/allows-escaped-optional-parameter-types.yaml +4 -0
- data/testdata/expression/allows-parameter-type-in-alternation-1.yaml +4 -0
- data/testdata/expression/allows-parameter-type-in-alternation-2.yaml +4 -0
- data/testdata/expression/does-allow-parameter-adjacent-to-alternation.yaml +5 -0
- data/testdata/expression/does-not-allow-alternation-in-optional.yaml +9 -0
- data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-left-parameter.yaml +10 -0
- data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-optional.yaml +9 -0
- data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-right-parameter.yaml +9 -0
- data/testdata/expression/does-not-allow-alternation-with-empty-alternative.yaml +9 -0
- data/testdata/expression/does-not-allow-empty-optional.yaml +9 -0
- data/testdata/expression/does-not-allow-nested-optional.yaml +8 -0
- data/testdata/expression/does-not-allow-optional-parameter-types.yaml +9 -0
- data/testdata/expression/does-not-allow-parameter-name-with-reserved-characters.yaml +10 -0
- data/testdata/expression/does-not-allow-unfinished-parenthesis-1.yaml +8 -0
- data/testdata/expression/does-not-allow-unfinished-parenthesis-2.yaml +8 -0
- data/testdata/expression/does-not-allow-unfinished-parenthesis-3.yaml +8 -0
- data/testdata/expression/does-not-match-misquoted-string.yaml +4 -0
- data/testdata/expression/doesnt-match-float-as-int.yaml +5 -0
- data/testdata/expression/matches-alternation.yaml +4 -0
- data/testdata/expression/matches-anonymous-parameter-type.yaml +5 -0
- data/testdata/expression/matches-double-quoted-empty-string-as-empty-string-along-with-other-strings.yaml +4 -0
- data/testdata/expression/matches-double-quoted-empty-string-as-empty-string.yaml +4 -0
- data/testdata/expression/matches-double-quoted-string-with-escaped-double-quote.yaml +4 -0
- data/testdata/expression/matches-double-quoted-string-with-single-quotes.yaml +4 -0
- data/testdata/expression/matches-double-quoted-string.yaml +4 -0
- data/testdata/expression/matches-doubly-escaped-parenthesis.yaml +4 -0
- data/testdata/expression/matches-doubly-escaped-slash-1.yaml +4 -0
- data/testdata/expression/matches-doubly-escaped-slash-2.yaml +4 -0
- data/testdata/expression/matches-escaped-parenthesis-1.yaml +4 -0
- data/testdata/expression/matches-escaped-parenthesis-2.yaml +4 -0
- data/testdata/expression/matches-escaped-parenthesis-3.yaml +4 -0
- data/testdata/expression/matches-escaped-slash.yaml +4 -0
- data/testdata/expression/matches-float-1.yaml +5 -0
- data/testdata/expression/matches-float-2.yaml +5 -0
- data/testdata/expression/matches-int.yaml +5 -0
- data/testdata/expression/matches-multiple-double-quoted-strings.yaml +4 -0
- data/testdata/expression/matches-multiple-single-quoted-strings.yaml +4 -0
- data/testdata/expression/matches-optional-before-alternation-1.yaml +4 -0
- data/testdata/expression/matches-optional-before-alternation-2.yaml +4 -0
- data/testdata/expression/matches-optional-before-alternation-with-regex-characters-1.yaml +4 -0
- data/testdata/expression/matches-optional-before-alternation-with-regex-characters-2.yaml +4 -0
- data/testdata/expression/matches-optional-in-alternation-1.yaml +5 -0
- data/testdata/expression/matches-optional-in-alternation-2.yaml +5 -0
- data/testdata/expression/matches-optional-in-alternation-3.yaml +5 -0
- data/testdata/expression/matches-single-quoted-empty-string-as-empty-string-along-with-other-strings.yaml +4 -0
- data/testdata/expression/matches-single-quoted-empty-string-as-empty-string.yaml +4 -0
- data/testdata/expression/matches-single-quoted-string-with-double-quotes.yaml +4 -0
- data/testdata/expression/matches-single-quoted-string-with-escaped-single-quote.yaml +4 -0
- data/testdata/expression/matches-single-quoted-string.yaml +4 -0
- data/testdata/expression/matches-word.yaml +4 -0
- data/testdata/expression/throws-unknown-parameter-type.yaml +10 -0
- data/testdata/regex/alternation-with-optional.yaml +2 -0
- data/testdata/regex/alternation.yaml +2 -0
- data/testdata/regex/empty.yaml +2 -0
- data/testdata/regex/escape-regex-characters.yaml +2 -0
- data/testdata/regex/optional.yaml +2 -0
- data/testdata/regex/parameter.yaml +2 -0
- data/testdata/regex/text.yaml +2 -0
- data/testdata/regex/unicode.yaml +2 -0
- data/testdata/tokens/alternation-phrase.yaml +13 -0
- data/testdata/tokens/alternation.yaml +9 -0
- data/testdata/tokens/empty-string.yaml +6 -0
- data/testdata/tokens/escape-non-reserved-character.yaml +8 -0
- data/testdata/tokens/escaped-alternation.yaml +9 -0
- data/testdata/tokens/escaped-char-has-start-index-of-text-token.yaml +9 -0
- data/testdata/tokens/escaped-end-of-line.yaml +8 -0
- data/testdata/tokens/escaped-optional.yaml +7 -0
- data/testdata/tokens/escaped-parameter.yaml +7 -0
- data/testdata/tokens/escaped-space.yaml +7 -0
- data/testdata/tokens/optional-phrase.yaml +13 -0
- data/testdata/tokens/optional.yaml +9 -0
- data/testdata/tokens/parameter-phrase.yaml +13 -0
- data/testdata/tokens/parameter.yaml +9 -0
- data/testdata/tokens/phrase.yaml +11 -0
- metadata +115 -9
- data/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb +0 -57
@@ -9,12 +9,16 @@ module Cucumber
|
|
9
9
|
attr_reader :name, :type, :regexps
|
10
10
|
|
11
11
|
def self.check_parameter_type_name(type_name)
|
12
|
+
unless is_valid_parameter_type_name(type_name)
|
13
|
+
raise CucumberExpressionError.new("Illegal character in parameter name {#{type_name}}. Parameter names may not contain '[]()$.|?*+'")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.is_valid_parameter_type_name(type_name)
|
12
18
|
unescaped_type_name = type_name.gsub(UNESCAPE_PATTERN) do
|
13
19
|
$2
|
14
20
|
end
|
15
|
-
|
16
|
-
raise CucumberExpressionError.new("Illegal character '#{$1}' in parameter name {#{unescaped_type_name}}")
|
17
|
-
end
|
21
|
+
!(ILLEGAL_PARAMETER_NAME_PATTERN =~ unescaped_type_name)
|
18
22
|
end
|
19
23
|
|
20
24
|
def prefer_for_regexp_match?
|
@@ -58,16 +62,17 @@ module Cucumber
|
|
58
62
|
|
59
63
|
private
|
60
64
|
|
65
|
+
|
61
66
|
def string_array(regexps)
|
62
67
|
array = regexps.is_a?(Array) ? regexps : [regexps]
|
63
|
-
array.map {|regexp| regexp.is_a?(String) ? regexp : regexp_source(regexp)}
|
68
|
+
array.map { |regexp| regexp.is_a?(String) ? regexp : regexp_source(regexp) }
|
64
69
|
end
|
65
70
|
|
66
71
|
def regexp_source(regexp)
|
67
72
|
[
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
'EXTENDED',
|
74
|
+
'IGNORECASE',
|
75
|
+
'MULTILINE'
|
71
76
|
].each do |option_name|
|
72
77
|
option = Regexp.const_get(option_name)
|
73
78
|
if regexp.options & option != 0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
require 'cucumber/cucumber_expressions/cucumber_expression_parser'
|
4
|
+
require 'cucumber/cucumber_expressions/errors'
|
5
|
+
|
6
|
+
module Cucumber
|
7
|
+
module CucumberExpressions
|
8
|
+
describe 'Cucumber expression parser' do
|
9
|
+
Dir['testdata/ast/*.yaml'].each do |testcase|
|
10
|
+
expectation = YAML.load_file(testcase) # encoding?
|
11
|
+
it "#{testcase}" do
|
12
|
+
parser = CucumberExpressionParser.new
|
13
|
+
if expectation['exception'].nil?
|
14
|
+
node = parser.parse(expectation['expression'])
|
15
|
+
node_hash = node.to_hash
|
16
|
+
expect(node_hash).to eq(JSON.parse(expectation['expected']))
|
17
|
+
else
|
18
|
+
expect { parser.parse(expectation['expression']) }.to raise_error(expectation['exception'])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,9 +1,39 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
1
3
|
require 'cucumber/cucumber_expressions/cucumber_expression'
|
2
4
|
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
3
5
|
|
4
6
|
module Cucumber
|
5
7
|
module CucumberExpressions
|
6
8
|
describe CucumberExpression do
|
9
|
+
|
10
|
+
Dir['testdata/expression/*.yaml'].each do |testcase|
|
11
|
+
expectation = YAML.load_file(testcase) # encoding?
|
12
|
+
it "#{testcase}" do
|
13
|
+
parameter_registry = ParameterTypeRegistry.new
|
14
|
+
if expectation['exception'].nil?
|
15
|
+
cucumber_expression = CucumberExpression.new(expectation['expression'], parameter_registry)
|
16
|
+
matches = cucumber_expression.match(expectation['text'])
|
17
|
+
values = matches.nil? ? nil : matches.map { |arg| arg.value(nil) }
|
18
|
+
expect(values).to eq(JSON.parse(expectation['expected']))
|
19
|
+
else
|
20
|
+
expect {
|
21
|
+
cucumber_expression = CucumberExpression.new(expectation['expression'], parameter_registry)
|
22
|
+
cucumber_expression.match(expectation['text'])
|
23
|
+
}.to raise_error(expectation['exception'])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Dir['testdata/regex/*.yaml'].each do |testcase|
|
29
|
+
expectation = YAML.load_file(testcase) # encoding?
|
30
|
+
it "#{testcase}" do
|
31
|
+
parameter_registry = ParameterTypeRegistry.new
|
32
|
+
cucumber_expression = CucumberExpression.new(expectation['expression'], parameter_registry)
|
33
|
+
expect(cucumber_expression.regexp.source).to eq(expectation['expected'])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
7
37
|
it "documents match arguments" do
|
8
38
|
parameter_registry = ParameterTypeRegistry.new
|
9
39
|
|
@@ -15,82 +45,6 @@ module Cucumber
|
|
15
45
|
### [capture-match-arguments]
|
16
46
|
end
|
17
47
|
|
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
48
|
it "matches float" do
|
95
49
|
expect(match("{float}", "")).to eq(nil)
|
96
50
|
expect(match("{float}", ".")).to eq(nil)
|
@@ -126,34 +80,12 @@ module Cucumber
|
|
126
80
|
expect(match("{float}", "-.1E2")).to eq([-10])
|
127
81
|
end
|
128
82
|
|
129
|
-
it "
|
130
|
-
expect(match("{}", "0
|
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}')
|
83
|
+
it "float with zero" do
|
84
|
+
expect(match("{float}", "0")).to eq([0.0])
|
153
85
|
end
|
154
86
|
|
155
|
-
it "
|
156
|
-
expect
|
87
|
+
it "matches anonymous" do
|
88
|
+
expect(match("{}", "0.22")).to eq(["0.22"])
|
157
89
|
end
|
158
90
|
|
159
91
|
it "exposes source" do
|
@@ -161,78 +93,68 @@ module Cucumber
|
|
161
93
|
expect(CucumberExpression.new(expr, ParameterTypeRegistry.new).source).to eq(expr)
|
162
94
|
end
|
163
95
|
|
164
|
-
it "
|
96
|
+
it "unmatched optional groups have undefined values" do
|
165
97
|
parameter_type_registry = ParameterTypeRegistry.new
|
166
98
|
parameter_type_registry.define_parameter_type(
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
99
|
+
ParameterType.new(
|
100
|
+
'textAndOrNumber',
|
101
|
+
/([A-Z]+)?(?: )?([0-9]+)?/,
|
102
|
+
Object,
|
103
|
+
-> (s1, s2) {
|
104
|
+
[s1, s2]
|
105
|
+
},
|
106
|
+
false,
|
107
|
+
true
|
108
|
+
)
|
177
109
|
)
|
178
110
|
expression = CucumberExpression.new(
|
179
|
-
|
180
|
-
|
111
|
+
'{textAndOrNumber}',
|
112
|
+
parameter_type_registry
|
181
113
|
)
|
182
114
|
|
183
115
|
class World
|
184
|
-
def create_widget(s)
|
185
|
-
"widget:#{s}"
|
186
|
-
end
|
187
116
|
end
|
188
117
|
|
189
|
-
|
190
|
-
expect(
|
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
|
118
|
+
expect(expression.match("TLA")[0].value(World.new)).to eq(["TLA", nil])
|
119
|
+
expect(expression.match("123")[0].value(World.new)).to eq([nil, "123"])
|
202
120
|
end
|
203
121
|
|
122
|
+
# Ruby specific
|
204
123
|
|
205
|
-
it "
|
124
|
+
it "delegates transform to custom object" do
|
206
125
|
parameter_type_registry = ParameterTypeRegistry.new
|
207
126
|
parameter_type_registry.define_parameter_type(
|
208
127
|
ParameterType.new(
|
209
|
-
'
|
210
|
-
|
128
|
+
'widget',
|
129
|
+
/\w+/,
|
211
130
|
Object,
|
212
|
-
-> (
|
213
|
-
|
131
|
+
-> (s) {
|
132
|
+
self.create_widget(s)
|
214
133
|
},
|
215
134
|
false,
|
216
135
|
true
|
217
136
|
)
|
218
137
|
)
|
219
138
|
expression = CucumberExpression.new(
|
220
|
-
'{
|
139
|
+
'I have a {widget}',
|
221
140
|
parameter_type_registry
|
222
141
|
)
|
223
142
|
|
224
143
|
class World
|
144
|
+
def create_widget(s)
|
145
|
+
"widget:#{s}"
|
146
|
+
end
|
225
147
|
end
|
226
148
|
|
227
|
-
|
228
|
-
expect(
|
149
|
+
args = expression.match("I have a bolt")
|
150
|
+
expect(args[0].value(World.new)).to eq('widget:bolt')
|
229
151
|
end
|
230
152
|
|
231
153
|
def match(expression, text)
|
232
154
|
cucumber_expression = CucumberExpression.new(expression, ParameterTypeRegistry.new)
|
233
155
|
args = cucumber_expression.match(text)
|
234
156
|
return nil if args.nil?
|
235
|
-
args.map {|arg| arg.value(nil)}
|
157
|
+
args.map { |arg| arg.value(nil) }
|
236
158
|
end
|
237
159
|
end
|
238
160
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
require 'cucumber/cucumber_expressions/cucumber_expression_tokenizer'
|
4
|
+
require 'cucumber/cucumber_expressions/errors'
|
5
|
+
|
6
|
+
module Cucumber
|
7
|
+
module CucumberExpressions
|
8
|
+
describe 'Cucumber expression tokenizer' do
|
9
|
+
Dir['testdata/tokens/*.yaml'].each do |testcase|
|
10
|
+
expectation = YAML.load_file(testcase) # encoding?
|
11
|
+
it "#{testcase}" do
|
12
|
+
tokenizer = CucumberExpressionTokenizer.new
|
13
|
+
if expectation['exception'].nil?
|
14
|
+
tokens = tokenizer.tokenize(expectation['expression'])
|
15
|
+
token_hashes = tokens.map{|token| token.to_hash}
|
16
|
+
expect(token_hashes).to eq(JSON.parse(expectation['expected']))
|
17
|
+
else
|
18
|
+
expect { tokenizer.tokenize(expectation['expression']) }.to raise_error(expectation['exception'])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -69,7 +69,7 @@ module Cucumber
|
|
69
69
|
true,
|
70
70
|
false
|
71
71
|
)
|
72
|
-
end.to raise_error("Illegal character
|
72
|
+
end.to raise_error("Illegal character in parameter name {[string]}. Parameter names may not contain '[]()$.|?*+'")
|
73
73
|
end
|
74
74
|
|
75
75
|
describe CucumberExpression do
|
@@ -7,7 +7,7 @@ module Cucumber
|
|
7
7
|
module CucumberExpressions
|
8
8
|
describe 'examples.txt' do
|
9
9
|
def match(expression_text, text)
|
10
|
-
expression = expression_text =~
|
10
|
+
expression = expression_text =~ /^\/(.*)\/$/ ?
|
11
11
|
RegularExpression.new(Regexp.new($1), ParameterTypeRegistry.new) :
|
12
12
|
CucumberExpression.new(expression_text, ParameterTypeRegistry.new)
|
13
13
|
|
@@ -14,10 +14,6 @@ module Cucumber
|
|
14
14
|
it 'creates a CucumberExpression' do
|
15
15
|
expect(@expression_factory.create_expression('{int}').class).to eq(CucumberExpression)
|
16
16
|
end
|
17
|
-
|
18
|
-
it 'creates a XXXRegularExpression' do
|
19
|
-
expect {@expression_factory.create_expression('hello {x}')}.to raise_error("Undefined parameter type {x}")
|
20
|
-
end
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
expression: three blind\ rat/cat(s)
|
2
|
+
expected: |-
|
3
|
+
{"type": "EXPRESSION_NODE", "start": 0, "end": 23, "nodes": [
|
4
|
+
{"type": "TEXT_NODE", "start": 0, "end": 5, "token": "three"},
|
5
|
+
{"type": "TEXT_NODE", "start": 5, "end": 6, "token": " "},
|
6
|
+
{"type": "ALTERNATION_NODE", "start": 6, "end": 23, "nodes": [
|
7
|
+
{"type": "ALTERNATIVE_NODE", "start": 6, "end": 16, "nodes": [
|
8
|
+
{"type": "TEXT_NODE", "start": 6, "end": 16, "token": "blind rat"}
|
9
|
+
]},
|
10
|
+
{"type": "ALTERNATIVE_NODE", "start": 17, "end": 23, "nodes": [
|
11
|
+
{"type": "TEXT_NODE", "start": 17, "end": 20, "token": "cat"},
|
12
|
+
{"type": "OPTIONAL_NODE", "start": 20, "end": 23, "nodes": [
|
13
|
+
{"type": "TEXT_NODE", "start": 21, "end": 22, "token": "s"}
|
14
|
+
]}
|
15
|
+
]}
|
16
|
+
]}
|
17
|
+
]}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
expression: three hungry/blind mice
|
2
|
+
expected: |-
|
3
|
+
{"type": "EXPRESSION_NODE", "start": 0, "end": 23, "nodes": [
|
4
|
+
{"type": "TEXT_NODE", "start": 0, "end": 5, "token": "three"},
|
5
|
+
{"type": "TEXT_NODE", "start": 5, "end": 6, "token": " "},
|
6
|
+
{"type": "ALTERNATION_NODE", "start": 6, "end": 18, "nodes": [
|
7
|
+
{"type": "ALTERNATIVE_NODE", "start": 6, "end": 12, "nodes": [
|
8
|
+
{"type": "TEXT_NODE", "start": 6, "end": 12, "token": "hungry"}
|
9
|
+
]},
|
10
|
+
{"type": "ALTERNATIVE_NODE", "start": 13, "end": 18, "nodes": [
|
11
|
+
{"type": "TEXT_NODE", "start": 13, "end": 18, "token": "blind"}
|
12
|
+
]}
|
13
|
+
]},
|
14
|
+
{"type": "TEXT_NODE", "start": 18, "end": 19, "token": " "},
|
15
|
+
{"type": "TEXT_NODE", "start": 19, "end": 23, "token": "mice"}
|
16
|
+
]}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
expression: I select the {int}st/nd/rd/th
|
2
|
+
expected: |-
|
3
|
+
{"type": "EXPRESSION_NODE", "start": 0, "end": 29, "nodes": [
|
4
|
+
{"type": "TEXT_NODE", "start": 0, "end": 1, "token": "I"},
|
5
|
+
{"type": "TEXT_NODE", "start": 1, "end": 2, "token": " "},
|
6
|
+
{"type": "TEXT_NODE", "start": 2, "end": 8, "token": "select"},
|
7
|
+
{"type": "TEXT_NODE", "start": 8, "end": 9, "token": " "},
|
8
|
+
{"type": "TEXT_NODE", "start": 9, "end": 12, "token": "the"},
|
9
|
+
{"type": "TEXT_NODE", "start": 12, "end": 13, "token": " "},
|
10
|
+
{"type": "PARAMETER_NODE", "start": 13, "end": 18, "nodes": [
|
11
|
+
{"type": "TEXT_NODE", "start": 14, "end": 17, "token": "int"}
|
12
|
+
]},
|
13
|
+
{"type": "ALTERNATION_NODE", "start": 18, "end": 29, "nodes": [
|
14
|
+
{"type": "ALTERNATIVE_NODE", "start": 18, "end": 20, "nodes": [
|
15
|
+
{"type": "TEXT_NODE", "start": 18, "end": 20, "token": "st"}
|
16
|
+
]},
|
17
|
+
{"type": "ALTERNATIVE_NODE", "start": 21, "end": 23, "nodes": [
|
18
|
+
{"type": "TEXT_NODE", "start": 21, "end": 23, "token": "nd"}
|
19
|
+
]},
|
20
|
+
{"type": "ALTERNATIVE_NODE", "start": 24, "end": 26, "nodes": [
|
21
|
+
{"type": "TEXT_NODE", "start": 24, "end": 26, "token": "rd"}
|
22
|
+
]},
|
23
|
+
{"type": "ALTERNATIVE_NODE", "start": 27, "end": 29, "nodes": [
|
24
|
+
{"type": "TEXT_NODE", "start": 27, "end": 29, "token": "th"}
|
25
|
+
]}
|
26
|
+
]}
|
27
|
+
]}
|