# encoding: utf-8
shared_examples_for "stubbing requests" do |*adapter_info|
describe "when requests are stubbed" do
describe "based on uri" do
it "should return stubbed response even if request have escaped parameters" do
stub_request(:get, "www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}").to_return(:body => "abc")
http_request(:get, "http://www.example.com/hello%2B/?#{ESCAPED_PARAMS}").body.should == "abc"
end
it "should return stubbed response even if query params have integer values" do
stub_request(:get, "www.example.com").with(:query => {"a" => 1}).to_return(:body => "abc")
http_request(:get, "http://www.example.com/?a=1").body.should == "abc"
end
it "should return stubbed response even if request has non escaped params" do
stub_request(:get, "www.example.com/hello%2B/?#{ESCAPED_PARAMS}").to_return(:body => "abc")
http_request(:get, "http://www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}").body.should == "abc"
end
it "should return stubbed response for url with non utf query params", "ruby>1.9" => true do
param = 'aäoöuü'.encode('iso-8859-1')
param = CGI.escape(param)
stub_request(:get, "www.example.com/?#{param}").to_return(:body => "abc")
http_request(:get, "http://www.example.com/?#{param}").body.should == "abc"
end
it "should return stubbed response even if stub uri is declared as regexp and request params are escaped" do
stub_request(:get, /.*x=ab c.*/).to_return(:body => "abc")
http_request(:get, "http://www.example.com/hello/?#{ESCAPED_PARAMS}").body.should == "abc"
end
it "should raise error specifying stubbing instructions with escaped characters in params if there is no matching stub" do
begin
http_request(:get, "http://www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}")
rescue WebMock::NetConnectNotAllowedError => e
e.message.should match /Unregistered request: GET http:\/\/www\.example\.com\/hello\+\/\?x=ab%20c&z='Stop!'%20said%20Fred%20m/m
e.message.should match /stub_request\(:get, "http:\/\/www\.example\.com\/hello\+\/\?x=ab%20c&z='Stop!'%20said%20Fred%20m"\)/m
end
stub_request(:get, "http://www.example.com/hello+/?x=ab%20c&z='Stop!'%20said%20Fred%20m")
http_request(:get, "http://www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}")
end
end
describe "based on query params" do
it "should return stubbed response when stub declares query params as a hash" do
stub_request(:get, "www.example.com").with(:query => {"a" => ["b x", "c d"]}).to_return(:body => "abc")
http_request(:get, "http://www.example.com/?a[]=b+x&a[]=c%20d").body.should == "abc"
end
it "should return stubbed response when stub declares query params as a hash" do
stub_request(:get, "www.example.com").with(:query => "a[]=b&a[]=c").to_return(:body => "abc")
http_request(:get, "http://www.example.com/?a[]=b&a[]=c").body.should == "abc"
end
it "should return stubbed response when stub declares query params both in uri and as a hash" do
stub_request(:get, "www.example.com/?x=3").with(:query => {"a" => ["b", "c"]}).to_return(:body => "abc")
http_request(:get, "http://www.example.com/?x=3&a[]=b&a[]=c").body.should == "abc"
end
it "should return stubbed response when stub expects only part of query params" do
stub_request(:get, "www.example.com").with(:query => hash_including({"a" => ["b", "c"]})).to_return(:body => "abc")
http_request(:get, "http://www.example.com/?a[]=b&a[]=c&b=1").body.should == "abc"
end
end
describe "based on method" do
it "should return stubbed response" do
stub_request(:get, "www.example.com")
http_request(:get, "http://www.example.com/").status.should == "200"
end
it "should raise error if stubbed request has different method" do
stub_request(:get, "www.example.com")
http_request(:get, "http://www.example.com/").status.should == "200"
lambda {
http_request(:delete, "http://www.example.com/")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: DELETE http://www.example.com/)
)
end
end
describe "based on body" do
it "should match requests if body is the same" do
stub_request(:post, "www.example.com").with(:body => "abc")
http_request(
:post, "http://www.example.com/",
:body => "abc").status.should == "200"
end
it "should match requests if body is not set in the stub" do
stub_request(:post, "www.example.com")
http_request(
:post, "http://www.example.com/",
:body => "abc").status.should == "200"
end
it "should not match requests if body is different" do
stub_request(:post, "www.example.com").with(:body => "abc")
lambda {
http_request(:post, "http://www.example.com/", :body => "def")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: POST http://www.example.com/ with body 'def'))
end
describe "with regular expressions" do
it "should match requests if body matches regexp" do
stub_request(:post, "www.example.com").with(:body => /\d+abc$/)
http_request(
:post, "http://www.example.com/",
:body => "123abc").status.should == "200"
end
it "should not match requests if body doesn't match regexp" do
stub_request(:post, "www.example.com").with(:body => /^abc/)
lambda {
http_request(:post, "http://www.example.com/", :body => "xabc")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: POST http://www.example.com/ with body 'xabc'))
end
end
describe "when body is declared as a hash" do
before(:each) do
stub_request(:post, "www.example.com").
with(:body => {:a => '1', :b => 'five x', 'c' => {'d' => ['e', 'f']} })
end
describe "for request with url encoded body" do
it "should match request if hash matches body" do
http_request(
:post, "http://www.example.com/",
:body => 'a=1&c[d][]=e&c[d][]=f&b=five+x').status.should == "200"
end
it "should match request if hash matches body in different order of params" do
http_request(
:post, "http://www.example.com/",
:body => 'a=1&c[d][]=e&b=five+x&c[d][]=f').status.should == "200"
end
it "should not match if hash doesn't match url encoded body" do
lambda {
http_request(
:post, "http://www.example.com/",
:body => 'c[d][]=f&a=1&c[d][]=e')
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: POST http://www.example.com/ with body 'c\[d\]\[\]=f&a=1&c\[d\]\[\]=e'))
end
end
describe "for request with json body and content type is set to json" do
it "should match if hash matches body" do
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
:body => "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five x\"}").status.should == "200"
end
it "should match if hash matches body in different form" do
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
:body => "{\"a\":\"1\",\"b\":\"five x\",\"c\":{\"d\":[\"e\",\"f\"]}}").status.should == "200"
end
it "should match if hash contains date string" do #Crack creates date object
WebMock.reset!
stub_request(:post, "www.example.com").
with(:body => {"foo" => "2010-01-01"})
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
:body => "{\"foo\":\"2010-01-01\"}").status.should == "200"
end
it "should match if any of the strings have spaces" do
WebMock.reset!
stub_request(:post, "www.example.com").with(:body => {"foo" => "a b c"})
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
:body => "{\"foo\":\"a b c\"}").status.should == "200"
end
end
describe "for request with xml body and content type is set to xml" do
before(:each) do
WebMock.reset!
stub_request(:post, "www.example.com").
with(:body => { "opt" => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']} }})
end
it "should match if hash matches body" do
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
:body => "\n \n e\n f\n \n\n").status.should == "200"
end
it "should match if hash matches body in different form" do
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
:body => "\n \n e\n f\n \n\n").status.should == "200"
end
it "should match if hash contains date string" do #Crack creates date object
WebMock.reset!
stub_request(:post, "www.example.com").
with(:body => {"opt" => {"foo" => "2010-01-01"}})
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
:body => "\n\n").status.should == "200"
end
end
end
describe "when body is declared as partial hash matcher" do
before(:each) do
stub_request(:post, "www.example.com").
with(:body => hash_including({:a => '1', 'c' => {'d' => ['e', 'f']} }))
end
describe "for request with url encoded body" do
it "should match request if hash matches body" do
http_request(
:post, "http://www.example.com/",
:body => 'a=1&c[d][]=e&c[d][]=f&b=five').status.should == "200"
end
it "should not match if hash doesn't match url encoded body" do
lambda {
http_request(
:post, "http://www.example.com/",
:body => 'c[d][]=f&a=1&c[d][]=e').status
}.should raise_error
end
end
describe "for request with json body and content type is set to json" do
it "should match if hash matches body" do
http_request(
:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
:body => "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}").status.should == "200"
end
end
end
end
describe "based on headers" do
it "should match requests if headers are the same" do
stub_request(:get, "www.example.com").with(:headers => SAMPLE_HEADERS )
http_request(
:get, "http://www.example.com/",
:headers => SAMPLE_HEADERS).status.should == "200"
end
it "should match requests if headers are the same and declared as array" do
stub_request(:get, "www.example.com").with(:headers => {"a" => ["b"]} )
http_request(
:get, "http://www.example.com/",
:headers => {"a" => "b"}).status.should == "200"
end
describe "when multiple headers with the same key are used" do
it "should match requests if headers are the same" do
stub_request(:get, "www.example.com").with(:headers => {"a" => ["b", "c"]} )
http_request(
:get, "http://www.example.com/",
:headers => {"a" => ["b", "c"]}).status.should == "200"
end
it "should match requests if headers are the same but in different order" do
stub_request(:get, "www.example.com").with(:headers => {"a" => ["b", "c"]} )
http_request(
:get, "http://www.example.com/",
:headers => {"a" => ["c", "b"]}).status.should == "200"
end
it "should not match requests if headers are different" do
stub_request(:get, "www.example.com").with(:headers => {"a" => ["b", "c"]})
lambda {
http_request(
:get, "http://www.example.com/",
:headers => {"a" => ["b", "d"]})
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/ with headers))
end
end
it "should match requests if request headers are not stubbed" do
stub_request(:get, "www.example.com")
http_request(
:get, "http://www.example.com/",
:headers => SAMPLE_HEADERS).status.should == "200"
end
it "should not match requests if headers are different" do
stub_request(:get, "www.example.com").with(:headers => SAMPLE_HEADERS)
lambda {
http_request(
:get, "http://www.example.com/",
:headers => { 'Content-Length' => '9999'})
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/ with headers))
end
it "should not match if accept header is different" do
stub_request(:get, "www.example.com").
with(:headers => { 'Accept' => 'application/json'})
lambda {
http_request(
:get, "http://www.example.com/",
:headers => { 'Accept' => 'application/xml'})
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/ with headers))
end
describe "declared as regular expressions" do
it "should match requests if header values match regular expression" do
stub_request(:get, "www.example.com").with(:headers => { :some_header => /^MyAppName$/ })
http_request(
:get, "http://www.example.com/",
:headers => { 'some-header' => 'MyAppName' }).status.should == "200"
end
it "should not match requests if headers values do not match regular expression" do
stub_request(:get, "www.example.com").with(:headers => { :some_header => /^MyAppName$/ })
lambda {
http_request(
:get, "http://www.example.com/",
:headers => { 'some-header' => 'xMyAppName' })
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/ with headers))
end
end
end
describe "when stubbing request with basic authentication", :unless => (adapter_info.include?(:no_url_auth)) do
it "should match if credentials are the same" do
stub_request(:get, "user:pass@www.example.com")
http_request(:get, "http://user:pass@www.example.com/").status.should == "200"
end
it "should not match if credentials are different" do
stub_request(:get, "user:pass@www.example.com")
lambda {
http_request(:get, "http://user:pazz@www.example.com/").status.should == "200"
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://user:pazz@www.example.com/))
end
it "should not match if credentials are stubbed but not provided in the request" do
stub_request(:get, "user:pass@www.example.com")
lambda {
http_request(:get, "http://www.example.com/").status.should == "200"
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
end
it "should not match if credentials are not stubbed but exist in the request" do
stub_request(:get, "www.example.com")
lambda {
http_request(:get, "http://user:pazz@www.example.com/").status.should == "200"
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://user:pazz@www.example.com/))
end
end
describe "when stubbing request with a global hook" do
after(:each) do
WebMock::StubRegistry.instance.global_stubs.clear
end
it 'returns the response returned by the hook' do
WebMock.globally_stub_request do |request|
{ :body => "global stub body" }
end
http_request(:get, "http://www.example.com/").body.should == "global stub body"
end
it 'does not get cleared when a user calls WebMock.reset!' do
WebMock.globally_stub_request do |request|
{ :body => "global stub body" }
end
WebMock.reset!
http_request(:get, "http://www.example.com/").body.should == "global stub body"
end
it "does not stub the request if the hook does not return anything" do
WebMock.globally_stub_request { |r| }
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
end
it "passes the request to the block" do
passed_request = nil
WebMock.globally_stub_request do |request|
passed_request = request
{ :body => "global stub body" }
end
http_request(:get, "http://www.example.com:456/bar")
passed_request.uri.to_s.should == "http://www.example.com:456/bar"
end
it "should call the block only once per request" do
call_count = 0
WebMock.globally_stub_request do |request|
call_count += 1
{ :body => "global stub body" }
end
http_request(:get, "http://www.example.com/")
call_count.should == 1
end
it 'supports multiple global stubs; the first registered one that returns a non-nil value determines the stub' do
stub_invocation_order = []
WebMock.globally_stub_request do |request|
stub_invocation_order << :nil_stub
nil
end
WebMock.globally_stub_request do |request|
stub_invocation_order << :hash_stub
{ :body => "global stub body" }
end
http_request(:get, "http://www.example.com/").body.should == "global stub body"
stub_invocation_order.should eq([:nil_stub, :hash_stub])
end
[:before, :after].each do |before_or_after|
context "when there is also a non-global registered stub #{before_or_after} the global stub" do
def stub_non_globally
stub_request(:get, "www.example.com").to_return(:body => 'non-global stub body')
end
define_method :register_stubs do |block|
stub_non_globally if before_or_after == :before
WebMock.globally_stub_request(&block)
stub_non_globally if before_or_after == :after
end
it 'uses the response from the global stub if the block returns a non-nil value' do
register_stubs(lambda { |req| { :body => 'global stub body' } })
http_request(:get, "http://www.example.com/").body.should == "global stub body"
end
it 'uses the response from the non-global stub if the block returns a nil value' do
register_stubs(lambda { |req| nil })
http_request(:get, "http://www.example.com/").body.should == "non-global stub body"
end
end
end
end
describe "when stubbing request with a block evaluated on request" do
it "should match if block returns true" do
stub_request(:get, "www.example.com").with { |request| true }
http_request(:get, "http://www.example.com/").status.should == "200"
end
it "should not match if block returns false" do
stub_request(:get, "www.example.com").with { |request| false }
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
end
it "should pass the request to the block" do
stub_request(:post, "www.example.com").with { |request| request.body == "wadus" }
http_request(
:post, "http://www.example.com/",
:body => "wadus").status.should == "200"
lambda {
http_request(:post, "http://www.example.com/", :body => "jander")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: POST http://www.example.com/ with body 'jander'))
end
it "should call the block only once per request" do
call_count = 0
stub_request(:get, "www.example.com").with { |request| call_count += 1; true }
http_request(:get, "http://www.example.com/").status.should == "200"
call_count.should == 1
end
end
end
describe "when request stub was removed" do
it "should raise an error on request" do
stub = stub_request(:get, "www.example.com")
http_request(:get, "http://www.example.com/")
remove_request_stub(stub)
lambda {
http_request(:get, "http://www.example.com/")
}.should raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
end
end
end