brine-dsl 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +1,19 @@
1
1
  ##
2
- # @file transforming.rb
3
- # Argument Parameter transforming for Brine.
2
+ # @file transforming.rb
3
+ # Transform parameter values for use in Brine.
4
4
  ##
5
5
  module Brine
6
6
 
7
7
  ##
8
8
  #
9
- # A module that converts provided paramters to richer types.
9
+ # Convert provided paramters to richer types.
10
10
  #
11
11
  # This eases use of types beyond the Cucumber-provided simple strings.
12
12
  ##
13
13
  module ParameterTransforming
14
14
 
15
15
  ##
16
- # A class which will transform supported input.
16
+ # Transform supported input.
17
17
  #
18
18
  # This implementation is designed around instances being
19
19
  # defined with patterns which define whether they should handle
@@ -21,15 +21,19 @@ module Brine
21
21
  # (when the patterns match).
22
22
  ##
23
23
  class Transformer
24
+
25
+ ##
26
+ # Provide an identifier for this Transformer.
27
+ ##
24
28
  attr_reader :type
25
29
 
26
30
  ##
27
- # Return a new Transformer instance configured as specified.
31
+ # Construct a new Transformer instance configured as specified.
28
32
  #
29
- # @param [String] type The name of the type produced by this transformer.
33
+ # @param type [String] Define the name of the type produced by this transformer.
30
34
  # This will be used for upcoming explicit type conversion.
31
- # @param [Regexp] pattern A pattern which input should match for this Transformer to function.
32
- # @param [Proc] xfunk The function which will be passed string input and will return
35
+ # @param pattern [Regexp] Specify a pattern for which this Transformer will handle matching input.
36
+ # @param xfunk [Proc] Provide the function which will be passed string input and will return
33
37
  # the output type of this Transformer.
34
38
  ##
35
39
  def initialize(type, pattern, &xfunc)
@@ -39,10 +43,10 @@ module Brine
39
43
  end
40
44
 
41
45
  ##
42
- # Whether this instance should attempt to transform the input.
46
+ # Indicate whether this instance should attempt to transform the input.
43
47
  #
44
- # @param [String] input The String input as provided by Cucumber.
45
- # @return [Boolean] Whether this#transform should be called for input.
48
+ # @param input [String] Pass the String input as provided by Cucumber.
49
+ # @return [Boolean] Indicate whether this#transform should be called for input.
46
50
  ##
47
51
  def can_handle?(input)
48
52
  input =~ @pattern
@@ -51,8 +55,8 @@ module Brine
51
55
  ##
52
56
  # Transform the provided input.
53
57
  #
54
- # @param [String] input The String input as provided by Cucumber.
55
- # @return [Object] The transformed input into the appropriate type.
58
+ # @param input [String] Pass the String input as provided by Cucumber.
59
+ # @return [Object] Return input transformed into the appropriate type.
56
60
  ##
57
61
  def transform(input)
58
62
  STDERR.puts("Handling #{input} as #{@type}") if ENV['BRINE_LOG_TRANSFORMS']
@@ -67,7 +71,7 @@ module Brine
67
71
  TZ='(?:Z|(?:[+-]\d{2}:\d{2}))'
68
72
 
69
73
  ##
70
- # The chain of Transformers which will be used to convert parameters.
74
+ # Expose the chain of Transformers which will be used to convert parameters.
71
75
  #
72
76
  # In the default implicit mode the list will be iterated over in sequence
73
77
  # and the first Transformer which can handle the input will be used.
@@ -130,8 +134,8 @@ module Brine
130
134
  ##
131
135
  # Transform the provided input using #parameter_transformers.
132
136
  #
133
- # @param [String] input The String input as provided by Cucumber.
134
- # @return [Object] The input converted by the handling Transformer.
137
+ # @param input [String] Pass the String input as provided by Cucumber.
138
+ # @return [Object] Return input as converted by the handling Transformer.
135
139
  ##
136
140
  def transformed_parameter(input)
137
141
  parameter_transformers.find {|it| it.can_handle? input }
