puffing-billy 1.0.0 → 1.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 +5 -5
- data/CHANGELOG.md +7 -0
- data/README.md +78 -3
- data/lib/billy.rb +1 -0
- data/lib/billy/config.rb +2 -1
- data/lib/billy/handlers/request_handler.rb +16 -4
- data/lib/billy/handlers/request_log.rb +36 -0
- data/lib/billy/handlers/stub_handler.rb +4 -4
- data/lib/billy/init/rspec.rb +5 -1
- data/lib/billy/proxy.rb +27 -1
- data/lib/billy/proxy_request_stub.rb +11 -1
- data/lib/billy/version.rb +1 -1
- data/spec/lib/billy/handlers/request_handler_spec.rb +17 -0
- data/spec/lib/billy/handlers/request_log_spec.rb +74 -0
- data/spec/lib/billy/handlers/stub_handler_spec.rb +17 -4
- data/spec/lib/billy/proxy_request_stub_spec.rb +35 -2
- data/spec/lib/proxy_spec.rb +8 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ebc4280168375f52adf8bd5452297a202ea9e7b66821ca7d0641d82215a1fe85
|
4
|
+
data.tar.gz: 947d554aa9a49dac255e88db0968092be0446b975bfcad688609976176bd51c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c64ebf7794856afabaa2445cdf545489f0ba57e2e57785ffa8ff9b51c5081662c070b18f8229f1f6588121b3a3bf2f8496ce730cb9f36a686c748398f40d941
|
7
|
+
data.tar.gz: c6e850c90888de3f027c1c4c333c359ad2f2dbc0ecd2f6466f11c6fa04ace0078e9c5bb63281202c22d114ad0a703a60ed4a41e7ee7bab9c1b8cf3a92b2d7ccb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
v1.1.0, 2018-04-29
|
2
|
+
-------------------
|
3
|
+
* Expose stub instances via puffing billy [#224](https://github.com/oesmith/puffing-billy/pull/224)
|
4
|
+
* Add additional request tracking [#225](https://github.com/oesmith/puffing-billy/pull/225)
|
5
|
+
* Allow request/response interception on stubs [#232](https://github.com/oesmith/puffing-billy/pull/232)
|
6
|
+
* Add after suite stop hook for event machine [#239](https://github.com/oesmith/puffing-billy/pull/239)
|
7
|
+
|
1
8
|
v1.0.0, 2018-03-05
|
2
9
|
-------------------
|
3
10
|
* Add #unstub method, replace deprecated watir-webdriver with watir [#212](https://github.com/oesmith/puffing-billy/pull/212)
|
data/README.md
CHANGED
@@ -103,9 +103,25 @@ proxy.stub('https://example.com:443/secure/').and_return(:text => 'secrets!!1!')
|
|
103
103
|
# params: Query string parameters hash, CGI::escape-style
|
104
104
|
# headers: Headers hash
|
105
105
|
# body: Request body string
|
106
|
-
#
|
107
|
-
|
108
|
-
|
106
|
+
# url: The actual URL which was requested
|
107
|
+
# method: The HTTP verb which was requested
|
108
|
+
proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, body, url, method|
|
109
|
+
{
|
110
|
+
:code => 200,
|
111
|
+
:text => "Hello, #{params['name'][0]}"
|
112
|
+
}
|
113
|
+
})
|
114
|
+
|
115
|
+
# You can also use Puffing Billy to intercept requests and responses. Just pass
|
116
|
+
# a Proc and use the pass_request method. You can manipulate the request
|
117
|
+
# (headers, URL, HTTP method, etc) and also the response from the upstream
|
118
|
+
# server.
|
119
|
+
proxy.stub('http://example.com/').and_return(Proc.new { |*args|
|
120
|
+
response = pass_request(*args)
|
121
|
+
response[:headers]['Content-Type'] = 'text/plain'
|
122
|
+
response[:body] = 'Hello World!'
|
123
|
+
response[:code] = 200
|
124
|
+
response
|
109
125
|
})
|
110
126
|
|
111
127
|
# Stub out a POST. Don't forget to allow a CORS request and set the method to 'post'
|
@@ -269,6 +285,7 @@ Billy.configure do |c|
|
|
269
285
|
c.proxy_port = 12345 # defaults to random
|
270
286
|
c.proxied_request_host = nil
|
271
287
|
c.proxied_request_port = 80
|
288
|
+
c.record_requests = true # defaults to false
|
272
289
|
c.cache_request_body_methods = ['post', 'patch', 'put'] # defaults to ['post']
|
273
290
|
end
|
274
291
|
```
|
@@ -351,6 +368,64 @@ directory/puffing-billy/certs`.
|
|
351
368
|
`c.proxied_request_host` and `c.proxied_request_port` are used if an internal proxy
|
352
369
|
server is required to access the internet. Most common in larger companies.
|
353
370
|
|
371
|
+
`c.record_requests` can be used to record all requests that puffing billy proxied.
|
372
|
+
This can be useful for debugging purposes, for instance if you are unsure why
|
373
|
+
your stubbed requests are not being successfully proxied.
|
374
|
+
|
375
|
+
Example usage:
|
376
|
+
|
377
|
+
```ruby
|
378
|
+
require 'table_print' # Add this dependency to your gemfile
|
379
|
+
|
380
|
+
Billy.configure do |c|
|
381
|
+
c.record_requests = true
|
382
|
+
end
|
383
|
+
|
384
|
+
RSpec.configure do |config|
|
385
|
+
config.prepend_after(:example, type: :feature) do
|
386
|
+
puts "Requests received via Puffing Billy Proxy:"
|
387
|
+
|
388
|
+
puts TablePrint::Printer.table_print(Billy.proxy.requests, [
|
389
|
+
:status,
|
390
|
+
:handler,
|
391
|
+
:method,
|
392
|
+
{ url: { width: 100 } },
|
393
|
+
:headers,
|
394
|
+
:body
|
395
|
+
])
|
396
|
+
end
|
397
|
+
end
|
398
|
+
```
|
399
|
+
|
400
|
+
This will generate a human readable list of all requests after each test run:
|
401
|
+
|
402
|
+
```
|
403
|
+
Requests received via Puffing Billy Proxy:
|
404
|
+
STATUS | HANDLER | METHOD | URL | HEADERS | BODY
|
405
|
+
---------|---------|---------|-----------------------------------------|--------------------------------|-----
|
406
|
+
complete | proxy | GET | http://127.0.0.1:56692/ | {"Accept"=>"text/html,appli... |
|
407
|
+
complete | proxy | GET | http://127.0.0.1:56692/assets/appl... | {"Accept"=>"text/css,*/*;q=... |
|
408
|
+
complete | proxy | GET | http://127.0.0.1:56692/assets/app... | {"Accept"=>"*/*", "Referer"... |
|
409
|
+
complete | proxy | GET | http://127.0.0.1:56692/javascript/index | {"Accept"=>"text/html,appli... |
|
410
|
+
complete | stubs | OPTIONS | https://api.github.com:443/ | {"Access-Control-Request-Me... |
|
411
|
+
complete | stubs | GET | https://api.github.com:443/ | {"Accept"=>"*/*", "Referer"... |
|
412
|
+
inflight | | GET | http://127.0.0.1:56692/example | {"Referer"=>"http://127.0.0... |
|
413
|
+
.
|
414
|
+
|
415
|
+
Finished in 1.98 seconds (files took 2.11 seconds to load)
|
416
|
+
1 example, 0 failures
|
417
|
+
```
|
418
|
+
|
419
|
+
The handler column indicates how Puffing Billy handled your request:
|
420
|
+
|
421
|
+
- proxy: This request was successfully routed to the original target
|
422
|
+
- stubs: This was handled via a stub
|
423
|
+
- error: This request was not handled by a stub, and was not successfully handled
|
424
|
+
- cache: This response was handled by a previous cache
|
425
|
+
|
426
|
+
If your `status` is set to in_flight this request has not yet been handled fully. Either puffing billy crashed
|
427
|
+
internally on this request, or your test ended before it could complete successfully.
|
428
|
+
|
354
429
|
`c.cache_request_body_methods` is used to specify HTTP methods of requests that you would like to cache separately based on the contents of the request body. The default is ['post'].
|
355
430
|
|
356
431
|
`c.after_cache_handles_request` is used to configure a callback that can operate on the response after it has been retrieved from the cache but before it is returned. The callback receives the request and response as arguments, with a request object like: `{ method: method, url: url, headers: headers, body: body }`. An example usage would be manipulating the Access-Control-Allow-Origin header so that your test server doesn't always have to run on the same port in order to accept cached responses to CORS requests:
|
data/lib/billy.rb
CHANGED
@@ -2,6 +2,7 @@ require 'billy/version'
|
|
2
2
|
require 'billy/config'
|
3
3
|
require 'billy/handlers/handler'
|
4
4
|
require 'billy/handlers/request_handler'
|
5
|
+
require 'billy/handlers/request_log'
|
5
6
|
require 'billy/handlers/stub_handler'
|
6
7
|
require 'billy/handlers/proxy_handler'
|
7
8
|
require 'billy/handlers/cache_handler'
|
data/lib/billy/config.rb
CHANGED
@@ -11,7 +11,7 @@ module Billy
|
|
11
11
|
:non_whitelisted_requests_disabled, :cache_path, :certs_path, :proxy_host, :proxy_port, :proxied_request_inactivity_timeout,
|
12
12
|
:proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys, :dynamic_jsonp_callback_name, :merge_cached_responses_whitelist,
|
13
13
|
:strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods, :after_cache_handles_request,
|
14
|
-
:cache_simulates_network_delays, :cache_simulates_network_delay_time, :record_stub_requests, :use_ignore_params
|
14
|
+
:cache_simulates_network_delays, :cache_simulates_network_delay_time, :record_requests, :record_stub_requests, :use_ignore_params
|
15
15
|
|
16
16
|
def initialize
|
17
17
|
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
@@ -47,6 +47,7 @@ module Billy
|
|
47
47
|
@after_cache_handles_request = nil
|
48
48
|
@cache_simulates_network_delays = false
|
49
49
|
@cache_simulates_network_delay_time = 0.1
|
50
|
+
@record_requests = false
|
50
51
|
@record_stub_requests = false
|
51
52
|
@use_ignore_params = true
|
52
53
|
end
|
@@ -6,6 +6,7 @@ module Billy
|
|
6
6
|
include Handler
|
7
7
|
|
8
8
|
def_delegators :stub_handler, :stub, :unstub
|
9
|
+
def_delegators :request_log, :requests
|
9
10
|
|
10
11
|
def handlers
|
11
12
|
@handlers ||= { stubs: StubHandler.new,
|
@@ -14,33 +15,44 @@ module Billy
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def handle_request(method, url, headers, body)
|
18
|
+
request = request_log.record(method, url, headers, body)
|
19
|
+
|
17
20
|
# Process the handlers by order of importance
|
18
21
|
[:stubs, :cache, :proxy].each do |key|
|
19
22
|
if (response = handlers[key].handle_request(method, url, headers, body))
|
23
|
+
@request_log.complete(request, key)
|
20
24
|
return response
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
28
|
body_msg = Billy.config.cache_request_body_methods.include?(method) ? " with body '#{body}'" : ''
|
29
|
+
request_log.complete(request, :error)
|
25
30
|
{ error: "Connection to #{url}#{body_msg} not cached and new http connections are disabled" }
|
26
31
|
rescue => error
|
27
32
|
{ error: error.message }
|
28
33
|
end
|
29
34
|
|
30
35
|
def handles_request?(method, url, headers, body)
|
31
|
-
[:stubs, :cache, :proxy].
|
32
|
-
|
36
|
+
[:stubs, :cache, :proxy].any? do |key|
|
37
|
+
handlers[key].handles_request?(method, url, headers, body)
|
33
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def request_log
|
42
|
+
@request_log ||= RequestLog.new
|
43
|
+
end
|
34
44
|
|
35
|
-
|
45
|
+
def stubs
|
46
|
+
stub_handler.stubs
|
36
47
|
end
|
37
48
|
|
38
49
|
def reset
|
39
50
|
handlers.each_value(&:reset)
|
51
|
+
request_log.reset
|
40
52
|
end
|
41
53
|
|
42
54
|
def reset_stubs
|
43
|
-
|
55
|
+
stub_handler.reset
|
44
56
|
end
|
45
57
|
|
46
58
|
def reset_cache
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Billy
|
2
|
+
class RequestLog
|
3
|
+
attr_reader :requests
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@requests = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def reset
|
10
|
+
@requests = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def record(method, url, headers, body)
|
14
|
+
return unless Billy.config.record_requests
|
15
|
+
|
16
|
+
request = {
|
17
|
+
status: :inflight,
|
18
|
+
handler: nil,
|
19
|
+
method: method,
|
20
|
+
url: url,
|
21
|
+
headers: headers,
|
22
|
+
body: body
|
23
|
+
}
|
24
|
+
@requests.push(request)
|
25
|
+
|
26
|
+
request
|
27
|
+
end
|
28
|
+
|
29
|
+
def complete(request, handler)
|
30
|
+
return unless Billy.config.record_requests
|
31
|
+
|
32
|
+
request.merge! status: :complete,
|
33
|
+
handler: handler
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -38,14 +38,14 @@ module Billy
|
|
38
38
|
stubs.delete stub
|
39
39
|
end
|
40
40
|
|
41
|
-
private
|
42
|
-
|
43
|
-
attr_writer :stubs
|
44
|
-
|
45
41
|
def stubs
|
46
42
|
@stubs ||= []
|
47
43
|
end
|
48
44
|
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_writer :stubs
|
48
|
+
|
49
49
|
def find_stub(method, url)
|
50
50
|
stubs.find { |stub| stub.matches?(method, url) }
|
51
51
|
end
|
data/lib/billy/init/rspec.rb
CHANGED
data/lib/billy/proxy.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
require 'eventmachine'
|
3
|
+
require 'timeout'
|
3
4
|
|
4
5
|
module Billy
|
5
6
|
class Proxy
|
6
7
|
extend Forwardable
|
7
8
|
attr_reader :request_handler
|
8
9
|
|
9
|
-
def_delegators :request_handler, :stub, :unstub, :reset, :reset_cache, :restore_cache, :handle_request
|
10
|
+
def_delegators :request_handler, :stub, :stubs, :unstub, :reset, :reset_cache, :restore_cache, :requests, :handle_request
|
10
11
|
|
11
12
|
def initialize
|
12
13
|
@request_handler = Billy::RequestHandler.new
|
@@ -22,6 +23,14 @@ module Billy
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
def stop
|
27
|
+
return if @signature.nil?
|
28
|
+
|
29
|
+
server_port = port
|
30
|
+
EM.stop
|
31
|
+
wait_for_server_shutdown! server_port
|
32
|
+
end
|
33
|
+
|
25
34
|
def url
|
26
35
|
"http://#{host}:#{port}"
|
27
36
|
end
|
@@ -40,6 +49,23 @@ module Billy
|
|
40
49
|
|
41
50
|
protected
|
42
51
|
|
52
|
+
def wait_for_server_shutdown!(server_port)
|
53
|
+
Timeout::timeout(60) do
|
54
|
+
sleep(0.01) while port_in_use? server_port
|
55
|
+
end
|
56
|
+
rescue Timeout::Error
|
57
|
+
Billy.log(:error, "puffing-billy: Event machine not shutdown correctly on port #{port}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def port_in_use?(port)
|
61
|
+
s = TCPSocket.new(host, port)
|
62
|
+
s.close
|
63
|
+
Billy.log(:info, "puffing-billy: Waiting for event machine to shutdown on port #{port}")
|
64
|
+
s
|
65
|
+
rescue Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
43
69
|
def main_loop
|
44
70
|
EM.run do
|
45
71
|
EM.error_handler do |e|
|
@@ -21,7 +21,7 @@ module Billy
|
|
21
21
|
push_request(method, url, params, headers, body)
|
22
22
|
|
23
23
|
if @response.respond_to?(:call)
|
24
|
-
res =
|
24
|
+
res = instance_exec(params, headers, body, url, method, &@response)
|
25
25
|
else
|
26
26
|
res = @response
|
27
27
|
end
|
@@ -71,6 +71,16 @@ module Billy
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def pass_request(params, headers, body, url, method)
|
75
|
+
handler = Billy.proxy.request_handler.handlers[:proxy]
|
76
|
+
response = handler.handle_request(method, url, headers, body)
|
77
|
+
{
|
78
|
+
code: response[:status],
|
79
|
+
body: response[:content],
|
80
|
+
headers: response[:headers]
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
74
84
|
private
|
75
85
|
|
76
86
|
attr_writer :requests
|
data/lib/billy/version.rb
CHANGED
@@ -69,11 +69,16 @@ describe Billy::RequestHandler do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
describe '#handle_request' do
|
72
|
+
before do
|
73
|
+
allow(Billy::config).to receive(:record_requests).and_return(true)
|
74
|
+
end
|
75
|
+
|
72
76
|
it 'returns stubbed responses' do
|
73
77
|
expect(stub_handler).to receive(:handle_request).with(*args).and_return('foo')
|
74
78
|
expect(cache_handler).to_not receive(:handle_request)
|
75
79
|
expect(proxy_handler).to_not receive(:handle_request)
|
76
80
|
expect(subject.handle_request(*args)).to eql 'foo'
|
81
|
+
expect(subject.requests).to eql([{status: :complete, handler: :stubs, method: 'get', url: 'url', headers: 'headers', body: 'body'}])
|
77
82
|
end
|
78
83
|
|
79
84
|
it 'returns cached responses' do
|
@@ -81,6 +86,7 @@ describe Billy::RequestHandler do
|
|
81
86
|
expect(cache_handler).to receive(:handle_request).with(*args).and_return('bar')
|
82
87
|
expect(proxy_handler).to_not receive(:handle_request)
|
83
88
|
expect(subject.handle_request(*args)).to eql 'bar'
|
89
|
+
expect(subject.requests).to eql([{status: :complete, handler: :cache, method: 'get', url: 'url', headers: 'headers', body: 'body'}])
|
84
90
|
end
|
85
91
|
|
86
92
|
it 'returns proxied responses' do
|
@@ -88,6 +94,7 @@ describe Billy::RequestHandler do
|
|
88
94
|
expect(cache_handler).to receive(:handle_request).with(*args)
|
89
95
|
expect(proxy_handler).to receive(:handle_request).with(*args).and_return('baz')
|
90
96
|
expect(subject.handle_request(*args)).to eql 'baz'
|
97
|
+
expect(subject.requests).to eql([{status: :complete, handler: :proxy, method: 'get', url: 'url', headers: 'headers', body: 'body'}])
|
91
98
|
end
|
92
99
|
|
93
100
|
it 'returns an error hash if request is not handled' do
|
@@ -95,6 +102,7 @@ describe Billy::RequestHandler do
|
|
95
102
|
expect(cache_handler).to receive(:handle_request).with(*args)
|
96
103
|
expect(proxy_handler).to receive(:handle_request).with(*args)
|
97
104
|
expect(subject.handle_request(*args)).to eql(error: 'Connection to url not cached and new http connections are disabled')
|
105
|
+
expect(subject.requests).to eql([{status: :complete, handler: :error, method: 'get', url: 'url', headers: 'headers', body: 'body'}])
|
98
106
|
end
|
99
107
|
|
100
108
|
it 'returns an error hash with body message if request cached based on body is not handled' do
|
@@ -103,6 +111,7 @@ describe Billy::RequestHandler do
|
|
103
111
|
expect(cache_handler).to receive(:handle_request).with(*args)
|
104
112
|
expect(proxy_handler).to receive(:handle_request).with(*args)
|
105
113
|
expect(subject.handle_request(*args)).to eql(error: "Connection to url with body 'body' not cached and new http connections are disabled")
|
114
|
+
expect(subject.requests).to eql([{status: :complete, handler: :error, method: 'post', url: 'url', headers: 'headers', body: 'body'}])
|
106
115
|
end
|
107
116
|
|
108
117
|
it 'returns an error hash on unhandled exceptions' do
|
@@ -121,6 +130,13 @@ describe Billy::RequestHandler do
|
|
121
130
|
end
|
122
131
|
end
|
123
132
|
|
133
|
+
describe '#stubs' do
|
134
|
+
it 'delegates to the stub_handler' do
|
135
|
+
expect(stub_handler).to receive(:stubs)
|
136
|
+
subject.stubs
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
124
140
|
describe '#stub' do
|
125
141
|
it 'delegates to the stub_handler' do
|
126
142
|
expect(stub_handler).to receive(:stub).with('some args')
|
@@ -133,6 +149,7 @@ describe Billy::RequestHandler do
|
|
133
149
|
handlers.each do |_key, handler|
|
134
150
|
expect(handler).to receive(:reset)
|
135
151
|
end
|
152
|
+
expect(subject.request_log).to receive(:reset)
|
136
153
|
subject.reset
|
137
154
|
end
|
138
155
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Billy::RequestLog do
|
4
|
+
let(:request_log) { Billy::RequestLog.new }
|
5
|
+
|
6
|
+
describe '#record' do
|
7
|
+
it 'returns the request details if record_requests is enabled' do
|
8
|
+
allow(Billy::config).to receive(:record_requests).and_return(true)
|
9
|
+
expected_request = {
|
10
|
+
status: :inflight,
|
11
|
+
handler: nil,
|
12
|
+
method: :method,
|
13
|
+
url: :url,
|
14
|
+
headers: :headers,
|
15
|
+
body: :body
|
16
|
+
}
|
17
|
+
expect(request_log.record(:method, :url, :headers, :body)).to eql(expected_request)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns nil if record_requests is disabled' do
|
21
|
+
allow(Billy::config).to receive(:record_requests).and_return(false)
|
22
|
+
expect(request_log.record(:method, :url, :headers, :body)).to be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#complete' do
|
27
|
+
it 'marks the request as complete if record_requests is enabled' do
|
28
|
+
allow(Billy::config).to receive(:record_requests).and_return(true)
|
29
|
+
|
30
|
+
request = request_log.record(:method, :url, :headers, :body)
|
31
|
+
expected_request = {
|
32
|
+
status: :complete,
|
33
|
+
handler: :handler,
|
34
|
+
method: :method,
|
35
|
+
url: :url,
|
36
|
+
headers: :headers,
|
37
|
+
body: :body
|
38
|
+
}
|
39
|
+
expect(request_log.complete(request, :handler)).to eql(expected_request)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'marks the request as complete if record_requests is disabled' do
|
43
|
+
allow(Billy::config).to receive(:record_requests).and_return(false)
|
44
|
+
expect(request_log.complete(nil, :handler)).to be_nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#requests' do
|
49
|
+
it 'returns an empty array when there are no requests' do
|
50
|
+
expect(request_log.requests).to be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns the currently known requests' do
|
54
|
+
allow(Billy::config).to receive(:record_requests).and_return(true)
|
55
|
+
|
56
|
+
request1 = request_log.record(:method, :url, :headers, :body)
|
57
|
+
request2 = request_log.record(:method, :url, :headers, :body)
|
58
|
+
expect(request_log.requests).to eql([request1, request2])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#reset' do
|
63
|
+
it 'resets known requests' do
|
64
|
+
allow(Billy::config).to receive(:record_requests).and_return(true)
|
65
|
+
|
66
|
+
request1 = request_log.record(:method, :url, :headers, :body)
|
67
|
+
request2 = request_log.record(:method, :url, :headers, :body)
|
68
|
+
expect(request_log.requests).to eql([request1, request2])
|
69
|
+
|
70
|
+
request_log.reset
|
71
|
+
expect(request_log.requests).to be_empty
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -44,18 +44,18 @@ describe Billy::StubHandler do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe '#reset' do
|
47
|
-
|
47
|
+
it 'resets the stubs' do
|
48
48
|
# Can't use request params when creating the stub.
|
49
49
|
# See https://github.com/oesmith/puffing-billy/issues/21
|
50
|
-
handler.stub('http://example.test:8080/index')
|
51
|
-
end
|
50
|
+
stub = handler.stub('http://example.test:8080/index')
|
52
51
|
|
53
|
-
|
52
|
+
expect(handler.stubs).to eql([stub])
|
54
53
|
expect(handler.handles_request?('GET',
|
55
54
|
request[:url],
|
56
55
|
request[:headers],
|
57
56
|
request[:body])).to be true
|
58
57
|
handler.reset
|
58
|
+
expect(handler.stubs).to be_empty
|
59
59
|
expect(handler.handles_request?('GET',
|
60
60
|
request[:url],
|
61
61
|
request[:headers],
|
@@ -101,4 +101,17 @@ describe Billy::StubHandler do
|
|
101
101
|
request[:headers],
|
102
102
|
request[:body])).to be true
|
103
103
|
end
|
104
|
+
|
105
|
+
describe '#stubs' do
|
106
|
+
it 'is empty by default' do
|
107
|
+
expect(handler.stubs).to be_empty
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'keeps track of created stubs' do
|
111
|
+
stub1 = handler.stub('http://example.test:8080/index')
|
112
|
+
stub2 = handler.stub('http://example.test:8080/index')
|
113
|
+
|
114
|
+
expect(handler.stubs).to eql([stub2, stub1])
|
115
|
+
end
|
116
|
+
end
|
104
117
|
end
|
@@ -157,18 +157,51 @@ describe Billy::ProxyRequestStub do
|
|
157
157
|
expected_headers = { 'header1' => 'three', 'header2' => 'four' }
|
158
158
|
expected_body = 'body text'
|
159
159
|
|
160
|
-
|
160
|
+
# Required due to the instance_exec implementation
|
161
|
+
subject.extend(RSpec::Matchers)
|
162
|
+
|
163
|
+
subject.and_return(proc do |params, headers, body, url, method|
|
161
164
|
expect(params).to eql expected_params
|
162
165
|
expect(headers).to eql expected_headers
|
163
166
|
expect(body).to eql 'body text'
|
167
|
+
expect(url).to eql 'url'
|
168
|
+
expect(method).to eql 'GET'
|
164
169
|
{ code: 418, text: 'success' }
|
165
170
|
end)
|
166
|
-
expect(subject.call('', '', expected_params, expected_headers, expected_body)).to eql [
|
171
|
+
expect(subject.call('GET', 'url', expected_params, expected_headers, expected_body)).to eql [
|
167
172
|
418,
|
168
173
|
{ 'Content-Type' => 'text/plain' },
|
169
174
|
'success'
|
170
175
|
]
|
171
176
|
end
|
177
|
+
|
178
|
+
it 'should use a callable with pass_request' do
|
179
|
+
# Add the missing em-synchrony call which is done by
|
180
|
+
# ProxyConnection#handle_request instead.
|
181
|
+
EM.synchrony do
|
182
|
+
# Required due to the instance_exec implementation
|
183
|
+
subject.extend(RSpec::Matchers)
|
184
|
+
|
185
|
+
subject.and_return(proc do |*args|
|
186
|
+
response = pass_request(*args)
|
187
|
+
response[:body] = 'modified'
|
188
|
+
response[:code] = 205
|
189
|
+
response
|
190
|
+
end)
|
191
|
+
|
192
|
+
# The test server can't be used at this scenario due to the limitations
|
193
|
+
# of the Ruby GIL. We cannot use fibers (via eventmachine) and ask
|
194
|
+
# ourself on a different thread to serve a HTTP request. This results
|
195
|
+
# in +fiber called across threads (FiberError)+ errors. Unfortunately
|
196
|
+
# we have to ask an external resource.
|
197
|
+
url = 'http://google.com'
|
198
|
+
|
199
|
+
expect(subject.call('GET', url, {}, {}, 'original')).to eql [
|
200
|
+
205,
|
201
|
+
'modified'
|
202
|
+
]
|
203
|
+
end
|
204
|
+
end
|
172
205
|
end
|
173
206
|
|
174
207
|
context '#stub_requests' do
|
data/spec/lib/proxy_spec.rb
CHANGED
@@ -69,6 +69,14 @@ shared_examples_for 'a request stub' do
|
|
69
69
|
.and_return(text: 'hello, OPTIONS!')
|
70
70
|
expect(http.run_request(:options, '/bim', nil, nil).body).to eql 'hello, OPTIONS!'
|
71
71
|
end
|
72
|
+
|
73
|
+
it 'should expose the currently registered stubs' do
|
74
|
+
stub1 = proxy.stub("#{url}/foo", method: :options)
|
75
|
+
.and_return(text: 'hello, OPTIONS!')
|
76
|
+
stub2 = proxy.stub("#{url}/bar", method: :options)
|
77
|
+
.and_return(text: 'hello, OPTIONS!')
|
78
|
+
expect(proxy.stubs).to eql([stub2, stub1])
|
79
|
+
end
|
72
80
|
end
|
73
81
|
|
74
82
|
shared_examples_for 'a cache' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puffing-billy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Olly Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -334,6 +334,7 @@ files:
|
|
334
334
|
- lib/billy/handlers/handler.rb
|
335
335
|
- lib/billy/handlers/proxy_handler.rb
|
336
336
|
- lib/billy/handlers/request_handler.rb
|
337
|
+
- lib/billy/handlers/request_log.rb
|
337
338
|
- lib/billy/handlers/stub_handler.rb
|
338
339
|
- lib/billy/init/cucumber.rb
|
339
340
|
- lib/billy/init/rspec.rb
|
@@ -365,6 +366,7 @@ files:
|
|
365
366
|
- spec/lib/billy/handlers/handler_spec.rb
|
366
367
|
- spec/lib/billy/handlers/proxy_handler_spec.rb
|
367
368
|
- spec/lib/billy/handlers/request_handler_spec.rb
|
369
|
+
- spec/lib/billy/handlers/request_log_spec.rb
|
368
370
|
- spec/lib/billy/handlers/stub_handler_spec.rb
|
369
371
|
- spec/lib/billy/proxy_connection_spec.rb
|
370
372
|
- spec/lib/billy/proxy_request_stub_spec.rb
|
@@ -395,7 +397,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
395
397
|
version: '0'
|
396
398
|
requirements: []
|
397
399
|
rubyforge_project:
|
398
|
-
rubygems_version: 2.
|
400
|
+
rubygems_version: 2.7.3
|
399
401
|
signing_key:
|
400
402
|
specification_version: 4
|
401
403
|
summary: Easy request stubs for browser tests.
|
@@ -410,6 +412,7 @@ test_files:
|
|
410
412
|
- spec/lib/billy/handlers/handler_spec.rb
|
411
413
|
- spec/lib/billy/handlers/proxy_handler_spec.rb
|
412
414
|
- spec/lib/billy/handlers/request_handler_spec.rb
|
415
|
+
- spec/lib/billy/handlers/request_log_spec.rb
|
413
416
|
- spec/lib/billy/handlers/stub_handler_spec.rb
|
414
417
|
- spec/lib/billy/proxy_connection_spec.rb
|
415
418
|
- spec/lib/billy/proxy_request_stub_spec.rb
|