brine-dsl 0.9.0 → 0.10.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 +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/brine-dsl.gemspec +1 -2
- data/lib/brine/cleaning_up.rb +120 -0
- data/lib/brine/client_building.rb +123 -0
- data/lib/brine/coercing.rb +91 -0
- data/lib/brine/hooks.rb +8 -1
- data/lib/brine/mustache_expanding.rb +51 -0
- data/lib/brine/performing.rb +159 -0
- data/lib/brine/requesting.rb +171 -0
- data/lib/brine/rest_steps.rb +1 -1
- data/lib/brine/selecting.rb +166 -0
- data/lib/brine/step_definitions/assertions.rb +15 -15
- data/lib/brine/step_definitions/assignment.rb +5 -4
- data/lib/brine/step_definitions/cleanup.rb +2 -2
- data/lib/brine/step_definitions/perform.rb +16 -0
- data/lib/brine/step_definitions/request_construction.rb +12 -8
- data/lib/brine/step_definitions/selection.rb +24 -12
- data/lib/brine/test_steps.rb +20 -0
- data/lib/brine/transforms.rb +12 -4
- data/lib/brine/type_checking.rb +88 -0
- data/lib/brine/util.rb +1 -0
- data/lib/brine.rb +13 -20
- metadata +12 -9
- data/lib/brine/cleaner_upper.rb +0 -101
- data/lib/brine/coercer.rb +0 -68
- data/lib/brine/mustache_binder.rb +0 -25
- data/lib/brine/requester.rb +0 -161
- data/lib/brine/selector.rb +0 -66
- data/lib/brine/type_checks.rb +0 -36
@@ -0,0 +1,88 @@
|
|
1
|
+
##
|
2
|
+
# @file type_checking.rb
|
3
|
+
# Checks whether provided values are instances of a specified type.
|
4
|
+
#
|
5
|
+
# Provides validation for an extended set of types supported byJSON.
|
6
|
+
##
|
7
|
+
|
8
|
+
module Brine
|
9
|
+
|
10
|
+
##
|
11
|
+
# Module which adds functionality to check the type of values.
|
12
|
+
##
|
13
|
+
module TypeChecking
|
14
|
+
|
15
|
+
require 'rspec/expectations'
|
16
|
+
|
17
|
+
##
|
18
|
+
# A registry of checks for types which can return a Matcher for provided types.
|
19
|
+
##
|
20
|
+
class TypeChecks
|
21
|
+
include RSpec::Matchers
|
22
|
+
|
23
|
+
##
|
24
|
+
# Initialize an instance with default checks or those provided.
|
25
|
+
#
|
26
|
+
# @param [Hash<String, Matcher>] A hash of Matchers by type, where the Matcher value will be
|
27
|
+
# used as the Matcher for the specified type.
|
28
|
+
# It is expected that no map will be provided and the default
|
29
|
+
# mapping will therefore be used.
|
30
|
+
##
|
31
|
+
def initialize(map={Object: be_a_kind_of(Hash),
|
32
|
+
String: be_a_kind_of(String),
|
33
|
+
Number: be_a_kind_of(Numeric),
|
34
|
+
Integer: be_a_kind_of(Integer),
|
35
|
+
Array: be_a_kind_of(Array),
|
36
|
+
DateTime: be_a_kind_of(Time),
|
37
|
+
Boolean: satisfy{|it| it == true || it == false } })
|
38
|
+
@map = map
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Return the Matcher for the specified type or die if not present.
|
43
|
+
#
|
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`.
|
47
|
+
##
|
48
|
+
def for_type(type)
|
49
|
+
@map[type.to_sym] || raise("Unsupported type #{type}")
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Register the provided matcher for the specified type.
|
54
|
+
#
|
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.
|
57
|
+
##
|
58
|
+
def register_matcher(type, matcher)
|
59
|
+
@map[type.to_sym] = matcher
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# The currently active TypeCheck instance as a property, instantiating as needed.
|
65
|
+
##
|
66
|
+
def type_checks
|
67
|
+
@type_check ||= TypeChecks.new
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Return the Matcher for the specified type.
|
72
|
+
#
|
73
|
+
# This is the primary interface for type_checking to the rest of the system,
|
74
|
+
# and is the only one expected to be used during test execution.
|
75
|
+
#
|
76
|
+
# @param [Class] type The type for which a Matcher should be returned.
|
77
|
+
# @return [RSpec::Matcher] The Matcher currently registered for the type.
|
78
|
+
##
|
79
|
+
def type_check_for(type)
|
80
|
+
type_checks.for_type(type)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Mix the TypeChecking module functionality into the main Brine module.
|
86
|
+
##
|
87
|
+
include TypeChecking
|
88
|
+
end
|
data/lib/brine/util.rb
CHANGED
data/lib/brine.rb
CHANGED
@@ -5,40 +5,33 @@
|
|
5
5
|
# The primary goal of this file is to load all resources needed to use brine.
|
6
6
|
# A secondary goal which should inform how that is done is that loading this
|
7
7
|
# file by itself should provide new objects but not otherwise impact existing
|
8
|
-
# state such as by
|
8
|
+
# state such as by modifying the World or defining any Steps, Transforms, etc.
|
9
9
|
# Those types of changes should be done by @ref #brine_mix.
|
10
|
-
|
11
|
-
require 'brine/cleaner_upper'
|
12
|
-
require 'brine/mustache_binder'
|
13
|
-
require 'brine/requester'
|
14
|
-
require 'brine/util'
|
15
|
-
require 'brine/selector'
|
16
|
-
require 'brine/type_checks'
|
17
|
-
|
18
10
|
##
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
include TypeChecking
|
27
|
-
end
|
11
|
+
|
12
|
+
require 'brine/cleaning_up'
|
13
|
+
require 'brine/mustache_expanding'
|
14
|
+
require 'brine/performing'
|
15
|
+
require 'brine/requesting'
|
16
|
+
require 'brine/selecting'
|
17
|
+
require 'brine/type_checking'
|
28
18
|
|
29
19
|
##
|
30
|
-
# Load the files with side effects
|
20
|
+
# Load the files with side effects.
|
31
21
|
#
|
32
22
|
# Expected to be called as `World(brine_mix)`
|
23
|
+
# @return [module] The `Brine` module.
|
24
|
+
##
|
33
25
|
def brine_mix
|
34
26
|
require 'brine/step_definitions/assignment'
|
35
27
|
require 'brine/step_definitions/request_construction'
|
36
28
|
require 'brine/step_definitions/assertions'
|
37
29
|
require 'brine/step_definitions/cleanup'
|
30
|
+
require 'brine/step_definitions/perform'
|
38
31
|
require 'brine/step_definitions/selection'
|
39
32
|
|
40
33
|
require 'brine/transforms'
|
41
|
-
require 'brine/rest_steps'
|
42
34
|
require 'brine/hooks'
|
35
|
+
|
43
36
|
Brine
|
44
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brine-dsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.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-05-
|
11
|
+
date: 2019-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -137,21 +137,24 @@ files:
|
|
137
137
|
- brine-dsl.gemspec
|
138
138
|
- feature_setup.rb
|
139
139
|
- lib/brine.rb
|
140
|
-
- lib/brine/
|
141
|
-
- lib/brine/
|
140
|
+
- lib/brine/cleaning_up.rb
|
141
|
+
- lib/brine/client_building.rb
|
142
|
+
- lib/brine/coercing.rb
|
142
143
|
- lib/brine/hooks.rb
|
143
|
-
- lib/brine/
|
144
|
-
- lib/brine/
|
144
|
+
- lib/brine/mustache_expanding.rb
|
145
|
+
- lib/brine/performing.rb
|
146
|
+
- lib/brine/requesting.rb
|
145
147
|
- lib/brine/rest_steps.rb
|
146
|
-
- lib/brine/
|
148
|
+
- lib/brine/selecting.rb
|
147
149
|
- lib/brine/step_definitions/assertions.rb
|
148
150
|
- lib/brine/step_definitions/assignment.rb
|
149
151
|
- lib/brine/step_definitions/cleanup.rb
|
152
|
+
- lib/brine/step_definitions/perform.rb
|
150
153
|
- lib/brine/step_definitions/request_construction.rb
|
151
154
|
- lib/brine/step_definitions/selection.rb
|
152
155
|
- lib/brine/test_steps.rb
|
153
156
|
- lib/brine/transforms.rb
|
154
|
-
- lib/brine/
|
157
|
+
- lib/brine/type_checking.rb
|
155
158
|
- lib/brine/util.rb
|
156
159
|
homepage: http://github.com/brightcove/brine
|
157
160
|
licenses:
|
@@ -173,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
176
|
version: '0'
|
174
177
|
requirements: []
|
175
178
|
rubyforge_project:
|
176
|
-
rubygems_version: 2.5.
|
179
|
+
rubygems_version: 2.5.1
|
177
180
|
signing_key:
|
178
181
|
specification_version: 4
|
179
182
|
summary: Cucumber@REST in Brine
|
data/lib/brine/cleaner_upper.rb
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# @file cleaner_upper.rb
|
3
|
-
# Clean up resources created during test run.
|
4
|
-
#
|
5
|
-
# Will issue DELETE call for all tracked URLs which will normally be triggered
|
6
|
-
# in a hook.
|
7
|
-
#
|
8
|
-
# The present approach for this is to explicitly track created resources to
|
9
|
-
# which DELETE calls will be sent. Cleaning up of resources will be given some
|
10
|
-
# further attention in the future, but this functionality should be preserved.
|
11
|
-
|
12
|
-
##
|
13
|
-
# A command object for the delete which will be executed as part of cleaning up.
|
14
|
-
class DeleteCommand
|
15
|
-
|
16
|
-
##
|
17
|
-
# Construct a command with the required paramters to perform the delete.
|
18
|
-
#
|
19
|
-
# @param client The Faraday client which will send the delete message.
|
20
|
-
# @param path The path of the resource to be deleted.
|
21
|
-
# @param oks The response status codes which will be considered successful.
|
22
|
-
# @param attempts The number of times this command should be tried,
|
23
|
-
# retrying if an unsuccessful status code is received.
|
24
|
-
def initialize(client, path, oks: [200,204], attempts: 3)
|
25
|
-
@client = client
|
26
|
-
@path = path
|
27
|
-
@oks = oks
|
28
|
-
@attempts = attempts
|
29
|
-
end
|
30
|
-
|
31
|
-
##
|
32
|
-
# Issue the delete based on the parameters provided during construction.
|
33
|
-
#
|
34
|
-
# @returns true if a successful response is obtained, otherwise false.
|
35
|
-
def cleanup
|
36
|
-
while @attempts > 0
|
37
|
-
begin
|
38
|
-
resp=@client.delete(@path)
|
39
|
-
return true if @oks.include?(resp.status)
|
40
|
-
rescue ex
|
41
|
-
puts "WARNING: #{ex}"
|
42
|
-
end
|
43
|
-
@attempts -= 1
|
44
|
-
end
|
45
|
-
puts "ERROR: Could not DELETE #{@path}"
|
46
|
-
false
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
##
|
51
|
-
# A mixin which provides resource cleanup.
|
52
|
-
#
|
53
|
-
# Exposes methods to keep a stack of DeleteCommands corresponding to each
|
54
|
-
# created resource which are then popped and invoked to perform the cleanup.
|
55
|
-
#
|
56
|
-
# The LIFO behavior is adopted as it is more likely to preserve integrity,
|
57
|
-
# such as removing children added to parents or similar dependencies.
|
58
|
-
module CleanerUpper
|
59
|
-
|
60
|
-
##
|
61
|
-
# Set the Faraday HTTP client object used to issue DELETE calls.
|
62
|
-
#
|
63
|
-
# The client provided will be subsequently used to create DeleteCommands.
|
64
|
-
# This can be called multiple times where each DeleteCommand will use the
|
65
|
-
# most recently set value. In most use cases this will also be the client
|
66
|
-
# used to issue the creation requests and could therefore be passed to this
|
67
|
-
# method prior to use.
|
68
|
-
#
|
69
|
-
# @param client - The client to use to DELETE subsequently tracked resources.
|
70
|
-
def set_cleaning_client(client)
|
71
|
-
@client = client
|
72
|
-
end
|
73
|
-
|
74
|
-
##
|
75
|
-
# Record resource to be later cleaned (pushes a DeleteCommand).
|
76
|
-
#
|
77
|
-
# @param path - The path for the created resource, will be issued a DELETE.
|
78
|
-
def track_created_resource(path)
|
79
|
-
created_resources << DeleteCommand.new(@client, path)
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# Clean recorded resources (normally after a test run).
|
84
|
-
def cleanup_created_resources
|
85
|
-
created_resources.reverse.each{|it| it.cleanup}
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
##
|
91
|
-
# The array which serves as the stack of DeleteCommands.
|
92
|
-
#
|
93
|
-
# Works as a "module provided property" which is a name I
|
94
|
-
# may have just made up.
|
95
|
-
#
|
96
|
-
# TODO: Find proper term for module provided property
|
97
|
-
# TODO: The name of this property seems sloppy as it contains commands.
|
98
|
-
def created_resources
|
99
|
-
@created_resources ||= []
|
100
|
-
end
|
101
|
-
end
|
data/lib/brine/coercer.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# @file coercer.rb
|
3
|
-
# Type coercion to support assertions.
|
4
|
-
|
5
|
-
##
|
6
|
-
# Coerces the types of provided objects to support desired assertions.
|
7
|
-
#
|
8
|
-
# Coercion is used to support handling richer data types in Brine without
|
9
|
-
# introducing noisy type information to the language.
|
10
|
-
# Argument Transforms can be used to convert input provided directly
|
11
|
-
# to a Brine step, however data extracted from JSON will by default be
|
12
|
-
# limited to the small amount of JSON supported data types. As normally
|
13
|
-
# the data extracted from JSON will only be directly present on one side
|
14
|
-
# of the assertion (most likely the left), the simpler JSON data types can
|
15
|
-
# be coerced to a richer type based on the right hand side.
|
16
|
-
#
|
17
|
-
# A standard example (and that which is defined at the moment here) is date/time
|
18
|
-
# values. When testing an API that returns such values it is likely desirable to
|
19
|
-
# perform assertions with proper date/time semantics, and the coercer allows
|
20
|
-
# such assertions against a value retrieved out of a JSON structure.
|
21
|
-
#
|
22
|
-
# The combination of Argument Transforms and the Coercer can also effectively
|
23
|
-
# allow for user defined types to seemlessly exist within the Brine tests.
|
24
|
-
# The date/time implementation is an example of this.
|
25
|
-
# TODO: Document this in a friendlier place, with a contrived example.
|
26
|
-
# TODO: Having the default Time stuff should likely be removed for v2.
|
27
|
-
#
|
28
|
-
# Implementation (Most of the non-implementation info should later be moved).
|
29
|
-
# ---
|
30
|
-
# Internally the Coercer is a wrapper around a map of coercion functions
|
31
|
-
# where the keys are the pairs of classes for the operands and the
|
32
|
-
# values are the functions which accept a pair of instances (ostensibly) of the
|
33
|
-
# classes and return a pair of transformed values. The default coercion function
|
34
|
-
# returns the inputs unmodified (a nop), so any pair of classes which does not
|
35
|
-
# have a key will pass through unchanged.
|
36
|
-
#
|
37
|
-
# Note that this relies solely on the hash lookup and does not attempt any kind
|
38
|
-
# of inheritance lookup or similar. The current thinking is that there should be
|
39
|
-
# few expected types and lineage could be covered through explicit keys so the
|
40
|
-
# simple, dumb approach is likely sufficient.
|
41
|
-
class Coercer
|
42
|
-
##
|
43
|
-
# Instantiate a new Coercer.
|
44
|
-
#
|
45
|
-
# Initialize the standard map of coercion functions.
|
46
|
-
def initialize
|
47
|
-
@map = Hash.new(->(lhs, rhs){[lhs, rhs]})
|
48
|
-
@map[[String, Time]] = ->(lhs, rhs){[Time.parse(lhs), rhs]}
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
# Coerce the provided inputs as needed.
|
53
|
-
#
|
54
|
-
# Looks up and invokes the associated coercion function.
|
55
|
-
#
|
56
|
-
# @param lhs - The left hand side input.
|
57
|
-
# @param rhs - The right hand side input.
|
58
|
-
# @returns A pair (2 element array) of potentially coerced values.
|
59
|
-
def coerce(lhs, rhs)
|
60
|
-
@map[[lhs.class, rhs.class]].call(lhs, rhs)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
module Coercion
|
65
|
-
def coercer
|
66
|
-
@coercer ||= Coercer.new
|
67
|
-
end
|
68
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'mustache'
|
2
|
-
|
3
|
-
# Provides a binding environment and template expansion functions that use that
|
4
|
-
# environment
|
5
|
-
module MustacheBinder
|
6
|
-
|
7
|
-
# getter for mutable hash which serves as binding environment
|
8
|
-
def binding
|
9
|
-
@binding ||= {}
|
10
|
-
end
|
11
|
-
|
12
|
-
# assign `value' to `key' within binding
|
13
|
-
# defined in a method to allow observability/interception
|
14
|
-
def bind(key, value)
|
15
|
-
puts "Assigning #{value} to #{key}" if ENV['BRINE_LOG_BINDING']
|
16
|
-
binding[key] = value
|
17
|
-
end
|
18
|
-
|
19
|
-
# return value as expanded Mustache template using binding environment
|
20
|
-
# Mustache in...no Mustache out
|
21
|
-
def shave_value(val)
|
22
|
-
Mustache.render(val, binding)
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
data/lib/brine/requester.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# @file requester.rb
|
3
|
-
# Request construction and response storage
|
4
|
-
##
|
5
|
-
|
6
|
-
require 'oauth2'
|
7
|
-
require 'faraday_middleware'
|
8
|
-
require 'brine/util'
|
9
|
-
|
10
|
-
##
|
11
|
-
# The root url to which Brine will send requests.
|
12
|
-
#
|
13
|
-
# This will normally be the value of ENV['BRINE_ROOT_URL'],
|
14
|
-
# and that value should be directly usable after older
|
15
|
-
# ENV['ROOT_URL'] is end-of-lifed (at which point this can be removed.
|
16
|
-
#
|
17
|
-
# @return [String] The root URL to use or nil if none is provided.
|
18
|
-
##
|
19
|
-
def brine_root_url
|
20
|
-
if ENV['BRINE_ROOT_URL']
|
21
|
-
ENV['BRINE_ROOT_URL']
|
22
|
-
elsif ENV['ROOT_URL']
|
23
|
-
deprecation_message('1.0', 'ROOT_URL is deprecated, replace with BRINE_ROOT_URL') if ENV['ROOT_URL']
|
24
|
-
ENV['ROOT_URL']
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
##
|
29
|
-
# Parameter object used to configure OAuth2 middleware
|
30
|
-
#
|
31
|
-
# Also used to provide basic DSL for configuration
|
32
|
-
##
|
33
|
-
class OAuth2Params
|
34
|
-
attr_accessor :token, :token_type
|
35
|
-
|
36
|
-
def initialize
|
37
|
-
@token_type = 'bearer'
|
38
|
-
end
|
39
|
-
|
40
|
-
def fetch_from(id, secret, opts)
|
41
|
-
@token = OAuth2::Client.new(id, secret, opts)
|
42
|
-
.client_credentials.get_token.token
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Construct a Faraday client to be used to send built requests
|
47
|
-
module ClientBuilding
|
48
|
-
|
49
|
-
# authenticate using provided info and save token for use in later requests
|
50
|
-
def use_oauth2_token(&block)
|
51
|
-
@oauth2 = OAuth2Params.new
|
52
|
-
@oauth2.instance_eval(&block)
|
53
|
-
end
|
54
|
-
|
55
|
-
def with_oauth2_token(&block)
|
56
|
-
use_oauth2_token(&block)
|
57
|
-
self
|
58
|
-
end
|
59
|
-
|
60
|
-
# This is represented as list of functions so that it can be more easily customized for
|
61
|
-
# unexpected use cases.
|
62
|
-
# It should likely be broken up a bit more sensibly and more useful insertion commands added...
|
63
|
-
# but it's likely enough of a power feature and platform specific to leave pretty raw.
|
64
|
-
def connection_handlers
|
65
|
-
@connection_handlers ||= [
|
66
|
-
proc do |conn|
|
67
|
-
conn.request :json
|
68
|
-
if @oauth2
|
69
|
-
conn.request :oauth2, @oauth2.token, :token_type => @oauth2.token_type
|
70
|
-
end
|
71
|
-
end,
|
72
|
-
proc do |conn|
|
73
|
-
if @logging
|
74
|
-
conn.response :logger, nil, :bodies => (@logging.casecmp('DEBUG') == 0)
|
75
|
-
end
|
76
|
-
conn.response :json, :content_type => /\bjson$/
|
77
|
-
end,
|
78
|
-
proc{|conn| conn.adapter Faraday.default_adapter }
|
79
|
-
]
|
80
|
-
end
|
81
|
-
|
82
|
-
def client_for_host(host, logging: ENV['BRINE_LOG_HTTP'])
|
83
|
-
@logging = logging
|
84
|
-
Faraday.new(host) do |conn|
|
85
|
-
connection_handlers.each{|h| h.call(conn) }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
class ClientBuilder
|
91
|
-
include ClientBuilding
|
92
|
-
end
|
93
|
-
|
94
|
-
# Module in charge of constructing requests and saving responses
|
95
|
-
module Requesting
|
96
|
-
include ClientBuilding
|
97
|
-
|
98
|
-
# Utility Methods
|
99
|
-
#
|
100
|
-
# Normalize an HTTP method passed from a specification into a form
|
101
|
-
# expected by the HTTP client library (lowercased symbol)
|
102
|
-
def parse_method(method)
|
103
|
-
method.downcase.to_sym
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_client(client)
|
107
|
-
@client = client
|
108
|
-
end
|
109
|
-
|
110
|
-
# return Faraday client object so that it could be used directly
|
111
|
-
# or passed to another object
|
112
|
-
def client
|
113
|
-
@client ||= client_for_host(brine_root_url || 'http://localhost:8080',
|
114
|
-
logging: ENV['BRINE_LOG_HTTP'])
|
115
|
-
end
|
116
|
-
|
117
|
-
# clear out any previously built request state and set defaults
|
118
|
-
def reset_request
|
119
|
-
@params = @headers = @body = nil
|
120
|
-
end
|
121
|
-
|
122
|
-
# store the provided body in the request options being built
|
123
|
-
# overriding any previously provided object
|
124
|
-
def set_request_body(obj)
|
125
|
-
@body = obj
|
126
|
-
end
|
127
|
-
|
128
|
-
# send a request using method to url using whatever options
|
129
|
-
# have been built for the present request
|
130
|
-
def send_request(method, url)
|
131
|
-
@response = client.run_request(method, url, @body, headers) do |req|
|
132
|
-
req.params = params
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# getter for the latest response returned
|
137
|
-
def response
|
138
|
-
@response
|
139
|
-
end
|
140
|
-
|
141
|
-
def headers
|
142
|
-
@headers ||= {content_type: 'application/json'}
|
143
|
-
end
|
144
|
-
|
145
|
-
def add_header(k, v)
|
146
|
-
headers[k] = v
|
147
|
-
end
|
148
|
-
|
149
|
-
def params
|
150
|
-
@params ||= {}
|
151
|
-
end
|
152
|
-
|
153
|
-
def add_request_param(k, v)
|
154
|
-
params[k] = v
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
|
159
|
-
class Requester
|
160
|
-
include Requesting
|
161
|
-
end
|
data/lib/brine/selector.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'brine/coercer'
|
2
|
-
require 'rspec/expectations'
|
3
|
-
require 'jsonpath'
|
4
|
-
|
5
|
-
# Selectors here are small wrappers around RSpec
|
6
|
-
# expectation behavior to encapsulate variations in
|
7
|
-
# some expecation associated behavior in classes.
|
8
|
-
class Selector
|
9
|
-
include RSpec::Matchers
|
10
|
-
attr_accessor :coercer
|
11
|
-
|
12
|
-
def initialize(target, negated)
|
13
|
-
@target = target
|
14
|
-
@message = negated ? :to_not : :to
|
15
|
-
end
|
16
|
-
|
17
|
-
def filter_matcher(matcher)
|
18
|
-
matcher
|
19
|
-
end
|
20
|
-
|
21
|
-
def assert_that(value)
|
22
|
-
target, value = coercer.coerce(@target, value)
|
23
|
-
matcher = filter_matcher(yield(value))
|
24
|
-
expect(target).send(@message, matcher)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class AnySelector < Selector
|
29
|
-
def filter_matcher(matcher)
|
30
|
-
include(matcher)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class AllSelector < Selector
|
35
|
-
def filter_matcher(matcher)
|
36
|
-
all(matcher)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
#
|
41
|
-
# Module
|
42
|
-
#
|
43
|
-
module Selection
|
44
|
-
include Coercion
|
45
|
-
attr_reader :selector
|
46
|
-
|
47
|
-
def use_selector(selector)
|
48
|
-
selector.coercer = coercer
|
49
|
-
@selector = selector
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
#
|
54
|
-
# Steps
|
55
|
-
#
|
56
|
-
RESPONSE_ATTRIBUTES='(status|headers|body)'
|
57
|
-
Then(/^the value of `([^`]*)` is( not)? (.*)$/) do |value, negated, assertion|
|
58
|
-
use_selector(Selector.new(value, (!negated.nil?)))
|
59
|
-
step "it is #{assertion}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def dig_from_response(attribute, path=nil, plural=false)
|
63
|
-
root = response.send(attribute.to_sym)
|
64
|
-
return root if !path
|
65
|
-
JsonPath.new("$.#{path}").send(plural ? :on : :first, root)
|
66
|
-
end
|
data/lib/brine/type_checks.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# type_checks.rb -- checks whether provided is a valid instance of a specified type
|
2
|
-
#
|
3
|
-
# Provides validation for standard JSON type
|
4
|
-
|
5
|
-
require 'rspec/expectations'
|
6
|
-
|
7
|
-
# This will be made extensible so it can replace current domain specific check logic
|
8
|
-
class TypeChecks
|
9
|
-
include RSpec::Matchers
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@map = {
|
13
|
-
Object: be_a_kind_of(Hash),
|
14
|
-
String: be_a_kind_of(String),
|
15
|
-
Number: be_a_kind_of(Numeric),
|
16
|
-
Integer: be_a_kind_of(Integer),
|
17
|
-
Array: be_a_kind_of(Array),
|
18
|
-
DateTime: be_a_kind_of(Time),
|
19
|
-
Boolean: satisfy{|it| it == true || it == false }
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def for_type(type)
|
24
|
-
@map[type.to_sym] || raise("Unsupported type #{type}")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
module TypeChecking
|
29
|
-
def type_checks
|
30
|
-
@type_check ||= TypeChecks.new
|
31
|
-
end
|
32
|
-
|
33
|
-
def type_check_for(type)
|
34
|
-
type_checks.for_type(type)
|
35
|
-
end
|
36
|
-
end
|