pinch_hitter 0.5.5 → 0.5.6
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/.travis.yml +2 -0
- data/Changelog +5 -0
- data/features/response_headers.feature +10 -0
- data/features/step_definitions/response_steps.rb +13 -0
- data/lib/pinch_hitter/core_ext/nil_class.rb +4 -0
- data/lib/pinch_hitter/message/message_store.rb +0 -1
- data/lib/pinch_hitter/service/endpoint_handlers.rb +17 -18
- data/lib/pinch_hitter/service/endpoint_recorders.rb +23 -0
- data/lib/pinch_hitter/service/message_queue.rb +4 -0
- data/lib/pinch_hitter/service/replay_ws.rb +32 -7
- data/lib/pinch_hitter/service/runner.rb +6 -0
- data/lib/pinch_hitter/version.rb +1 -1
- data/test/test_endpoint_handlers.rb +10 -5
- data/test/test_endpoint_recorders.rb +16 -0
- data/test/test_service.rb +35 -0
- metadata +10 -5
- data/lib/pinch_hitter/service/endpoint_recorder.rb +0 -28
- data/test/test_endpoint_recorder.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61b0f448b1236a0470c64ffdd3015e536db68cf9
|
4
|
+
data.tar.gz: a451b062d54056d41397a2d187d260bf7ec00162
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b266a49251d14f0adb19d9103f9a750eaec21073f32986723d8687aeb8f331d63fb91b61e6dd4baf559d7f16ce3ab088fa13cc3ef7d79bb00a86fb44d9e459aa
|
7
|
+
data.tar.gz: 664117aff93c40d35fd9b09b1cf5257d35c5050c70869c70ae6df49ef64b9c7f7f96a01653f7b52176d41f7b46bb28e189f2e3b01d821e1901c267c193b5314b
|
data/.travis.yml
CHANGED
data/Changelog
CHANGED
@@ -32,3 +32,8 @@ test logs.
|
|
32
32
|
|
33
33
|
=== Release 0.5.5 / 2015-11-5
|
34
34
|
* Allow Cross-Origin requests
|
35
|
+
|
36
|
+
=== Release 0.5.6 / 2016-03-19
|
37
|
+
* Add ability to disable cache control (useful for IE testing)
|
38
|
+
* Allow client to register a module that will hydrate the response object.
|
39
|
+
* Break apart recording and responding to better support full response payloads
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Feature: Response headers
|
2
|
+
I want to put headers on my responses
|
3
|
+
As a tester trying to test the application
|
4
|
+
So that my application works with something close to my production server
|
5
|
+
|
6
|
+
Scenario: Disable caching
|
7
|
+
Given I setup my replay service with no-cache
|
8
|
+
When I make a request
|
9
|
+
Then my response has a no-cache,no-store Cache-Control header
|
10
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Given(/^I setup my replay service with no\-cache$/) do
|
2
|
+
mock.reset
|
3
|
+
mock.no_cache
|
4
|
+
end
|
5
|
+
|
6
|
+
When(/^I make a request$/) do
|
7
|
+
mock.prime '/car_rental', :car_rental
|
8
|
+
@response = app.post '/car_rental', '{"reservation": "yes"}'
|
9
|
+
end
|
10
|
+
|
11
|
+
Then(/^my response has a no\-cache,no\-store Cache\-Control header$/) do
|
12
|
+
@response.header['Cache-Control'].should == 'no-cache, no-store'
|
13
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
+
require 'pinch_hitter/core_ext/string'
|
2
|
+
require 'pinch_hitter/core_ext/nil_class'
|
1
3
|
require_relative 'message_queue'
|
2
|
-
require_relative 'endpoint_recorder'
|
3
4
|
|
4
5
|
module PinchHitter::Service
|
5
6
|
class EndpointHandlers
|
@@ -7,21 +8,22 @@ module PinchHitter::Service
|
|
7
8
|
@handlers ||= {}
|
8
9
|
end
|
9
10
|
|
10
|
-
def store_message(endpoint,
|
11
|
-
handler_for(endpoint)
|
11
|
+
def store_message(endpoint, message)
|
12
|
+
handler = handler_for(endpoint)
|
13
|
+
handler.store(message.squish) if handler.respond_to? :store
|
12
14
|
end
|
13
15
|
|
14
|
-
def respond_to(endpoint='/', request=nil)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def respond_to(endpoint='/', body=nil, request=nil, response = nil)
|
17
|
+
handler = handler_for(endpoint)
|
18
|
+
if handler.respond_to?(:handle_request)
|
19
|
+
handler.handle_request(request, response)
|
20
|
+
else
|
21
|
+
handler.respond_to(body).squish
|
22
|
+
end
|
21
23
|
end
|
22
24
|
|
23
25
|
def handler_for(endpoint='/')
|
24
|
-
handlers[
|
26
|
+
handlers[endpoint] || store_handler(endpoint)
|
25
27
|
end
|
26
28
|
|
27
29
|
def register_module(endpoint, mod)
|
@@ -31,16 +33,13 @@ module PinchHitter::Service
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def store_handler(endpoint, handler=MessageQueue.new)
|
34
|
-
handlers[
|
35
|
-
end
|
36
|
-
|
37
|
-
def normalize(endpoint)
|
38
|
-
return endpoint if endpoint =~ /^\//
|
39
|
-
"/#{endpoint}"
|
36
|
+
handlers[endpoint] = handler
|
40
37
|
end
|
41
38
|
|
42
39
|
def reset
|
43
|
-
handlers.values.each
|
40
|
+
handlers.values.each do |handler|
|
41
|
+
handler.reset if handler.respond_to? :reset
|
42
|
+
end
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PinchHitter::Service
|
2
|
+
class EndpointRecorders
|
3
|
+
def recorders
|
4
|
+
@recorders ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def record(endpoint, request)
|
8
|
+
recorder_for(endpoint) << request
|
9
|
+
end
|
10
|
+
|
11
|
+
def requests(endpoint)
|
12
|
+
recorder_for(endpoint)
|
13
|
+
end
|
14
|
+
|
15
|
+
def recorder_for(endpoint='/')
|
16
|
+
recorders[endpoint] ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset
|
20
|
+
recorders.clear
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -5,6 +5,7 @@ require 'nokogiri'
|
|
5
5
|
require 'json'
|
6
6
|
|
7
7
|
require 'pinch_hitter/service/endpoint_handlers'
|
8
|
+
require 'pinch_hitter/service/endpoint_recorders'
|
8
9
|
require 'pinch_hitter/message/content_type'
|
9
10
|
|
10
11
|
module PinchHitter::Service
|
@@ -16,13 +17,21 @@ module PinchHitter::Service
|
|
16
17
|
configure do
|
17
18
|
enable :cross_origin
|
18
19
|
@@handlers = EndpointHandlers.new
|
20
|
+
@@recorder = EndpointRecorders.new
|
19
21
|
#SOAP expects a mime_type of text/xml
|
20
22
|
mime_type :xml, "text/xml"
|
21
23
|
mime_type :json, "application/json"
|
24
|
+
disable :no_cache
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
before do
|
29
|
+
cache_control :no_cache, :no_store if settings.no_cache
|
22
30
|
end
|
23
31
|
|
24
32
|
post '/reset' do
|
25
33
|
@@handlers.reset
|
34
|
+
@@recorder.reset
|
26
35
|
status 200
|
27
36
|
end
|
28
37
|
|
@@ -70,32 +79,48 @@ module PinchHitter::Service
|
|
70
79
|
end
|
71
80
|
|
72
81
|
def store(endpoint='/', message=nil)
|
82
|
+
endpoint = normalize(endpoint)
|
73
83
|
@@handlers.store_message endpoint, message
|
74
84
|
end
|
75
85
|
|
76
86
|
def respond(endpoint='/', request=nil)
|
77
|
-
|
78
|
-
|
79
|
-
|
87
|
+
endpoint = normalize(endpoint)
|
88
|
+
body, request = wrap(request)
|
89
|
+
@@recorder.record(endpoint, request)
|
90
|
+
message = @@handlers.respond_to(endpoint, body, request, response)
|
91
|
+
if message.is_a? String
|
92
|
+
content_type determine_content_type message
|
93
|
+
puts "No message found for #{endpoint}" unless message
|
94
|
+
end
|
80
95
|
message
|
81
96
|
end
|
82
97
|
|
83
98
|
def register_module(endpoint='/', mod='')
|
99
|
+
endpoint = normalize(endpoint)
|
84
100
|
@@handlers.register_module endpoint, Marshal.load(mod)
|
85
101
|
end
|
86
102
|
|
87
103
|
def requests endpoint
|
104
|
+
endpoint = normalize(endpoint)
|
88
105
|
content_type 'application/json'
|
89
|
-
{ requests: @@
|
106
|
+
{ requests: @@recorder.requests(endpoint) }.to_json
|
90
107
|
end
|
91
108
|
|
92
|
-
def wrap
|
93
|
-
return nil unless request
|
94
|
-
|
109
|
+
def wrap(request)
|
110
|
+
return [nil, nil] unless request
|
111
|
+
|
112
|
+
body = request.body.read
|
113
|
+
[body, { headers: request_headers, body: body }]
|
95
114
|
end
|
96
115
|
|
97
116
|
def request_headers
|
98
117
|
env.select { |key, value| key.upcase == key }
|
99
118
|
end
|
119
|
+
|
120
|
+
def normalize(endpoint)
|
121
|
+
return endpoint if endpoint =~ /^\//
|
122
|
+
"/#{endpoint}"
|
123
|
+
end
|
124
|
+
|
100
125
|
end
|
101
126
|
end
|
@@ -8,9 +8,15 @@ module PinchHitter::Service::Runner
|
|
8
8
|
@silent_console = true
|
9
9
|
end
|
10
10
|
|
11
|
+
def no_cache
|
12
|
+
@no_cache = true
|
13
|
+
@app.settings.enable :no_cache if @app
|
14
|
+
end
|
15
|
+
|
11
16
|
def start_service(host, port, timeout=10)
|
12
17
|
Thread.abort_on_exception = true
|
13
18
|
@app = PinchHitter::Service::ReplayWs.new
|
19
|
+
@app.settings.enable :no_cache if @no_cache
|
14
20
|
@replay_service = Thread.new do
|
15
21
|
Rack::Handler::WEBrick.run @app, service_options(host, port)
|
16
22
|
end
|
data/lib/pinch_hitter/version.rb
CHANGED
@@ -40,13 +40,12 @@ class TestEndpointHandlers < MiniTest::Test
|
|
40
40
|
assert_equal "THIS IS A TEST", @handlers.respond_to('endpoint')
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
@handlers.
|
46
|
-
assert_equal
|
43
|
+
def test_full_request_module_with_marshalling
|
44
|
+
mod = Marshal.dump(RequestHandlerTest)
|
45
|
+
@handlers.register_module('endpoint', Marshal.load(mod))
|
46
|
+
assert_equal "HANDLING REQUESTS", @handlers.respond_to('endpoint')
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
module TestModule
|
51
50
|
def respond_to(msg)
|
52
51
|
test_message
|
@@ -55,4 +54,10 @@ class TestEndpointHandlers < MiniTest::Test
|
|
55
54
|
"THIS IS A TEST"
|
56
55
|
end
|
57
56
|
end
|
57
|
+
|
58
|
+
module RequestHandlerTest
|
59
|
+
def handle_request(request, response)
|
60
|
+
"HANDLING REQUESTS"
|
61
|
+
end
|
62
|
+
end
|
58
63
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
ENV['RACK_ENV'] = 'test'
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
class TestEndpointRecorders < MiniTest::Test
|
7
|
+
def setup
|
8
|
+
@recorders = PinchHitter::Service::EndpointRecorders.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_requests
|
12
|
+
request = { body: '{"Hot Rod" : "Williams"}' }
|
13
|
+
@recorders.record('endpoint', request)
|
14
|
+
assert_equal [request], @recorders.requests('endpoint')
|
15
|
+
end
|
16
|
+
end
|
data/test/test_service.rb
CHANGED
@@ -131,4 +131,39 @@ class TestService < MiniTest::Test
|
|
131
131
|
assert_equal user_post, response.first['body']
|
132
132
|
assert response.first['headers']
|
133
133
|
end
|
134
|
+
|
135
|
+
def test_cache_control_defaults_to_nil
|
136
|
+
post "/store", xml_message
|
137
|
+
post "/respond", ''
|
138
|
+
|
139
|
+
assert_nil last_response['Cache-Control']
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_cache_control
|
143
|
+
app.enable :no_cache
|
144
|
+
post "/store", xml_message
|
145
|
+
post "/respond", ''
|
146
|
+
|
147
|
+
assert_equal 'no-cache, no-store', last_response['Cache-Control']
|
148
|
+
app.disable :no_cache
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_request_handler
|
152
|
+
post '/register_module?endpoint=stuff', Marshal.dump(TestRequestHandler)
|
153
|
+
post '/stuff', ''
|
154
|
+
|
155
|
+
assert_received xml_message
|
156
|
+
assert_equal 202, last_response.status
|
157
|
+
assert(last_response.headers.include? "Kyrie")
|
158
|
+
end
|
159
|
+
|
160
|
+
module TestRequestHandler
|
161
|
+
include MessageAssertions
|
162
|
+
def handle_request(request, response)
|
163
|
+
response.status = 202
|
164
|
+
response["Kyrie"] = "Irving"
|
165
|
+
response.body = xml_message.squish
|
166
|
+
response
|
167
|
+
end
|
168
|
+
end
|
134
169
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pinch_hitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Jackson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -158,20 +158,23 @@ files:
|
|
158
158
|
- features/messages/car_rental.xml
|
159
159
|
- features/messages/glossary.json
|
160
160
|
- features/replay.feature
|
161
|
+
- features/response_headers.feature
|
161
162
|
- features/step_definitions/replay_steps.rb
|
163
|
+
- features/step_definitions/response_steps.rb
|
162
164
|
- features/step_definitions/verify_requests_steps.rb
|
163
165
|
- features/support/env.rb
|
164
166
|
- features/support/mock_web_service.rb
|
165
167
|
- features/support/xml_parser.rb
|
166
168
|
- features/verify.feature
|
167
169
|
- lib/pinch_hitter.rb
|
170
|
+
- lib/pinch_hitter/core_ext/nil_class.rb
|
168
171
|
- lib/pinch_hitter/core_ext/string.rb
|
169
172
|
- lib/pinch_hitter/message/content_type.rb
|
170
173
|
- lib/pinch_hitter/message/json.rb
|
171
174
|
- lib/pinch_hitter/message/message_store.rb
|
172
175
|
- lib/pinch_hitter/message/xml.rb
|
173
176
|
- lib/pinch_hitter/service/endpoint_handlers.rb
|
174
|
-
- lib/pinch_hitter/service/
|
177
|
+
- lib/pinch_hitter/service/endpoint_recorders.rb
|
175
178
|
- lib/pinch_hitter/service/message_queue.rb
|
176
179
|
- lib/pinch_hitter/service/replay_ws.rb
|
177
180
|
- lib/pinch_hitter/service/runner.rb
|
@@ -179,7 +182,7 @@ files:
|
|
179
182
|
- pinch_hitter.gemspec
|
180
183
|
- test/message_assertions.rb
|
181
184
|
- test/test_endpoint_handlers.rb
|
182
|
-
- test/
|
185
|
+
- test/test_endpoint_recorders.rb
|
183
186
|
- test/test_json_message.rb
|
184
187
|
- test/test_message.rb
|
185
188
|
- test/test_pinch_hitter.rb
|
@@ -213,7 +216,9 @@ test_files:
|
|
213
216
|
- features/messages/car_rental.xml
|
214
217
|
- features/messages/glossary.json
|
215
218
|
- features/replay.feature
|
219
|
+
- features/response_headers.feature
|
216
220
|
- features/step_definitions/replay_steps.rb
|
221
|
+
- features/step_definitions/response_steps.rb
|
217
222
|
- features/step_definitions/verify_requests_steps.rb
|
218
223
|
- features/support/env.rb
|
219
224
|
- features/support/mock_web_service.rb
|
@@ -221,7 +226,7 @@ test_files:
|
|
221
226
|
- features/verify.feature
|
222
227
|
- test/message_assertions.rb
|
223
228
|
- test/test_endpoint_handlers.rb
|
224
|
-
- test/
|
229
|
+
- test/test_endpoint_recorders.rb
|
225
230
|
- test/test_json_message.rb
|
226
231
|
- test/test_message.rb
|
227
232
|
- test/test_pinch_hitter.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module PinchHitter::Service
|
2
|
-
class EndpointRecorder
|
3
|
-
attr_reader :handler
|
4
|
-
|
5
|
-
def initialize(handler)
|
6
|
-
@handler = handler
|
7
|
-
end
|
8
|
-
|
9
|
-
def store message
|
10
|
-
handler << message if handler.respond_to? :<<
|
11
|
-
end
|
12
|
-
|
13
|
-
def respond_to(request)
|
14
|
-
requests << request if request
|
15
|
-
message = request[:body] if request
|
16
|
-
handler.respond_to message
|
17
|
-
end
|
18
|
-
|
19
|
-
def requests
|
20
|
-
@requests ||= []
|
21
|
-
end
|
22
|
-
|
23
|
-
def reset
|
24
|
-
requests.clear
|
25
|
-
handler.reset if handler.respond_to? :reset
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
ENV['RACK_ENV'] = 'test'
|
2
|
-
|
3
|
-
require 'minitest/autorun'
|
4
|
-
|
5
|
-
class TestEndpointRecorder < MiniTest::Test
|
6
|
-
|
7
|
-
def setup
|
8
|
-
@mock = MiniTest::Mock.new
|
9
|
-
@recorder = PinchHitter::Service::EndpointRecorder.new @mock
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_is_facade_for_handler
|
13
|
-
@mock.expect(:<<, nil, ['blah'])
|
14
|
-
@recorder.store 'blah'
|
15
|
-
@mock.verify
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_is_facade_reset
|
19
|
-
@mock.expect(:reset, nil)
|
20
|
-
@recorder.reset
|
21
|
-
@mock.verify
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_stores_request_if_present
|
25
|
-
@mock.expect(:respond_to, '', [String])
|
26
|
-
@recorder.respond_to({ body: 'request' })
|
27
|
-
assert_equal [{body: 'request'}], @recorder.requests
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_passes_body_to_handler_if_present
|
31
|
-
@mock.expect(:respond_to, '', ['request'])
|
32
|
-
@recorder.respond_to({ body: 'request' })
|
33
|
-
@mock.verify
|
34
|
-
end
|
35
|
-
|
36
|
-
def reset_clears_stored_requests
|
37
|
-
@mock.expect(:respond_to, '', [String])
|
38
|
-
@mock.expect(:reset, nil)
|
39
|
-
@recorder.respond_to({ body: 'request' })
|
40
|
-
@recorder.reset
|
41
|
-
assert_empty @recorder.requests
|
42
|
-
end
|
43
|
-
end
|