cucumber-expressions 2.0.1 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c8c5e8a795eb6fea91f46e61cc01985a8af0572d
4
- data.tar.gz: 92fa95001cddb0f9d931a02602c0e2d793678d53
3
+ metadata.gz: 8ec8564fdc53d2078266f3cfb82f7eb8db6e8957
4
+ data.tar.gz: 2bb4c9234813e74029bd93c6448ff41ae1a85abb
5
5
  SHA512:
6
- metadata.gz: 7baf62e65277d441049bce8133cc50a6b44a48027cdf53a921b14006cac39358b45ba838890d43d1b1f7ec0edd8a74197e32b2979bfe8885bc5c4b1c963f0c12
7
- data.tar.gz: 44b4dd881b1b7d8649f185b4f60a31ecf91f4ff1ccf6b7934ecd9d1b143200bf0c2ee74f4913c3f4ea308457943ffbacf02d3bfede92dca31746cc698e522749
6
+ metadata.gz: a3c592d0e6e4fad991e45fd27e1f54c466f418f204ba2f65f304c9f9400d9c5289b9472712e19a71637a71fedc762ccea4ef4bf3e00a7600d68dba2c02992dc4
7
+ data.tar.gz: 26195cf45a0624e6920e44fb1a6c99e05300603ec053be5cb13f99df70d55e48a98ecdfda78fb085cbeadaddc394ddceb2149bb244399d1bfde199ad498550d0
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'cucumber-expressions'
4
- s.version = '2.0.1'
4
+ s.version = '3.0.0'
5
5
  s.authors = ["Aslak Hellesøy"]
6
6
  s.description = 'Cucumber Expressions - a simpler alternative to Regular Expressions'
7
7
  s.summary = "cucumber-expressions-#{s.version}"
@@ -3,12 +3,12 @@ module Cucumber
3
3
  class Argument
4
4
  attr_reader :offset, :value
5
5
 
6
- def initialize(offset, value, parameter)
7
- @offset, @value, @parameter = offset, value, parameter
6
+ def initialize(offset, value, parameter_type)
7
+ @offset, @value, @parameter_type = offset, value, parameter_type
8
8
  end
9
9
 
10
10
  def transformed_value
11
- @parameter.transform(@value)
11
+ @parameter_type.transform(@value)
12
12
  end
13
13
  end
14
14
  end
@@ -3,13 +3,13 @@ require 'cucumber/cucumber_expressions/argument'
3
3
  module Cucumber
4
4
  module CucumberExpressions
5
5
  class ArgumentBuilder
6
- def self.build_arguments(regexp, text, parameters)
6
+ def self.build_arguments(regexp, text, parameter_types)
7
7
  m = regexp.match(text)
8
8
  return nil if m.nil?
9
9
  (1...m.length).map do |index|
10
10
  value = m[index]
11
- parameter = parameters[index-1]
12
- Argument.new(m.offset(index)[0], value, parameter)
11
+ parameter_type = parameter_types[index-1]
12
+ Argument.new(m.offset(index)[0], value, parameter_type)
13
13
  end
14
14
  end
15
15
  end
@@ -1,58 +1,62 @@
1
1
  require 'cucumber/cucumber_expressions/argument_builder'
2
- require 'cucumber/cucumber_expressions/parameter'
2
+ require 'cucumber/cucumber_expressions/parameter_type'
3
3
 
4
4
  module Cucumber
5
5
  module CucumberExpressions
6
6
  class CucumberExpression
7
- PARAMETER_PATTERN = /\{([^}:]+)(:([^}]+))?}/
8
- OPTIONAL_PATTERN = /\(([^)]+)\)/
7
+ PARAMETER_REGEXP = /\{([^}:]+)(:([^}]+))?}/
8
+ OPTIONAL_REGEXP = /\(([^)]+)\)/
9
+ ALTERNATIVE_WORD_REGEXP = /([[:alpha:]]+)((\/[[:alpha:]]+)+)/
9
10
 
10
11
  attr_reader :source
11
12
 
12
- def initialize(expression, types, parameter_registry)
13
+ def initialize(expression, types, parameter_type_registry)
13
14
  @source = expression
14
- @parameters = []
15
+ @parameter_types = []
15
16
  regexp = "^"
16
17
  type_index = 0
17
- match = nil
18
18
  match_offset = 0
19
19
 
20
- # Does not include (){} because they have special meaning
20
+ # Escape Does not include (){} because they have special meaning
21
21
  expression = expression.gsub(/([\\\^\[$.|?*+\]])/, '\\\\\1')
22
22
 
23
23
  # Create non-capturing, optional capture groups from parenthesis
24
- expression = expression.gsub(OPTIONAL_PATTERN, '(?:\1)?')
24
+ expression = expression.gsub(OPTIONAL_REGEXP, '(?:\1)?')
25
+
26
+ expression = expression.gsub(ALTERNATIVE_WORD_REGEXP) do |_|
27
+ "(?:#{$1}#{$2.tr('/', '|')})"
28
+ end
25
29
 
26
30
  loop do
27
- match = PARAMETER_PATTERN.match(expression, match_offset)
31
+ match = PARAMETER_REGEXP.match(expression, match_offset)
28
32
  break if match.nil?
29
33
 
30
34
  parameter_name = match[1]
