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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50c9796de315f381ef13e5ce25d8e6342b71c02a2e0b15067858806e3e312716
4
- data.tar.gz: c21a0b6a20af97e368833ba1ef95e22c7316d3fd9db677895c9ad0d2653b5f3e
3
+ metadata.gz: 705a1aa48bf85408fc0db737e50091584f930c7e73e6ffe485f5c8cdf0c8a9f4
4
+ data.tar.gz: 3d40ff2d7b847cb5b44aa547ab6e46791e769abccf7beaf14e5de9f0440710e3
5
5
  SHA512:
6
- metadata.gz: 56bb332b0b0bab9c250e855c13d94bd166ff660e3c6f054946a4f3b65dfc2ec9d79ef360ff4d2bf93fa73d943e396c38ac1405aaa348a5fa0bf9f35c65755339
7
- data.tar.gz: b60ff154a2f586a4765271e5ff838331d89337c3a13c32e039169a81d3ad42ebfc22332f9a6fcb518577ff17edc543781e83eb2849e45076f0a207379b4747d8
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 = '10.0.0'
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
- ifneq (,$(GEMSPEC))
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 -f .deps .linked .tested* Gemfile.lock *.gem
82
+ rm -rf .deps .linked .tested* Gemfile.lock *.gem acceptance
76
83
  .PHONY: clean-ruby
@@ -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]
@@ -11,7 +11,7 @@ module Cucumber
11
11
  end
12
12
 
13
13
  def values
14
- (children.empty? ? [self] : children).map(&:value).compact
14
+ (children.empty? ? [self] : children).map(&:value)
15
15
  end
16
16
  end
17
17
  end
@@ -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(/\s|\p{P}/)
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(/\s|\p{P}/)
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 {|s = nil| s && s.gsub(/\\"/, '"').gsub(/\\'/, "'")}, true, false))
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
- @stack = [GroupBuilder.new]
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
- @stack.push(GroupBuilder.new)
26
- group_start_stack.push(n + 1)
27
- @non_capturing_maybe = false
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 = @stack.pop
68
+ gb = stack.pop
30
69
  group_start = group_start_stack.pop
31
70
  if gb.capturing?
32
- gb.source = @regexp.source[group_start...n]
33
- @stack.last.add(gb)
71
+ gb.source = source[group_start + 1...i]
72
+ stack.last.add(gb)
34
73
  else
35
- gb.move_children_to(@stack.last)
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
- @group_builder = @stack.pop
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 'throws an error when there are named capture groups because they are buggy in Ruby' do
126
- # https://github.com/cucumber/cucumber/issues/329
127
- expect {
128
- TreeRegexp.new(/^I am a person( named "(?<first_name>.+) (?<last_name>.+)")?$/)
129
- }.to raise_error(/Named capture groups are not supported/)
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.0.0
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-03-31 00:00:00.000000000 Z
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
- rubyforge_project:
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.0.0
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