stub_requests 0.1.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 +7 -0
- data/.codeclimate.yml +23 -0
- data/.editorconfig +13 -0
- data/.gitignore +10 -0
- data/.mdlrc +1 -0
- data/.reek.yml +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +112 -0
- data/.ruby-version +1 -0
- data/.simplecov +23 -0
- data/.travis.yml +37 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +64 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +138 -0
- data/Rakefile +8 -0
- data/_config.yml +1 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/index.md +37 -0
- data/lib/stub_requests/api.rb +73 -0
- data/lib/stub_requests/argument_validation.rb +39 -0
- data/lib/stub_requests/core_ext/all.rb +3 -0
- data/lib/stub_requests/core_ext/object/blank.rb +171 -0
- data/lib/stub_requests/core_ext.rb +3 -0
- data/lib/stub_requests/endpoint.rb +100 -0
- data/lib/stub_requests/endpoint_registry.rb +157 -0
- data/lib/stub_requests/hash_util.rb +30 -0
- data/lib/stub_requests/service.rb +118 -0
- data/lib/stub_requests/service_registry.rb +105 -0
- data/lib/stub_requests/stub_requests.rb +90 -0
- data/lib/stub_requests/uri/builder.rb +226 -0
- data/lib/stub_requests/uri/scheme.rb +34 -0
- data/lib/stub_requests/uri/suffix.rb +31 -0
- data/lib/stub_requests/uri/validator.rb +69 -0
- data/lib/stub_requests/version.rb +13 -0
- data/lib/stub_requests/webmock_builder.rb +108 -0
- data/lib/stub_requests.rb +25 -0
- data/stub_requests.gemspec +56 -0
- metadata +363 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "singleton"
|
4
|
+
require "concurrent/map"
|
5
|
+
|
6
|
+
#
|
7
|
+
# Abstraction over WebMock to reduce duplication
|
8
|
+
#
|
9
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
10
|
+
# @since 0.1.0
|
11
|
+
#
|
12
|
+
module StubRequests
|
13
|
+
#
|
14
|
+
# Class ServiceRegistry provides registration of services
|
15
|
+
#
|
16
|
+
class ServiceRegistry
|
17
|
+
include Singleton
|
18
|
+
include Enumerable
|
19
|
+
|
20
|
+
#
|
21
|
+
# @!attribute [rw] services
|
22
|
+
# @return [Concurrent::Map<Symbol, Service>] a map with services
|
23
|
+
attr_reader :services
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@services = Concurrent::Map.new
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Resets the map with registered services
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
def reset
|
35
|
+
services.clear
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Required by Enumerable
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# @return [Concurrent::Map<Symbol, Service>] an map with services
|
43
|
+
#
|
44
|
+
# @yield used by Enumerable
|
45
|
+
#
|
46
|
+
def each(&block)
|
47
|
+
services.each(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Registers a service in the registry
|
52
|
+
#
|
53
|
+
#
|
54
|
+
# @param [Symbol] service_id a symbolic id of the service
|
55
|
+
# @param [String] service_uri a string with a base_uri to the service
|
56
|
+
#
|
57
|
+
# @return [Service] the service that was just registered
|
58
|
+
#
|
59
|
+
def register_service(service_id, service_uri)
|
60
|
+
if (service = get_service(service_id))
|
61
|
+
StubRequests.logger.warn("Service already registered #{service}")
|
62
|
+
raise ServiceHaveEndpoints, service if service.endpoints?
|
63
|
+
end
|
64
|
+
services[service_id] = Service.new(service_id, service_uri)
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Removes a service from the registry
|
69
|
+
#
|
70
|
+
#
|
71
|
+
# @param [Symbol] service_id the service_id to remove
|
72
|
+
#
|
73
|
+
# @raise [ServiceNotFound] when the service was not removed
|
74
|
+
#
|
75
|
+
def remove_service(service_id)
|
76
|
+
services.delete(service_id) || raise(ServiceNotFound, service_id)
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Fetches a service from the registry
|
81
|
+
#
|
82
|
+
#
|
83
|
+
# @param [Symbol] service_id id of the service to remove
|
84
|
+
#
|
85
|
+
# @return [Service] the found service
|
86
|
+
#
|
87
|
+
def get_service(service_id)
|
88
|
+
services[service_id]
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Fetches a service from the registry or raises {ServiceNotFound}
|
93
|
+
#
|
94
|
+
#
|
95
|
+
# @param [Symbol] service_id the id of a service
|
96
|
+
#
|
97
|
+
# @raise [ServiceNotFound] when an endpoint couldn't be found
|
98
|
+
#
|
99
|
+
# @return [Endpoint]
|
100
|
+
#
|
101
|
+
def get_service!(service_id)
|
102
|
+
get_service(service_id) || raise(ServiceNotFound, service_id)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# Error is a base class for all gem errors
|
12
|
+
#
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
#
|
16
|
+
# ServiceHaveEndpoints is raised to prevent overwriting a registered service's endpoints
|
17
|
+
#
|
18
|
+
class ServiceHaveEndpoints < StandardError
|
19
|
+
def initialize(service)
|
20
|
+
super("Service with id #{service.id} have already been registered. #{service}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# InvalidType is raised when an argument is invalid
|
26
|
+
#
|
27
|
+
class InvalidType < Error
|
28
|
+
def initialize(actual:, expected:)
|
29
|
+
super("Expected `#{actual}` to be any of [#{expected}]")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# EndpointNotFound is raised when an endpoint cannot be found
|
35
|
+
#
|
36
|
+
class EndpointNotFound < Error; end
|
37
|
+
|
38
|
+
#
|
39
|
+
# ServiceNotFound is raised when a service cannot be found
|
40
|
+
#
|
41
|
+
class ServiceNotFound < Error
|
42
|
+
def initialize(service_id)
|
43
|
+
super("Couldn't find a service with id=:#{service_id}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# UriSegmentMismatch is raised when a segment cannot be replaced
|
49
|
+
#
|
50
|
+
class UriSegmentMismatch < Error; end
|
51
|
+
|
52
|
+
#
|
53
|
+
# InvalidUri is raised when a URI is invalid
|
54
|
+
#
|
55
|
+
class InvalidUri < Error
|
56
|
+
def initialize(uri)
|
57
|
+
super("'#{uri}' is not a valid URI.")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# extends "self"
|
62
|
+
# @!parse extend self
|
63
|
+
extend self
|
64
|
+
|
65
|
+
# includes "UriFor" and extends "UriFor"
|
66
|
+
# using the API.included callback
|
67
|
+
# @!parse include UriFor
|
68
|
+
# @!parse extend UriFor
|
69
|
+
|
70
|
+
# includes "API" and extends "API"
|
71
|
+
# using the API.included callback
|
72
|
+
# @!parse include API
|
73
|
+
# @!parse extend API
|
74
|
+
include API
|
75
|
+
|
76
|
+
#
|
77
|
+
# @!attribute [rw] logger
|
78
|
+
# @return [Logger] the logger to use in the gem
|
79
|
+
attr_accessor :logger
|
80
|
+
|
81
|
+
#
|
82
|
+
# The current version of the gem
|
83
|
+
#
|
84
|
+
#
|
85
|
+
# @return [String] version string, `"1.0.0"`
|
86
|
+
#
|
87
|
+
def version
|
88
|
+
VERSION
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# Builds a URI from a #host, #template and #replacements
|
12
|
+
#
|
13
|
+
module URI
|
14
|
+
#
|
15
|
+
# Builder constructs and validates URIs
|
16
|
+
#
|
17
|
+
# :reek:TooManyInstanceVariables { max_instance_variables: 6 }
|
18
|
+
class Builder
|
19
|
+
#
|
20
|
+
# @return [Regexp] A pattern for matching url segment keys
|
21
|
+
URL_SEGMENT_REGEX = /(:\w+)/.freeze
|
22
|
+
|
23
|
+
#
|
24
|
+
# Convenience method to avoid .new.build
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# @raise [UriSegmentMismatch] when there are unused URI segments
|
28
|
+
# @raise [UriSegmentMismatch] when the template have unplaced URI segments
|
29
|
+
#
|
30
|
+
# @param [String] host the URI used to reach the service
|
31
|
+
# @param [String] template the endpoint template
|
32
|
+
# @param [Hash<Symbol>] replacements a list of uri_replacement keys
|
33
|
+
#
|
34
|
+
# @return [String] a validated URI string
|
35
|
+
#
|
36
|
+
def self.build(host, template, replacements = {})
|
37
|
+
new(host, template, replacements).build
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# @!attribute [r] uri
|
42
|
+
# @return [String] the request host {Service#service_uri}
|
43
|
+
attr_reader :host
|
44
|
+
#
|
45
|
+
# @!attribute [r] template
|
46
|
+
# @return [String] a string template for the endpoint
|
47
|
+
attr_reader :template
|
48
|
+
#
|
49
|
+
# @!attribute [r] path
|
50
|
+
# @return [String] a valid URI path
|
51
|
+
attr_reader :path
|
52
|
+
#
|
53
|
+
# @!attribute [r] replacements
|
54
|
+
# @return [Hash<Symbol] a hash with keys matching the {#template}
|
55
|
+
attr_reader :replacements
|
56
|
+
#
|
57
|
+
# @!attribute [r] unused
|
58
|
+
# @return [Array<String>] a list with unused {#replacements}
|
59
|
+
attr_reader :unused
|
60
|
+
#
|
61
|
+
# @!attribute [r] unreplaced
|
62
|
+
# @return [Array<String>] a list of uri_segments that should have been replaced
|
63
|
+
attr_reader :unreplaced
|
64
|
+
|
65
|
+
#
|
66
|
+
# Initializes a new Builder
|
67
|
+
#
|
68
|
+
#
|
69
|
+
# @param [String] host the URI used to reach the service
|
70
|
+
# @param [String] template the endpoint template
|
71
|
+
# @param [Hash<Symbol>] replacements a list of uri_replacement keys
|
72
|
+
#
|
73
|
+
def initialize(host, template, replacements = {})
|
74
|
+
@host = +host
|
75
|
+
@template = +template
|
76
|
+
@path = +@template.dup
|
77
|
+
@replacements = replacements
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Builds a URI string
|
82
|
+
#
|
83
|
+
#
|
84
|
+
# @raise [UriSegmentMismatch] when there are unused URI segments
|
85
|
+
# @raise [UriSegmentMismatch] when the template have unplaced URI segments
|
86
|
+
#
|
87
|
+
# @return [String] a validated URI string
|
88
|
+
#
|
89
|
+
def build
|
90
|
+
build_uri
|
91
|
+
run_validations
|
92
|
+
|
93
|
+
uri
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def build_uri
|
99
|
+
replace_segments
|
100
|
+
parse_unreplaced_segments
|
101
|
+
end
|
102
|
+
|
103
|
+
def uri
|
104
|
+
@uri ||= [host, path].join("/")
|
105
|
+
end
|
106
|
+
|
107
|
+
def run_validations
|
108
|
+
validate_replacements_used
|
109
|
+
validate_segments_replaced
|
110
|
+
validate_uri
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Replaces the URI segments with the arguments in replacements
|
115
|
+
#
|
116
|
+
#
|
117
|
+
# @return [Array] an list with unused replacements
|
118
|
+
#
|
119
|
+
def replace_segments
|
120
|
+
@unused = replacements.map do |key, value|
|
121
|
+
uri_segment = ":#{key}"
|
122
|
+
if path.include?(uri_segment)
|
123
|
+
path.gsub!(uri_segment.to_s, value.to_s)
|
124
|
+
next
|
125
|
+
else
|
126
|
+
uri_segment
|
127
|
+
end
|
128
|
+
end.compact
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Validates that all replacements have been used
|
133
|
+
#
|
134
|
+
#
|
135
|
+
# @raise [UriSegmentMismatch] when there are unused replacements
|
136
|
+
#
|
137
|
+
# @return [void]
|
138
|
+
#
|
139
|
+
def validate_replacements_used
|
140
|
+
return if replacents_used?
|
141
|
+
|
142
|
+
raise UriSegmentMismatch,
|
143
|
+
"The URI segment(s) [#{unused.join(',')}] are missing in template (#{path})"
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# Checks that no replacements are left
|
148
|
+
#
|
149
|
+
#
|
150
|
+
# @return [true,false]
|
151
|
+
#
|
152
|
+
def replacents_used?
|
153
|
+
unused.none?
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Validates that all URI segments have been replaced in {#path}
|
158
|
+
#
|
159
|
+
#
|
160
|
+
# @raise [UriSegmentMismatch] when the path have unplaced URI segments
|
161
|
+
#
|
162
|
+
# @return [void]
|
163
|
+
#
|
164
|
+
def validate_segments_replaced
|
165
|
+
return if segments_replaced?
|
166
|
+
|
167
|
+
raise UriSegmentMismatch,
|
168
|
+
"The URI segment(s) [#{unreplaced.join(',')}]" \
|
169
|
+
" were not replaced in template (#{path})." \
|
170
|
+
" Given replacements=[#{segment_keys.join(',')}]"
|
171
|
+
end
|
172
|
+
|
173
|
+
def segment_keys
|
174
|
+
@segment_keys ||= replacements.keys.map { |segment_key| ":#{segment_key}" }
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# Checks that all URI segments were replaced
|
179
|
+
#
|
180
|
+
#
|
181
|
+
# @return [true,false]
|
182
|
+
#
|
183
|
+
def segments_replaced?
|
184
|
+
unreplaced.none?
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Parses out all unused URI segments
|
189
|
+
#
|
190
|
+
#
|
191
|
+
# @return [Array<String>] a list of not replaced uri_segments
|
192
|
+
#
|
193
|
+
def parse_unreplaced_segments
|
194
|
+
@unreplaced = URL_SEGMENT_REGEX.match(path).to_a.uniq
|
195
|
+
end
|
196
|
+
|
197
|
+
#
|
198
|
+
# Validates {#uri} is valid
|
199
|
+
#
|
200
|
+
#
|
201
|
+
# @return [true, false]
|
202
|
+
#
|
203
|
+
def validate_uri
|
204
|
+
StubRequests::URI::Validator.valid?(uri)
|
205
|
+
rescue InvalidUri
|
206
|
+
StubRequests.logger.warn("URI (#{uri}) is not valid.")
|
207
|
+
false
|
208
|
+
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# Raise exception when {#validate_uri} is false
|
212
|
+
#
|
213
|
+
# @see #validate_uri
|
214
|
+
#
|
215
|
+
# @raise [InvalidUri] when #{uri} is invalid
|
216
|
+
#
|
217
|
+
# @return [void]
|
218
|
+
#
|
219
|
+
# :nocov:
|
220
|
+
# :nodoc:
|
221
|
+
def validate_uri!
|
222
|
+
raise InvalidUri, uri unless validate_uri
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# Provides convenience methods for URI
|
12
|
+
#
|
13
|
+
module URI
|
14
|
+
#
|
15
|
+
# Module Scheme handles validation of {URI} schemes
|
16
|
+
#
|
17
|
+
module Scheme
|
18
|
+
#
|
19
|
+
# @return [Array<String>] a list of valid HTTP schemes
|
20
|
+
SCHEMES = %w[http https].freeze
|
21
|
+
|
22
|
+
#
|
23
|
+
# Checks if the scheme is valid
|
24
|
+
#
|
25
|
+
# @param [String] scheme a string with the URI scheme to check
|
26
|
+
#
|
27
|
+
# @return [true,false]
|
28
|
+
#
|
29
|
+
def self.valid?(scheme)
|
30
|
+
SCHEMES.include?(scheme.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
module URI
|
11
|
+
#
|
12
|
+
# Module Suffix deals with validating {URI} suffix
|
13
|
+
#
|
14
|
+
module Suffix
|
15
|
+
#
|
16
|
+
# @return [RegExp] a pattern used for matching HTTP(S) ports
|
17
|
+
PORT_REGEX = %r{:(\d+)/}.freeze
|
18
|
+
|
19
|
+
#
|
20
|
+
# Checks if the host has a valid suffix
|
21
|
+
#
|
22
|
+
# @param [String] host a string to check
|
23
|
+
#
|
24
|
+
# @return [true,false]
|
25
|
+
#
|
26
|
+
def self.valid?(host)
|
27
|
+
PublicSuffix.valid?(host, default_rule: nil)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# Provides convenience methods for URI
|
12
|
+
#
|
13
|
+
module URI
|
14
|
+
#
|
15
|
+
# Validator provides functionality for validating a {::URI}
|
16
|
+
#
|
17
|
+
class Validator
|
18
|
+
#
|
19
|
+
# Validates a URI
|
20
|
+
#
|
21
|
+
# @param [String] uri a full uri with path
|
22
|
+
#
|
23
|
+
# @return [true, false]
|
24
|
+
#
|
25
|
+
def self.valid?(uri)
|
26
|
+
new(uri).valid?
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# @!attribute [r] uri
|
31
|
+
# @return [String] a complete URI
|
32
|
+
attr_reader :uri
|
33
|
+
#
|
34
|
+
# @!attribute [r] host
|
35
|
+
# @return [String] the URI host
|
36
|
+
attr_reader :host
|
37
|
+
#
|
38
|
+
# @!attribute [r] scheme
|
39
|
+
# @return [String] the URI scheme
|
40
|
+
attr_reader :scheme
|
41
|
+
|
42
|
+
#
|
43
|
+
# Initialize a new instance of {Validator}
|
44
|
+
#
|
45
|
+
# @raise [InvalidUri] when URI can't be parsed
|
46
|
+
#
|
47
|
+
# @param [String] uri the full URI
|
48
|
+
#
|
49
|
+
#
|
50
|
+
def initialize(uri)
|
51
|
+
@uri = ::URI.parse(uri)
|
52
|
+
@host = @uri.host
|
53
|
+
@scheme = @uri.scheme
|
54
|
+
rescue ::URI::InvalidURIError
|
55
|
+
raise InvalidUri, uri
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Checks if a URI is valid
|
60
|
+
#
|
61
|
+
#
|
62
|
+
# @return [true,false] <description>
|
63
|
+
#
|
64
|
+
def valid?
|
65
|
+
URI::Scheme.valid?(scheme) && URI::Suffix.valid?(host)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# @return [String] a version string
|
12
|
+
VERSION = "0.1.0"
|
13
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Abstraction over WebMock to reduce duplication
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
# @since 0.1.0
|
8
|
+
#
|
9
|
+
module StubRequests
|
10
|
+
#
|
11
|
+
# Module API abstraction to reduce the amount of WebMock.stub_request
|
12
|
+
#
|
13
|
+
# @note This module can either be used by its class methods
|
14
|
+
# or included in say RSpec
|
15
|
+
#
|
16
|
+
class WebMockBuilder
|
17
|
+
include HashUtil
|
18
|
+
|
19
|
+
#
|
20
|
+
# Builds and registers a WebMock::RequestStub
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# @param [Symbol] verb a HTTP verb/method
|
24
|
+
# @param [String] uri a URI to call
|
25
|
+
# @param [Hash<Symbol>] options request/response options for Webmock::RequestStub
|
26
|
+
#
|
27
|
+
# @yield a callback to eventually yield to the caller
|
28
|
+
#
|
29
|
+
# @return [WebMock::RequestStub] the registered stub
|
30
|
+
#
|
31
|
+
def self.build(verb, uri, options = {}, &callback)
|
32
|
+
new(verb, uri, options, &callback).build
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# @!attribute [r] request_stub
|
37
|
+
# @return [WebMock::RequestStub] a stubbed webmock request
|
38
|
+
attr_reader :request_stub
|
39
|
+
#
|
40
|
+
# @!attribute [r] options
|
41
|
+
# @return [Hash<Symbol>] options for the stub_request
|
42
|
+
attr_reader :options
|
43
|
+
#
|
44
|
+
# @!attribute [r] callback
|
45
|
+
# @return [Block] call back when given a block
|
46
|
+
attr_reader :callback
|
47
|
+
|
48
|
+
#
|
49
|
+
# Initializes a new instance of
|
50
|
+
#
|
51
|
+
#
|
52
|
+
# @param [Symbol] verb a HTTP verb/method
|
53
|
+
# @param [String] uri a URI to call
|
54
|
+
# @param [Hash<Symbol>] options request/response options for Webmock::RequestStub
|
55
|
+
#
|
56
|
+
# @yield a block to eventually yield to the caller
|
57
|
+
#
|
58
|
+
def initialize(verb, uri, options = {}, &callback)
|
59
|
+
@request_stub = WebMock::RequestStub.new(verb, uri)
|
60
|
+
@options = options
|
61
|
+
@callback = callback
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Prepares a WebMock::RequestStub and registers it in WebMock
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# @return [WebMock::RequestStub] the registered stub
|
69
|
+
#
|
70
|
+
def build
|
71
|
+
if callback.present?
|
72
|
+
Docile.dsl_eval(request_stub, &callback)
|
73
|
+
else
|
74
|
+
prepare_mock_request
|
75
|
+
end
|
76
|
+
|
77
|
+
WebMock::StubRegistry.instance.register_request_stub(request_stub)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def prepare_mock_request
|
83
|
+
prepare_with
|
84
|
+
prepare_to_return
|
85
|
+
prepare_to_raise
|
86
|
+
request_stub.to_timeout if options[:timeout]
|
87
|
+
request_stub
|
88
|
+
end
|
89
|
+
|
90
|
+
def prepare_with
|
91
|
+
HashUtil.compact(options[:request]) do |request_options|
|
92
|
+
request_stub.with(request_options)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def prepare_to_return
|
97
|
+
HashUtil.compact(options[:response]) do |response_options|
|
98
|
+
request_stub.to_return(response_options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def prepare_to_raise
|
103
|
+
return unless (error = options[:error])
|
104
|
+
|
105
|
+
request_stub.to_raise(*Array(error))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "singleton"
|
4
|
+
require "docile"
|
5
|
+
require "webmock"
|
6
|
+
require "webmock/api"
|
7
|
+
|
8
|
+
require "stub_requests/version"
|
9
|
+
|
10
|
+
require "stub_requests/core_ext"
|
11
|
+
require "stub_requests/hash_util"
|
12
|
+
require "stub_requests/argument_validation"
|
13
|
+
require "stub_requests/endpoint"
|
14
|
+
require "stub_requests/endpoint_registry"
|
15
|
+
require "stub_requests/service"
|
16
|
+
require "stub_requests/service_registry"
|
17
|
+
require "stub_requests/uri/scheme"
|
18
|
+
require "stub_requests/uri/suffix"
|
19
|
+
require "stub_requests/uri/validator"
|
20
|
+
require "stub_requests/uri/builder"
|
21
|
+
require "stub_requests/webmock_builder"
|
22
|
+
|
23
|
+
require "stub_requests/api"
|
24
|
+
|
25
|
+
require "stub_requests/stub_requests"
|