31
- type_name = match[3]
32
- if type_name
33
- $stderr.puts("Cucumber expression parameter syntax {#{parameter_name}:#{type_name}} is deprecated. Please use {#{type_name}} instead.")
35
+ parameter_type_name = match[3]
36
+ if parameter_type_name
37
+ $stderr.puts("Cucumber expression parameter syntax {#{parameter_name}:#{parameter_type_name}} is deprecated. Please use {#{parameter_type_name}} instead.")
34
38
  end
35
39
 
36
40
  type = types.length <= type_index ? nil : types[type_index]
37
41
  type_index += 1
38
42
 
39
- parameter = nil
43
+ parameter_type = nil
40
44
  if type
41
- parameter = parameter_registry.lookup_by_type(type)
45
+ parameter_type = parameter_type_registry.lookup_by_type(type)
42
46
  end
43
- if parameter.nil? && type_name
44
- parameter = parameter_registry.lookup_by_type_name(type_name)
47
+ if parameter_type.nil? && parameter_type_name
48
+ parameter_type = parameter_type_registry.lookup_by_name(parameter_type_name)
45
49
  end
46
- if parameter.nil?
47
- parameter = parameter_registry.lookup_by_type_name(parameter_name)
50
+ if parameter_type.nil?
51
+ parameter_type = parameter_type_registry.lookup_by_name(parameter_name)
48
52
  end
49
- if parameter.nil?
50
- parameter = parameter_registry.create_anonymous_lookup(lambda {|s| s})
53
+ if parameter_type.nil?
54
+ parameter_type = parameter_type_registry.create_anonymous_lookup(lambda {|s| s})
51
55
  end
52
- @parameters.push(parameter)
56
+ @parameter_types.push(parameter_type)
53
57
 
54
58
  text = expression.slice(match_offset...match.offset(0)[0])
55
- capture_regexp = capture_group_regexp(parameter.capture_group_regexps)
59
+ capture_regexp = regexp(parameter_type.regexps)
56
60
  match_offset = match.offset(0)[1]
57
61
  regexp += text
58
62
  regexp += capture_regexp
@@ -63,14 +67,14 @@ module Cucumber
63
67
  end
64
68
 
65
69
  def match(text)
66
- ArgumentBuilder.build_arguments(@regexp, text, @parameters)
70
+ ArgumentBuilder.build_arguments(@regexp, text, @parameter_types)
67
71
  end
68
72
 
69
73
  private
70
74
 
71
- def capture_group_regexp(capture_group_regexps)
72
- return "(#{capture_group_regexps[0]})" if capture_group_regexps.size == 1
73
- capture_groups = capture_group_regexps.map { |group| "(?:#{group})" }
75
+ def regexp(regexps)
76
+ return "(#{regexps[0]})" if regexps.size == 1
77
+ capture_groups = regexps.map { |group| "(?:#{group})" }
74
78
  "(#{capture_groups.join('|')})"
75
79
  end
76
80
  end
@@ -1,44 +1,44 @@
1
- require 'cucumber/cucumber_expressions/parameter_matcher'
1
+ require 'cucumber/cucumber_expressions/parameter_type_matcher'
2
2
  require 'cucumber/cucumber_expressions/generated_expression'
3
3
 
4
4
  module Cucumber
5
5
  module CucumberExpressions
6
6
  class CucumberExpressionGenerator
7
- def initialize(parameter_registry)
8
- @parameter_registry = parameter_registry
7
+ def initialize(parameter_type_registry)
8
+ @parameter_type_registry = parameter_type_registry
9
9
  end
10
10
 
11
11
  def generate_expression(text)
12
12
  parameter_names = []
13
- parameter_matchers = create_parameter_matchers(text)
14
- parameters = []
15
- usage_by_type_name = Hash.new(0)
13
+ parameter_type_matchers = create_parameter_type_matchers(text)
14
+ parameter_types = []
15
+ usage_by_name = Hash.new(0)
16
16
 
17
17
  expression = ""
18
18
  pos = 0
19
19
 
20
20
  loop do
21
- matching_parameter_matchers = []
22
- parameter_matchers.each do |parameter_matcher|
23
- advanced_parameter_matcher = parameter_matcher.advance_to(pos)
24
- if advanced_parameter_matcher.find
25
- matching_parameter_matchers.push(advanced_parameter_matcher)
21
+ matching_parameter_type_matchers = []
22
+ parameter_type_matchers.each do |parameter_type_matcher|
23
+ advanced_parameter_type_matcher = parameter_type_matcher.advance_to(pos)
24
+ if advanced_parameter_type_matcher.find
25
+ matching_parameter_type_matchers.push(advanced_parameter_type_matcher)
26
26
  end
27
27
  end
28
28
 
29
- if matching_parameter_matchers.any?
30
- matching_parameter_matchers = matching_parameter_matchers.sort
31
- best_parameter_matcher = matching_parameter_matchers[0]
32
- parameter = best_parameter_matcher.parameter
33
- parameters.push(parameter)
29
+ if matching_parameter_type_matchers.any?
30
+ matching_parameter_type_matchers = matching_parameter_type_matchers.sort
31
+ best_parameter_type_matcher = matching_parameter_type_matchers[0]
32
+ parameter_type = best_parameter_type_matcher.parameter
33
+ parameter_types.push(parameter_type)
34
34
 
35
- parameter_name = get_parameter_name(parameter.type_name, usage_by_type_name)
35
+ parameter_name = get_parameter_name(parameter_type.name, usage_by_name)
36
36
  parameter_names.push(parameter_name)
37
37
 
38
- expression += text.slice(pos...best_parameter_matcher.start)
39
- expression += "{#{parameter.type_name}}"
38
+ expression += text.slice(pos...best_parameter_type_matcher.start)
39
+ expression += "{#{parameter_type.name}}"
40
40
 
