contracts_api_test 0.0.1
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.
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +117 -0
- data/Rakefile +7 -0
- data/TODO.md +19 -0
- data/contracts.gemspec +29 -0
- data/lib/contracts.rb +46 -0
- data/lib/contracts/contract.rb +18 -0
- data/lib/contracts/extensions.rb +18 -0
- data/lib/contracts/instantiated_contract.rb +63 -0
- data/lib/contracts/rake_task.rb +75 -0
- data/lib/contracts/request.rb +62 -0
- data/lib/contracts/response.rb +27 -0
- data/lib/contracts/response_adapter.rb +24 -0
- data/lib/contracts/version.rb +3 -0
- data/lib/json-generator.rb +1 -0
- data/lib/json/generator.rb +18 -0
- data/lib/json/generator/array_attribute.rb +11 -0
- data/lib/json/generator/attribute_factory.rb +18 -0
- data/lib/json/generator/basic_attribute.rb +17 -0
- data/lib/json/generator/boolean_attribute.rb +7 -0
- data/lib/json/generator/dereferencer.rb +22 -0
- data/lib/json/generator/empty_attribute.rb +7 -0
- data/lib/json/generator/integer_attribute.rb +7 -0
- data/lib/json/generator/object_attribute.rb +18 -0
- data/lib/json/generator/string_attribute.rb +7 -0
- data/spec/contracts/contract_spec.rb +50 -0
- data/spec/contracts/contracts_spec.rb +77 -0
- data/spec/contracts/extensions_spec.rb +34 -0
- data/spec/contracts/instantiated_contract_spec.rb +224 -0
- data/spec/contracts/request_spec.rb +73 -0
- data/spec/contracts/response_adapter_spec.rb +27 -0
- data/spec/contracts/response_spec.rb +114 -0
- data/spec/data/contract.json +25 -0
- data/spec/json/generator/array_attribute_spec.rb +42 -0
- data/spec/json/generator/attribute_factory_spec.rb +72 -0
- data/spec/json/generator/basic_attribute_spec.rb +41 -0
- data/spec/json/generator/boolean_attribute_spec.rb +17 -0
- data/spec/json/generator/dereferencer_spec.rb +72 -0
- data/spec/json/generator/empty_attribute_spec.rb +17 -0
- data/spec/json/generator/integer_attribute_spec.rb +17 -0
- data/spec/json/generator/object_attribute_spec.rb +100 -0
- data/spec/json/generator/string_attribute_spec.rb +17 -0
- data/spec/json/generator_spec.rb +20 -0
- data/spec/spec_helper.rb +1 -0
- metadata +259 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
module Contracts
|
2
|
+
class Request
|
3
|
+
def initialize(host, definition)
|
4
|
+
@host = host
|
5
|
+
@definition = definition
|
6
|
+
end
|
7
|
+
|
8
|
+
def host
|
9
|
+
@host
|
10
|
+
end
|
11
|
+
|
12
|
+
def method
|
13
|
+
@definition['method'].to_s.downcase.to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
def path
|
17
|
+
@definition['path']
|
18
|
+
end
|
19
|
+
|
20
|
+
def path=(value)
|
21
|
+
@definition['path'] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def headers
|
25
|
+
@definition['headers']
|
26
|
+
end
|
27
|
+
|
28
|
+
def params
|
29
|
+
@definition['params']
|
30
|
+
end
|
31
|
+
|
32
|
+
def absolute_uri
|
33
|
+
@host + path
|
34
|
+
end
|
35
|
+
|
36
|
+
def full_uri
|
37
|
+
return absolute_uri if params.empty?
|
38
|
+
|
39
|
+
uri = Addressable::URI.new
|
40
|
+
uri.query_values = params
|
41
|
+
|
42
|
+
absolute_uri + '?' + uri.query
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute
|
46
|
+
response = HTTParty.send(method, @host + path, {
|
47
|
+
httparty_params_key => normalized_params,
|
48
|
+
:headers => headers
|
49
|
+
})
|
50
|
+
ResponseAdapter.new(response)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def httparty_params_key
|
55
|
+
method == :get ? :query : :body
|
56
|
+
end
|
57
|
+
|
58
|
+
def normalized_params
|
59
|
+
method == :get ? params : params.to_json
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Contracts
|
2
|
+
class Response
|
3
|
+
def initialize(definition)
|
4
|
+
@definition = definition
|
5
|
+
end
|
6
|
+
|
7
|
+
def instantiate
|
8
|
+
OpenStruct.new({
|
9
|
+
'status' => @definition['status'],
|
10
|
+
'headers' => @definition['headers'],
|
11
|
+
'body' => JSON::Generator.generate(@definition['body'])
|
12
|
+
})
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate(response)
|
16
|
+
@errors = []
|
17
|
+
if @definition['status'] != response.status
|
18
|
+
@errors << "Invalid status: expected #{@definition['status']} but got #{response.status}"
|
19
|
+
end
|
20
|
+
unless @definition['headers'].normalize_keys.subset_of?(response.headers.normalize_keys)
|
21
|
+
@errors << "Invalid headers: expected #{@definition['headers'].inspect} to be a subset of #{response.headers.inspect}"
|
22
|
+
end
|
23
|
+
@errors << JSON::Validator.fully_validate(@definition['body'], response.body)
|
24
|
+
@errors.flatten
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Contracts
|
2
|
+
class ResponseAdapter
|
3
|
+
def initialize(response)
|
4
|
+
@response = response
|
5
|
+
end
|
6
|
+
|
7
|
+
def status
|
8
|
+
@response.code
|
9
|
+
end
|
10
|
+
|
11
|
+
def body
|
12
|
+
@response.body
|
13
|
+
end
|
14
|
+
|
15
|
+
def headers
|
16
|
+
# Normalize headers values according to RFC2616
|
17
|
+
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
18
|
+
normalized_headers = @response.headers.map do |(key, value)|
|
19
|
+
[key, value.join(',')]
|
20
|
+
end
|
21
|
+
Hash[normalized_headers]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'json/generator'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "json/generator/basic_attribute"
|
2
|
+
require "json/generator/empty_attribute"
|
3
|
+
require "json/generator/string_attribute"
|
4
|
+
require "json/generator/integer_attribute"
|
5
|
+
require "json/generator/array_attribute"
|
6
|
+
require "json/generator/object_attribute"
|
7
|
+
require "json/generator/boolean_attribute"
|
8
|
+
require "json/generator/attribute_factory"
|
9
|
+
require "json/generator/dereferencer"
|
10
|
+
|
11
|
+
module JSON
|
12
|
+
module Generator
|
13
|
+
def self.generate(schema)
|
14
|
+
dereferenced_schema = Dereferencer.dereference(schema)
|
15
|
+
AttributeFactory.create(dereferenced_schema).generate
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module JSON
|
2
|
+
module Generator
|
3
|
+
class AttributeFactory
|
4
|
+
CLASSES = {
|
5
|
+
'string' => StringAttribute,
|
6
|
+
'object' => ObjectAttribute,
|
7
|
+
'integer' => IntegerAttribute,
|
8
|
+
'array' => ArrayAttribute,
|
9
|
+
'boolean' => BooleanAttribute,
|
10
|
+
nil => EmptyAttribute
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.create(properties)
|
14
|
+
CLASSES[Array(properties['type']).first].new(properties)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module JSON
|
2
|
+
module Generator
|
3
|
+
class BasicAttribute
|
4
|
+
def initialize(attributes)
|
5
|
+
@attributes = attributes
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate
|
9
|
+
@attributes['default'] || self.class::DEFAULT_VALUE
|
10
|
+
end
|
11
|
+
|
12
|
+
def required?
|
13
|
+
@attributes['required']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module JSON
|
2
|
+
module Generator
|
3
|
+
class Dereferencer
|
4
|
+
def self.dereference(schema)
|
5
|
+
return schema unless schema.has_key?('properties')
|
6
|
+
|
7
|
+
definitions = schema.delete('definitions')
|
8
|
+
schema['properties'].each do |name, property|
|
9
|
+
next unless property.has_key?('$ref')
|
10
|
+
|
11
|
+
ref_name = property['$ref'].split('/').last
|
12
|
+
raise NameError, "definition for #{ref_name} not found" unless definitions.has_key?(ref_name)
|
13
|
+
|
14
|
+
property.merge!(definitions[ref_name])
|
15
|
+
property.delete('$ref')
|
16
|
+
end
|
17
|
+
|
18
|
+
schema
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module JSON
|
2
|
+
module Generator
|
3
|
+
class ObjectAttribute < BasicAttribute
|
4
|
+
def generate
|
5
|
+
return nil unless required?
|
6
|
+
return {} unless @attributes.has_key?('properties')
|
7
|
+
|
8
|
+
@attributes['properties'].inject({}) do |json, (property_name, property_attributes)|
|
9
|
+
attribute = AttributeFactory.create(property_attributes)
|
10
|
+
if attribute.required?
|
11
|
+
json[property_name] = attribute.generate
|
12
|
+
end
|
13
|
+
json
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Contracts
|
2
|
+
describe Contract do
|
3
|
+
let(:request) { double('request') }
|
4
|
+
let(:response) { double('response') }
|
5
|
+
|
6
|
+
let(:contract) { described_class.new(request, response) }
|
7
|
+
|
8
|
+
describe '#instantiate' do
|
9
|
+
let(:instantiated_response) { double('instantiated response') }
|
10
|
+
let(:instantiated_contract) { double('instantiated contract') }
|
11
|
+
|
12
|
+
context 'by default' do
|
13
|
+
it 'should instantiate a contract with default attributes' do
|
14
|
+
response.should_receive(:instantiate).and_return(instantiated_response)
|
15
|
+
InstantiatedContract.should_receive(:new).
|
16
|
+
with(request, instantiated_response).
|
17
|
+
and_return(instantiated_contract)
|
18
|
+
instantiated_contract.should_not_receive(:replace!)
|
19
|
+
|
20
|
+
contract.instantiate.should == instantiated_contract
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with extra attributes' do
|
25
|
+
let(:attributes) { {:foo => 'bar'} }
|
26
|
+
|
27
|
+
it 'should instantiate a contract and overwrite default attributes' do
|
28
|
+
response.should_receive(:instantiate).and_return(instantiated_response)
|
29
|
+
InstantiatedContract.should_receive(:new).
|
30
|
+
with(request, instantiated_response).
|
31
|
+
and_return(instantiated_contract)
|
32
|
+
instantiated_contract.should_receive(:replace!).with(attributes)
|
33
|
+
|
34
|
+
contract.instantiate(attributes).should == instantiated_contract
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#validate' do
|
40
|
+
let(:fake_response) { double('fake response') }
|
41
|
+
let(:validation_result) { double('validation result') }
|
42
|
+
|
43
|
+
it 'should execute the request and match it against the expected response' do
|
44
|
+
request.should_receive(:execute).and_return(fake_response)
|
45
|
+
response.should_receive(:validate).with(fake_response).and_return(validation_result)
|
46
|
+
contract.validate.should == validation_result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
describe Contracts do
|
2
|
+
let(:host) { 'http://localhost' }
|
3
|
+
let(:contract_name) { 'contract' }
|
4
|
+
let(:contract_path) { File.join('spec', 'data', "#{contract_name}.json") }
|
5
|
+
let(:contract) { double('contract') }
|
6
|
+
|
7
|
+
after do
|
8
|
+
described_class.unregister_all!
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.register' do
|
12
|
+
context 'by default' do
|
13
|
+
it 'should register a contract under a given name' do
|
14
|
+
described_class.register(contract_name, contract)
|
15
|
+
described_class.registered[contract_name].should == contract
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when a contract has already been registered with the same name' do
|
20
|
+
it 'should raise an argument error' do
|
21
|
+
described_class.register(contract_name, contract)
|
22
|
+
expect { described_class.register(contract_name, contract) }.to raise_error(ArgumentError)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.build_from_file' do
|
28
|
+
it 'should build a contract given a file path and a host' do
|
29
|
+
described_class.build_from_file(contract_path, host).should be_a_kind_of(Contracts::Contract)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.use' do
|
34
|
+
before do
|
35
|
+
described_class.register(contract_name, contract)
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'by default' do
|
39
|
+
let(:instantiated_contract) { double('instantiated contract', :response_body => response_body)}
|
40
|
+
let(:response_body) { double('response_body') }
|
41
|
+
|
42
|
+
before do
|
43
|
+
described_class.registered[contract_name].stub(:instantiate => instantiated_contract)
|
44
|
+
instantiated_contract.stub(:stub!)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should instantiate a contract with default values' do
|
48
|
+
described_class.registered[contract_name].should_receive(:instantiate).with(nil).and_return(instantiated_contract)
|
49
|
+
described_class.use(contract_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return the instantiated contract' do
|
53
|
+
described_class.use(contract_name).should == instantiated_contract
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should stub further requests with the instantiated contract' do
|
57
|
+
instantiated_contract.should_receive(:stub!)
|
58
|
+
described_class.use(contract_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when contract has not been registered' do
|
64
|
+
it 'should raise an argument error' do
|
65
|
+
expect { described_class.use('unregistered') }.to raise_error ArgumentError
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.unregister_all!' do
|
71
|
+
it 'should unregister all previously registered contracts' do
|
72
|
+
described_class.register(contract_name, contract)
|
73
|
+
described_class.unregister_all!
|
74
|
+
described_class.registered.should be_empty
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Contracts
|
2
|
+
module Extensions
|
3
|
+
describe HashSubsetOf do
|
4
|
+
describe '#subset_of?' do
|
5
|
+
context 'when the other hash is the same' do
|
6
|
+
it 'should return true' do
|
7
|
+
{:a => 'a'}.should be_subset_of({:a => 'a'})
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when the other hash is a subset' do
|
12
|
+
it 'should return true' do
|
13
|
+
{:a => 'a'}.should be_subset_of({:a => 'a', :b => 'b'})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when the other hash is not a subset' do
|
18
|
+
it 'should return false' do
|
19
|
+
{:a => 'a'}.subset_of?({:a => 'b'}).should be_false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#normalize_keys' do
|
25
|
+
it 'should turn keys into downcased strings' do
|
26
|
+
{:A => 'a'}.normalize_keys.should == {'a' => 'a'}
|
27
|
+
{:a => 'a'}.normalize_keys.should == {'a' => 'a'}
|
28
|
+
{'A' => 'a'}.normalize_keys.should == {'a' => 'a'}
|
29
|
+
{'a' => 'a'}.normalize_keys.should == {'a' => 'a'}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
module Contracts
|
2
|
+
describe InstantiatedContract do
|
3
|
+
describe '#replace!' do
|
4
|
+
let(:body) { double('body') }
|
5
|
+
let(:response) { double(:body => body) }
|
6
|
+
let(:values) { double('values') }
|
7
|
+
|
8
|
+
context 'when response body is a hash' do
|
9
|
+
let(:normalized_values) { double('normalized values') }
|
10
|
+
let(:normalized_body) { double('normalized body') }
|
11
|
+
let(:merged_body) { double('merged body') }
|
12
|
+
|
13
|
+
it 'should normalize keys and deep merge response body with given values' do
|
14
|
+
values.should_receive(:normalize_keys).and_return(normalized_values)
|
15
|
+
response.body.should_receive(:normalize_keys).and_return(normalized_body)
|
16
|
+
normalized_body.should_receive(:deep_merge).with(normalized_values).and_return(merged_body)
|
17
|
+
|
18
|
+
instantiated_contract = described_class.new(nil, response)
|
19
|
+
instantiated_contract.replace!(values)
|
20
|
+
|
21
|
+
instantiated_contract.response_body.should == merged_body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when response body is a string' do
|
26
|
+
let(:body) { 'foo' }
|
27
|
+
|
28
|
+
it 'should replace response body with given values' do
|
29
|
+
instantiated_contract = described_class.new(nil, response)
|
30
|
+
instantiated_contract.replace!(values)
|
31
|
+
instantiated_contract.response_body.should == values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when response body is nil' do
|
36
|
+
let(:body) { nil }
|
37
|
+
|
38
|
+
it 'should replace response body with given values' do
|
39
|
+
instantiated_contract = described_class.new(nil, response)
|
40
|
+
instantiated_contract.replace!(values)
|
41
|
+
instantiated_contract.response_body.should == values
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#response_body' do
|
47
|
+
let(:response) { double(:body => double('body')) }
|
48
|
+
|
49
|
+
it "should return response body" do
|
50
|
+
described_class.new(nil, response).response_body.should == response.body
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#request_path' do
|
55
|
+
let(:request) { double('request', :absolute_uri => "http://dummy_link/hello_world") }
|
56
|
+
let(:response) { double('response', :body => double('body')) }
|
57
|
+
|
58
|
+
it "should return the request absolute uri" do
|
59
|
+
described_class.new(request, response).request_path.should == "http://dummy_link/hello_world"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#request_uri' do
|
64
|
+
let(:request) { double('request', :full_uri => "http://dummy_link/hello_world?param=value#fragment") }
|
65
|
+
let(:response) { double('response', :body => double('body')) }
|
66
|
+
|
67
|
+
it "should return request full uri" do
|
68
|
+
described_class.new(request, response).request_uri.should == "http://dummy_link/hello_world?param=value#fragment"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#stub!' do
|
73
|
+
let(:request) do
|
74
|
+
double({
|
75
|
+
:host => 'http://localhost',
|
76
|
+
:method => method,
|
77
|
+
:path => '/hello_world',
|
78
|
+
:headers => {'Accept' => 'application/json'},
|
79
|
+
:params => {'foo' => 'bar'}
|
80
|
+
})
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:method) { :get }
|
84
|
+
|
85
|
+
let(:response) do
|
86
|
+
double({
|
87
|
+
:status => 200,
|
88
|
+
:headers => {},
|
89
|
+
:body => body
|
90
|
+
})
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:body) do
|
94
|
+
{'message' => 'foo'}
|
95
|
+
end
|
96
|
+
|
97
|
+
let(:stubbed_request) { double('stubbed request') }
|
98
|
+
|
99
|
+
before do
|
100
|
+
WebMock.should_receive(:stub_request).
|
101
|
+
with(request.method, "#{request.host}#{request.path}").
|
102
|
+
and_return(stubbed_request)
|
103
|
+
|
104
|
+
stubbed_request.stub(:to_return).with({
|
105
|
+
:status => response.status,
|
106
|
+
:headers => response.headers,
|
107
|
+
:body => response.body.to_json
|
108
|
+
})
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when the response body is an object' do
|
112
|
+
let(:body) do
|
113
|
+
{'message' => 'foo'}
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should stub the response body with a json representation' do
|
117
|
+
stubbed_request.should_receive(:to_return).with({
|
118
|
+
:status => response.status,
|
119
|
+
:headers => response.headers,
|
120
|
+
:body => response.body.to_json
|
121
|
+
})
|
122
|
+
|
123
|
+
stubbed_request.stub(:with).and_return(stubbed_request)
|
124
|
+
|
125
|
+
described_class.new(request, response).stub!
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when the response body is an array' do
|
130
|
+
let(:body) do
|
131
|
+
[1, 2, 3]
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should stub the response body with a json representation' do
|
135
|
+
stubbed_request.should_receive(:to_return).with({
|
136
|
+
:status => response.status,
|
137
|
+
:headers => response.headers,
|
138
|
+
:body => response.body.to_json
|
139
|
+
})
|
140
|
+
|
141
|
+
stubbed_request.stub(:with).and_return(stubbed_request)
|
142
|
+
|
143
|
+
described_class.new(request, response).stub!
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when the response body is not an object or an array' do
|
148
|
+
let(:body) { nil }
|
149
|
+
|
150
|
+
it 'should stub the response body with the original body' do
|
151
|
+
stubbed_request.should_receive(:to_return).with({
|
152
|
+
:status => response.status,
|
153
|
+
:headers => response.headers,
|
154
|
+
:body => response.body
|
155
|
+
})
|
156
|
+
|
157
|
+
stubbed_request.stub(:with).and_return(stubbed_request)
|
158
|
+
|
159
|
+
described_class.new(request, response).stub!
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'a GET request' do
|
164
|
+
let(:method) { :get }
|
165
|
+
|
166
|
+
it 'should use WebMock to stub the request' do
|
167
|
+
stubbed_request.should_receive(:with).
|
168
|
+
with({:headers => request.headers, :query => request.params}).
|
169
|
+
and_return(stubbed_request)
|
170
|
+
described_class.new(request, response).stub!
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'a POST request' do
|
175
|
+
let(:method) { :post }
|
176
|
+
|
177
|
+
it 'should use WebMock to stub the request' do
|
178
|
+
stubbed_request.should_receive(:with).
|
179
|
+
with({:headers => request.headers, :body => request.params}).
|
180
|
+
and_return(stubbed_request)
|
181
|
+
described_class.new(request, response).stub!
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'a request with no headers' do
|
186
|
+
let(:request) do
|
187
|
+
double({
|
188
|
+
:host => 'http://localhost',
|
189
|
+
:method => :get,
|
190
|
+
:path => '/hello_world',
|
191
|
+
:headers => {},
|
192
|
+
:params => {'foo' => 'bar'}
|
193
|
+
})
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'should use WebMock to stub the request' do
|
197
|
+
stubbed_request.should_receive(:with).
|
198
|
+
with({:query => request.params}).
|
199
|
+
and_return(stubbed_request)
|
200
|
+
described_class.new(request, response).stub!
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'a request with no params' do
|
205
|
+
let(:request) do
|
206
|
+
double({
|
207
|
+
:host => 'http://localhost',
|
208
|
+
:method => :get,
|
209
|
+
:path => '/hello_world',
|
210
|
+
:headers => {},
|
211
|
+
:params => {}
|
212
|
+
})
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should use WebMock to stub the request' do
|
216
|
+
stubbed_request.should_receive(:with).
|
217
|
+
with({}).
|
218
|
+
and_return(stubbed_request)
|
219
|
+
described_class.new(request, response).stub!
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|