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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9dcfc87385c54e63251237553f7ceb2f71d072dc
4
- data.tar.gz: e2eb85158a087358686d7501d86809768dd838cc
2
+ SHA256:
3
+ metadata.gz: ebc4280168375f52adf8bd5452297a202ea9e7b66821ca7d0641d82215a1fe85
4
+ data.tar.gz: 947d554aa9a49dac255e88db0968092be0446b975bfcad688609976176bd51c0
5
5
  SHA512:
6
- metadata.gz: 445dc2a1115c10d077561903dbcd58e418eb01c810542bf6c7d2256d1653afdf0ff0e41d0bd9e077f2d525999a2759b5e22f70ae7b04657720a5c0f69e685123
7
- data.tar.gz: ce5f7ee19a3c7fdad6c60fbe6b8c5fd28b43c4219e4d039d93ae3b90c444d2285df27f447fb77eed61fa835b894de1ac247bdc65642d6222d2e4b2f31bd9eba9
6
+ metadata.gz: 9c64ebf7794856afabaa2445cdf545489f0ba57e2e57785ffa8ff9b51c5081662c070b18f8229f1f6588121b3a3bf2f8496ce730cb9f36a686c748398f40d941
7
+ data.tar.gz: c6e850c90888de3f027c1c4c333c359ad2f2dbc0ecd2f6466f11c6fa04ace0078e9c5bb63281202c22d114ad0a703a60ed4a41e7ee7bab9c1b8cf3a92b2d7ccb
@@ -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
- proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, body|
108
- { :text => "Hello, #{params['name'][0]}"}
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:
@@ -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'
@@ -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].each do |key|
32
- return true if handlers[key].handles_request?(method, url, headers, body)
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
- false
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
- handlers[:stubs].reset
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
@@ -9,7 +9,11 @@ end
9
9
  RSpec.configure do |config|
10
10
  config.include(Billy::RspecHelper)
11
11
 
12
- config.prepend_after(:each) do
12
+ config.append_after(:each) do
13
13
  proxy.reset
14
14
  end
15
+
16
+ config.after(:suite) do
17
+ Billy.proxy.stop
18
+ end
15
19
  end
@@ -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 = @response.call(params, headers, body)
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
@@ -1,3 +1,3 @@
1
1
  module Billy
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -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
- before do
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
- it 'resets the stubs' do
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
- subject.and_return(proc do |params, headers, body|
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
@@ -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.0.0
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-03-06 00:00:00.000000000 Z
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.5.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