41
- pos = best_parameter_matcher.start + best_parameter_matcher.group.length
41
+ pos = best_parameter_type_matcher.start + best_parameter_type_matcher.group.length
42
42
  else
43
43
  break
44
44
  end
@@ -49,30 +49,30 @@ module Cucumber
49
49
  end
50
50
 
51
51
  expression += text.slice(pos..-1)
52
- GeneratedExpression.new(expression, parameter_names, parameters)
52
+ GeneratedExpression.new(expression, parameter_names, parameter_types)
53
53
  end
54
54
 
55
55
  private
56
56
 
57
- def get_parameter_name(type_name, usage_by_type_name)
58
- count = (usage_by_type_name[type_name] += 1)
59
- count == 1 ? type_name : "#{type_name}#{count}"
57
+ def get_parameter_name(name, usage_by_name)
58
+ count = (usage_by_name[name] += 1)
59
+ count == 1 ? name : "#{name}#{count}"
60
60
  end
61
61
 
62
- def create_parameter_matchers(text)
62
+ def create_parameter_type_matchers(text)
63
63
  parameter_matchers = []
64
- @parameter_registry.parameters.each do |parameter|
65
- parameter_matchers += create_parameter_matchers2(parameter, text)
64
+ @parameter_type_registry.parameter_types.each do |parameter_type|
65
+ parameter_matchers += create_parameter_type_matchers2(parameter_type, text)
66
66
  end
67
67
  parameter_matchers
68
68
  end
69
69
 
70
- def create_parameter_matchers2(parameter, text)
70
+ def create_parameter_type_matchers2(parameter_type, text)
71
71
  result = []
72
- capture_group_regexps = parameter.capture_group_regexps
73
- capture_group_regexps.each do |capture_group_regexp|
74
- regexp = Regexp.new("(#{capture_group_regexp})")
75
- result.push(ParameterMatcher.new(parameter, regexp, text))
72
+ regexps = parameter_type.regexps
73
+ regexps.each do |regexp|
74
+ regexp = Regexp.new("(#{regexp})")
75
+ result.push(ParameterTypeMatcher.new(parameter_type, regexp, text))
76
76
  end
77
77
  result
78
78
  end
@@ -1,10 +1,10 @@
1
1
  module Cucumber
2
2
  module CucumberExpressions
3
3
  class GeneratedExpression
4
- attr_reader :source, :parameter_names, :parameters
4
+ attr_reader :source, :parameter_names, :parameter_types
5
5
 
6
- def initialize(source, parameter_names, parameters)
7
- @source, @parameter_names, @parameters = source, parameter_names, parameters
6
+ def initialize(source, parameter_names, parameters_types)
7
+ @source, @parameter_names, @parameter_types = source, parameter_names, parameters_types
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,29 @@
1
+ module Cucumber
2
+ module CucumberExpressions
3
+ class ParameterType
4
+ attr_reader :name, :type, :regexps
5
+
6
+ # Create a new Parameter
7
+ #
8
+ # @param name the name of the parameter type
9
+ # @param regexps [Array] list of regexps for capture groups. A single regexp can also be used.
10
+ # @param transformer lambda that transforms a String to (possibly) another type
11
+ #
12
+ def initialize(name, type, regexp, transformer)
13
+ @name, @type, @transformer = name, type, transformer
14
+ @regexps = string_array(regexp)
15
+ end
16
+
17
+ def transform(value)
18
+ @transformer ? @transformer.call(value) : value
19
+ end
20
+
21
+ private
22
+
23
+ def string_array(regexp)
24
+ array = regexp.is_a?(Array) ? regexp : [regexp]
25
+ array.map { |r| r.is_a?(String) ? r : r.source }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,6 +1,6 @@
1
1
  module Cucumber
2
2
  module CucumberExpressions
3
- class ParameterMatcher
3
+ class ParameterTypeMatcher
4
4
  attr_reader :parameter
5
5
 
6
6
  def initialize(parameter, regexp, text, match_position=0)
