puffing-billy 2.4.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +2 -2
  4. data/lib/billy/browsers/capybara.rb +13 -9
  5. data/lib/billy/browsers/watir.rb +4 -2
  6. data/lib/billy/proxy.rb +1 -1
  7. data/lib/billy/version.rb +1 -1
  8. metadata +29 -79
  9. data/.gitignore +0 -6
  10. data/.rspec +0 -2
  11. data/.travis.yml +0 -36
  12. data/Dockerfile +0 -14
  13. data/Gemfile +0 -4
  14. data/Guardfile +0 -23
  15. data/Rakefile +0 -11
  16. data/bin/proxy.rb +0 -3
  17. data/examples/README.md +0 -1
  18. data/examples/facebook_api.html +0 -59
  19. data/examples/intercept_request.html +0 -10
  20. data/examples/post_api.html +0 -16
  21. data/examples/preflight_request.html +0 -22
  22. data/examples/tumblr_api.html +0 -22
  23. data/examples/tumblr_api_https.html +0 -22
  24. data/log/.gitkeep +0 -0
  25. data/puffing-billy.gemspec +0 -39
  26. data/spec/features/examples/facebook_api_spec.rb +0 -23
  27. data/spec/features/examples/intercept_request_spec.rb +0 -31
  28. data/spec/features/examples/post_api_spec.rb +0 -15
  29. data/spec/features/examples/preflight_request_spec.rb +0 -29
  30. data/spec/features/examples/tumblr_api_spec.rb +0 -59
  31. data/spec/lib/billy/browsers/capybara_spec.rb +0 -28
  32. data/spec/lib/billy/cache_spec.rb +0 -158
  33. data/spec/lib/billy/handlers/cache_handler_spec.rb +0 -191
  34. data/spec/lib/billy/handlers/handler_spec.rb +0 -16
  35. data/spec/lib/billy/handlers/proxy_handler_spec.rb +0 -254
  36. data/spec/lib/billy/handlers/request_handler_spec.rb +0 -200
  37. data/spec/lib/billy/handlers/request_log_spec.rb +0 -74
  38. data/spec/lib/billy/handlers/stub_handler_spec.rb +0 -117
  39. data/spec/lib/billy/proxy_connection_spec.rb +0 -20
  40. data/spec/lib/billy/proxy_request_stub_spec.rb +0 -252
  41. data/spec/lib/billy/resource_utils_spec.rb +0 -55
  42. data/spec/lib/billy/ssl/authority_spec.rb +0 -84
  43. data/spec/lib/billy/ssl/certificate_chain_spec.rb +0 -39
  44. data/spec/lib/billy/ssl/certificate_spec.rb +0 -89
  45. data/spec/lib/billy/watir/watir_spec.rb +0 -18
  46. data/spec/lib/proxy_spec.rb +0 -431
  47. data/spec/spec_helper.rb +0 -52
  48. data/spec/support/test_server.rb +0 -79
