stub_requests 0.1.2 → 0.1.3
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/.simplecov +1 -0
- data/CHANGELOG.md +8 -0
- data/README.md +27 -0
- data/gemfiles/webmock_2.3.gemfile.lock +1 -1
- data/gemfiles/webmock_3.5.gemfile.lock +1 -1
- data/gemfiles/webmock_develop.gemfile.lock +1 -1
- data/lib/stub_requests.rb +19 -14
- data/lib/stub_requests/api.rb +30 -16
- data/lib/stub_requests/argument_validation.rb +12 -12
- data/lib/stub_requests/endpoint.rb +12 -10
- data/lib/stub_requests/exceptions.rb +2 -6
- data/lib/stub_requests/metrics.rb +5 -4
- data/lib/stub_requests/metrics/{endpoint_stat.rb → endpoint.rb} +23 -22
- data/lib/stub_requests/metrics/registry.rb +25 -25
- data/lib/stub_requests/metrics/{stub_stat.rb → request.rb} +22 -13
- data/lib/stub_requests/observable.rb +62 -0
- data/lib/stub_requests/observable/registry.rb +152 -0
- data/lib/stub_requests/observable/subscription.rb +58 -0
- data/lib/stub_requests/property.rb +9 -3
- data/lib/stub_requests/property/validator.rb +4 -4
- data/lib/stub_requests/registration.rb +87 -0
- data/lib/stub_requests/registration/endpoint.rb +107 -0
- data/lib/stub_requests/registration/endpoints.rb +156 -0
- data/lib/stub_requests/registration/registry.rb +112 -0
- data/lib/stub_requests/registration/service.rb +85 -0
- data/lib/stub_requests/uri.rb +1 -1
- data/lib/stub_requests/version.rb +1 -1
- data/lib/tasks/changelog.rake +11 -2
- data/update_docs.sh +33 -0
- metadata +13 -8
- data/bin/update_docs.sh +0 -16
- data/lib/stub_requests/endpoint_registry.rb +0 -159
- data/lib/stub_requests/service.rb +0 -77
- data/lib/stub_requests/service_registry.rb +0 -104
@@ -8,7 +8,7 @@
|
|
8
8
|
#
|
9
9
|
module StubRequests
|
10
10
|
#
|
11
|
-
# Module Metrics contains logic for collecting metrics about
|
11
|
+
# Module Metrics contains logic for collecting metrics about requests stubs
|
12
12
|
#
|
13
13
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
14
14
|
# @since 0.1.2
|
@@ -32,15 +32,15 @@ module StubRequests
|
|
32
32
|
|
33
33
|
#
|
34
34
|
# @!attribute [rw] services
|
35
|
-
# @return [Concurrent::Array<
|
36
|
-
attr_reader :
|
35
|
+
# @return [Concurrent::Array<Endpoint>] a map with stubbed endpoints
|
36
|
+
attr_reader :endpoints
|
37
37
|
|
38
38
|
#
|
39
39
|
# Initialize a new registry
|
40
40
|
#
|
41
41
|
#
|
42
42
|
def initialize
|
43
|
-
@
|
43
|
+
@endpoints = Concurrent::Array.new
|
44
44
|
end
|
45
45
|
|
46
46
|
#
|
@@ -49,41 +49,41 @@ module StubRequests
|
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
def reset
|
52
|
-
|
52
|
+
endpoints.clear
|
53
53
|
end
|
54
54
|
|
55
55
|
#
|
56
56
|
# Required by Enumerable
|
57
57
|
#
|
58
58
|
#
|
59
|
-
# @return [Concurrent::Array<
|
59
|
+
# @return [Concurrent::Array<Endpoint>] an array with stubbed endpoints
|
60
60
|
#
|
61
61
|
# @yield used by Enumerable
|
62
62
|
#
|
63
63
|
def each(&block)
|
64
|
-
|
64
|
+
endpoints.each(&block)
|
65
65
|
end
|
66
66
|
|
67
67
|
#
|
68
68
|
# Records metrics about stubbed endpoints
|
69
69
|
#
|
70
70
|
#
|
71
|
-
# @param [Service] service a symbolic id of the service
|
72
|
-
# @param [Endpoint] endpoint a string with a base_uri to the service
|
71
|
+
# @param [Registration::Service] service a symbolic id of the service
|
72
|
+
# @param [Registration::Endpoint] endpoint a string with a base_uri to the service
|
73
73
|
# @param [WebMock::RequestStub] request_stub the stubbed request
|
74
74
|
#
|
75
75
|
# @return [Service] the service that was just registered
|
76
76
|
#
|
77
77
|
def record(service, endpoint, request_stub)
|
78
|
-
|
79
|
-
|
78
|
+
endpoint = find_or_initialize_endpoint(service, endpoint)
|
79
|
+
endpoint.record(request_stub)
|
80
80
|
|
81
|
-
|
82
|
-
|
81
|
+
endpoints.push(endpoint)
|
82
|
+
endpoint
|
83
83
|
end
|
84
84
|
|
85
85
|
#
|
86
|
-
# Mark a {
|
86
|
+
# Mark a {Request} as having responded
|
87
87
|
#
|
88
88
|
# @note Called when webmock responds successfully
|
89
89
|
#
|
@@ -92,20 +92,20 @@ module StubRequests
|
|
92
92
|
# @return [void]
|
93
93
|
#
|
94
94
|
def mark_as_responded(request_stub)
|
95
|
-
return unless (
|
95
|
+
return unless (request = find_request(request_stub))
|
96
96
|
|
97
|
-
|
97
|
+
request.mark_as_responded
|
98
98
|
end
|
99
99
|
|
100
100
|
#
|
101
|
-
# Finds a {
|
101
|
+
# Finds a {Request} amongst the endpoint stubs
|
102
102
|
#
|
103
103
|
#
|
104
104
|
# @param [WebMock::RequestStub] request_stub a stubbed webmock response
|
105
105
|
#
|
106
|
-
# @return [
|
106
|
+
# @return [Request] the request_stubbed matching the request stub
|
107
107
|
#
|
108
|
-
def
|
108
|
+
def find_request(request_stub)
|
109
109
|
map do |endpoint|
|
110
110
|
endpoint.find_by(attribute: :request_stub, value: request_stub)
|
111
111
|
end.compact.first
|
@@ -113,19 +113,19 @@ module StubRequests
|
|
113
113
|
|
114
114
|
private
|
115
115
|
|
116
|
-
def
|
117
|
-
|
116
|
+
def find_or_initialize_endpoint(service, endpoint)
|
117
|
+
find_endpoint(service, endpoint) || initialize_endpoint(service, endpoint)
|
118
118
|
end
|
119
119
|
|
120
120
|
# :reek:UtilityFunction
|
121
121
|
# :reek:FeatureEnvy
|
122
|
-
def
|
123
|
-
find { |
|
122
|
+
def find_endpoint(service, endpoint)
|
123
|
+
find { |ep| ep.service_id == service.id && ep.endpoint_id == endpoint.id }
|
124
124
|
end
|
125
125
|
|
126
126
|
# :reek:UtilityFunction
|
127
|
-
def
|
128
|
-
Metrics::
|
127
|
+
def initialize_endpoint(service, endpoint)
|
128
|
+
Metrics::Endpoint.new(service, endpoint)
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
@@ -8,21 +8,29 @@
|
|
8
8
|
#
|
9
9
|
module StubRequests
|
10
10
|
#
|
11
|
-
# Module Metrics contains logic for collecting metrics about
|
11
|
+
# Module Metrics contains logic for collecting metrics about requests stubs
|
12
12
|
#
|
13
13
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
14
14
|
# @since 0.1.2
|
15
15
|
#
|
16
16
|
module Metrics
|
17
17
|
#
|
18
|
-
# Class
|
18
|
+
# Class Stub tracks the WebMock::RequestStub life cycle
|
19
19
|
#
|
20
20
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
21
21
|
# @since 0.1.2
|
22
22
|
#
|
23
23
|
# :reek:TooManyInstanceVariables
|
24
|
-
class
|
24
|
+
class Request
|
25
25
|
include Property
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
# Delegate service_id, endpoint_id, verb and uri_template to endpoint
|
29
|
+
delegate [:service_id, :endpoint_id, :verb, :uri_template] => :endpoint
|
30
|
+
#
|
31
|
+
# @!attribute [r] endpoint
|
32
|
+
# @return [StubRequests::Metrics::Endpoint] a stubbed endpoint
|
33
|
+
property :endpoint, type: StubRequests::Metrics::Endpoint
|
26
34
|
#
|
27
35
|
# @!attribute [r] verb
|
28
36
|
# @return [Symbol] a HTTP verb/method
|
@@ -52,18 +60,18 @@ module StubRequests
|
|
52
60
|
# Initialize a new Record
|
53
61
|
#
|
54
62
|
#
|
55
|
-
# @param [
|
63
|
+
# @param [Endpoint] endpoint a stubbed endpoint
|
56
64
|
# @param [WebMock::RequestStub] request_stub the stubbed webmock request
|
57
65
|
#
|
58
|
-
def initialize(
|
66
|
+
def initialize(endpoint, request_stub)
|
59
67
|
request_pattern = request_stub.request_pattern
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@responded_at
|
68
|
+
self.endpoint = endpoint
|
69
|
+
self.verb = request_pattern.method_pattern.to_s.to_sym
|
70
|
+
self.uri = request_pattern.uri_pattern.to_s
|
71
|
+
self.request_stub = request_stub
|
72
|
+
self.recorded_at = Time.now
|
73
|
+
self.recorded_from = RSpec.current_example.metadata[:location]
|
74
|
+
@responded_at = nil # ByPass the validation for the initializer
|
67
75
|
end
|
68
76
|
|
69
77
|
#
|
@@ -73,7 +81,8 @@ module StubRequests
|
|
73
81
|
# @return [Time] the time it was marked responded
|
74
82
|
#
|
75
83
|
def mark_as_responded
|
76
|
-
|
84
|
+
self.responded_at = Time.now
|
85
|
+
Observable.notify_subscribers(self)
|
77
86
|
end
|
78
87
|
end
|
79
88
|
end
|
@@ -0,0 +1,62 @@
|
|
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 Observable handles observing webmock requests
|
12
|
+
#
|
13
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
14
|
+
# @since 0.1.3
|
15
|
+
#
|
16
|
+
module Observable
|
17
|
+
#
|
18
|
+
# Subscribe to a service endpoint call
|
19
|
+
# @see Observable::Registry#subscribe
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# @param [Symbol] service_id the id of a service
|
23
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
24
|
+
# @param [Symbol] verb the HTTP verb to subscribe to
|
25
|
+
# @param [Proc] callback the callback to use for when.a request was made
|
26
|
+
#
|
27
|
+
# @return [Subscription]
|
28
|
+
#
|
29
|
+
# :reek:LongParameterList
|
30
|
+
def self.subscribe_to(service_id, endpoint_id, verb, callback)
|
31
|
+
Registry.instance.subscribe(service_id, endpoint_id, verb, callback)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Unsubscribe from a service endpoint call
|
36
|
+
# @see Observable::Registry#unsubscribe
|
37
|
+
#
|
38
|
+
#
|
39
|
+
# @param [Symbol] service_id the id of a service
|
40
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
41
|
+
# @param [Symbol] verb the HTTP verb to subscribe to
|
42
|
+
#
|
43
|
+
# @return [Subscription]
|
44
|
+
#
|
45
|
+
def self.unsubscribe_from(service_id, endpoint_id, verb)
|
46
|
+
Registry.instance.unsubscribe(service_id, endpoint_id, verb)
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Notifies subscribers that a request was made
|
51
|
+
# @see Observable::Registry#notify_subscribers
|
52
|
+
#
|
53
|
+
#
|
54
|
+
# @param [Metrics::Request] request the stubbed request
|
55
|
+
#
|
56
|
+
# @return [Request]
|
57
|
+
#
|
58
|
+
def self.notify_subscribers(request)
|
59
|
+
Registry.instance.notify_subscribers(request)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,152 @@
|
|
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 Observable handles listening to endpoint invocations
|
12
|
+
#
|
13
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
14
|
+
# @since 0.1.3
|
15
|
+
#
|
16
|
+
module Observable
|
17
|
+
#
|
18
|
+
# Class Registry handles subscriptions to webmock requests
|
19
|
+
#
|
20
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
21
|
+
# @since 0.1.3
|
22
|
+
#
|
23
|
+
# :reek:UtilityFunction
|
24
|
+
# :reek:DataClump
|
25
|
+
# :reek:FeatureEnvy
|
26
|
+
class Registry
|
27
|
+
include Singleton
|
28
|
+
include Enumerable
|
29
|
+
|
30
|
+
#
|
31
|
+
# @!attribute [r] subscriptions
|
32
|
+
# @return [Concurrent::Array<Subscription>] a list of subscriptions
|
33
|
+
attr_reader :subscriptions
|
34
|
+
|
35
|
+
#
|
36
|
+
# Used by Singleton
|
37
|
+
#
|
38
|
+
#
|
39
|
+
def initialize
|
40
|
+
@subscriptions = Concurrent::Array.new
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Resets the map with registered services
|
45
|
+
#
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
def reset
|
49
|
+
subscriptions.clear
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Required by Enumerable
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# @return [Concurrent::Array<Subscription>] a list with subscriptions
|
57
|
+
#
|
58
|
+
# @yield used by Enumerable
|
59
|
+
#
|
60
|
+
def each(&block)
|
61
|
+
subscriptions.each(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Subscribe to a service endpoint call
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# @param [Symbol] service_id the id of a service
|
69
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
70
|
+
# @param [optional, Symbol] verb the HTTP verb to subscribe to
|
71
|
+
# @param [proc] callback the callback to use for when.a request was made
|
72
|
+
#
|
73
|
+
# @return [Subscription] the added subscription
|
74
|
+
#
|
75
|
+
# :reek:LongParameterList
|
76
|
+
def subscribe(service_id, endpoint_id, verb, callback)
|
77
|
+
subscription = find_by(service_id, endpoint_id, verb)
|
78
|
+
return subscription if subscription
|
79
|
+
|
80
|
+
subscription = Subscription.new(service_id, endpoint_id, verb, callback)
|
81
|
+
subscriptions.push(subscription)
|
82
|
+
subscription
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Unsubscribe to a service endpoint call
|
87
|
+
#
|
88
|
+
#
|
89
|
+
# @param [Symbol] service_id the id of a service
|
90
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
91
|
+
# @param [optional, Symbol] verb the HTTP verb to subscribe to
|
92
|
+
#
|
93
|
+
# @return [Subscription] the deleted subscription
|
94
|
+
#
|
95
|
+
# :reek:ControlParameter
|
96
|
+
def unsubscribe(service_id, endpoint_id, verb)
|
97
|
+
return unless (subscription = find_by(service_id, endpoint_id, verb))
|
98
|
+
|
99
|
+
subscriptions.delete(subscription)
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Notifies subscribers that a request was made
|
104
|
+
#
|
105
|
+
# @param [Metrics::Request] request the stubbed request
|
106
|
+
#
|
107
|
+
# @return [void]
|
108
|
+
#
|
109
|
+
def notify_subscribers(request)
|
110
|
+
return unless (subscription = find_by(request.service_id, request.endpoint_id, request.verb))
|
111
|
+
|
112
|
+
send_notification(request, subscription)
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
#
|
118
|
+
# Finds a subscription for a service endpoint
|
119
|
+
#
|
120
|
+
#
|
121
|
+
# @param [Symbol] service_id the id of a service
|
122
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
123
|
+
# @param [optional, Symbol] verb the HTTP verb to subscribe to
|
124
|
+
#
|
125
|
+
# @return [Subscription]
|
126
|
+
#
|
127
|
+
# :reek:ControlParameter
|
128
|
+
# :reek:DuplicateMethodCall
|
129
|
+
def find_by(service_id, endpoint_id, verb)
|
130
|
+
find do |sub|
|
131
|
+
sub.service_id == service_id &&
|
132
|
+
sub.endpoint_id == endpoint_id &&
|
133
|
+
([sub.verb, verb].include?(:any) || sub.verb == verb)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def send_notification(request, subscription)
|
138
|
+
callback = subscription.callback
|
139
|
+
arity = callback.arity
|
140
|
+
|
141
|
+
case arity
|
142
|
+
when 0
|
143
|
+
callback.call
|
144
|
+
when 1
|
145
|
+
callback.call(request)
|
146
|
+
else
|
147
|
+
raise InvalidCallback, "The callback for a subscription can either take 0 or 1 arguments (was #{arity})"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,58 @@
|
|
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 Observable handles listening to endpoint invocations
|
12
|
+
#
|
13
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
14
|
+
# @since 0.1.3
|
15
|
+
#
|
16
|
+
module Observable
|
17
|
+
#
|
18
|
+
# Class Subscription contains information about a subscription
|
19
|
+
#
|
20
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
21
|
+
# @since 0.1.3
|
22
|
+
#
|
23
|
+
class Subscription
|
24
|
+
include Property
|
25
|
+
#
|
26
|
+
# @!attribute [rw] service_id
|
27
|
+
# @return [Symbol] the id of a service
|
28
|
+
property :service_id, type: Symbol
|
29
|
+
#
|
30
|
+
# @!attribute [rw] endpoint_id
|
31
|
+
# @return [Symbol] the id of an endpoint
|
32
|
+
property :endpoint_id, type: Symbol
|
33
|
+
#
|
34
|
+
# @!attribute [rw] verb
|
35
|
+
# @return [Symbol] the HTTP verb/method
|
36
|
+
property :verb, type: Symbol, default: :any
|
37
|
+
#
|
38
|
+
# @!attribute [rw] callback
|
39
|
+
# @return [Proc] a proc to callback on notify
|
40
|
+
property :callback, type: Proc
|
41
|
+
|
42
|
+
#
|
43
|
+
# Initialize a new Subscription
|
44
|
+
#
|
45
|
+
# @param [Symbol] service_id the id of a service
|
46
|
+
# @param [Symbol] endpoint_id the id of an endpoint
|
47
|
+
# @param [Symbol] verb the HTTP verb/method
|
48
|
+
# @param [Proc] callback a proc to callback on notify
|
49
|
+
#
|
50
|
+
def initialize(service_id, endpoint_id, verb, callback)
|
51
|
+
self.service_id = service_id
|
52
|
+
self.endpoint_id = endpoint_id
|
53
|
+
self.verb = verb
|
54
|
+
self.callback = callback
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|