@@ -0,0 +1,82 @@
1
+ require 'cucumber/cucumber_expressions/parameter_type'
2
+
3
+ module Cucumber
4
+ module CucumberExpressions
5
+ class ParameterTypeRegistry
6
+ INTEGER_REGEXPS = [/-?\d+/, /\d+/]
7
+ FLOAT_REGEXP = /-?\d*\.?\d+/
8
+
9
+ def initialize
10
+ @parameter_types_by_name = {}
11
+ @parameter_types_by_regexp = {}
12
+ @parameter_types_by_class = {}
13
+
14
+ define_predefined_parameter_type(ParameterType.new('int', Integer, INTEGER_REGEXPS, lambda { |s| s.to_i }))
15
+ define_predefined_parameter_type(ParameterType.new('float', Float, FLOAT_REGEXP, lambda { |s| s.to_f }))
16
+ end
17
+
18
+ def lookup_by_type(type)
19
+ if type.is_a?(Class)
20
+ lookup_by_class(type)
21
+ elsif type.is_a?(String)
22
+ lookup_by_name(type)
23
+ else
24
+ raise Exception.new("Type must be string or class, but was #{type} of type #{type.class}")
25
+ end
26
+ end
27
+
28
+ def lookup_by_class(clazz)
29
+ parameter = @parameter_types_by_class[clazz]
30
+ if parameter.nil?
31
+ create_anonymous_lookup(lambda { |s| clazz.new(s) })
32
+ else
33
+ parameter
34
+ end
35
+ end
36
+
37
+ def lookup_by_name(name)
38
+ @parameter_types_by_name[name]
39
+ end
40
+
41
+ def lookup_by_regexp(regexp)
42
+ @parameter_types_by_regexp[regexp]
43
+ end
44
+
45
+ def create_anonymous_lookup(proc)
46
+ ParameterType.new(nil, nil, ['.+'], proc)
47
+ end
48
+
49
+ def parameter_types
50
+ @parameter_types_by_name.values
51
+ end
52
+
53
+ def define_parameter_type(parameter_type)
54
+ define_parameter_type0(parameter_type, true)
55
+ end
56
+
57
+ private
58
+
59
+ def define_predefined_parameter_type(parameter_type)
60
+ define_parameter_type0(parameter_type, false)
61
+ end
62
+
63
+ def define_parameter_type0(parameter_type, check_conflicts)
64
+ if parameter_type.type
65
+ put(@parameter_types_by_class, parameter_type.type, parameter_type, "type", check_conflicts)
66
+ end
67
+ put(@parameter_types_by_name, parameter_type.name, parameter_type, "type name", check_conflicts)
68
+
69
+ parameter_type.regexps.each do |regexp|
70
+ put(@parameter_types_by_regexp, regexp, parameter_type, "regexp", check_conflicts)
71
+ end
72
+ end
73
+
74
+ def put(map, key, parameter, prop, check_conflicts)
75
+ if check_conflicts && map.has_key?(key)
76
+ raise "There is already a parameter with #{prop} #{key}"
77
+ end
78
+ map[key] = parameter
79
+ end
80
+ end
81
+ end
82
+ end
@@ -5,9 +5,9 @@ module Cucumber
5
5
  class RegularExpression
