puffing-billy 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|