cucumber-cucumber-expressions 10.0.0 → 10.3.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/VERSION +1 -0
- data/cucumber-cucumber-expressions.gemspec +4 -1
- data/default.mk +13 -6
- data/examples.txt +8 -0
- data/lib/cucumber/cucumber_expressions/group.rb +1 -1
- data/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb +2 -2
- data/lib/cucumber/cucumber_expressions/parameter_type_registry.rb +1 -1
- data/lib/cucumber/cucumber_expressions/tree_regexp.rb +53 -46
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +27 -0
- data/spec/cucumber/cucumber_expressions/tree_regexp_spec.rb +58 -5
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 705a1aa48bf85408fc0db737e50091584f930c7e73e6ffe485f5c8cdf0c8a9f4
|
4
|
+
data.tar.gz: 3d40ff2d7b847cb5b44aa547ab6e46791e769abccf7beaf14e5de9f0440710e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9407c5108c578c553831398255986de2bee9393500adb35f3528b359e05ae0cc3df966b163da15052623b0dfe01efb2b64e624a1976030dc0c9d355e279cf89
|
7
|
+
data.tar.gz: 51ce8f4c93b3948dbb36c34cd221f48aa29c2eb812fb4d7a582b2644b4118d1e6373d1de644c5d78470525bc80a9ab4dae6f414eec27ef55e3c6a76fedce2ee1
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
10.3.0
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
version = File.read(File.expand_path("VERSION", __dir__)).strip
|
4
|
+
|
2
5
|
Gem::Specification.new do |s|
|
3
6
|
s.name = 'cucumber-cucumber-expressions'
|
4
|
-
s.version =
|
7
|
+
s.version = version
|
5
8
|
s.authors = ["Aslak Hellesøy"]
|
6
9
|
s.description = 'Cucumber Expressions - a simpler alternative to Regular Expressions'
|
7
10
|
s.summary = "cucumber-expressions-#{s.version}"
|
data/default.mk
CHANGED
@@ -3,6 +3,10 @@ RUBY_SOURCE_FILES = $(shell find . -name "*.rb")
|
|
3
3
|
GEMSPEC = $(shell find . -name "*.gemspec")
|
4
4
|
LIBNAME := $(shell basename $$(dirname $$(pwd)))
|
5
5
|
GEM := cucumber-$(LIBNAME)-$(NEW_VERSION).gem
|
6
|
+
IS_TESTDATA = $(findstring -testdata,${CURDIR})
|
7
|
+
|
8
|
+
# https://stackoverflow.com/questions/2483182/recursive-wildcards-in-gnu-make
|
9
|
+
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
6
10
|
|
7
11
|
default: .tested
|
8
12
|
.PHONY: default
|
@@ -45,22 +49,25 @@ pre-release: remove-local-dependencies update-version update-dependencies gem
|
|
45
49
|
.PHONY: pre-release
|
46
50
|
|
47
51
|
update-version:
|
52
|
+
ifeq ($(IS_TESTDATA),-testdata)
|
53
|
+
# no-op
|
54
|
+
else
|
48
55
|
ifdef NEW_VERSION
|
49
|
-
|
50
|
-
sed -i "s/\(s\.version *= *'\)[0-9]*\.[0-9]*\.[0-9]*\('\)/\1$(NEW_VERSION)\2/" $(GEMSPEC)
|
56
|
+
@echo "$(NEW_VERSION)" > VERSION
|
51
57
|
endif
|
52
|
-
else
|
53
|
-
@echo -e "\033[0;31mNEW_VERSION is not defined. Can't update version :-(\033[0m"
|
54
|
-
exit 1
|
55
58
|
endif
|
56
59
|
.PHONY: update-version
|
57
60
|
|
58
61
|
publish: gem
|
62
|
+
ifeq ($(IS_TESTDATA),-testdata)
|
63
|
+
# no-op
|
64
|
+
else
|
59
65
|
ifneq (,$(GEMSPEC))
|
60
66
|
gem push $(GEM)
|
61
67
|
else
|
62
68
|
@echo "Not publishing because there is no gemspec"
|
63
69
|
endif
|
70
|
+
endif
|
64
71
|
.PHONY: publish
|
65
72
|
|
66
73
|
post-release:
|
@@ -72,5 +79,5 @@ clean: clean-ruby
|
|
72
79
|
.PHONY: clean
|
73
80
|
|
74
81
|
clean-ruby:
|
75
|
-
rm -
|
82
|
+
rm -rf .deps .linked .tested* Gemfile.lock *.gem acceptance
|
76
83
|
.PHONY: clean-ruby
|
data/examples.txt
CHANGED
@@ -29,3 +29,11 @@ I have 22 cukes in my belly now
|
|
29
29
|
I have {} cuke(s) in my {} now
|
30
30
|
I have 22 cukes in my belly now
|
31
31
|
["22","belly"]
|
32
|
+
---
|
33
|
+
/^a (pre-commercial transaction |pre buyer fee model )?purchase(?: for \$(\d+))?$/
|
34
|
+
a purchase for $33
|
35
|
+
[null,33]
|
36
|
+
---
|
37
|
+
Some ${float} of cukes at {int}° Celsius
|
38
|
+
Some $3.50 of cukes at 42° Celsius
|
39
|
+
[3.5,42]
|
@@ -47,12 +47,12 @@ module Cucumber
|
|
47
47
|
|
48
48
|
def space_before_match_or_sentence_start?
|
49
49
|
match_begin = @match.begin(0)
|
50
|
-
match_begin == 0 || @text[match_begin - 1].match(/\
|
50
|
+
match_begin == 0 || @text[match_begin - 1].match(/\p{Z}|\p{P}|\p{S}/)
|
51
51
|
end
|
52
52
|
|
53
53
|
def space_after_match_or_sentence_end?
|
54
54
|
match_end = @match.end(0)
|
55
|
-
match_end == @text.length || @text[match_end].match(/\
|
55
|
+
match_end == @text.length || @text[match_end].match(/\p{Z}|\p{P}|\p{S}/)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -18,7 +18,7 @@ module Cucumber
|
|
18
18
|
define_parameter_type(ParameterType.new('int', INTEGER_REGEXPS, Integer, lambda {|s = nil| s && s.to_i}, true, true))
|
19
19
|
define_parameter_type(ParameterType.new('float', FLOAT_REGEXP, Float, lambda {|s = nil| s && s.to_f}, true, false))
|
20
20
|
define_parameter_type(ParameterType.new('word', WORD_REGEXP, String, lambda {|s = nil| s}, false, false))
|
21
|
-
define_parameter_type(ParameterType.new('string', STRING_REGEXP, String, lambda {|
|
21
|
+
define_parameter_type(ParameterType.new('string', STRING_REGEXP, String, lambda { |s1, s2| arg = s1 != nil ? s1 : s2; arg.gsub(/\\"/, '"').gsub(/\\'/, "'")}, true, false))
|
22
22
|
define_parameter_type(ParameterType.new('', ANONYMOUS_REGEXP, String, lambda {|s = nil| s}, false, true))
|
23
23
|
end
|
24
24
|
|
@@ -8,68 +8,75 @@ module Cucumber
|
|
8
8
|
|
9
9
|
def initialize(regexp)
|
10
10
|
@regexp = regexp.is_a?(Regexp) ? regexp : Regexp.new(regexp)
|
11
|
-
@
|
11
|
+
@group_builder = create_group_builder(@regexp)
|
12
|
+
end
|
13
|
+
|
14
|
+
def match(s)
|
15
|
+
match = @regexp.match(s)
|
16
|
+
return nil if match.nil?
|
17
|
+
group_indices = (0..match.length).to_a.to_enum
|
18
|
+
@group_builder.build(match, group_indices)
|
19
|
+
end
|
20
|
+
|
21
|
+
private def is_non_capturing(source, i)
|
22
|
+
# Regex is valid. Bounds check not required.
|
23
|
+
if source[i+1] != '?'
|
24
|
+
# (X)
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
if source[i+2] != '<'
|
29
|
+
# (?:X)
|
30
|
+
# (?idmsuxU-idmsuxU)
|
31
|
+
# (?idmsux-idmsux:X)
|
32
|
+
# (?=X)
|
33
|
+
# (?!X)
|
34
|
+
# (?>X)
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
|
38
|
+
if source[i+3] == '=' || source[i+3] == '!'
|
39
|
+
# (?<=X)
|
40
|
+
# (?<!X)
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
|
44
|
+
# (?<name>X)
|
45
|
+
raise CucumberExpressionError.new("Named capture groups are not supported. See https://github.com/cucumber/cucumber/issues/329")
|
46
|
+
end
|
47
|
+
|
48
|
+
private def create_group_builder(regexp)
|
49
|
+
source = regexp.source
|
50
|
+
stack = [GroupBuilder.new]
|
12
51
|
group_start_stack = []
|
13
|
-
last = nil
|
14
52
|
escaping = false
|
15
|
-
@non_capturing_maybe = false
|
16
|
-
@name_capturing_maybe = false
|
17
53
|
char_class = false
|
18
|
-
|
19
|
-
@regexp.source.each_char.with_index do |c, n|
|
54
|
+
source.each_char.with_index do |c, i|
|
20
55
|
if c == '[' && !escaping
|
21
56
|
char_class = true
|
22
57
|
elsif c == ']' && !escaping
|
23
58
|
char_class = false
|
24
59
|
elsif c == '(' && !escaping && !char_class
|
25
|
-
|
26
|
-
|
27
|
-
|
60
|
+
group_start_stack.push(i)
|
61
|
+
group_builder = GroupBuilder.new
|
62
|
+
non_capturing = is_non_capturing(source, i)
|
63
|
+
if non_capturing
|
64
|
+
group_builder.set_non_capturing!
|
65
|
+
end
|
66
|
+
stack.push(group_builder)
|
28
67
|
elsif c == ')' && !escaping && !char_class
|
29
|
-
gb =
|
68
|
+
gb = stack.pop
|
30
69
|
group_start = group_start_stack.pop
|
31
70
|
if gb.capturing?
|
32
|
-
gb.source =
|
33
|
-
|
71
|
+
gb.source = source[group_start + 1...i]
|
72
|
+
stack.last.add(gb)
|
34
73
|
else
|
35
|
-
gb.move_children_to(
|
74
|
+
gb.move_children_to(stack.last)
|
36
75
|
end
|
37
|
-
end_group
|
38
|
-
elsif c == '?' && last == '('
|
39
|
-
@non_capturing_maybe = true
|
40
|
-
elsif (c == '<') && @non_capturing_maybe
|
41
|
-
@name_capturing_maybe = true
|
42
|
-
elsif (c == ':' || c == '!' || c == '=') && last == '?' && @non_capturing_maybe
|
43
|
-
end_non_capturing_group
|
44
|
-
elsif (c == '=' || c == '!') && last == '<' && @name_capturing_maybe
|
45
|
-
end_non_capturing_group
|
46
|
-
elsif @name_capturing_maybe
|
47
|
-
raise CucumberExpressionError.new("Named capture groups are not supported. See https://github.com/cucumber/cucumber/issues/329")
|
48
76
|
end
|
49
|
-
|
50
77
|
escaping = c == '\\' && !escaping
|
51
|
-
last = c
|
52
78
|
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
def match(s)
|
57
|
-
match = @regexp.match(s)
|
58
|
-
return nil if match.nil?
|
59
|
-
group_indices = (0..match.length).to_a.to_enum
|
60
|
-
@group_builder.build(match, group_indices)
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def end_non_capturing_group
|
66
|
-
@stack.last.set_non_capturing!
|
67
|
-
end_group
|
68
|
-
end
|
69
|
-
|
70
|
-
def end_group
|
71
|
-
@non_capturing_maybe = false
|
72
|
-
@name_capturing_maybe = false
|
79
|
+
stack.pop
|
73
80
|
end
|
74
81
|
end
|
75
82
|
end
|
@@ -201,6 +201,33 @@ module Cucumber
|
|
201
201
|
end
|
202
202
|
end
|
203
203
|
|
204
|
+
|
205
|
+
it "unmatched optional groups have undefined values" do
|
206
|
+
parameter_type_registry = ParameterTypeRegistry.new
|
207
|
+
parameter_type_registry.define_parameter_type(
|
208
|
+
ParameterType.new(
|
209
|
+
'textAndOrNumber',
|
210
|
+
/([A-Z]+)?(?: )?([0-9]+)?/,
|
211
|
+
Object,
|
212
|
+
-> (s1, s2) {
|
213
|
+
[s1, s2]
|
214
|
+
},
|
215
|
+
false,
|
216
|
+
true
|
217
|
+
)
|
218
|
+
)
|
219
|
+
expression = CucumberExpression.new(
|
220
|
+
'{textAndOrNumber}',
|
221
|
+
parameter_type_registry
|
222
|
+
)
|
223
|
+
|
224
|
+
class World
|
225
|
+
end
|
226
|
+
|
227
|
+
expect(expression.match("TLA")[0].value(World.new)).to eq(["TLA", nil])
|
228
|
+
expect(expression.match("123")[0].value(World.new)).to eq([nil, "123"])
|
229
|
+
end
|
230
|
+
|
204
231
|
def match(expression, text)
|
205
232
|
cucumber_expression = CucumberExpression.new(expression, ParameterTypeRegistry.new)
|
206
233
|
args = cucumber_expression.match(text)
|
@@ -22,6 +22,7 @@ module Cucumber
|
|
22
22
|
group = tr.match('abc')
|
23
23
|
expect(group.value).to eq('abc')
|
24
24
|
expect(group.children.length).to eq 1
|
25
|
+
expect(group.children[0].value).to eq('c')
|
25
26
|
end
|
26
27
|
|
27
28
|
it 'ignores `?!` as a non-capturing group' do
|
@@ -55,6 +56,28 @@ module Cucumber
|
|
55
56
|
expect(group.children.length).to eq 1
|
56
57
|
end
|
57
58
|
|
59
|
+
it 'ignores `?<!` as a non-capturing group' do
|
60
|
+
tr = TreeRegexp.new(/a(.+)(?<!b)$/)
|
61
|
+
group = tr.match('abc')
|
62
|
+
expect(group.value).to eq('abc')
|
63
|
+
expect(group.children[0].value).to eq('bc')
|
64
|
+
expect(group.children.length).to eq 1
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'ignores `?>` as a non-capturing group' do
|
68
|
+
tr = TreeRegexp.new(/a(?>b)c/)
|
69
|
+
group = tr.match('abc')
|
70
|
+
expect(group.value).to eq('abc')
|
71
|
+
expect(group.children.length).to eq 0
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'throws an error when there are named capture groups because they are buggy in Ruby' do
|
75
|
+
# https://github.com/cucumber/cucumber/issues/329
|
76
|
+
expect {
|
77
|
+
TreeRegexp.new(/^I am a person( named "(?<first_name>.+) (?<last_name>.+)")?$/)
|
78
|
+
}.to raise_error(/Named capture groups are not supported/)
|
79
|
+
end
|
80
|
+
|
58
81
|
it 'matches optional group' do
|
59
82
|
tr = TreeRegexp.new(/^Something( with an optional argument)?/)
|
60
83
|
group = tr.match('Something')
|
@@ -122,12 +145,42 @@ module Cucumber
|
|
122
145
|
expect(group.children.length).to eq(1)
|
123
146
|
end
|
124
147
|
|
125
|
-
it '
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
148
|
+
it 'works with inline flags' do
|
149
|
+
tr = TreeRegexp.new(/(?i)HELLO/)
|
150
|
+
group = tr.match('hello')
|
151
|
+
expect(group.value).to eq('hello')
|
152
|
+
expect(group.children.length).to eq 0
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'works with non capturing inline flags' do
|
156
|
+
tr = TreeRegexp.new(/(?i:HELLO)/)
|
157
|
+
group = tr.match('hello')
|
158
|
+
expect(group.value).to eq('hello')
|
159
|
+
expect(group.children.length).to eq 0
|
130
160
|
end
|
161
|
+
|
162
|
+
it 'works with empty capturing group' do
|
163
|
+
tr = TreeRegexp.new(/()/)
|
164
|
+
group = tr.match('')
|
165
|
+
expect(group.value).to eq('')
|
166
|
+
expect(group.children[0].value).to eq('')
|
167
|
+
expect(group.children.length).to eq 1
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'works with empty non-capturing group' do
|
171
|
+
tr = TreeRegexp.new(/(?:)/)
|
172
|
+
group = tr.match('')
|
173
|
+
expect(group.value).to eq('')
|
174
|
+
expect(group.children.length).to eq 0
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'works with empty non-look ahead' do
|
178
|
+
tr = TreeRegexp.new(/(?<=)/)
|
179
|
+
group = tr.match('')
|
180
|
+
expect(group.value).to eq('')
|
181
|
+
expect(group.children.length).to eq 0
|
182
|
+
end
|
183
|
+
|
131
184
|
end
|
132
185
|
end
|
133
186
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-cucumber-expressions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.
|
4
|
+
version: 10.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aslak Hellesøy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- Makefile
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
|
+
- VERSION
|
69
70
|
- cucumber-cucumber-expressions.gemspec
|
70
71
|
- default.mk
|
71
72
|
- examples.txt
|
@@ -122,11 +123,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
123
|
- !ruby/object:Gem::Version
|
123
124
|
version: '0'
|
124
125
|
requirements: []
|
125
|
-
|
126
|
-
rubygems_version: 2.7.6.2
|
126
|
+
rubygems_version: 3.1.2
|
127
127
|
signing_key:
|
128
128
|
specification_version: 4
|
129
|
-
summary: cucumber-expressions-10.
|
129
|
+
summary: cucumber-expressions-10.3.0
|
130
130
|
test_files:
|
131
131
|
- spec/capture_warnings.rb
|
132
132
|
- spec/cucumber/cucumber_expressions/argument_spec.rb
|