6
6
  CAPTURE_GROUP_PATTERN = /\(([^(]+)\)/
7
7
 
8
- def initialize(regexp, types, parameter_registry)
8
+ def initialize(regexp, types, parameter_type_registry)
9
9
  @regexp = regexp
10
- @parameters = []
10
+ @parameter_types = []
11
11
 
12
12
  type_index = 0
13
13
  match = nil
@@ -21,24 +21,24 @@ module Cucumber
21
21
  type = types.length <= type_index ? nil : types[type_index]
22
22
  type_index += 1
23
23
 
24
- parameter = nil
24
+ parameter_type = nil
25
25
  if (type)
26
- parameter = parameter_registry.lookup_by_type(type)
26
+ parameter_type = parameter_type_registry.lookup_by_type(type)
27
27
  end
28
- if (parameter.nil?)
29
- parameter = parameter_registry.lookup_by_capture_group_regexp(capture_group_pattern)
28
+ if (parameter_type.nil?)
29
+ parameter_type = parameter_type_registry.lookup_by_regexp(capture_group_pattern)
30
30
  end
31
- if (parameter.nil?)
32
- parameter = parameter_registry.create_anonymous_lookup(lambda {|s| s})
31
+ if (parameter_type.nil?)
32
+ parameter_type = parameter_type_registry.create_anonymous_lookup(lambda {|s| s})
33
33
  end
34
34
 
35
- @parameters.push(parameter)
35
+ @parameter_types.push(parameter_type)
36
36
  match_offset = match.offset(0)[1]
37
37
  end
38
38
  end
39
39
 
40
40
  def match(text)
41
- ArgumentBuilder.build_arguments(@regexp, text, @parameters)
41
+ ArgumentBuilder.build_arguments(@regexp, text, @parameter_types)
42
42
  end
43
43
 
44
44
  def source
@@ -1,6 +1,6 @@
1
1
  require 'cucumber/cucumber_expressions/cucumber_expression_generator'
2
- require 'cucumber/cucumber_expressions/parameter'
3
- require 'cucumber/cucumber_expressions/parameter_registry'
2
+ require 'cucumber/cucumber_expressions/parameter_type'
3
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
4
4
 
5
5
  module Cucumber
6
6
  module CucumberExpressions
@@ -9,18 +9,18 @@ module Cucumber
9
9
  end
10
10
 
11
11
  before do
12
- @parameter_registry = ParameterRegistry.new
13
- @generator = CucumberExpressionGenerator.new(@parameter_registry)
12
+ @parameter_type_registry = ParameterTypeRegistry.new
13
+ @generator = CucumberExpressionGenerator.new(@parameter_type_registry)
14
14
  end
15
15
 
16
16
  it "documents expression generation" do
17
- parameter_registry = ParameterRegistry.new
17
+ parameter_registry = ParameterTypeRegistry.new
18
18
  ### [generate-expression]
19
19
  generator = CucumberExpressionGenerator.new(parameter_registry)
20
20
  undefined_step_text = "I have 2 cucumbers and 1.5 tomato"
21
21
  generated_expression = generator.generate_expression(undefined_step_text)
22
22
  expect(generated_expression.source).to eq("I have {int} cucumbers and {float} tomato")
23
- expect(generated_expression.parameters[1].type).to eq(Float)
23
+ expect(generated_expression.parameter_types[1].type).to eq(Float)
24
24
  ### [generate-expression]
25
25
  end
26
26
 
@@ -47,7 +47,7 @@ module Cucumber
47
47
  end
48
48
 
49
49
  it "numbers only second argument when type is not reserved keyword" do
50
- @parameter_registry.add_parameter(Parameter.new(
50
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
51
51
  'currency',
52
52
  Currency,
53
53
  '[A-Z]{3}',
@@ -61,7 +61,7 @@ module Cucumber
61
61
 
62
62
  it "exposes parameters in generated expression" do
63
63
  expression = @generator.generate_expression("I have 2 cukes and 1.5 euro")
64
- types = expression.parameters.map(&:type)
64
+ types = expression.parameter_types.map(&:type)
65
65
  expect(types).to eq([Integer, Float])
66
66
  end
67
67
 
@@ -1,12 +1,12 @@
1
1
  require 'cucumber/cucumber_expressions/cucumber_expression'
2
- require 'cucumber/cucumber_expressions/parameter_registry'
2
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
3
3
 
4
4
  module Cucumber
5
5
  module CucumberExpressions
6
6
  describe CucumberExpression do
7
7
  context "Regexp translation" do
8
8
  def assert_regexp(expression, regexp)
9
- cucumber_expression = CucumberExpression.new(expression, [], ParameterRegistry.new)
9
+ cucumber_expression = CucumberExpression.new(expression, [], ParameterTypeRegistry.new)
10
10
  expect(regexp).to eq(cucumber_expression.instance_variable_get('@regexp'))
11
11
  end
12
12
 
@@ -17,6 +17,13 @@ module Cucumber
17
17
  )
18
18
  end
19
19
 
20
+ it "translates alternation" do
21
+ assert_regexp(
22
+ "I had/have a great/nice/charming friend",
23
+ /^I (?:had|have) a (?:great|nice|charming) friend$/
24
+ )
25
+ end
26
+
20
27
  it "translates two untyped arguments" do
21
28
  assert_regexp(
22
29
  "I have {n} cukes in my {bodypart} now",
@@ -1,11 +1,11 @@
1
1
  require 'cucumber/cucumber_expressions/cucumber_expression'
2
- require 'cucumber/cucumber_expressions/parameter_registry'
2
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
3
3
 
4
4
  module Cucumber
5
5
  module CucumberExpressions
6
6
  describe CucumberExpression do
7
7
  it "documents match arguments" do
8
- parameter_registry = ParameterRegistry.new
8
+ parameter_registry = ParameterTypeRegistry.new
9
9
 
10
10
  ### [capture-match-arguments]
11
11
  expr = "I have {n} cuke(s) in my {bodypart} now"
@@ -58,12 +58,12 @@ module Cucumber
58
58
 
59
59
  it "exposes source" do
60
60
  expr = "I have {int} cuke(s) in my {bodypart} now"
61
- expect(CucumberExpression.new(expr, [], ParameterRegistry.new).source).to eq(expr)
61
+ expect(CucumberExpression.new(expr, [], ParameterTypeRegistry.new).source).to eq(expr)
62
62
  end
63
63
 
64
64
  it "exposes offset and value" do
65
65
  expr = "I have {int} cuke(s) in my {bodypart} now"
66
- expression = CucumberExpression.new(expr, [], ParameterRegistry.new)
66
+ expression = CucumberExpression.new(expr, [], ParameterTypeRegistry.new)
67
67
  arg1 = expression.match("I have 800 cukes in my brain now")[0]
68
68
  expect(arg1.offset).to eq(7)
69
69
  expect(arg1.value).to eq("800")
@@ -73,7 +73,7 @@ module Cucumber
73
73
  %w(\\ [ ] ^ $ . | ? * +).each do |character|
74
74
  it "escapes #{character}" do
75
75
  expr = "I have {int} cuke(s) and #{character}"
76
- expression = CucumberExpression.new(expr, [], ParameterRegistry.new)
76
+ expression = CucumberExpression.new(expr, [], ParameterTypeRegistry.new)
77
77
  arg1 = expression.match("I have 800 cukes and #{character}")[0]
78
78
  expect(arg1.offset).to eq(7)
79
79
  expect(arg1.value).to eq("800")
@@ -82,7 +82,7 @@ module Cucumber
82
82
  end
83
83
 
84
84
  def match(expression, text, types = [])
85
- cucumber_expression = CucumberExpression.new(expression, types, ParameterRegistry.new)
85
+ cucumber_expression = CucumberExpression.new(expression, types, ParameterTypeRegistry.new)
86
86
  args = cucumber_expression.match(text)
87
87
  return nil if args.nil?
88
88
  args.map { |arg| arg.transformed_value }
@@ -0,0 +1,164 @@
1
+ require 'cucumber/cucumber_expressions/cucumber_expression'
2
+ require 'cucumber/cucumber_expressions/regular_expression'
3
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
4
+
5
+ module Cucumber
6
+ module CucumberExpressions
7
+ class Color
8
+ attr_reader :name
9
+
10
+ ### [color-constructor]
11
+ def initialize(name)
12
+ @name = name
13
+ end
14
+ ### [color-constructor]
15
+
16
+ def ==(other)
17
+ other.is_a?(Color) && other.name == name
18
+ end
19
+ end
20
+
21
+ describe "Custom parameter" do
22
+ before do
23
+ parameter_registry = ParameterTypeRegistry.new
24
+ ### [add-color-parameter]
25
+ parameter_registry.define_parameter_type(ParameterType.new(
26
+ 'color',
27
+ Color,
28
+ /red|blue|yellow/,
29
+ lambda { |s| Color.new(s) }
30
+ ))
31
+ ### [add-color-parameter]
32
+ @parameter_type_registry = parameter_registry
33
+ end
34
+
35
+ describe CucumberExpression do
36
+ it "matches parameters with custom parameter type" do
37
+ expression = CucumberExpression.new("I have a {color} ball", [], @parameter_type_registry)
38
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
39
+ expect( transformed_argument_value ).to eq(Color.new('red'))
40
+ end
41
+
42
+ it "matches parameters with custom parameter type using optional capture group" do
43
+ parameter_registry = ParameterTypeRegistry.new
44
+ parameter_registry.define_parameter_type(ParameterType.new(
45
+ 'color',
46
+ Color,
47
+ [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/],
48
+ lambda { |s| Color.new(s) }
49
+ ))
50
+ expression = CucumberExpression.new("I have a {color} ball", [], parameter_registry)
51
+ transformed_argument_value = expression.match("I have a dark red ball")[0].transformed_value
52
+ expect( transformed_argument_value ).to eq(Color.new('dark red'))
53
+ end
54
+
55
+ it "matches parameters with custom parameter type without constructor function and transform" do
56
+ parameter_registry = ParameterTypeRegistry.new
57
+ parameter_registry.define_parameter_type(ParameterType.new(
58
+ 'color',
59
+ nil,
60
+ /red|blue|yellow/,
61
+ nil
62
+ ))
63
+ expression = CucumberExpression.new("I have a {color} ball", [], parameter_registry)
64
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
65
+ expect( transformed_argument_value ).to eq('red')
66
+ end
67
+
68
+ it "matches parameters with explicit type" do
69
+ expression = CucumberExpression.new("I have a {color} ball", [Color], @parameter_type_registry)
70
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
71
+ expect( transformed_argument_value ).to eq(Color.new('red'))
72
+ end
73
+
74
+ it "matches parameters with explicit type that isn't registered" do
75
+ expression = CucumberExpression.new("I have a {color} ball", [Color], ParameterTypeRegistry.new)
76
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
77
+ expect( transformed_argument_value ).to eq(Color.new('red'))
78
+ end
79
+
80
+ it "defers transformation until queried from argument" do
81
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
82
+ 'throwing',
83
+ String,
84
+ /bad/,
85
+ lambda { |s| raise "Can't transform [#{s}]" }
86
+ ))
87
+ expression = CucumberExpression.new("I have a {throwing} parameter", [], @parameter_type_registry)
88
+ args = expression.match("I have a bad parameter")
89
+ expect { args[0].transformed_value }.to raise_error("Can't transform [bad]")
90
+ end
91
+
92
+ describe "conflicting parameter type" do
93
+ it "is detected for type name" do
94
+ expect {
95
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
96
+ 'color',
97
+ String,
98
+ /.*/,
99
+ lambda { |s| s }
100
+ ))
101
+ }.to raise_error("There is already a parameter with type name color")
102
+ end
103
+
104
+ it "is detected for type" do
105
+ expect {
106
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
107
+ 'color2',
108
+ Color,
109
+ /.*/,
110
+ lambda { |s| Color.new(s) }
111
+ ))
112
+ }.to raise_error("There is already a parameter with type Cucumber::CucumberExpressions::Color")
113
+ end
114
+
115
+ it "is detected for regexp" do
116
+ expect {
117
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
118
+ 'color2',
119
+ String,
120
+ /red|blue|yellow/,
121
+ lambda { |s| s }
122
+ ))
123
+ }.to raise_error("There is already a parameter with regexp red|blue|yellow")
124
+ end
125
+
126
+ it "is not detected when type is nil" do
127
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
128
+ 'foo',
129
+ nil,
130
+ /foo/,
131
+ lambda { |s| s }
132
+ ))
133
+ @parameter_type_registry.define_parameter_type(ParameterType.new(
134
+ 'bar',
135
+ nil,
136
+ /bar/,
137
+ lambda { |s| s }
138
+ ))
139
+ end
140
+ end
141
+ end
142
+
143
+ describe RegularExpression do
144
+ it "matches parameters with explicit constructor" do
145
+ expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], @parameter_type_registry)
146
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
147
+ expect( transformed_argument_value ).to eq(Color.new('red'))
148
+ end
149
+
150
+ it "matches parameters without explicit constructor" do
151
+ expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [], @parameter_type_registry)
152
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
153
+ expect( transformed_argument_value ).to eq(Color.new('red'))
154
+ end
155
+
156
+ it "matches parameters with explicit type that isn't registered" do
157
+ expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], ParameterTypeRegistry.new)
158
+ transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
159
+ expect( transformed_argument_value ).to eq(Color.new('red'))
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -1,6 +1,6 @@
1
1
  require 'cucumber/cucumber_expressions/cucumber_expression'
