brine-dsl 0.11.0 → 0.12.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.
@@ -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