cucumber-cucumber-expressions 10.3.0 → 11.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.rsync +1 -0
  3. data/VERSION +1 -1
  4. data/cucumber-cucumber-expressions.gemspec +1 -1
  5. data/examples.txt +5 -1
  6. data/lib/cucumber/cucumber_expressions/ast.rb +201 -0
  7. data/lib/cucumber/cucumber_expressions/cucumber_expression.rb +80 -76
  8. data/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +4 -8
  9. data/lib/cucumber/cucumber_expressions/cucumber_expression_parser.rb +219 -0
  10. data/lib/cucumber/cucumber_expressions/cucumber_expression_tokenizer.rb +95 -0
  11. data/lib/cucumber/cucumber_expressions/errors.rb +175 -4
  12. data/lib/cucumber/cucumber_expressions/parameter_type.rb +12 -7
  13. data/spec/cucumber/cucumber_expressions/cucumber_expression_parser_spec.rb +24 -0
  14. data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +62 -140
  15. data/spec/cucumber/cucumber_expressions/cucumber_expression_tokenizer_spec.rb +24 -0
  16. data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +1 -1
  17. data/spec/cucumber/cucumber_expressions/expression_examples_spec.rb +1 -1
  18. data/spec/cucumber/cucumber_expressions/expression_factory_spec.rb +0 -4
  19. data/testdata/ast/alternation-followed-by-optional.yaml +17 -0
  20. data/testdata/ast/alternation-phrase.yaml +16 -0
  21. data/testdata/ast/alternation-with-parameter.yaml +27 -0
  22. data/testdata/ast/alternation-with-unused-end-optional.yaml +15 -0
  23. data/testdata/ast/alternation-with-unused-start-optional.yaml +8 -0
  24. data/testdata/ast/alternation-with-white-space.yaml +12 -0
  25. data/testdata/ast/alternation.yaml +12 -0
  26. data/testdata/ast/anonymous-parameter.yaml +5 -0
  27. data/testdata/ast/closing-brace.yaml +5 -0
  28. data/testdata/ast/closing-parenthesis.yaml +5 -0
  29. data/testdata/ast/empty-alternation.yaml +8 -0
  30. data/testdata/ast/empty-alternations.yaml +9 -0
  31. data/testdata/ast/empty-string.yaml +3 -0
  32. data/testdata/ast/escaped-alternation.yaml +5 -0
  33. data/testdata/ast/escaped-backslash.yaml +5 -0
  34. data/testdata/ast/escaped-opening-parenthesis.yaml +5 -0
  35. data/testdata/ast/escaped-optional-followed-by-optional.yaml +15 -0
  36. data/testdata/ast/escaped-optional-phrase.yaml +10 -0
  37. data/testdata/ast/escaped-optional.yaml +7 -0
  38. data/testdata/ast/opening-brace.yaml +8 -0
  39. data/testdata/ast/opening-parenthesis.yaml +8 -0
  40. data/testdata/ast/optional-containing-nested-optional.yaml +15 -0
  41. data/testdata/ast/optional-phrase.yaml +12 -0
  42. data/testdata/ast/optional.yaml +7 -0
  43. data/testdata/ast/parameter.yaml +7 -0
  44. data/testdata/ast/phrase.yaml +9 -0
  45. data/testdata/ast/unfinished-parameter.yaml +8 -0
  46. data/testdata/expression/allows-escaped-optional-parameter-types.yaml +4 -0
  47. data/testdata/expression/allows-parameter-type-in-alternation-1.yaml +4 -0
  48. data/testdata/expression/allows-parameter-type-in-alternation-2.yaml +4 -0
  49. data/testdata/expression/does-allow-parameter-adjacent-to-alternation.yaml +5 -0
  50. data/testdata/expression/does-not-allow-alternation-in-optional.yaml +9 -0
  51. data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-left-parameter.yaml +10 -0
  52. data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-optional.yaml +9 -0
  53. data/testdata/expression/does-not-allow-alternation-with-empty-alternative-by-adjacent-right-parameter.yaml +9 -0
  54. data/testdata/expression/does-not-allow-alternation-with-empty-alternative.yaml +9 -0
  55. data/testdata/expression/does-not-allow-empty-optional.yaml +9 -0
  56. data/testdata/expression/does-not-allow-nested-optional.yaml +8 -0
  57. data/testdata/expression/does-not-allow-optional-parameter-types.yaml +9 -0
  58. data/testdata/expression/does-not-allow-parameter-name-with-reserved-characters.yaml +10 -0
  59. data/testdata/expression/does-not-allow-unfinished-parenthesis-1.yaml +8 -0
  60. data/testdata/expression/does-not-allow-unfinished-parenthesis-2.yaml +8 -0
  61. data/testdata/expression/does-not-allow-unfinished-parenthesis-3.yaml +8 -0
  62. data/testdata/expression/does-not-match-misquoted-string.yaml +4 -0
  63. data/testdata/expression/doesnt-match-float-as-int.yaml +5 -0
  64. data/testdata/expression/matches-alternation.yaml +4 -0
  65. data/testdata/expression/matches-anonymous-parameter-type.yaml +5 -0
  66. data/testdata/expression/matches-double-quoted-empty-string-as-empty-string-along-with-other-strings.yaml +4 -0
  67. data/testdata/expression/matches-double-quoted-empty-string-as-empty-string.yaml +4 -0
  68. data/testdata/expression/matches-double-quoted-string-with-escaped-double-quote.yaml +4 -0
  69. data/testdata/expression/matches-double-quoted-string-with-single-quotes.yaml +4 -0
  70. data/testdata/expression/matches-double-quoted-string.yaml +4 -0
  71. data/testdata/expression/matches-doubly-escaped-parenthesis.yaml +4 -0
  72. data/testdata/expression/matches-doubly-escaped-slash-1.yaml +4 -0
  73. data/testdata/expression/matches-doubly-escaped-slash-2.yaml +4 -0
  74. data/testdata/expression/matches-escaped-parenthesis-1.yaml +4 -0
  75. data/testdata/expression/matches-escaped-parenthesis-2.yaml +4 -0
  76. data/testdata/expression/matches-escaped-parenthesis-3.yaml +4 -0
  77. data/testdata/expression/matches-escaped-slash.yaml +4 -0
  78. data/testdata/expression/matches-float-1.yaml +5 -0
  79. data/testdata/expression/matches-float-2.yaml +5 -0
  80. data/testdata/expression/matches-int.yaml +5 -0
  81. data/testdata/expression/matches-multiple-double-quoted-strings.yaml +4 -0
  82. data/testdata/expression/matches-multiple-single-quoted-strings.yaml +4 -0
  83. data/testdata/expression/matches-optional-before-alternation-1.yaml +4 -0
  84. data/testdata/expression/matches-optional-before-alternation-2.yaml +4 -0
  85. data/testdata/expression/matches-optional-before-alternation-with-regex-characters-1.yaml +4 -0
  86. data/testdata/expression/matches-optional-before-alternation-with-regex-characters-2.yaml +4 -0
  87. data/testdata/expression/matches-optional-in-alternation-1.yaml +5 -0
  88. data/testdata/expression/matches-optional-in-alternation-2.yaml +5 -0
  89. data/testdata/expression/matches-optional-in-alternation-3.yaml +5 -0
  90. data/testdata/expression/matches-single-quoted-empty-string-as-empty-string-along-with-other-strings.yaml +4 -0
  91. data/testdata/expression/matches-single-quoted-empty-string-as-empty-string.yaml +4 -0
  92. data/testdata/expression/matches-single-quoted-string-with-double-quotes.yaml +4 -0
  93. data/testdata/expression/matches-single-quoted-string-with-escaped-single-quote.yaml +4 -0
  94. data/testdata/expression/matches-single-quoted-string.yaml +4 -0
  95. data/testdata/expression/matches-word.yaml +4 -0
  96. data/testdata/expression/throws-unknown-parameter-type.yaml +10 -0
  97. data/testdata/regex/alternation-with-optional.yaml +2 -0
  98. data/testdata/regex/alternation.yaml +2 -0
  99. data/testdata/regex/empty.yaml +2 -0
  100. data/testdata/regex/escape-regex-characters.yaml +2 -0
  101. data/testdata/regex/optional.yaml +2 -0
  102. data/testdata/regex/parameter.yaml +2 -0
  103. data/testdata/regex/text.yaml +2 -0
  104. data/testdata/regex/unicode.yaml +2 -0
  105. data/testdata/tokens/alternation-phrase.yaml +13 -0
  106. data/testdata/tokens/alternation.yaml +9 -0
  107. data/testdata/tokens/empty-string.yaml +6 -0
  108. data/testdata/tokens/escape-non-reserved-character.yaml +8 -0
  109. data/testdata/tokens/escaped-alternation.yaml +9 -0
  110. data/testdata/tokens/escaped-char-has-start-index-of-text-token.yaml +9 -0
  111. data/testdata/tokens/escaped-end-of-line.yaml +8 -0
  112. data/testdata/tokens/escaped-optional.yaml +7 -0
  113. data/testdata/tokens/escaped-parameter.yaml +7 -0
  114. data/testdata/tokens/escaped-space.yaml +7 -0
  115. data/testdata/tokens/optional-phrase.yaml +13 -0
  116. data/testdata/tokens/optional.yaml +9 -0
  117. data/testdata/tokens/parameter-phrase.yaml +13 -0
  118. data/testdata/tokens/parameter.yaml +9 -0
  119. data/testdata/tokens/phrase.yaml +11 -0
  120. metadata +115 -9
  121. 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