2
2
  require 'cucumber/cucumber_expressions/regular_expression'
3
- require 'cucumber/cucumber_expressions/parameter_registry'
3
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
4
4
  require 'json'
5
5
 
6
6
  module Cucumber
@@ -8,8 +8,8 @@ module Cucumber
8
8
  describe 'examples.txt' do
9
9
  def match(expression_text, text)
10
10
  expression = expression_text =~ /\/(.*)\// ?
11
- RegularExpression.new(Regexp.new($1), [], ParameterRegistry.new) :
12
- CucumberExpression.new(expression_text, [], ParameterRegistry.new)
11
+ RegularExpression.new(Regexp.new($1), [], ParameterTypeRegistry.new) :
12
+ CucumberExpression.new(expression_text, [], ParameterTypeRegistry.new)
13
13
 
14
14
  arguments = expression.match(text)
15
15
  return nil if arguments.nil?
@@ -1,16 +1,16 @@
1
1
  require 'cucumber/cucumber_expressions/regular_expression'
2
- require 'cucumber/cucumber_expressions/parameter_registry'
2
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
3
3
 
4
4
  module Cucumber
5
5
  module CucumberExpressions
6
6
  describe RegularExpression do
7
7
  it "documents match arguments" do
8
- parameter_registry = ParameterRegistry.new
8
+ parameter_type_registry = ParameterTypeRegistry.new
9
9
 
