cucumber-cucumber-expressions 8.3.1
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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +5 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
- data/.rspec +1 -0
- data/.rsync +4 -0
- data/.subrepo +1 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/Makefile +1 -0
- data/README.md +5 -0
- data/Rakefile +27 -0
- data/cucumber-cucumber-expressions.gemspec +33 -0
- data/default.mk +70 -0
- data/examples.txt +31 -0
- data/lib/cucumber/cucumber_expressions/argument.rb +37 -0
- data/lib/cucumber/cucumber_expressions/combinatorial_generated_expression_factory.rb +49 -0
- data/lib/cucumber/cucumber_expressions/cucumber_expression.rb +119 -0
- data/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +105 -0
- data/lib/cucumber/cucumber_expressions/errors.rb +40 -0
- data/lib/cucumber/cucumber_expressions/generated_expression.rb +31 -0
- data/lib/cucumber/cucumber_expressions/group.rb +18 -0
- data/lib/cucumber/cucumber_expressions/group_builder.rb +42 -0
- data/lib/cucumber/cucumber_expressions/parameter_type.rb +81 -0
- data/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb +59 -0
- data/lib/cucumber/cucumber_expressions/parameter_type_registry.rb +70 -0
- data/lib/cucumber/cucumber_expressions/regular_expression.rb +48 -0
- data/lib/cucumber/cucumber_expressions/tree_regexp.rb +76 -0
- data/scripts/update-gemspec +32 -0
- data/spec/capture_warnings.rb +74 -0
- data/spec/coverage.rb +7 -0
- data/spec/cucumber/cucumber_expressions/argument_spec.rb +17 -0
- data/spec/cucumber/cucumber_expressions/combinatorial_generated_expression_factory_test.rb +43 -0
- data/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb +231 -0
- data/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb +57 -0
- data/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +212 -0
- data/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb +202 -0
- data/spec/cucumber/cucumber_expressions/expression_examples_spec.rb +30 -0
- data/spec/cucumber/cucumber_expressions/parameter_type_registry_spec.rb +86 -0
- data/spec/cucumber/cucumber_expressions/parameter_type_spec.rb +15 -0
- data/spec/cucumber/cucumber_expressions/regular_expression_spec.rb +80 -0
- data/spec/cucumber/cucumber_expressions/tree_regexp_spec.rb +133 -0
- metadata +162 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'cucumber/cucumber_expressions/argument'
|
2
|
+
require 'cucumber/cucumber_expressions/parameter_type'
|
3
|
+
require 'cucumber/cucumber_expressions/tree_regexp'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
module CucumberExpressions
|
7
|
+
class RegularExpression
|
8
|
+
|
9
|
+
def initialize(expression_regexp, parameter_type_registry)
|
10
|
+
@expression_regexp = expression_regexp
|
11
|
+
@parameter_type_registry = parameter_type_registry
|
12
|
+
@tree_regexp = TreeRegexp.new(@expression_regexp)
|
13
|
+
end
|
14
|
+
|
15
|
+
def match(text)
|
16
|
+
parameter_types = @tree_regexp.group_builder.children.map do |group_builder|
|
17
|
+
parameter_type_regexp = group_builder.source
|
18
|
+
@parameter_type_registry.lookup_by_regexp(
|
19
|
+
parameter_type_regexp,
|
20
|
+
@expression_regexp,
|
21
|
+
text
|
22
|
+
) || ParameterType.new(
|
23
|
+
nil,
|
24
|
+
parameter_type_regexp,
|
25
|
+
String,
|
26
|
+
lambda {|*s| s[0]},
|
27
|
+
false,
|
28
|
+
false
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
Argument.build(@tree_regexp, text, parameter_types)
|
33
|
+
end
|
34
|
+
|
35
|
+
def regexp
|
36
|
+
@expression_regexp
|
37
|
+
end
|
38
|
+
|
39
|
+
def source
|
40
|
+
@expression_regexp.source
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
regexp.inspect
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'cucumber/cucumber_expressions/group_builder'
|
2
|
+
require 'cucumber/cucumber_expressions/errors'
|
3
|
+
|
4
|
+
module Cucumber
|
5
|
+
module CucumberExpressions
|
6
|
+
class TreeRegexp
|
7
|
+
attr_reader :regexp, :group_builder
|
8
|
+
|
9
|
+
def initialize(regexp)
|
10
|
+
@regexp = regexp.is_a?(Regexp) ? regexp : Regexp.new(regexp)
|
11
|
+
@stack = [GroupBuilder.new]
|
12
|
+
group_start_stack = []
|
13
|
+
last = nil
|
14
|
+
escaping = false
|
15
|
+
@non_capturing_maybe = false
|
16
|
+
@name_capturing_maybe = false
|
17
|
+
char_class = false
|
18
|
+
|
19
|
+
@regexp.source.each_char.with_index do |c, n|
|
20
|
+
if c == '[' && !escaping
|
21
|
+
char_class = true
|
22
|
+
elsif c == ']' && !escaping
|
23
|
+
char_class = false
|
24
|
+
elsif c == '(' && !escaping && !char_class
|
25
|
+
@stack.push(GroupBuilder.new)
|
26
|
+
group_start_stack.push(n + 1)
|
27
|
+
@non_capturing_maybe = false
|
28
|
+
elsif c == ')' && !escaping && !char_class
|
29
|
+
gb = @stack.pop
|
30
|
+
group_start = group_start_stack.pop
|
31
|
+
if gb.capturing?
|
32
|
+
gb.source = @regexp.source[group_start...n]
|
33
|
+
@stack.last.add(gb)
|
34
|
+
else
|
35
|
+
gb.move_children_to(@stack.last)
|
36
|
+
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
|
+
end
|
49
|
+
|
50
|
+
escaping = c == '\\' && !escaping
|
51
|
+
last = c
|
52
|
+
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
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#
|
3
|
+
# Updates the *.gemspec in the current directory to use the latest releases of gems
|
4
|
+
#
|
5
|
+
set -uf -o pipefail
|
6
|
+
IFS=$'\n'
|
7
|
+
|
8
|
+
gemspec=$(find . -type f -maxdepth 1 -name "*.gemspec")
|
9
|
+
if [ "${gemspec}" = "" ]; then
|
10
|
+
exit 0
|
11
|
+
fi
|
12
|
+
add_dependency_lines=$(cat ${gemspec} | grep "s.add_[a-z_]*dependency '[^']*'")
|
13
|
+
if [ $? -ne 0 ]; then
|
14
|
+
# No add_dependency_lines found - nothing to do
|
15
|
+
exit 0
|
16
|
+
fi
|
17
|
+
|
18
|
+
set -e
|
19
|
+
|
20
|
+
gems=$(echo "${add_dependency_lines}" | tr -s ' ' | cut -d ' ' -f3 | cut -d"'" -f 2)
|
21
|
+
while read -r gem; do
|
22
|
+
echo "upgrading ${gem}"
|
23
|
+
if [ "${gem}" = "bundler" ]; then
|
24
|
+
cat "${gemspec}" | sed "s/\(s.add_[a-z_]*dependency\) '${gem}'.*/\1 '${gem}', '>= 1.16.2'/" > ${gemspec}.tmp
|
25
|
+
else
|
26
|
+
gem_line=$(gem list "${gem}" --remote --all --no-prerelease | grep "^${gem}\s")
|
27
|
+
latest_patch_version=$(echo "${gem_line}" | cut -d'(' -f2 | cut -d')' -f1 | cut -d',' -f1 | cut -d' ' -f1)
|
28
|
+
latest_minor_version=$(echo "${latest_patch_version}" | cut -d. -f1,2)
|
29
|
+
cat "${gemspec}" | sed "s/\(s.add_[a-z_]*dependency\) '${gem}'.*/\1 '${gem}', '~> ${latest_minor_version}', '>= ${latest_patch_version}'/" > ${gemspec}.tmp
|
30
|
+
fi
|
31
|
+
mv ${gemspec}.tmp ${gemspec}
|
32
|
+
done <<< "${gems}"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# With thanks to @myronmarston
|
3
|
+
# https://github.com/vcr/vcr/blob/master/spec/capture_warnings.rb
|
4
|
+
|
5
|
+
module CaptureWarnings
|
6
|
+
def report_warnings(&block)
|
7
|
+
current_dir = Dir.pwd
|
8
|
+
warnings, errors = capture_error(&block).partition { |line| line.include?('warning') }
|
9
|
+
project_warnings, other_warnings = warnings.uniq.partition { |line| line.include?(current_dir) }
|
10
|
+
|
11
|
+
if errors.any?
|
12
|
+
puts errors.join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
if other_warnings.any?
|
16
|
+
puts "#{ other_warnings.count } warnings detected, set VIEW_OTHER_WARNINGS=true to see them."
|
17
|
+
print_warnings('other', other_warnings) if ENV['VIEW_OTHER_WARNINGS']
|
18
|
+
end
|
19
|
+
|
20
|
+
# Until they fix https://bugs.ruby-lang.org/issues/10661
|
21
|
+
if RUBY_VERSION == "2.2.0"
|
22
|
+
project_warnings = project_warnings.reject { |w| w =~ /warning: possible reference to past scope/ }
|
23
|
+
end
|
24
|
+
|
25
|
+
if project_warnings.any?
|
26
|
+
puts "#{ project_warnings.count } warnings detected"
|
27
|
+
print_warnings('cucumber-expressions', project_warnings)
|
28
|
+
fail "Please remove all cucumber-expressions warnings."
|
29
|
+
end
|
30
|
+
|
31
|
+
ensure_system_exit_if_required
|
32
|
+
end
|
33
|
+
|
34
|
+
def capture_error(&block)
|
35
|
+
old_stderr = STDERR.clone
|
36
|
+
pipe_r, pipe_w = IO.pipe
|
37
|
+
pipe_r.sync = true
|
38
|
+
error = String.new
|
39
|
+
reader = Thread.new do
|
40
|
+
begin
|
41
|
+
loop do
|
42
|
+
error << pipe_r.readpartial(1024)
|
43
|
+
end
|
44
|
+
rescue EOFError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
STDERR.reopen(pipe_w)
|
48
|
+
block.call
|
49
|
+
ensure
|
50
|
+
capture_system_exit
|
51
|
+
STDERR.reopen(old_stderr)
|
52
|
+
pipe_w.close
|
53
|
+
reader.join
|
54
|
+
return error.split("\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_warnings(type, warnings)
|
58
|
+
puts
|
59
|
+
puts "-" * 30 + " #{type} warnings: " + "-" * 30
|
60
|
+
puts
|
61
|
+
puts warnings.join("\n")
|
62
|
+
puts
|
63
|
+
puts "-" * 75
|
64
|
+
puts
|
65
|
+
end
|
66
|
+
|
67
|
+
def ensure_system_exit_if_required
|
68
|
+
raise @system_exit if @system_exit
|
69
|
+
end
|
70
|
+
|
71
|
+
def capture_system_exit
|
72
|
+
@system_exit = $!
|
73
|
+
end
|
74
|
+
end
|
data/spec/coverage.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'cucumber/cucumber_expressions/argument'
|
2
|
+
require 'cucumber/cucumber_expressions/tree_regexp'
|
3
|
+
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
module CucumberExpressions
|
7
|
+
describe Argument do
|
8
|
+
it 'exposes parameter_type' do
|
9
|
+
tree_regexp = TreeRegexp.new(/three (.*) mice/)
|
10
|
+
parameter_type_registry = ParameterTypeRegistry.new
|
11
|
+
arguments = Argument.build(tree_regexp, "three blind mice", [parameter_type_registry.lookup_by_type_name("string")])
|
12
|
+
argument = arguments[0]
|
13
|
+
expect(argument.parameter_type.name).to eq("string")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'cucumber/cucumber_expressions/parameter_type'
|
2
|
+
require 'cucumber/cucumber_expressions/combinatorial_generated_expression_factory'
|
3
|
+
|
4
|
+
module Cucumber
|
5
|
+
module CucumberExpressions
|
6
|
+
|
7
|
+
class Color; end
|
8
|
+
class CssColor; end
|
9
|
+
class Date; end
|
10
|
+
class DateTime; end
|
11
|
+
class Timestamp; end
|
12
|
+
|
13
|
+
describe CombinatorialGeneratedExpressionFactory do
|
14
|
+
it 'generates multiple expressions' do
|
15
|
+
parameter_type_combinations = [
|
16
|
+
[
|
17
|
+
ParameterType.new('color', /red|blue|yellow/, Color, lambda {|s| Color.new}, true, false),
|
18
|
+
ParameterType.new('csscolor', /red|blue|yellow/, CssColor, lambda {|s| CssColor.new}, true, false)
|
19
|
+
],
|
20
|
+
[
|
21
|
+
ParameterType.new('date', /\d{4}-\d{2}-\d{2}/, Date, lambda {|s| Date.new}, true, false),
|
22
|
+
ParameterType.new('datetime', /\d{4}-\d{2}-\d{2}/, DateTime, lambda {|s| DateTime.new}, true, false),
|
23
|
+
ParameterType.new('timestamp', /\d{4}-\d{2}-\d{2}/, Timestamp, lambda {|s| Timestamp.new}, true, false)
|
24
|
+
]
|
25
|
+
]
|
26
|
+
|
27
|
+
factory = CombinatorialGeneratedExpressionFactory.new(
|
28
|
+
'I bought a {%s} ball on {%s}',
|
29
|
+
parameter_type_combinations
|
30
|
+
)
|
31
|
+
expressions = factory.generate_expressions.map {|ge| ge.source}
|
32
|
+
expect(expressions).to eq([
|
33
|
+
'I bought a {color} ball on {date}',
|
34
|
+
'I bought a {color} ball on {datetime}',
|
35
|
+
'I bought a {color} ball on {timestamp}',
|
36
|
+
'I bought a {csscolor} ball on {date}',
|
37
|
+
'I bought a {csscolor} ball on {datetime}',
|
38
|
+
'I bought a {csscolor} ball on {timestamp}',
|
39
|
+
])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'cucumber/cucumber_expressions/cucumber_expression_generator'
|
2
|
+
require 'cucumber/cucumber_expressions/cucumber_expression'
|
3
|
+
require 'cucumber/cucumber_expressions/parameter_type'
|
4
|
+
require 'cucumber/cucumber_expressions/parameter_type_registry'
|
5
|
+
|
6
|
+
module Cucumber
|
7
|
+
module CucumberExpressions
|
8
|
+
describe CucumberExpressionGenerator do
|
9
|
+
class Currency
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
@parameter_type_registry = ParameterTypeRegistry.new
|
14
|
+
@generator = CucumberExpressionGenerator.new(@parameter_type_registry)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "documents expression generation" do
|
18
|
+
parameter_registry = ParameterTypeRegistry.new
|
19
|
+
### [generate-expression]
|
20
|
+
generator = CucumberExpressionGenerator.new(parameter_registry)
|
21
|
+
undefined_step_text = "I have 2 cucumbers and 1.5 tomato"
|
22
|
+
generated_expression = generator.generate_expression(undefined_step_text)
|
23
|
+
expect(generated_expression.source).to eq("I have {int} cucumbers and {float} tomato")
|
24
|
+
expect(generated_expression.parameter_types[1].type).to eq(Float)
|
25
|
+
### [generate-expression]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "generates expression for no args" do
|
29
|
+
assert_expression("hello", [], "hello")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "generates expression with escaped left parenthesis" do
|
33
|
+
assert_expression(
|
34
|
+
"\\(iii)", [],
|
35
|
+
"(iii)")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "generates expression with escaped left curly brace" do
|
39
|
+
assert_expression(
|
40
|
+
"\\{iii}", [],
|
41
|
+
"{iii}")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "generates expression with escaped slashes" do
|
45
|
+
assert_expression(
|
46
|
+
"The {int}\\/{int}\\/{int} hey", ["int", "int2", "int3"],
|
47
|
+
"The 1814/05/17 hey")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "generates expression for int float arg" do
|
51
|
+
assert_expression(
|
52
|
+
"I have {int} cukes and {float} euro", ["int", "float"],
|
53
|
+
"I have 2 cukes and 1.5 euro")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "generates expression for strings" do
|
57
|
+
assert_expression(
|
58
|
+
"I like {string} and {string}", ["string", "string2"],
|
59
|
+
'I like "bangers" and \'mash\'')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "generates expression with % sign" do
|
63
|
+
assert_expression(
|
64
|
+
"I am {int}% foobar", ["int"],
|
65
|
+
'I am 20% foobar')
|
66
|
+
end
|
67
|
+
|
68
|
+
it "generates expression for just int" do
|
69
|
+
assert_expression(
|
70
|
+
"{int}", ["int"],
|
71
|
+
"99999")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "numbers only second argument when builtin type is not reserved keyword" do
|
75
|
+
assert_expression(
|
76
|
+
"I have {int} cukes and {int} euro", ["int", "int2"],
|
77
|
+
"I have 2 cukes and 5 euro")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "numbers only second argument when type is not reserved keyword" do
|
81
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
82
|
+
'currency',
|
83
|
+
'[A-Z]{3}',
|
84
|
+
Currency,
|
85
|
+
lambda {|s| Currency.new(s)},
|
86
|
+
true,
|
87
|
+
true
|
88
|
+
))
|
89
|
+
|
90
|
+
assert_expression(
|
91
|
+
"I have a {currency} account and a {currency} account", ["currency", "currency2"],
|
92
|
+
"I have a EUR account and a GBP account")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "exposes parameters in generated expression" do
|
96
|
+
expression = @generator.generate_expression("I have 2 cukes and 1.5 euro")
|
97
|
+
types = expression.parameter_types.map(&:type)
|
98
|
+
expect(types).to eq([Integer, Float])
|
99
|
+
end
|
100
|
+
|
101
|
+
it "matches parameter types with optional capture groups" do
|
102
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
103
|
+
'optional-flight',
|
104
|
+
/(1st flight)?/,
|
105
|
+
String,
|
106
|
+
lambda {|s| s},
|
107
|
+
true,
|
108
|
+
false
|
109
|
+
))
|
110
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
111
|
+
'optional-hotel',
|
112
|
+
/(1 hotel)?/,
|
113
|
+
String,
|
114
|
+
lambda {|s| s},
|
115
|
+
true,
|
116
|
+
false
|
117
|
+
))
|
118
|
+
|
119
|
+
expression = @generator.generate_expressions("I reach Stage 4: 1st flight -1 hotel")[0]
|
120
|
+
# While you would expect this to be `I reach Stage {int}: {optional-flight} -{optional-hotel}`
|
121
|
+
# the `-1` causes {int} to match just before {optional-hotel}.
|
122
|
+
expect(expression.source).to eq("I reach Stage {int}: {optional-flight} {int} hotel")
|
123
|
+
end
|
124
|
+
|
125
|
+
it "generates at most 256 expressions" do
|
126
|
+
for i in 0..3
|
127
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
128
|
+
"my-type-#{i}",
|
129
|
+
/([a-z] )*?[a-z]/,
|
130
|
+
String,
|
131
|
+
lambda {|s| s},
|
132
|
+
true,
|
133
|
+
false
|
134
|
+
))
|
135
|
+
end
|
136
|
+
# This would otherwise generate 4^11=4194300 expressions and consume just shy of 1.5GB.
|
137
|
+
expressions = @generator.generate_expressions("a s i m p l e s t e p")
|
138
|
+
expect(expressions.length).to eq(256)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "prefers expression with longest non empty match" do
|
142
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
143
|
+
'zero-or-more',
|
144
|
+
/[a-z]*/,
|
145
|
+
String,
|
146
|
+
lambda {|s| s},
|
147
|
+
true,
|
148
|
+
false
|
149
|
+
))
|
150
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
151
|
+
'exactly-one',
|
152
|
+
/[a-z]/,
|
153
|
+
String,
|
154
|
+
lambda {|s| s},
|
155
|
+
true,
|
156
|
+
false
|
157
|
+
))
|
158
|
+
|
159
|
+
expressions = @generator.generate_expressions("a simple step")
|
160
|
+
expect(expressions.length).to eq(2)
|
161
|
+
expect(expressions[0].source).to eq("{exactly-one} {zero-or-more} {zero-or-more}")
|
162
|
+
expect(expressions[1].source).to eq("{zero-or-more} {zero-or-more} {zero-or-more}")
|
163
|
+
end
|
164
|
+
|
165
|
+
context "does not suggest parameter when match is" do
|
166
|
+
before do
|
167
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
168
|
+
'direction',
|
169
|
+
/(up|down)/,
|
170
|
+
String,
|
171
|
+
lambda {|s| s},
|
172
|
+
true,
|
173
|
+
false
|
174
|
+
))
|
175
|
+
end
|
176
|
+
|
177
|
+
it "at the beginning of a word" do
|
178
|
+
expect(@generator.generate_expression("When I download a picture").source).not_to eq("When I {direction}load a picture")
|
179
|
+
expect(@generator.generate_expression("When I download a picture").source).to eq("When I download a picture")
|
180
|
+
end
|
181
|
+
|
182
|
+
it "inside a word" do
|
183
|
+
expect(@generator.generate_expression("When I watch the muppet show").source).not_to eq("When I watch the m{direction}pet show")
|
184
|
+
expect(@generator.generate_expression("When I watch the muppet show").source).to eq("When I watch the muppet show")
|
185
|
+
end
|
186
|
+
|
187
|
+
it "at the end of a word" do
|
188
|
+
expect(@generator.generate_expression("When I create a group").source).not_to eq("When I create a gro{direction}")
|
189
|
+
expect(@generator.generate_expression("When I create a group").source).to eq("When I create a group")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "does suggest parameter when match is" do
|
194
|
+
before do
|
195
|
+
@parameter_type_registry.define_parameter_type(ParameterType.new(
|
196
|
+
'direction',
|
197
|
+
/(up|down)/,
|
198
|
+
String,
|
199
|
+
lambda {|s| s},
|
200
|
+
true,
|
201
|
+
false
|
202
|
+
))
|
203
|
+
end
|
204
|
+
|
205
|
+
it "a full word" do
|
206
|
+
expect(@generator.generate_expression("When I go down the road").source).to eq("When I go {direction} the road")
|
207
|
+
expect(@generator.generate_expression("When I walk up the hill").source).to eq("When I walk {direction} the hill")
|
208
|
+
expect(@generator.generate_expression("up the hill, the road goes down").source).to eq("{direction} the hill, the road goes {direction}")
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'wrapped around punctuation characters' do
|
212
|
+
expect(@generator.generate_expression("When direction is:down").source).to eq("When direction is:{direction}")
|
213
|
+
expect(@generator.generate_expression("Then direction is down.").source).to eq("Then direction is {direction}.")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def assert_expression(expected_expression, expected_argument_names, text)
|
218
|
+
generated_expression = @generator.generate_expression(text)
|
219
|
+
expect(generated_expression.parameter_names).to eq(expected_argument_names)
|
220
|
+
expect(generated_expression.source).to eq(expected_expression)
|
221
|
+
|
222
|
+
cucumber_expression = CucumberExpression.new(generated_expression.source, @parameter_type_registry)
|
223
|
+
match = cucumber_expression.match(text)
|
224
|
+
if match.nil?
|
225
|
+
raise "Expected text '#{text}' to match generated expression '#{generated_expression.source}'"
|
226
|
+
end
|
227
|
+
expect(match.length).to eq(expected_argument_names.length)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|