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 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