diff --git a/README.md b/README.md index 2688c30..40710f6 100644 --- a/README.md +++ b/README.md @@ -115,9 +115,10 @@ proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, # You can also use Puffing Billy to intercept requests and responses. Just pass # a Proc and use the pass_request method. You can manipulate the request # (headers, URL, HTTP method, etc) and also the response from the upstream -# server. +# server. The scope of the delivered callable is the user scope where +# it was defined. proxy.stub('http://example.com/').and_return(Proc.new { |*args| - response = pass_request(*args) + response = Billy.pass_request(*args) response[:headers]['Content-Type'] = 'text/plain' response[:body] = 'Hello World!' response[:code] = 200 diff --git a/lib/billy.rb b/lib/billy.rb index d37b76c..839829a 100644 --- a/lib/billy.rb +++ b/lib/billy.rb @@ -28,4 +28,18 @@ def self.proxy def self.certificate_authority @certificate_authority ||= Billy::Authority.new end + + # This global shortcut can be used inside of request stubs. You can modify + # the request beforehand and/or modify the actual response which is passed + # back by this method. But you can also implement a custom proxy passing + # method if you like to. This is just a shortcut. + def self.pass_request(params, headers, body, url, method) + handler = proxy.request_handler.handlers[:proxy] + response = handler.handle_request(method, url, headers, body) + { + code: response[:status], + body: response[:content], + headers: response[:headers] + } + end end diff --git a/lib/billy/proxy_request_stub.rb b/lib/billy/proxy_request_stub.rb index d98cd22..feb93f2 100644 --- a/lib/billy/proxy_request_stub.rb +++ b/lib/billy/proxy_request_stub.rb @@ -21,7 +21,7 @@ def call(method, url, params, headers, body) push_request(method, url, params, headers, body) if @response.respond_to?(:call) - res = instance_exec(params, headers, body, url, method, &@response) + res = @response.call(params, headers, body, url, method) else res = @response end @@ -71,16 +71,6 @@ def matches?(method, url) end end - def pass_request(params, headers, body, url, method) - handler = Billy.proxy.request_handler.handlers[:proxy] - response = handler.handle_request(method, url, headers, body) - { - code: response[:status], - body: response[:content], - headers: response[:headers] - } - end - private attr_writer :requests diff --git a/spec/features/examples/tumblr_api_spec.rb b/spec/features/examples/tumblr_api_spec.rb index cb2d117..054024e 100644 --- a/spec/features/examples/tumblr_api_spec.rb +++ b/spec/features/examples/tumblr_api_spec.rb @@ -1,24 +1,6 @@ require 'spec_helper' -describe 'Tumblr API example', type: :feature, js: true do - before do - proxy.stub('http://blog.howmanyleft.co.uk/api/read/json').and_return( - jsonp: { - posts: [ - { - 'regular-title' => 'News Item 1', - 'url-with-slug' => 'http://example.com/news/1', - 'regular-body' => 'News item 1 content here' - }, - { - 'regular-title' => 'News Item 2', - 'url-with-slug' => 'http://example.com/news/2', - 'regular-body' => 'News item 2 content here' - } - ] - }) - end - +RSpec.shared_examples 'tumblr/expectations' do it 'should show news stories' do visit '/tumblr_api.html' expect(page).to have_link('News Item 1', href: 'http://example.com/news/1') @@ -27,3 +9,51 @@ expect(page).to have_content('News item 2 content here') end end + +describe 'Tumblr API example', type: :feature, js: true do + context 'without scope external references' do + before do + proxy.stub('http://blog.howmanyleft.co.uk/api/read/json').and_return( + jsonp: { + posts: [ + { + 'regular-title' => 'News Item 1', + 'url-with-slug' => 'http://example.com/news/1', + 'regular-body' => 'News item 1 content here' + }, + { + 'regular-title' => 'News Item 2', + 'url-with-slug' => 'http://example.com/news/2', + 'regular-body' => 'News item 2 content here' + } + ] + }) + end + + include_examples 'tumblr/expectations' + end + + context 'with scope external references' do + let(:posts) do + [ + { + 'regular-title' => 'News Item 1', + 'url-with-slug' => 'http://example.com/news/1', + 'regular-body' => 'News item 1 content here' + }, + { + 'regular-title' => 'News Item 2', + 'url-with-slug' => 'http://example.com/news/2', + 'regular-body' => 'News item 2 content here' + } + ] + end + + before do + proxy.stub('http://blog.howmanyleft.co.uk/api/read/json') + .and_return(proc { { jsonp: { posts: posts } } }) + end + + include_examples 'tumblr/expectations' + end +end diff --git a/spec/lib/billy/proxy_request_stub_spec.rb b/spec/lib/billy/proxy_request_stub_spec.rb index 7a52348..bcb24ff 100644 --- a/spec/lib/billy/proxy_request_stub_spec.rb +++ b/spec/lib/billy/proxy_request_stub_spec.rb @@ -157,9 +157,6 @@ expected_headers = { 'header1' => 'three', 'header2' => 'four' } expected_body = 'body text' - # Required due to the instance_exec implementation - subject.extend(RSpec::Matchers) - subject.and_return(proc do |params, headers, body, url, method| expect(params).to eql expected_params expect(headers).to eql expected_headers @@ -175,15 +172,12 @@ ] end - it 'should use a callable with pass_request' do + it 'should use a callable with Billy.pass_request' do # Add the missing em-synchrony call which is done by # ProxyConnection#handle_request instead. EM.synchrony do - # Required due to the instance_exec implementation - subject.extend(RSpec::Matchers) - subject.and_return(proc do |*args| - response = pass_request(*args) + response = Billy.pass_request(*args) response[:body] = 'modified' response[:code] = 205 response