pinch_hitter 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|