10
10
  ### [capture-match-arguments]
11
11
  expr = /I have (\d+) cukes? in my (\w*) now/
12
12
  types = ['int', nil]
13
- expression = RegularExpression.new(expr, types, parameter_registry)
13
+ expression = RegularExpression.new(expr, types, parameter_type_registry)
14
14
  args = expression.match("I have 7 cukes in my belly now")
15
15
  expect( args[0].transformed_value ).to eq(7)
16
16
  expect( args[1].transformed_value ).to eq("belly")
@@ -57,11 +57,11 @@ module Cucumber
57
57
 
58
58
  it "exposes source" do
59
59
  expr = /I have (\d+) cukes? in my (\+) now/
60
- expect(RegularExpression.new(expr, [], ParameterRegistry.new).source).to eq(expr)
60
+ expect(RegularExpression.new(expr, [], ParameterTypeRegistry.new).source).to eq(expr)
61
61
  end
62
62
 
63
63
  def match(expression, text, types = [])
64
- regular_expression = RegularExpression.new(expression, types, ParameterRegistry.new)
64
+ regular_expression = RegularExpression.new(expression, types, ParameterTypeRegistry.new)
65
65
  arguments = regular_expression.match(text)
66
66
  return nil if arguments.nil?
67
67
  arguments.map { |arg| arg.transformed_value }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-expressions
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.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: 2017-02-17 00:00:00.000000000 Z
11
+ date: 2017-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,16 +86,16 @@ files:
86
86
  - lib/cucumber/cucumber_expressions/cucumber_expression.rb
87
87
  - lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb
88
88
  - lib/cucumber/cucumber_expressions/generated_expression.rb
89
- - lib/cucumber/cucumber_expressions/parameter.rb
90
- - lib/cucumber/cucumber_expressions/parameter_matcher.rb
91
- - lib/cucumber/cucumber_expressions/parameter_registry.rb
89
+ - lib/cucumber/cucumber_expressions/parameter_type.rb
90
+ - lib/cucumber/cucumber_expressions/parameter_type_matcher.rb
91
+ - lib/cucumber/cucumber_expressions/parameter_type_registry.rb
92
92
  - lib/cucumber/cucumber_expressions/regular_expression.rb
93
93
  - spec/capture_warnings.rb
94
94
  - spec/coverage.rb
95
95
  - spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb
96
96
  - spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb
97
97
  - spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb
98
- - spec/cucumber/cucumber_expressions/custom_parameter_spec.rb
98
+ - spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb
99
99
  - spec/cucumber/cucumber_expressions/expression_examples_spec.rb
100
100
  - spec/cucumber/cucumber_expressions/regular_expression_spec.rb
101
101
  homepage: https://github.com/cucumber/cucumber-expressions-ruby#readme
@@ -122,13 +122,13 @@ rubyforge_project:
122
122
  rubygems_version: 2.5.2
123
123
  signing_key:
124
124
  specification_version: 4
125
- summary: cucumber-expressions-2.0.1
125
+ summary: cucumber-expressions-3.0.0
126
126
  test_files:
127
127
  - spec/capture_warnings.rb
128
128
  - spec/coverage.rb
129
129
  - spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb
130
130
  - spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb
131
131
  - spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb
132
- - spec/cucumber/cucumber_expressions/custom_parameter_spec.rb
132
+ - spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb
133
133
  - spec/cucumber/cucumber_expressions/expression_examples_spec.rb
134
134
  - spec/cucumber/cucumber_expressions/regular_expression_spec.rb
