puffing-billy 0.7.0 → 0.8.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
2
  SHA1:
3
- metadata.gz: 3655cba82676b1deab3539e52a0905e2235fd121
4
- data.tar.gz: 1b4fac47e1c38eed0c59038924ae10218bc753d0
3
+ metadata.gz: ab6b245ca1fa1295379ac58fcc023b9ae2d4be4b
4
+ data.tar.gz: d2ed68617bba9beca40b228fbfb116bed58f8641
5
5
  SHA512:
6
- metadata.gz: 161f4b1ac60dd9f946a60f78b2abe69f16c7fdf7cfe3a4e3e8599c495de9c32b2825c5b0f7beb3df644a2bde58694b77c6b1058d83eb9db49d067d547e5590e8
7
- data.tar.gz: 683a32965991b618db46c6943ccd535b9f92a11df8fc5da8dce371b1e4f8b58df4d581c54919047c347adf85f5c61ec4a48becd40597234fcd774d1c3199d814
6
+ metadata.gz: 7d4919dba7d0619860e035edf00580479228b3de38da97185b21356ba077f39c42add963de90f1521f30933e08f20c0e3494de359c892bb3b1e5fa1029bca704
7
+ data.tar.gz: dc18d1801cf9bb821a7fefa6f093cfdfe748f8ea500058f2d60f59e422c78c5135114bacf7f110acf9001c8ea0495e0899311e364d2cea7f84bf6110814db7b6
@@ -1,3 +1,9 @@
1
+ v0.8.0, 2016-06-02
2
+ ------------------
3
+ * Add optional after_cache_handles_request callback for manipulating cached responses [#149](https://github.com/oesmith/puffing-billy/pull/149)
4
+ * Remove rspec-expectations deprecation warning for README example [#153](https://github.com/oesmith/puffing-billy/pull/153)
5
+ * Make stub requests accessible [#154](https://github.com/oesmith/puffing-billy/pull/154)
6
+
1
7
  v0.7.0, 2016-05-05
2
8
  ------------------
3
9
  * Change WebKit driver to ignore SSL errors [#140](https://github.com/oesmith/puffing-billy/pull/140)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- puffing-billy (0.7.0)
4
+ puffing-billy (0.8.0)
5
5
  addressable
6
6
  em-http-request (~> 1.1.0)
7
7
  em-synchrony
data/README.md CHANGED
@@ -23,7 +23,7 @@ you can test it!
23
23
  it 'should stub google' do
24
24
  proxy.stub('http://www.google.com/').and_return(:text => "I'm not Google!")
25
25
  visit 'http://www.google.com/'
26
- page.should have_content("I'm not Google!")
26
+ expect(page).to have_content("I'm not Google!")
27
27
  end
28
28
  ```
29
29
 
@@ -145,7 +145,7 @@ end
145
145
  And /^a stub for google$/ do
146
146
  proxy.stub('http://www.google.com/').and_return(:text => "I'm not Google!")
147
147
  visit 'http://www.google.com/'
148
- page.should have_content("I'm not Google!")
148
+ expect(page).to have_content("I'm not Google!")
149
149
  end
150
150
  ```
151
151
 
@@ -284,6 +284,25 @@ server is required to access the internet. Most common in larger companies.
284
284
 
285
285
  `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'].
286
286
 
287
+ `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:
288
+
289
+ ```
290
+ Billy.configure do |c|
291
+ ...
292
+ fix_cors_header = proc do |_request, response|
293
+ allowed_origins = response[:headers]['Access-Control-Allow-Origin']
294
+ if allowed_origins.present?
295
+ localhost_port_pattern = %r{(?<=http://127\.0\.0\.1:)(\d+)}
296
+ allowed_origins.sub!(
297
+ localhost_port_pattern, Capybara.current_session.server.port.to_s
298
+ )
299
+ end
300
+ end
301
+ c.after_cache_handles_request = fix_cors_header
302
+ ...
303
+ end
304
+ ```
305
+
287
306
  ### Cache Scopes
288
307
 
289
308
  If you need to cache different responses to the same HTTP request, you can use
@@ -346,6 +365,27 @@ RSpec.configure do |config|
346
365
  end
347
366
  ```
348
367
 
368
+ ## Stub requests recording
369
+
370
+ If you want to record requests to stubbed URIs, set the following configuration option:
371
+
372
+ ```ruby
373
+ Billy.configure do |c|
374
+ c.record_stub_requests = true
375
+ end
376
+ ```
377
+
378
+ Example usage:
379
+
380
+ ```ruby
381
+ it 'should intercept a GET request' do
382
+ stub = proxy.stub('http://example.com/')
383
+ visit 'http://example.com/'
384
+ expect(stub.has_requests?).to be true
385
+ expect(stub.requests).not_to be_empty
386
+ end
387
+ ```
388
+
349
389
  ## Proxy timeouts
350
390
 
351
391
  By default, the Puffing Billy proxy will use the EventMachine:HttpRequest timeouts of 5 seconds
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <body>
3
+ <h1>Intercept request example</h1>
4
+ <script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.min.js'></script>
5
+ <script type='text/javascript'>
6
+ $(function () {
7
+ $.post('http://example.com/', { foo: 'bar' });
8
+ })
9
+ </script>
10
+ </body>
@@ -10,7 +10,8 @@ module Billy
10
10
  :persist_cache, :ignore_cache_port, :non_successful_cache_disabled, :non_successful_error_level,
11
11
  :non_whitelisted_requests_disabled, :cache_path, :proxy_host, :proxy_port, :proxied_request_inactivity_timeout,
12
12
  :proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys, :merge_cached_responses_whitelist,
13
- :strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods
13
+ :strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods, :after_cache_handles_request,
14
+ :record_stub_requests
14
15
 
15
16
  def initialize
16
17
  @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
@@ -40,6 +41,8 @@ module Billy
40
41
  @proxied_request_host = nil
41
42
  @proxied_request_port = 80
42
43
  @cache_request_body_methods = ['post']
44
+ @after_cache_handles_request = nil
45
+ @record_stub_requests = false
43
46
  end
44
47
  end
45
48
 
@@ -25,6 +25,11 @@ module Billy
25
25
  replace_response_callback(response, url)
26
26
  end
27
27
 
28
+ if Billy.config.after_cache_handles_request
29
+ request = { method: method, url: url, headers: headers, body: body }
30
+ Billy.config.after_cache_handles_request.call(request, response)
31
+ end
32
+
28
33
  return response
29
34
  end
30
35
  end
@@ -10,7 +10,7 @@ module Billy
10
10
  if (stub = find_stub(method, url))
11
11
  query_string = Addressable::URI.parse(url).query || ''
12
12
  params = CGI.parse(query_string)
13
- stub.call(params, headers, body).tap do |response|
13
+ stub.call(method, url, params, headers, body).tap do |response|
14
14
  Billy.log(:info, "puffing-billy: STUB #{method} for '#{url}'")
15
15
  return { status: response[0], headers: response[1], content: response[2] }
16
16
  end
@@ -2,10 +2,13 @@ require 'multi_json'
2
2
 
3
3
  module Billy
4
4
  class ProxyRequestStub
5
+ attr_reader :requests
6
+
5
7
  def initialize(url, options = {})
6
8
  @options = { method: :get }.merge(options)
7
9
  @method = @options[:method].to_s.upcase
8
10
  @url = url
11
+ @requests = []
9
12
  @response = { code: 204, headers: {}, text: '' }
10
13
  end
11
14
 
@@ -14,7 +17,9 @@ module Billy
14
17
  self
15
18
  end
16
19
 
17
- def call(params, headers, body)
20
+ def call(method, url, params, headers, body)
21
+ push_request(method, url, params, headers, body)
22
+
18
23
  if @response.respond_to?(:call)
19
24
  res = @response.call(params, headers, body)
20
25
  else
@@ -52,6 +57,10 @@ module Billy
52
57
  [code, headers, body]
53
58
  end
54
59
 
60
+ def has_requests?
61
+ @requests.any?
62
+ end
63
+
55
64
  def matches?(method, url)
56
65
  if method == @method
57
66
  if @url.is_a?(Regexp)
@@ -61,5 +70,21 @@ module Billy
61
70
  end
62
71
  end
63
72
  end
73
+
74
+ private
75
+
76
+ attr_writer :requests
77
+
78
+ def push_request(method, url, params, headers, body)
79
+ if Billy.config.record_stub_requests
80
+ @requests.push({
81
+ method: method,
82
+ url: url,
83
+ params: params,
84
+ headers: headers,
85
+ body: body
86
+ })
87
+ end
88
+ end
64
89
  end
65
90
  end
@@ -1,3 +1,3 @@
1
1
  module Billy
2
- VERSION = '0.7.0'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'timeout'
3
+
4
+ describe 'intercept request example', type: :feature, js: true do
5
+ before do
6
+ Billy.config.record_stub_requests = true
7
+ end
8
+
9
+ it 'should intercept a GET request directly' do
10
+ stub = proxy.stub('http://example.com/').and_return(
11
+ headers: { 'Access-Control-Allow-Origin' => '*' },
12
+ code: 200
13
+ )
14
+ visit 'http://example.com/'
15
+ expect(stub.has_requests?).to be true
16
+ expect(stub.requests).not_to be_empty
17
+ end
18
+
19
+ it 'should intercept a POST request through an intermediary page' do
20
+ stub = proxy.stub('http://example.com/', method: 'post').and_return(
21
+ headers: { 'Access-Control-Allow-Origin' => '*' },
22
+ code: 200
23
+ )
24
+ visit '/intercept_request.html'
25
+ Timeout::timeout(5) do
26
+ sleep(0.1) until stub.has_requests?
27
+ end
28
+ request = stub.requests.shift
29
+ expect(request[:body]).to eql 'foo=bar'
30
+ end
31
+ end
@@ -97,6 +97,23 @@ describe Billy::CacheHandler do
97
97
  other_request[:headers],
98
98
  other_request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'no jsonp but has parentheses()')
99
99
  end
100
+
101
+ context 'when after_cache_handles_request is set' do
102
+ it "should call the callback with the request and response" do
103
+ allow(Billy.config).to receive(:after_cache_handles_request) do
104
+ proc do |request, response|
105
+ response[:headers]['Access-Control-Allow-Origin'] = "*"
106
+ response[:content] = request[:body]
107
+ end
108
+ end
109
+ expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
110
+ expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
111
+ expect(handler.handle_request(request[:method],
112
+ request[:url],
113
+ request[:headers],
114
+ request[:body])).to eql(status: 200, headers: { 'Connection' => 'close', 'Access-Control-Allow-Origin' => "*" }, content: 'Some body')
115
+ end
116
+ end
100
117
  end
101
118
 
102
119
  context 'updating jsonp callback names disabled' do
@@ -62,7 +62,7 @@ describe Billy::ProxyRequestStub do
62
62
  let(:subject) { Billy::ProxyRequestStub.new('url') }
63
63
 
64
64
  it 'returns a 204 empty response' do
65
- expect(subject.call({}, {}, nil)).to eql [204, { 'Content-Type' => 'text/plain' }, '']
65
+ expect(subject.call('', '', {}, {}, nil)).to eql [204, { 'Content-Type' => 'text/plain' }, '']
66
66
  end
67
67
  end
68
68
 
@@ -71,7 +71,7 @@ describe Billy::ProxyRequestStub do
71
71
 
72
72
  it 'should generate bare responses' do
73
73
  subject.and_return body: 'baz foo bar'
74
- expect(subject.call({}, {}, nil)).to eql [
74
+ expect(subject.call('', '', {}, {}, nil)).to eql [
75
75
  200,
76
76
  {},
77
77
  'baz foo bar'
@@ -80,7 +80,7 @@ describe Billy::ProxyRequestStub do
80
80
 
81
81
  it 'should generate text responses' do
82
82
  subject.and_return text: 'foo bar baz'
83
- expect(subject.call({}, {}, nil)).to eql [
83
+ expect(subject.call('', '', {}, {}, nil)).to eql [
84
84
  200,
85
85
  { 'Content-Type' => 'text/plain' },
86
86
  'foo bar baz'
@@ -89,7 +89,7 @@ describe Billy::ProxyRequestStub do
89
89
 
90
90
  it 'should generate JSON responses' do
91
91
  subject.and_return json: { foo: 'bar' }
92
- expect(subject.call({}, {}, nil)).to eql [
92
+ expect(subject.call('', '', {}, {}, nil)).to eql [
93
93
  200,
94
94
  { 'Content-Type' => 'application/json' },
95
95
  '{"foo":"bar"}'
@@ -99,7 +99,7 @@ describe Billy::ProxyRequestStub do
99
99
  context 'JSONP' do
100
100
  it 'should generate JSONP responses' do
101
101
  subject.and_return jsonp: { foo: 'bar' }
102
- expect(subject.call({ 'callback' => ['baz'] }, {}, nil)).to eql [
102
+ expect(subject.call('', '', { 'callback' => ['baz'] }, {}, nil)).to eql [
103
103
  200,
104
104
  { 'Content-Type' => 'application/javascript' },
105
105
  'baz({"foo":"bar"})'
@@ -108,7 +108,7 @@ describe Billy::ProxyRequestStub do
108
108
 
109
109
  it 'should generate JSONP responses with custom callback parameter' do
110
110
  subject.and_return jsonp: { foo: 'bar' }, callback_param: 'cb'
111
- expect(subject.call({ 'cb' => ['bap'] }, {}, nil)).to eql [
111
+ expect(subject.call('', '', { 'cb' => ['bap'] }, {}, nil)).to eql [
112
112
  200,
113
113
  { 'Content-Type' => 'application/javascript' },
114
114
  'bap({"foo":"bar"})'
@@ -117,7 +117,7 @@ describe Billy::ProxyRequestStub do
117
117
 
118
118
  it 'should generate JSONP responses with custom callback name' do
119
119
  subject.and_return jsonp: { foo: 'bar' }, callback: 'cb'
120
- expect(subject.call({}, {}, nil)).to eql [
120
+ expect(subject.call('', '', {}, {}, nil)).to eql [
121
121
  200,
122
122
  { 'Content-Type' => 'application/javascript' },
123
123
  'cb({"foo":"bar"})'
@@ -127,7 +127,7 @@ describe Billy::ProxyRequestStub do
127
127
 
128
128
  it 'should generate redirection responses' do
129
129
  subject.and_return redirect_to: 'http://example.com'
130
- expect(subject.call({}, {}, nil)).to eql [
130
+ expect(subject.call('', '', {}, {}, nil)).to eql [
131
131
  302,
132
132
  { 'Location' => 'http://example.com' },
133
133
  nil
@@ -136,7 +136,7 @@ describe Billy::ProxyRequestStub do
136
136
 
137
137
  it 'should set headers' do
138
138
  subject.and_return text: 'foo', headers: { 'HTTP-X-Foo' => 'bar' }
139
- expect(subject.call({}, {}, nil)).to eql [
139
+ expect(subject.call('', '', {}, {}, nil)).to eql [
140
140
  200,
141
141
  { 'Content-Type' => 'text/plain', 'HTTP-X-Foo' => 'bar' },
142
142
  'foo'
@@ -145,7 +145,7 @@ describe Billy::ProxyRequestStub do
145
145
 
146
146
  it 'should set status codes' do
147
147
  subject.and_return text: 'baz', code: 410
148
- expect(subject.call({}, {}, nil)).to eql [
148
+ expect(subject.call('', '', {}, {}, nil)).to eql [
149
149
  410,
150
150
  { 'Content-Type' => 'text/plain' },
151
151
  'baz'
@@ -163,11 +163,52 @@ describe Billy::ProxyRequestStub do
163
163
  expect(body).to eql 'body text'
164
164
  { code: 418, text: 'success' }
165
165
  end)
166
- expect(subject.call(expected_params, expected_headers, expected_body)).to eql [
166
+ expect(subject.call('', '', expected_params, expected_headers, expected_body)).to eql [
167
167
  418,
168
168
  { 'Content-Type' => 'text/plain' },
169
169
  'success'
170
170
  ]
171
171
  end
172
172
  end
173
+
174
+ context '#stub_requests' do
175
+ let(:subject) { Billy::ProxyRequestStub.new('url') }
176
+
177
+ before :each do
178
+ Billy.config.record_stub_requests = true
179
+ end
180
+
181
+ it 'should record requests' do
182
+ subject.call('', '', {}, {}, nil)
183
+ expect(subject.has_requests?).to be true
184
+ end
185
+
186
+ it 'should record multiple requests' do
187
+ expected_amount = 3
188
+ expected_amount.times do
189
+ subject.call('', '', {}, {}, nil)
190
+ end
191
+
192
+ expect(subject.requests.length).to eql expected_amount
193
+ end
194
+
195
+ it 'should set a request' do
196
+ expected_request = {
197
+ method: 'POST',
198
+ url: 'test-url',
199
+ params: { 'param1' => ['one'], 'param2' => ['two'] },
200
+ headers: { 'header1' => 'three', 'header2' => 'four' },
201
+ body: 'body text'
202
+ }
203
+
204
+ subject.call(
205
+ expected_request[:method],
206
+ expected_request[:url],
207
+ expected_request[:params],
208
+ expected_request[:headers],
209
+ expected_request[:body]
210
+ )
211
+ expect(subject.requests[0]).to eql expected_request
212
+ end
213
+ end
173
214
  end
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: 0.7.0
4
+ version: 0.8.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: 2016-05-06 00:00:00.000000000 Z
11
+ date: 2016-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -298,6 +298,7 @@ files:
298
298
  - bin/proxy.rb
299
299
  - examples/README.md
300
300
  - examples/facebook_api.html
301
+ - examples/intercept_request.html
301
302
  - examples/post_api.html
302
303
  - examples/preflight_request.html
303
304
  - examples/tumblr_api.html
@@ -325,6 +326,7 @@ files:
325
326
  - log/.gitkeep
326
327
  - puffing-billy.gemspec
327
328
  - spec/features/examples/facebook_api_spec.rb
329
+ - spec/features/examples/intercept_request_spec.rb
328
330
  - spec/features/examples/post_api_spec.rb
329
331
  - spec/features/examples/preflight_request_spec.rb
330
332
  - spec/features/examples/tumblr_api_spec.rb
@@ -366,6 +368,7 @@ specification_version: 4
366
368
  summary: Easy request stubs for browser tests.
367
369
  test_files:
368
370
  - spec/features/examples/facebook_api_spec.rb
371
+ - spec/features/examples/intercept_request_spec.rb
369
372
  - spec/features/examples/post_api_spec.rb
370
373
  - spec/features/examples/preflight_request_spec.rb
371
374
  - spec/features/examples/tumblr_api_spec.rb