cucumber-cucumber-expressions 17.0.2 → 18.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 +21 -0
- metadata +14 -44
- data/.rubocop.yml +0 -37
- data/.rubocop_todo.yml +0 -443
- data/Gemfile +0 -4
- data/Rakefile +0 -12
- data/VERSION +0 -1
- data/cucumber-cucumber-expressions.gemspec +0 -38
- data/spec/cucumber/cucumber_expressions/argument_spec.rb +0 -19
- data/spec/cucumber/cucumber_expressions/combinatorial_generated_expression_factory_spec.rb +0 -41
- data/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb +0 -234
- data/spec/cucumber/cucumber_expressions/cucumber_expression_parser_spec.rb +0 -25
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +0 -178
- data/spec/cucumber/cucumber_expressions/cucumber_expression_tokenizer_spec.rb +0 -25
- data/spec/cucumber/cucumber_expressions/cucumber_expression_transformation_spec.rb +0 -29
- data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +0 -216
- data/spec/cucumber/cucumber_expressions/expression_factory_spec.rb +0 -21
- data/spec/cucumber/cucumber_expressions/parameter_type_registry_spec.rb +0 -81
- data/spec/cucumber/cucumber_expressions/parameter_type_spec.rb +0 -18
- data/spec/cucumber/cucumber_expressions/regular_expression_spec.rb +0 -93
- data/spec/cucumber/cucumber_expressions/tree_regexp_spec.rb +0 -186
@@ -1,216 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cucumber/cucumber_expressions/cucumber_expression'
|
4
|
-
require 'cucumber/cucumber_expressions/regular_expression'
|
5
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
6
|
-
|
7
|
-
module Cucumber
|
8
|
-
module CucumberExpressions
|
9
|
-
class Color
|
10
|
-
attr_reader :name
|
11
|
-
|
12
|
-
def initialize(name)
|
13
|
-
@name = name
|
14
|
-
end
|
15
|
-
|
16
|
-
def ==(other)
|
17
|
-
other.is_a?(Color) && other.name == name
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class CssColor
|
22
|
-
attr_reader :name
|
23
|
-
|
24
|
-
def initialize(name)
|
25
|
-
@name = name
|
26
|
-
end
|
27
|
-
|
28
|
-
def ==(other)
|
29
|
-
other.is_a?(CssColor) && other.name == name
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class Coordinate
|
34
|
-
attr_reader :x, :y, :z
|
35
|
-
|
36
|
-
def initialize(x, y, z)
|
37
|
-
@x, @y, @z = x, y, z
|
38
|
-
end
|
39
|
-
|
40
|
-
def ==(other)
|
41
|
-
other.is_a?(Coordinate) && other.x == x && other.y == y && other.z == z
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe 'Custom parameter type' do
|
46
|
-
before do
|
47
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
48
|
-
parameter_type_registry.define_parameter_type(
|
49
|
-
ParameterType.new(
|
50
|
-
'color', # name
|
51
|
-
/red|blue|yellow/, # regexp
|
52
|
-
Color, # type
|
53
|
-
->(s) { Color.new(s) }, # transform
|
54
|
-
true, # use_for_snippets
|
55
|
-
false # prefer_for_regexp_match
|
56
|
-
)
|
57
|
-
)
|
58
|
-
@parameter_type_registry = parameter_type_registry
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'throws exception for illegal character in parameter name' do
|
62
|
-
expect do
|
63
|
-
ParameterType.new(
|
64
|
-
'[string]',
|
65
|
-
/.*/,
|
66
|
-
String,
|
67
|
-
->(s) { s },
|
68
|
-
true,
|
69
|
-
false
|
70
|
-
)
|
71
|
-
end.to raise_error("Illegal character in parameter name {[string]}. Parameter names may not contain '[]()$.|?*+'")
|
72
|
-
end
|
73
|
-
|
74
|
-
describe CucumberExpression do
|
75
|
-
it 'matches parameters with custom parameter type' do
|
76
|
-
expression = described_class.new('I have a {color} ball', @parameter_type_registry)
|
77
|
-
transformed_argument_value = expression.match('I have a red ball')[0].value(nil)
|
78
|
-
|
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(
|
84
|
-
ParameterType.new(
|
85
|
-
'coordinate',
|
86
|
-
/(\d+),\s*(\d+),\s*(\d+)/,
|
87
|
-
Coordinate,
|
88
|
-
->(x, y, z) { Coordinate.new(x.to_i, y.to_i, z.to_i) },
|
89
|
-
true,
|
90
|
-
false
|
91
|
-
)
|
92
|
-
)
|
93
|
-
|
94
|
-
expression = described_class.new('A {int} thick line from {coordinate} to {coordinate}', @parameter_type_registry)
|
95
|
-
args = expression.match('A 5 thick line from 10,20,30 to 40,50,60')
|
96
|
-
|
97
|
-
thick = args[0].value(nil)
|
98
|
-
expect(thick).to eq(5)
|
99
|
-
|
100
|
-
from = args[1].value(nil)
|
101
|
-
expect(from).to eq(Coordinate.new(10, 20, 30))
|
102
|
-
|
103
|
-
to = args[2].value(nil)
|
104
|
-
expect(to).to eq(Coordinate.new(40, 50, 60))
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'matches parameters with custom parameter type using optional capture group' do
|
108
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
109
|
-
parameter_type_registry.define_parameter_type(
|
110
|
-
ParameterType.new(
|
111
|
-
'color',
|
112
|
-
[/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/],
|
113
|
-
Color,
|
114
|
-
->(s) { Color.new(s) },
|
115
|
-
true,
|
116
|
-
false
|
117
|
-
)
|
118
|
-
)
|
119
|
-
expression = described_class.new('I have a {color} ball', parameter_type_registry)
|
120
|
-
transformed_argument_value = expression.match('I have a dark red ball')[0].value(nil)
|
121
|
-
|
122
|
-
expect(transformed_argument_value).to eq(Color.new('dark red'))
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'defers transformation until queried from argument' do
|
126
|
-
@parameter_type_registry.define_parameter_type(
|
127
|
-
ParameterType.new(
|
128
|
-
'throwing',
|
129
|
-
/bad/,
|
130
|
-
CssColor,
|
131
|
-
->(s) { raise "Can't transform [#{s}]" },
|
132
|
-
true,
|
133
|
-
false
|
134
|
-
)
|
135
|
-
)
|
136
|
-
expression = described_class.new('I have a {throwing} parameter', @parameter_type_registry)
|
137
|
-
args = expression.match('I have a bad parameter')
|
138
|
-
|
139
|
-
expect { args[0].value(nil) }.to raise_error("Can't transform [bad]")
|
140
|
-
end
|
141
|
-
|
142
|
-
describe 'conflicting parameter type' do
|
143
|
-
it 'is detected for type name' do
|
144
|
-
expect {
|
145
|
-
@parameter_type_registry.define_parameter_type(
|
146
|
-
ParameterType.new(
|
147
|
-
'color',
|
148
|
-
/.*/,
|
149
|
-
CssColor,
|
150
|
-
->(s) { CssColor.new(s) },
|
151
|
-
true,
|
152
|
-
false
|
153
|
-
)
|
154
|
-
)
|
155
|
-
}.to raise_error('There is already a parameter with name color')
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'is not detected for type' do
|
159
|
-
@parameter_type_registry.define_parameter_type(
|
160
|
-
ParameterType.new(
|
161
|
-
'whatever',
|
162
|
-
/.*/,
|
163
|
-
Color,
|
164
|
-
->(s) { Color.new(s) },
|
165
|
-
false,
|
166
|
-
false
|
167
|
-
)
|
168
|
-
)
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'is not detected for regexp' do
|
172
|
-
@parameter_type_registry.define_parameter_type(
|
173
|
-
ParameterType.new(
|
174
|
-
'css-color',
|
175
|
-
/red|blue|yellow/,
|
176
|
-
CssColor,
|
177
|
-
->(s) { CssColor.new(s) },
|
178
|
-
true,
|
179
|
-
false
|
180
|
-
)
|
181
|
-
)
|
182
|
-
css_color = described_class.new('I have a {css-color} ball', @parameter_type_registry)
|
183
|
-
css_color_value = css_color.match('I have a blue ball')[0].value(nil)
|
184
|
-
|
185
|
-
expect(css_color_value).to eq(CssColor.new('blue'))
|
186
|
-
|
187
|
-
color = described_class.new('I have a {color} ball', @parameter_type_registry)
|
188
|
-
color_value = color.match('I have a blue ball')[0].value(nil)
|
189
|
-
|
190
|
-
expect(color_value).to eq(Color.new('blue'))
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
describe RegularExpression do
|
196
|
-
it 'matches arguments with custom parameter types without a name' do
|
197
|
-
parameter_type_registry = ParameterTypeRegistry.new
|
198
|
-
parameter_type_registry.define_parameter_type(
|
199
|
-
ParameterType.new(
|
200
|
-
nil,
|
201
|
-
/red|blue|yellow/,
|
202
|
-
Color,
|
203
|
-
->(s) { Color.new(s) },
|
204
|
-
true,
|
205
|
-
false
|
206
|
-
)
|
207
|
-
)
|
208
|
-
expression = described_class.new(/I have a (red|blue|yellow) ball/, parameter_type_registry)
|
209
|
-
value = expression.match('I have a red ball')[0].value(nil)
|
210
|
-
|
211
|
-
expect(value).to eq(Color.new('red'))
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cucumber/cucumber_expressions/expression_factory'
|
4
|
-
|
5
|
-
module Cucumber
|
6
|
-
module CucumberExpressions
|
7
|
-
describe ExpressionFactory do
|
8
|
-
before do
|
9
|
-
@expression_factory = described_class.new(ParameterTypeRegistry.new)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'creates a RegularExpression' do
|
13
|
-
expect(@expression_factory.create_expression(/x/).class).to eq(RegularExpression)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'creates a CucumberExpression' do
|
17
|
-
expect(@expression_factory.create_expression('{int}').class).to eq(CucumberExpression)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
4
|
-
require 'cucumber/cucumber_expressions/parameter_type'
|
5
|
-
require 'cucumber/cucumber_expressions/errors'
|
6
|
-
|
7
|
-
module Cucumber
|
8
|
-
module CucumberExpressions
|
9
|
-
CAPITALISED_WORD = /[A-Z]+\w+/.freeze
|
10
|
-
|
11
|
-
class Name; end
|
12
|
-
class Person; end
|
13
|
-
class Place; end
|
14
|
-
|
15
|
-
describe ParameterTypeRegistry do
|
16
|
-
before do
|
17
|
-
@registry = described_class.new
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'does not allow more than one prefer_for_regexp_match parameter type for each regexp' do
|
21
|
-
@registry.define_parameter_type(ParameterType.new('name', CAPITALISED_WORD, Name, ->(_) { Name.new }, true, true))
|
22
|
-
@registry.define_parameter_type(ParameterType.new('person', CAPITALISED_WORD, Person, ->(_) { Person.new }, true, false))
|
23
|
-
expect do
|
24
|
-
@registry.define_parameter_type(ParameterType.new('place', CAPITALISED_WORD, Place, ->(_) { Place.new }, true, true))
|
25
|
-
end.to raise_error(
|
26
|
-
CucumberExpressionError,
|
27
|
-
'There can only be one preferential parameter type per regexp. The regexp /[A-Z]+\\w+/ is used for two: {name} and {place}'
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'looks up prefer_for_regexp_match parameter type by regexp' do
|
32
|
-
name = ParameterType.new('name', CAPITALISED_WORD, Name, ->(_) { Name.new }, true, false)
|
33
|
-
person = ParameterType.new('person', CAPITALISED_WORD, Person, ->(_) { Person.new }, true, true)
|
34
|
-
place = ParameterType.new('place', CAPITALISED_WORD, Place, ->(_) { Place.new }, true, false)
|
35
|
-
|
36
|
-
@registry.define_parameter_type(name)
|
37
|
-
@registry.define_parameter_type(person)
|
38
|
-
@registry.define_parameter_type(place)
|
39
|
-
|
40
|
-
expect(@registry.lookup_by_regexp(CAPITALISED_WORD.source, /([A-Z]+\w+) and ([A-Z]+\w+)/, 'Lisa and Bob')).to eq(person)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'throws ambiguous exception when no parameter types are prefer_for_regexp_match' do
|
44
|
-
name = ParameterType.new('name', CAPITALISED_WORD, Name, ->(_) { Name.new }, true, false)
|
45
|
-
person = ParameterType.new('person', CAPITALISED_WORD, Person, ->(_) { Person.new }, true, false)
|
46
|
-
place = ParameterType.new('place', CAPITALISED_WORD, Place, ->(_) { Place.new }, true, false)
|
47
|
-
|
48
|
-
@registry.define_parameter_type(name)
|
49
|
-
@registry.define_parameter_type(person)
|
50
|
-
@registry.define_parameter_type(place)
|
51
|
-
|
52
|
-
expect do
|
53
|
-
expect(@registry.lookup_by_regexp(CAPITALISED_WORD.source, /([A-Z]+\w+) and ([A-Z]+\w+)/, 'Lisa and Bob')).to eq(person)
|
54
|
-
end.to raise_error(
|
55
|
-
CucumberExpressionError,
|
56
|
-
"Your Regular Expression /([A-Z]+\\w+) and ([A-Z]+\\w+)/\n" \
|
57
|
-
"matches multiple parameter types with regexp /[A-Z]+\\w+/:\n " \
|
58
|
-
"{name}\n " \
|
59
|
-
"{person}\n " \
|
60
|
-
"{place}\n" \
|
61
|
-
"\n" \
|
62
|
-
"I couldn't decide which one to use. You have two options:\n" \
|
63
|
-
"\n" \
|
64
|
-
"1) Use a Cucumber Expression instead of a Regular Expression. Try one of these:\n " \
|
65
|
-
"{name} and {name}\n " \
|
66
|
-
"{name} and {person}\n " \
|
67
|
-
"{name} and {place}\n " \
|
68
|
-
"{person} and {name}\n " \
|
69
|
-
"{person} and {person}\n " \
|
70
|
-
"{person} and {place}\n " \
|
71
|
-
"{place} and {name}\n " \
|
72
|
-
"{place} and {person}\n " \
|
73
|
-
"{place} and {place}\n" \
|
74
|
-
"\n" \
|
75
|
-
"2) Make one of the parameter types preferential and continue to use a Regular Expression.\n" \
|
76
|
-
"\n"
|
77
|
-
)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cucumber/cucumber_expressions/parameter_type'
|
4
|
-
|
5
|
-
module Cucumber
|
6
|
-
module CucumberExpressions
|
7
|
-
describe ParameterType do
|
8
|
-
it 'does not allow ignore flag on regexp' do
|
9
|
-
expect do
|
10
|
-
described_class.new('case-insensitive', /[a-z]+/i, String, ->(s) { s }, true, true)
|
11
|
-
end.to raise_error(
|
12
|
-
CucumberExpressionError,
|
13
|
-
"ParameterType Regexps can't use option Regexp::IGNORECASE"
|
14
|
-
)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'yaml'
|
4
|
-
require 'cucumber/cucumber_expressions/regular_expression'
|
5
|
-
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
6
|
-
|
7
|
-
module Cucumber
|
8
|
-
module CucumberExpressions
|
9
|
-
describe RegularExpression do
|
10
|
-
Dir['../testdata/regular-expression/matching/*.yaml'].each do |path|
|
11
|
-
expectation = YAML.load_file(path)
|
12
|
-
|
13
|
-
it "matches #{path}" do
|
14
|
-
parameter_registry = ParameterTypeRegistry.new
|
15
|
-
expression = described_class.new(Regexp.new(expectation['expression']), parameter_registry)
|
16
|
-
matches = expression.match(expectation['text'])
|
17
|
-
values = matches.map { |arg| arg.value(nil) }
|
18
|
-
|
19
|
-
expect(values).to eq(expectation['expected_args'])
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'does not transform by default' do
|
24
|
-
expect(match(/(\d\d)/, '22')).to eq(['22'])
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'does not transform anonymous' do
|
28
|
-
expect(match(/(.*)/, '22')).to eq(['22'])
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'transforms negative int' do
|
32
|
-
expect(match(/(-?\d+)/, '-22')).to eq([-22])
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'transforms positive int' do
|
36
|
-
expect(match(/(\d+)/, '22')).to eq([22])
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'returns nil when there is no match' do
|
40
|
-
expect(match(/hello/, 'world')).to be_nil
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'matches empty string when there is an empty string match' do
|
44
|
-
expect(match(/^The value equals "([^"]*)"$/, 'The value equals ""')).to eq([''])
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'matches nested capture group without match' do
|
48
|
-
expect(match(/^a user( named "([^"]*)")?$/, 'a user')).to eq([nil])
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'matches nested capture group with match' do
|
52
|
-
expect(match(/^a user( named "([^"]*)")?$/, 'a user named "Charlie"')).to eq(['Charlie'])
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'ignores non capturing groups' do
|
56
|
-
expect(
|
57
|
-
match(
|
58
|
-
/(\S+) ?(can|cannot) (?:delete|cancel) the (\d+)(?:st|nd|rd|th) (attachment|slide) ?(?:upload)?/,
|
59
|
-
'I can cancel the 1st slide upload'
|
60
|
-
)
|
61
|
-
).to eq(['I', 'can', 1, 'slide'])
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'matches capture group nested in optional one' do
|
65
|
-
regexp = /^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/
|
66
|
-
|
67
|
-
expect(match(regexp, 'a purchase')).to eq([nil, nil])
|
68
|
-
expect(match(regexp, 'a purchase for $33')).to eq([nil, 33])
|
69
|
-
expect(match(regexp, 'a pre buyer fee model purchase')).to eq(['pre buyer fee model ', nil])
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'works with escaped parentheses' do
|
73
|
-
expect(match(/Across the line\(s\)/, 'Across the line(s)')).to eq([])
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'exposes source and regexp' do
|
77
|
-
regexp = /I have (\d+) cukes? in my (\+) now/
|
78
|
-
expression = described_class.new(regexp, ParameterTypeRegistry.new)
|
79
|
-
|
80
|
-
expect(expression.regexp).to eq(regexp)
|
81
|
-
expect(expression.source).to eq(regexp.source)
|
82
|
-
end
|
83
|
-
|
84
|
-
def match(expression, text)
|
85
|
-
regular_expression = RegularExpression.new(expression, ParameterTypeRegistry.new)
|
86
|
-
arguments = regular_expression.match(text)
|
87
|
-
return nil if arguments.nil?
|
88
|
-
|
89
|
-
arguments.map { |arg| arg.value(nil) }
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cucumber/cucumber_expressions/tree_regexp'
|
4
|
-
|
5
|
-
module Cucumber
|
6
|
-
module CucumberExpressions
|
7
|
-
describe TreeRegexp do
|
8
|
-
it 'exposes the group source' do
|
9
|
-
tr = described_class.new(/(a(?:b)?)(c)/)
|
10
|
-
expect(tr.group_builder.children.map { |gb| gb.source }).to eq(['a(?:b)?', 'c'])
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'builds a tree' do
|
14
|
-
tr = described_class.new(/(a(?:b)?)(c)/)
|
15
|
-
group = tr.match('ac')
|
16
|
-
expect(group.value).to eq('ac')
|
17
|
-
expect(group.children[0].value).to eq('a')
|
18
|
-
expect(group.children[0].children).to eq([])
|
19
|
-
expect(group.children[1].value).to eq('c')
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'ignores `?:` as a non-capturing group' do
|
23
|
-
tr = described_class.new(/a(?:b)(c)/)
|
24
|
-
group = tr.match('abc')
|
25
|
-
expect(group.value).to eq('abc')
|
26
|
-
expect(group.children.length).to eq 1
|
27
|
-
expect(group.children[0].value).to eq('c')
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'ignores `?!` as a non-capturing group' do
|
31
|
-
tr = described_class.new(/a(?!b)(.+)/)
|
32
|
-
group = tr.match('aBc')
|
33
|
-
expect(group.value).to eq('aBc')
|
34
|
-
expect(group.children.length).to eq 1
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'ignores `?=` as a non-capturing group' do
|
38
|
-
tr = described_class.new(/a(?=b)(.+)$/)
|
39
|
-
group = tr.match('abc')
|
40
|
-
expect(group.value).to eq('abc')
|
41
|
-
expect(group.children[0].value).to eq('bc')
|
42
|
-
expect(group.children.length).to eq 1
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'ignores `?<=` as a non-capturing group' do
|
46
|
-
tr = described_class.new(/a(.+)(?<=c)$/)
|
47
|
-
group = tr.match('abc')
|
48
|
-
expect(group.value).to eq('abc')
|
49
|
-
expect(group.children[0].value).to eq('bc')
|
50
|
-
expect(group.children.length).to eq 1
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'ignores `?<!` as a non-capturing group' do
|
54
|
-
tr = described_class.new(/a(.+)(?<!b)$/)
|
55
|
-
group = tr.match('abc')
|
56
|
-
expect(group.value).to eq('abc')
|
57
|
-
expect(group.children[0].value).to eq('bc')
|
58
|
-
expect(group.children.length).to eq 1
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'ignores `?<!` as a non-capturing group' do
|
62
|
-
tr = described_class.new(/a(.+)(?<!b)$/)
|
63
|
-
group = tr.match('abc')
|
64
|
-
expect(group.value).to eq('abc')
|
65
|
-
expect(group.children[0].value).to eq('bc')
|
66
|
-
expect(group.children.length).to eq 1
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'ignores `?>` as a non-capturing group' do
|
70
|
-
tr = described_class.new(/a(?>b)c/)
|
71
|
-
group = tr.match('abc')
|
72
|
-
expect(group.value).to eq('abc')
|
73
|
-
expect(group.children.length).to eq 0
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'throws an error when there are named capture groups because they are buggy in Ruby' do
|
77
|
-
# https://github.com/cucumber/cucumber/issues/329
|
78
|
-
expect { described_class.new(/^I am a person( named "(?<first_name>.+) (?<last_name>.+)")?$/) }
|
79
|
-
.to raise_error(/Named capture groups are not supported/)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'matches an optional group' do
|
83
|
-
tr = described_class.new(/^Something( with an optional argument)?/)
|
84
|
-
group = tr.match('Something')
|
85
|
-
expect(group.children[0].value).to be_nil
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'matches nested groups' do
|
89
|
-
tr = described_class.new(/^A (\d+) thick line from ((\d+),\s*(\d+),\s*(\d+)) to ((\d+),\s*(\d+),\s*(\d+))/)
|
90
|
-
group = tr.match('A 5 thick line from 10,20,30 to 40,50,60')
|
91
|
-
|
92
|
-
expect(group.children[0].value).to eq('5')
|
93
|
-
expect(group.children[1].value).to eq('10,20,30')
|
94
|
-
expect(group.children[1].children[0].value).to eq('10')
|
95
|
-
expect(group.children[1].children[1].value).to eq('20')
|
96
|
-
expect(group.children[1].children[2].value).to eq('30')
|
97
|
-
expect(group.children[2].value).to eq('40,50,60')
|
98
|
-
expect(group.children[2].children[0].value).to eq('40')
|
99
|
-
expect(group.children[2].children[1].value).to eq('50')
|
100
|
-
expect(group.children[2].children[2].value).to eq('60')
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'detects multiple non-capturing groups' do
|
104
|
-
tr = described_class.new(/(?:a)(:b)(\?c)(d)/)
|
105
|
-
group = tr.match('a:b?cd')
|
106
|
-
expect(group.children.length).to eq(3)
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'works with escaped backslashes' do
|
110
|
-
tr = described_class.new(/foo\\(bar|baz)/)
|
111
|
-
group = tr.match('foo\\bar')
|
112
|
-
expect(group.children.length).to eq(1)
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'works with escaped slashes' do
|
116
|
-
tr = described_class.new(/^I go to '\/(.+)'$/)
|
117
|
-
group = tr.match("I go to '/hello'")
|
118
|
-
expect(group.children.length).to eq(1)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'works with digit and word regexp metacharacters' do
|
122
|
-
tr = described_class.new(/^(\d) (\w+)$/)
|
123
|
-
group = tr.match('2 you')
|
124
|
-
expect(group.children.length).to eq(2)
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'captures non-capturing groups with capturing groups inside' do
|
128
|
-
tr = described_class.new(/the stdout(?: from "(.*?)")?/)
|
129
|
-
group = tr.match('the stdout')
|
130
|
-
expect(group.value).to eq('the stdout')
|
131
|
-
expect(group.children[0].value).to eq(nil)
|
132
|
-
expect(group.children.length).to eq(1)
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'works with flags' do
|
136
|
-
tr = described_class.new(/HELLO/i)
|
137
|
-
group = tr.match('hello')
|
138
|
-
expect(group.value).to eq('hello')
|
139
|
-
end
|
140
|
-
|
141
|
-
it('does not consider parentheses in regexp character classes as a group') do
|
142
|
-
tr = described_class.new(/^drawings: ([A-Z_, ()]+)$/)
|
143
|
-
group = tr.match('drawings: ONE, TWO(ABC)')
|
144
|
-
expect(group.value).to eq('drawings: ONE, TWO(ABC)')
|
145
|
-
expect(group.children[0].value).to eq('ONE, TWO(ABC)')
|
146
|
-
expect(group.children.length).to eq(1)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'works with inline flags' do
|
150
|
-
tr = described_class.new(/(?i)HELLO/)
|
151
|
-
group = tr.match('hello')
|
152
|
-
expect(group.value).to eq('hello')
|
153
|
-
expect(group.children.length).to eq 0
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'works with non-capturing inline flags' do
|
157
|
-
tr = described_class.new(/(?i:HELLO)/)
|
158
|
-
group = tr.match('hello')
|
159
|
-
expect(group.value).to eq('hello')
|
160
|
-
expect(group.children.length).to eq 0
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'works with empty capturing groups' do
|
164
|
-
tr = described_class.new(/()/)
|
165
|
-
group = tr.match('')
|
166
|
-
expect(group.value).to eq('')
|
167
|
-
expect(group.children[0].value).to eq('')
|
168
|
-
expect(group.children.length).to eq 1
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'works with empty non-capturing groups' do
|
172
|
-
tr = described_class.new(/(?:)/)
|
173
|
-
group = tr.match('')
|
174
|
-
expect(group.value).to eq('')
|
175
|
-
expect(group.children.length).to eq 0
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'works with empty non-look ahead groups' do
|
179
|
-
tr = described_class.new(/(?<=)/)
|
180
|
-
group = tr.match('')
|
181
|
-
expect(group.value).to eq('')
|
182
|
-
expect(group.children.length).to eq 0
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|