@@ -1,29 +0,0 @@
1
- module Cucumber
2
- module CucumberExpressions
3
- class Parameter
4
- attr_reader :type_name, :type, :capture_group_regexps
5
-
6
- # Create a new Parameter
7
- #
8
- # @param type_name [Array] array of class or type name to use in {arg:type_name}
9
- # @param capture_group_regexps [Array] list of regexps for capture groups.
10
- # @param transformer lambda that transforms a String to (possibly) another type
11
- #
12
- def initialize(type_name, type, capture_group_regexps, transformer)
13
- @type_name, @type, @transformer = type_name, type, transformer
14
- @capture_group_regexps = string_array(capture_group_regexps)
15
- end
16
-
17
- def transform(value)
18
- @transformer.call(value)
19
- end
20
-
21
- private
22
-
23
- def string_array(capture_group_regexps)
24
- array = capture_group_regexps.is_a?(Array) ? capture_group_regexps : [capture_group_regexps]
25
- array.map { |r| r.is_a?(String) ? r : r.source }
26
- end
27
- end
28
- end
29
- end
@@ -1,64 +0,0 @@
1
- require 'cucumber/cucumber_expressions/parameter'
2
-
3
- module Cucumber
4
- module CucumberExpressions
5
- class ParameterRegistry
6
- INTEGER_REGEXPS = [/-?\d+/, /\d+/]
7
- FLOAT_REGEXPS = [/-?\d*\.?\d+/]
8
-
9
- def initialize
10
- @parameters_by_type_name = {}
11
- @parameters_by_capture_group_regexp = {}
12
- @parameters_by_class = {}
13
-
14
- add_parameter(Parameter.new('int', Integer, INTEGER_REGEXPS, lambda {|s| s.to_i}))
15
- add_parameter(Parameter.new('float', Float, FLOAT_REGEXPS, lambda {|s| s.to_f}))
16
- end
17
-
18
- def lookup_by_type(type)
19
- if type.is_a?(Class)
20
- lookup_by_class(type)
21
- elsif type.is_a?(String)
22
- lookup_by_type_name(type)
23
- else
24
- raise Exception.new("Type must be string or class, but was #{type} of type #{type.class}")
25
- end
26
- end
27
-
28
- def lookup_by_class(clazz)
29
- parameter = @parameters_by_class[clazz]
30
- if parameter.nil?
31
- create_anonymous_lookup(lambda {|s| clazz.new(s)})
32
- else
33
- parameter
34
- end
35
- end
36
-
37
- def lookup_by_type_name(type_name)
38
- @parameters_by_type_name[type_name]
39
- end
40
-
41
- def lookup_by_capture_group_regexp(capture_group_regexp)
42
- @parameters_by_capture_group_regexp[capture_group_regexp]
43
- end
44
-
45
- def create_anonymous_lookup(proc)
46
- Parameter.new(nil, nil, ['.+'], proc)
47
- end
48
-
49
- def add_parameter(parameter)
50
- @parameters_by_type_name[parameter.type_name] = parameter
51
- @parameters_by_class[parameter.type] = parameter
52
-
53
- parameter.capture_group_regexps.each do |capture_group_regexp|
54
- @parameters_by_capture_group_regexp[capture_group_regexp] = parameter
55
- end
56
- end
57
-
58
- def parameters
59
- @parameters_by_type_name.values
60
- end
61
-
62
- end
63
- end
64
- end
@@ -1,100 +0,0 @@
1
- require 'cucumber/cucumber_expressions/cucumber_expression'
2
- require 'cucumber/cucumber_expressions/regular_expression'
3
- require 'cucumber/cucumber_expressions/parameter_registry'
4
-
5
- module Cucumber
6
- module CucumberExpressions
7
- class Color
8
- attr_reader :name
9
-
10
- ### [color-constructor]
11
- def initialize(name)
12
- @name = name
13
- end
14
- ### [color-constructor]
15
-
16
- def ==(other)
17
- other.is_a?(Color) && other.name == name
18
- end
19
- end
20
-
21
- describe "Custom parameter" do
22
- before do
23
- ### [add-color-parameter]
24
- parameter_registry = ParameterRegistry.new
25
- parameter_registry.add_parameter(Parameter.new(
26
- 'color',
27
- Color,
28
- [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/],
29
- lambda { |s| Color.new(s) }
30
- ))
31
- ### [add-color-parameter]
32
- @parameter_registry = parameter_registry
33
- end
34
-
35
- describe CucumberExpression do
36
- it "matches typed parameters" do
37
- expression = CucumberExpression.new("I have a {color} ball", [], @parameter_registry)
38
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
39
- expect( transformed_argument_value ).to eq(Color.new('red'))
40
- end
41
-
42
- it "matches typed parameters with optional group" do
43
- expression = CucumberExpression.new("I have a {color} ball", [], @parameter_registry)
44
- transformed_argument_value = expression.match("I have a dark red ball")[0].transformed_value
45
- expect( transformed_argument_value ).to eq(Color.new('dark red'))
46
- end
47
-
48
- it "matches untyped parameters with explicit type" do
49
- expression = CucumberExpression.new("I have a {color} ball", [Color], @parameter_registry)
50
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
51
- expect( transformed_argument_value ).to eq(Color.new('red'))
52
- end
53
-
54
- it "matches untyped parameters with same name as type" do
55
- expression = CucumberExpression.new("I have a {color} ball", [], @parameter_registry)
56
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
57
- expect( transformed_argument_value ).to eq(Color.new('red'))
58
- end
59
-
60
- it "matches parameters with explicit type that isn't registered" do
61
- expression = CucumberExpression.new("I have a {color} ball", [Color], ParameterRegistry.new)
62
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
63
- expect( transformed_argument_value ).to eq(Color.new('red'))
64
- end
65
-
66
- it("defers transformation until queried from argument") do
67
- @parameter_registry.add_parameter(Parameter.new(
68
- 'throwing',
69
- String,
70
- /bad/,
71
- lambda { |s| raise "Can't transform [#{s}]" }
72
- ))
73
- expression = CucumberExpression.new("I have a {throwing} parameter", [], @parameter_registry)
74
- args = expression.match("I have a bad parameter")
75
- expect { args[0].transformed_value }.to raise_error("Can't transform [bad]")
76
- end
77
- end
78
-
79
- describe RegularExpression do
80
- it "matches parameters with explicit constructor" do
81
- expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], @parameter_registry)
82
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
83
- expect( transformed_argument_value ).to eq(Color.new('red'))
84
- end
85
-
86
- it "matches parameters without explicit constructor" do
87
- expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [], @parameter_registry)
88
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
89
- expect( transformed_argument_value ).to eq(Color.new('red'))
90
- end
91
-
92
- it "matches parameters with explicit type that isn't registered" do
93
- expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], ParameterRegistry.new)
94
- transformed_argument_value = expression.match("I have a red ball")[0].transformed_value
95
- expect( transformed_argument_value ).to eq(Color.new('red'))
96
- end
97
- end
98
- end
99
- end
100
- end