@@ -1,31 +0,0 @@
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
@@ -1,15 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'jQuery POST API example', type: :feature, js: true do
4
- before do
5
- proxy.stub('http://example.com/api', method: 'post').and_return(
6
- headers: { 'Access-Control-Allow-Origin' => '*' },
7
- code: 201
8
- )
9
- end
10
-
11
- it 'posts to an API' do
12
- visit '/post_api.html'
13
- expect(page.find('#result')).to have_content 'Success!'
14
- end
15
- end
@@ -1,29 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'jQuery preflight request example', type: :feature, js: true do
4
- let(:url) { 'http://example.com/api' }
5
-
6
- before do
7
- proxy.stub(url, method: 'get').and_return(
8
- headers: { 'Access-Control-Allow-Origin' => '*' },
9
- code: 201
10
- )
11
- end
12
-
13
- it 'stubs out the OPTIONS request' do
14
- visit '/preflight_request.html'
15
- expect(page.find('#result')).to have_content 'Fail!'
16
-
17
- proxy.stub(url, method: 'options').and_return(
18
- headers: {
19
- 'Access-Control-Allow-Methods' => 'GET, OPTIONS',
20
- 'Access-Control-Allow-Headers' => 'Content-Type',
21
- 'Access-Control-Allow-Origin' => '*'
22
- },
23
- code: 200
24
- )
25
-
26
- visit '/preflight_request.html'
27
- expect(page.find('#result')).to have_content 'Success!'
28
- end
29
- end
@@ -1,59 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.shared_examples 'tumblr/expectations' do
4
- it 'should show news stories' do
5
- visit '/tumblr_api.html'
6
- expect(page).to have_link('News Item 1', href: 'http://example.com/news/1')
7
- expect(page).to have_content('News item 1 content here')
8
- expect(page).to have_link('News Item 2', href: 'http://example.com/news/2')
9
- expect(page).to have_content('News item 2 content here')
10
- end
11
- end
12
-
13
- describe 'Tumblr API example', type: :feature, js: true do
14
- context 'without scope external references' do
15
- before do
16
- proxy.stub('http://blog.howmanyleft.co.uk/api/read/json').and_return(
17
- jsonp: {
18
- posts: [
19
- {
20
- 'regular-title' => 'News Item 1',
21
- 'url-with-slug' => 'http://example.com/news/1',
22
- 'regular-body' => 'News item 1 content here'
23
- },
24
- {
25
- 'regular-title' => 'News Item 2',
26
- 'url-with-slug' => 'http://example.com/news/2',
27
- 'regular-body' => 'News item 2 content here'
28
- }
29
- ]
30
- })
31
- end
32
-
33
- include_examples 'tumblr/expectations'
34
- end
35
-
36
- context 'with scope external references' do
37
- let(:posts) do
38
- [
39
- {
40
- 'regular-title' => 'News Item 1',
41
- 'url-with-slug' => 'http://example.com/news/1',
42
- 'regular-body' => 'News item 1 content here'
43
- },
44
- {
45
- 'regular-title' => 'News Item 2',
46
- 'url-with-slug' => 'http://example.com/news/2',
47
- 'regular-body' => 'News item 2 content here'
48
- }
49
- ]
50
- end
51
-
52
- before do
53
- proxy.stub('http://blog.howmanyleft.co.uk/api/read/json')
54
- .and_return(proc { { jsonp: { posts: posts } } })
55
- end
56
-
57
- include_examples 'tumblr/expectations'
58
- end
59
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Capybara drivers', type: :feature, js: true do
4
- it 'allows HTTPS calls' do
5
- proxy.stub('https://blog.howmanyleft.co.uk:443/api/read/json').and_return(
6
- jsonp: {
7
- posts: [
8
- {
9
- 'regular-title' => 'News Item 1',
10
- 'url-with-slug' => 'http://example.com/news/1',
11
- 'regular-body' => 'News item 1 content here'
12
- },
13
- {
14
- 'regular-title' => 'News Item 2',
15
- 'url-with-slug' => 'http://example.com/news/2',
16
- 'regular-body' => 'News item 2 content here'
17
- }
18
- ]
19
- })
20
-
21
- visit '/tumblr_api_https.html'
22
-
23
- expect(page).to have_link('News Item 1', href: 'http://example.com/news/1')
24
- expect(page).to have_content('News item 1 content here')
25
- expect(page).to have_link('News Item 2', href: 'http://example.com/news/2')
26
- expect(page).to have_content('News item 2 content here')
27
- end
28
- end
@@ -1,158 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Billy::Cache do
4
- let(:cache) { Billy::Cache.instance }
5
- let(:params) { '?foo=bar' }
6
- let(:callback) { '&callback=quux' }
7
- let(:fragment) { '#baz' }
8
- let(:base_url) { 'http://example.com' }
9
- let(:pipe_url) { 'https://fonts.googleapis.com:443/css?family=Cabin+Sketch:400,700|Love+Ya+Like+A+Sister' }
10
- let(:fragment_url) { "#{base_url}/#{fragment}" }
11
- let(:params_url) { "#{base_url}#{params}" }
12
- let(:params_url_with_callback) { "#{base_url}#{params}#{callback}" }
13
- let(:params_fragment_url) { "#{base_url}#{params}#{fragment}" }
14
-
15
- describe 'format_url' do
16
- context 'with ignore_params set to false' do
17
- it 'is a no-op if there are no params' do
18
- expect(cache.format_url(base_url)).to eq base_url
19
- end
20
- it 'appends params if there are params' do
21
- expect(cache.format_url(params_url)).to eq params_url
22
- end
23
- it 'appends params and fragment if both are present' do
24
- expect(cache.format_url(params_fragment_url)).to eq params_fragment_url
25
- end
26
- it 'does not raise error for URLs with pipes' do
27
- expect { cache.format_url(pipe_url) }.not_to raise_error
28
- end
29
-
30
- context 'when dynamic_jsonp is true' do
31
- it 'omits the callback param by default' do
32
- expect(cache.format_url(params_url_with_callback, false, true)).to eq params_url
33
- end
34
-
35
- it 'omits the params listed in Billy.config.dynamic_jsonp_keys' do
36
- allow(Billy.config).to receive(:dynamic_jsonp_keys) { ['foo'] }
37
-
38
- expect(cache.format_url(params_url_with_callback, false, true)).to eq "#{base_url}?callback=quux"
39
- end
40
- end
41
-
42
- it 'retains the callback param is dynamic_jsonp is false' do
43
- expect(cache.format_url(params_url_with_callback)).to eq params_url_with_callback
44
- end
45
- end
46
-
47
- context 'with ignore_params set to true' do
48
- it 'is a no-op if there are no params' do
49
- expect(cache.format_url(base_url, true)).to eq base_url
50
- end
51
- it 'omits params if there are params' do
52
- expect(cache.format_url(params_url, true)).to eq base_url
53
- end
54
- it 'omits params and fragment if both are present' do
55
- expect(cache.format_url(params_fragment_url, true)).to eq base_url
56
- end
57
- end
58
-
59
- context 'with merge_cached_responses_whitelist set' do
60
- let(:analytics_url1) { 'http://www.example-analytics.com/user/SDF879932/' }
61
- let(:analytics_url2) { 'http://www.example-analytics.com/user/OIWEMLW39/' }
62
- let(:regular_url) { 'http://www.example-analytics.com/user.js' }
63
-
64
- let(:regex_to_match_analytics_urls_only) do
65
- # Note that it matches the forward slash at the end of the URL, which doesn't match regular_url:
66
- /www\.example\-analytics\.com\/user\//
67
- end
68
-
69
- before do
70
- allow(Billy.config).to receive(:merge_cached_responses_whitelist) {
71
- [regex_to_match_analytics_urls_only]
72
- }
73
- end
74
-
75
- it "has one cache key for the two analytics urls that match, and a separate one for the other that doesn't" do
76
- expect(cache.key('post', analytics_url1, 'body')).to eq cache.key('post', analytics_url2, 'body')
77
- expect(cache.key('post', analytics_url1, 'body')).not_to eq cache.key('post', regular_url, 'body')
78
- end
79
-
80
- it 'More specifically, the cache keys should be identical for the 2 analytics urls' do
81
- identical_cache_key = 'post_5fcb7a450e4cd54dcffcb526212757ee0ca9dc17'
82
- distinct_cache_key = 'post_www.example-analytics.com_81f097654a523bd7ddb10fd4aee781723e076a1a_02083f4579e08a612425c0c1a17ee47add783b94'
83
-
84
- expect(cache.key('post', analytics_url1, 'body')).to eq identical_cache_key
85
- expect(cache.key('post', regular_url, 'body')).to eq distinct_cache_key
86
- expect(cache.key('post', analytics_url2, 'body')).to eq identical_cache_key
87
- end
88
- end
89
-
90
- context 'with cache_request_body_methods set' do
91
- before do
92
- allow(Billy.config).to receive(:cache_request_body_methods) {
93
- ['patch']
94
- }
95
- end
96
-
97
- context "for requests with methods specified in cache_request_body_methods" do
98
- it "should have a different cache key for requests with different bodies" do
99
- key1 = cache.key('patch', "http://example.com", "body1")
100
- key2 = cache.key('patch', "http://example.com", "body2")
101
- expect(key1).not_to eq key2
102
- end
103
-
104
- it "should have the same cache key for requests with the same bodies" do
105
- key1 = cache.key('patch', "http://example.com", "body1")
106
- key2 = cache.key('patch', "http://example.com", "body1")
107
- expect(key1).to eq key2
108
- end
109
- end
110
-
111
- it "should have the same cache key for request with different bodies if their methods are not included in cache_request_body_methods" do
112
- key1 = cache.key('put', "http://example.com", "body1")
113
- key2 = cache.key('put', "http://example.com", "body2")
114
- expect(key1).to eq key2
115
- end
116
- end
117
- end
118
-
119
- describe 'key' do
120
- context 'with use_ignore_params set to false' do
121
- before do
122
- allow(Billy.config).to receive(:use_ignore_params) { false }
123
- end
124
-
125
- it "should use the same cache key if the base url IS NOT whitelisted in allow_params" do
126
- key1 = cache.key('put', params_url, 'body')
127
- key2 = cache.key('put', params_url, 'body')
128
- expect(key1).to eq key2
129
- end
130
-
131
- it "should have the same cache key if the base IS whitelisted in allow_params" do
132
- allow(Billy.config).to receive(:allow_params) { [base_url] }
133
- key1 = cache.key('put', params_url, 'body')
134
- key2 = cache.key('put', params_url, 'body')
135
- expect(key1).to eq key2
136
- end
137
-
138
- it "should have different cache keys if the base url is added in between two requests" do
139
- key1 = cache.key('put', params_url, 'body')
140
- allow(Billy.config).to receive(:allow_params) { [base_url] }
141
- key2 = cache.key('put', params_url, 'body')
142
- expect(key1).not_to eq key2
143
- end
144
-
145
- it "should not use ignore_params when whitelisted" do
146
- allow(Billy.config).to receive(:allow_params) { [base_url] }
147
- expect(cache).to receive(:format_url).once.with(params_url, true).and_call_original
148
- expect(cache).to receive(:format_url).once.with(params_url, false).and_call_original
149
- key1 = cache.key('put', params_url, 'body')
150
- end
151
-
152
- it "should use ignore_params when not whitelisted" do
153
- expect(cache).to receive(:format_url).twice.with(params_url, true).and_call_original
154
- cache.key('put', params_url, 'body')
155
- end
156
- end
157
- end
158
- end
@@ -1,191 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Billy::CacheHandler do
4
- let(:handler) { Billy::CacheHandler.new }
5
- let(:request_url) { 'http://example.test:8080/index?some=param&callback=dynamicCallback5678' }
6
- let(:request) do
7
- {
8
- method: 'post',
9
- url: request_url,
10
- headers: { 'Accept-Encoding' => 'gzip',
11
- 'Cache-Control' => 'no-cache' },
12
- body: 'Some body'
13
- }
14
- end
15
-
16
- it 'delegates #reset to the cache' do
17
- expect(Billy::Cache.instance).to receive(:reset).at_least(:once)
18
- handler.reset
19
- end
20
-
21
- it 'delegates #cached? to the cache' do
22
- expect(Billy::Cache.instance).to receive :cached?
23
- handler.cached?
24
- end
25
-
26
- describe '#handles_request?' do
27
- it 'handles the request if it is cached' do
28
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
29
- expect(handler.handles_request?(nil, nil, nil, nil)).to be true
30
- end
31
-
32
- it 'does not handle the request if it is not cached' do
33
- expect(Billy::Cache.instance).to receive(:cached?).and_return(false)
34
- expect(handler.handles_request?(nil, nil, nil, nil)).to be false
35
- end
36
- end
37
-
38
- describe '#handle_request' do
39
- it 'returns nil if the request cannot be handled' do
40
- expect(Billy::Cache.instance).to receive(:cached?).and_return(false)
41
- expect(handler.handle_request(request[:method],
42
- request[:url],
43
- request[:headers],
44
- request[:body])).to be nil
45
- end
46
-
47
- it 'returns a cached response if the request can be handled' do
48
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
49
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
50
- expect(handler.handle_request(request[:method],
51
- request[:url],
52
- request[:headers],
53
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
54
- end
55
-
56
- context 'updating jsonp callback names enabled' do
57
- before do
58
- Billy.config.dynamic_jsonp = true
59
- end
60
-
61
- it 'updates the cached response if the callback is dynamic' do
62
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
63
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
64
- expect(handler.handle_request(request[:method],
65
- request[:url],
66
- request[:headers],
67
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback5678({"yolo":"kitten"})')
68
- end
69
-
70
- it 'is flexible about the format of the response body' do
71
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
72
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: "/**/ dynamicCallback1234(\n{\"yolo\":\"kitten\"})")
73
- expect(handler.handle_request(request[:method],
74
- request[:url],
75
- request[:headers],
76
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: "/**/ dynamicCallback5678(\n{\"yolo\":\"kitten\"})")
77
- end
78
-
79
- it 'does not interfere with non-jsonp requests' do
80
- jsonp_request = request
81
- other_request = {
82
- method: 'get',
83
- url: 'http://example.test:8080/index?hanukkah=latkes',
84
- headers: { 'Accept-Encoding' => 'gzip', 'Cache-Control' => 'no-cache' },
85
- body: 'no jsonp'
86
- }
87
-
88
- allow(Billy::Cache.instance).to receive(:cached?).and_return(true)
89
- allow(Billy::Cache.instance).to receive(:fetch).with(jsonp_request[:method], jsonp_request[:url], jsonp_request[:body]).and_return(status: 200,
90
- headers: { 'Connection' => 'close' },
91
- content: 'dynamicCallback1234({"yolo":"kitten"})')
92
- allow(Billy::Cache.instance).to receive(:fetch).with(other_request[:method], other_request[:url], other_request[:body]).and_return(status: 200,
93
- headers: { 'Connection' => 'close' },
94
- content: 'no jsonp but has parentheses()')
95
-
96
- expect(handler.handle_request(other_request[:method],
97
- other_request[:url],
98
- other_request[:headers],
99
- other_request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'no jsonp but has parentheses()')
100
- end
101
-
102
- context 'when after_cache_handles_request is set' do
103
- it "should call the callback with the request and response" do
104
- allow(Billy.config).to receive(:after_cache_handles_request) do
105
- proc do |request, response|
106
- response[:headers]['Access-Control-Allow-Origin'] = "*"
107
- response[:content] = request[:body]
108
- end
109
- end
110
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
111
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'The response body')
112
- expect(handler.handle_request(request[:method],
113
- request[:url],
114
- request[:headers],
115
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close', 'Access-Control-Allow-Origin' => "*" }, content: 'Some body')
116
- end
117
- end
118
-
119
- context 'when dynamic_jsonp_callback_name is set' do
120
- let(:dynamic_jsonp_callback_name) { 'customCallback' }
121
- let(:request_url) { "http://example.test:8080/index?some=param&#{dynamic_jsonp_callback_name}=dynamicCallback5678" }
122
-
123
- before do
124
- allow(Billy.config).to receive(:dynamic_jsonp_callback_name) do
125
- dynamic_jsonp_callback_name
126
- end
127
- end
128
-
129
- it 'should call the callback with the specified name' do
130
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
131
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
132
- expect(handler.handle_request(request[:method],
133
- request[:url],
134
- request[:headers],
135
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback5678({"yolo":"kitten"})')
136
- end
137
- end
138
- end
139
-
140
- context 'updating jsonp callback names disabled' do
141
- before do
142
- Billy.config.dynamic_jsonp = false
143
- end
144
-
145
- it 'does not change the response' do
146
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
147
- expect(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
148
- expect(handler.handle_request(request[:method],
149
- request[:url],
150
- request[:headers],
151
- request[:body])).to eql(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
152
- end
153
- end
154
-
155
- it 'returns nil if the Cache fails to handle the response for some reason' do
156
- expect(Billy::Cache.instance).to receive(:cached?).and_return(true)
157
- expect(Billy::Cache.instance).to receive(:fetch).and_return(nil)
158
- expect(handler.handle_request(request[:method],
159
- request[:url],
160
- request[:headers],
161
- request[:body])).to be nil
162
- end
163
-
164
- context 'network delay simulation' do
165
- before do
166
- allow(Billy::Cache.instance).to receive(:cached?).and_return(true)
167
- allow(Billy::Cache.instance).to receive(:fetch).and_return(status: 200, headers: { 'Connection' => 'close' }, content: 'dynamicCallback1234({"yolo":"kitten"})')
168
- end
169
-
170
- context 'when cache_simulates_network_delays is disabled' do
171
- it 'does not sleep for default delay before responding' do
172
- expect(Kernel).not_to receive(:sleep)
173
- handler.handle_request(request[:method], request[:url], request[:headers], request[:body])
174
- end
175
- end
176
-
177
- context 'when cache_simulates_network_delays is enabled' do
178
- around do |example|
179
- Billy.config.cache_simulates_network_delays = true
180
- example.call
181
- Billy.config.cache_simulates_network_delays = false
182
- end
183
-
184
- it 'sleeps for default delay before responding' do
185
- expect(Kernel).to receive(:sleep).with(Billy.config.cache_simulates_network_delay_time)
186
- handler.handle_request(request[:method], request[:url], request[:headers], request[:body])
187
- end
188
- end
189
- end
190
- end
191
- end
@@ -1,16 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Billy::Handler do
4
- let(:handler) { Class.new { include Billy::Handler }.new }
5
- it '#handle_request raises an error if not overridden' do
6
- expect(handler.handle_request(nil, nil, nil, nil)).to eql(error: 'The handler has not overridden the handle_request method!')
7
- end
8
-
9
- it '#handles_request returns false by default' do
10
- expect(handler.handles_request?(nil, nil, nil, nil)).to be false
11
- end
12
-
13
- it 'responds to #reset' do
14
- expect(handler).to respond_to :reset
15
- end
16
- end