- if ILLEGAL_PARAMETER_NAME_PATTERN =~ unescaped_type_name
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
- 'EXTENDED',
69
- 'IGNORECASE',
70
- 'MULTILINE'
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 "matches anonymous" do
130
- expect(match("{}", "0.22")).to eq(["0.22"])
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 "does not allow parameter type/text alternation" do
156
- expect {match("{int}/x", "3")}.to raise_error('Parameter types cannot be alternative: {int}/x')
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 "delegates transform to custom object" do
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
- ParameterType.new(
168
- 'widget',
169
- /\w+/,
170
- Object,
171
- -> (s) {
172
- self.create_widget(s)
173
- },
174
- false,
175
- true
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
- 'I have a {widget}',
180
- parameter_type_registry
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
- args = expression.match("I have a bolt")
190
- expect(args[0].value(World.new)).to eq('widget:bolt')
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 "unmatched optional groups have undefined values" do
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
- 'textAndOrNumber',
210
- /([A-Z]+)?(?: )?([0-9]+)?/,
128
+ 'widget',
129
+ /\w+/,
211
130
  Object,
212
- -> (s1, s2) {
213
- [s1, s2]
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
- '{textAndOrNumber}',
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
- 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"])
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 '[' in parameter name {[string]}")
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
+ ]}