@@ -143,12 +147,12 @@ module Brine
143
147
  #
144
148
  # If val is not `expand`able it will be returned as is.
145
149
  #
146
- # @param [Object] val The value to potentially expand.
147
- # @return The expanded value of val.
150
+ # @param val [Object] Provide the value to potentially expand.
151
+ # @return [Object] Return the value of val, expanding as appropriate.
148
152
  ##
149
- def expand(val)
153
+ def expand(val, binding)
150
154
  if val.respond_to? :expand
151
- transformed_parameter(val.expand)
155
+ transformed_parameter(val.expand(binding))
152
156
  else
153
157
  val
154
158
  end
@@ -163,8 +167,10 @@ module Brine
163
167
  end
164
168
 
165
169
  ##
166
- # Configure Cucumber to use these transformers.
170
+ # Transform grave accent delimited parameters, performing implicit type transformation.
167
171
  ##
168
- Transform /.*/ do |input|
169
- transformed_parameter(input)
170
- end
172
+ ParameterType(
173
+ name: 'grave_param',
174
+ regexp: /`([^`]*)`/,
175
+ transformer: -> (input) { transformed_parameter(input) }
176
+ )
@@ -1,21 +1,20 @@
1
1
  ##
2
2
  # @file type_checking.rb
3
- # Checks whether provided values are instances of a specified type.
3
+ # Check whether provided values are instances of a specified type.
4
4
  #
5
- # Provides validation for an extended set of types supported byJSON.
5
+ # Provide validation for an extended set of types beyond those supported by JSON.
6
6
  ##
7
-
8
7
  module Brine
9
8
 
10
9
  ##
11
- # Module which adds functionality to check the type of values.
10
+ # Support asserting the type of values.
12
11
  ##
13
12
  module TypeChecking
14
13
 
15
14
  require 'rspec/expectations'
16
15
 
17
16
  ##
18
- # A registry of checks for types which can return a Matcher for provided types.
17
+ # Define a registry of checks for types which can return a Matcher for registered types.
19
18
  ##
20
19
  class TypeChecks
21
20
  include RSpec::Matchers
@@ -23,7 +22,7 @@ module Brine
23
22
  ##
24
23
  # Initialize an instance with default checks or those provided.
25
24
  #
26
- # @param [Hash<String, Matcher>] A hash of Matchers by type, where the Matcher value will be
25
+ # @param [Hash<String, Matcher>] Provide a hash of Matchers by type, where the Matcher value will be
27
26
  # used as the Matcher for the specified type.
28
27
  # It is expected that no map will be provided and the default
29
28
  # mapping will therefore be used.
@@ -41,9 +40,9 @@ module Brine
41
40
  ##
42
41
  # Return the Matcher for the specified type or die if not present.
43
42
  #
44
- # @param [Class] type The type whose Matcher should be returned.
45
- # @return [RSpec::Matcher] The Matcher configured for `type`.
46
- # @throw Exception if no Matcher exists for `type`.
43
+ # @param type [Class] Specify the type whose Matcher should be returned.
44
+ # @return [RSpec::Matcher] Return the Matcher registered for `type`.
45
+ # @throw Exception Raise an exception if no Matcher exists for `type`.
47
46
  ##
48
47
  def for_type(type)
49
48
  @map[type.to_sym] || raise("Unsupported type #{type}")
@@ -52,8 +51,8 @@ module Brine
52
51
  ##
53
52
  # Register the provided matcher for the specified type.
54
53
  #
55
- # @param[Class] type The type for which the Matcher will be registered.
56
- # @param[RSpec::Matcher] matcher A matcher to verify that input is an instance of type.
54
+ # @param type [Class] Specify the type for which the Matcher will be registered.
55
+ # @param[RSpec::Matcher] matcher Provide a matcher to verify that input is an instance of type.
57
56
  ##
58
57
  def register_matcher(type, matcher)
59
58
  @map[type.to_sym] = matcher
@@ -61,7 +60,7 @@ module Brine
61
60
  end
62
61
 
63
62
  ##
64
- # The currently active TypeCheck instance as a property, instantiating as needed.
63
+ # Expose the currently active TypeCheck instance as a property, instantiating as needed.
65
64
  ##
66
65
  def type_checks
67
66
  @type_check ||= TypeChecks.new
@@ -73,8 +72,9 @@ module Brine
73
72
  # This is the primary interface for type_checking to the rest of the system,
74
73
  # and is the only one expected to be used during test execution.
75
74
  #
76
- # @param [Class] type The type for which a Matcher should be returned.
77
- # @return [RSpec::Matcher] The Matcher currently registered for the type.
75
+ # @param type [Class] Specify the type for which a Matcher should be returned.
76
+ # @return [RSpec::Matcher] Return the Matcher currently registered for the type.
77
+ # @throw Exception Raise an exception if no Matcher exists for `type`.
78
78
  ##
79
79
  def type_check_for(type)
80
80
  type_checks.for_type(type)
@@ -86,3 +86,14 @@ module Brine
86
86
  ##
87
87
  include TypeChecking
88
88
  end
89
+
90
+ require 'brine/transforming'
91
+
92
+ ##
93
+ # Assert that the selected value satisfies the specified type check.
94
+ #
95
+ # @param type [Object] Specify the key for the type checker to evaluate the selection.
96
+ ##
97
+ Then('it is a valid {grave_param}') do |type|
98
+ perform { selector.assert_that(type, binding) {|t| type_check_for(t) } }
99
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brine-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Whipple
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-20 00:00:00.000000000 Z
11
+ date: 2019-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: '2.4'
19
+ version: 4.0.0.rc.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: '2.4'
26
+ version: 4.0.0.rc.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: mustache
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -137,6 +137,7 @@ files:
137
137
  - brine-dsl.gemspec
138
138
  - feature_setup.rb
139
139
  - lib/brine.rb
140
+ - lib/brine/assertions.rb
140
141
  - lib/brine/cleaning_up.rb
141
142
  - lib/brine/client_building.rb
142
143
  - lib/brine/coercing.rb
@@ -144,18 +145,10 @@ files:
144
145
  - lib/brine/mustache_expanding.rb
145
146
  - lib/brine/performing.rb
146
147
  - lib/brine/requesting.rb
147
- - lib/brine/rest_steps.rb
148
148
  - lib/brine/selecting.rb
149
- - lib/brine/step_definitions/assertions.rb
150
- - lib/brine/step_definitions/assignment.rb
151
- - lib/brine/step_definitions/cleanup.rb
152
- - lib/brine/step_definitions/perform.rb
153
- - lib/brine/step_definitions/request_construction.rb
154
- - lib/brine/step_definitions/selection.rb
155
149
  - lib/brine/test_steps.rb
156
150
  - lib/brine/transforming.rb
157
151
  - lib/brine/type_checking.rb
158
- - lib/brine/util.rb
159
152
  homepage: http://github.com/brightcove/brine
160
153
  licenses:
161
154
  - MIT
@@ -1,119 +0,0 @@
1
- require 'rspec'
2
- require 'brine/util'
3
- require 'brine/selecting'
4
- require 'jsonpath'
5
-
6
- # Chopping Block
7
- Then(/^the response #{RESPONSE_ATTRIBUTES} has `([^`]*)` with a value that is not empty$/) do
8
- |attribute, member|
9
- replaced_with('Then', "the value of the response #{attribute} child `#{member}` is not empty", '0.9')
10
- end
11
-
12
- Then(/^the response #{RESPONSE_ATTRIBUTES} includes? the entries:$/) do |attribute, table|
13
- replaced_with('Then', "the value of the response #{attribute} is including:", '0.9', kv_table(table).to_json)
14
- end
15
-
16
- Then(/^the response body is a list of length (\d+)$/) do |length|
17
- replaced_with('Then', "the value of the response body is of length `#{length}`", '0.9')
18
- end
19
-
20
- Then(/^the response body is a list (with|without) an entry containing:$/) do |with, data|
21
- neg = (with == 'without') ? 'not ' : ''
22
- replaced_with('Then', "the value of the response body does #{neg}have any element that is including:", '0.9', table.hashes.to_json)
23
- end
24
-
25
- Then(/^the response body has `([^`]*)` which (in|ex)cludes? the entries:$/) do
26
- |child, in_or_ex, table|
27
- neg = (in_or_ex=='ex') ? 'not ' : ''
28
- replaced_with('Then', "the value of the response body child `#{child}` is #{neg}including:", '0.9', kv_table(table).to_json)
29
- end
30
-
31
- # This file is legacy or unsorted steps which will be deprecated or moved into
32
- # more appropriate homes
33
-
34
- def not_if(val) val ? :not_to : :to end
35
-
36
- # Return a table that that is a key value pair in a format ready for consumption
37
- def kv_table(table)
38
- transform_table!(table).rows_hash
39
- end
40
-
41
- # TODO: Requires extensible is_a_valid for deprecation
42
- Then(/^the response body is a list which all are (\w+)$/) do |matcher|
43
- pass_it = method(matcher.to_sym).call
44
- expect(response_body_child.first).to all(pass_it)
45
- end
46
-
47
- # FIXME: In the process of being deprecated
48
- When(/^`([^`]*)` is bound to `([^`]*)` from the response body$/) do |name, path|
49
- binding[name] = response_body_child(path).first
50
- end
51
-
52
- #
53
- # Response attribute (non-body) assertions
54
- #
55
- Then(/^the response #{RESPONSE_ATTRIBUTES} contains? null fields:$/) do |attribute, table|
56
- expect(response)
57
- .to have_attributes(attribute.to_sym =>
58
- include(table.raw.flatten.collect{|v| [v, be_nil]}.to_h))
59
- end
60
-
61
- Then(/^the response #{RESPONSE_ATTRIBUTES} contains? non null fields:$/) do |attribute, table|
62
- expect(response)
63
- .to have_attributes(attribute.to_sym =>
64
- include(table.raw.flatten.collect{|v| [v, be_not_nil]}.to_h))
65
- end
66
-
67
- #
68
- # Response body assertions
69
- #
70
- # TODO: Write specifications around this
71
- Then(/^the response body does not contain fields:$/) do |table|
72
- expect(response_body_child.first.keys).to_not include(*table.raw.flatten)
73
- end
74
-
75
- #TODO: Maybe worth optimizing these 2 to O(n) after tests are in place
76
- Then(/^the response body is a list sorted by `([^`]*)` ascending$/) do |path|
77
- values = response_body_child(path)
78
- expect(values).to eq values.sort{|a,b| a.to_s.downcase <=> b.to_s.downcase}
79
- end
80
-
81
- Then(/^the response body is a list sorted by `([^`]*)` descending$/) do |path|
82
- values = response_body_child(path)
83
- expect(values).to eq values.sort{|a,b| b.to_s.downcase <=> a.to_s.downcase}
84
- end
85
-
86
-
87
- Then(/^the response body is (\w+)$/) do |matcher|
88
- pass_it = method(matcher.to_sym).call
89
- expect(response_body_child.first).to pass_it
90
- end
91
-
92
- #
93
- # Polling assertions
94
- #
95
- Then(/^a non\-empty list is eventually returned at `([^`]*)`$/) do |path|
96
- retry_for(120, 3) do
97
- send_request(parse_method('GET'), path)
98
- expect(response_body_child.first).to_not be_empty
99
- end
100
- end
101
-
102
- Then(/^the resource is eventually available at `([^`]*)`$/) do |path|
103
- retry_for(120, 3) do
104
- send_request(parse_method('GET'), path)
105
- expect(response).to have_attributes(:status => 200)
106
- end
107
- end
108
-
109
- # TODO: Parameterize polling length
110
- Then(/^the property `([^`]*)` is eventually `([^`]*)` at `([^`]*)`$/) do |field, value, path|
111
- retry_for(180) do
112
- send_request(parse_method('GET'), path)
113
- expect(response_body_child.first).to include(field => value)
114
- end
115
- end
116
-
117
- def response_body_child(path="")
118
- JsonPath.new("$.#{path}").on(response.body.to_json)
119
- end
@@ -1,50 +0,0 @@
1
- # assertions.rb - General assertions to be used with a Selector
2
-
3
- Then(/^it is equal to `([^`]*)`$/) do |value|
4
- perform { selector.assert_that(value) {|v| eq v} }
5
- end
6
- Then(/^it is equal to:$/) do |value|
7
- perform { selector.assert_that(value) {|v| eq v} }
8
- end
9
- Then(/^it is matching `([^`]*)`$/) do |value|
10
- perform { selector.assert_that(value) {|v| match v} }
11
- end
12
- Then (/^it is matching:$/) do |value|
13
- perform { selector.assert_that(value) {|v| match v} }
14
- end
15
- Then(/^it is greater than `([^`]*)`$/) do |value|
16
- perform { selector.assert_that(value) {|v| be > v} }
17
- end
18
- Then(/^it is greater than or equal to `([^`]*)`$/) do |value|
19
- perform { selector.assert_that(value) {|v| be >= v} }
20
- end
21
- Then(/^it is less than `([^`]*)`$/) do |value|
22
- perform { selector.assert_that(value) {|v| be < v} }
23
- end
24
- Then(/^it is less than or equal to `([^`]*)`$/) do |value|
25
- perform { selector.assert_that(value) {|v| be <= v} }
26
- end
27
-
28
- # Be a little smarter than default.
29
- Then(/^it is empty$/) do
30
- perform { selector.assert_that(nil) do
31
- satisfy{|i| i.nil? || (i.respond_to?(:empty?) && i.empty?) }
32
- end }
33
- end
34
-
35
- Then(/^it is including `([^`]*)`$/) do |value|
36
- perform { selector.assert_that(value) {|v| include v } }
37
- end
38
- Then(/^it is including:$/) do |value|
39
- perform { selector.assert_that(value) {|v| include v } }
40
- end
41
-
42
- Then(/^it is a valid `([^`]*)`$/) do |type|
43
- perform { selector.assert_that(type) {|t| type_check_for(t) } }
44
- end
45
-
46
- Then(/^it is of length `([^`]*)`$/) do |length|
47
- perform { selector.assert_that(length) do |l|
48
- satisfy{|i| i.respond_to?(:length) && i.length == l}
49
- end }
50
- end
@@ -1,42 +0,0 @@
1
- ##
2
- # @file assignment.rb
3
- # Assignment related steps.
4
- ##
5
-
6
- ##
7
- # Assign the provided parameter.
8
- #
9
- # @param name - The identifier to which the value will be bound.
10
- # @param value - The value to bind to the identifier.
11
- When(/^`([^`]*)` is assigned `([^`]*)`$/) do |name, value|
12
- perform { bind(name, value) }
13
- end
14
-
15
- ##
16
- # Assign a random string (UUID).
17
- #
18
- # @param name - The identifier to which a random string will be bound.
19
- When(/^`([^`]*)` is assigned a random string$/) do |name|
20
- perform { bind(name, SecureRandom.uuid) }
21
- end
22
-
23
- ##
24
- # Assign a current timestamp.
25
- #
26
- # @param name - The identifier to which the current timestamp will be bound.
27
- When(/^`([^`]*)` is assigned a timestamp$/) do |name|
28
- perform { bind(name, DateTime.now) }
29
- end
30
-
31
- ##
32
- # Assign a value extracted from a response attribute.
33
- #
34
- # @param name - The identifier to which the extracted value will be bound.
35
- # @param attribute - The response member from which the value will be extracted.
36
- # @param plural - When the path is provided,
37
- # @param path - The path within the member to extract.
38
- # whether to extract a single match or a collection of all matching.
39
- When(/^`([^`]*)` is assigned the response #{RESPONSE_ATTRIBUTES}(?: child(ren)? `([^`]*)`)?$/) do
40
- |name, attribute, plural, path|
41
- perform { bind(name, dig_from_response(attribute, path, !plural.nil?)) }
42
- end