webmock-3.18.1/0000755000004100000410000000000014333126774013275 5ustar www-datawww-datawebmock-3.18.1/test/0000755000004100000410000000000014333126774014254 5ustar www-datawww-datawebmock-3.18.1/test/http_request.rb0000644000004100000410000000131214333126774017325 0ustar www-datawww-datarequire 'ostruct' module HttpRequestTestHelper def http_request(method, uri, options = {}) begin uri = URI.parse(uri) rescue uri = Addressable::URI.heuristic_parse(uri) end response = nil clazz = ::Net::HTTP.const_get("#{method.to_s.capitalize}") req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers]) req.basic_auth uri.user, uri.password if uri.user http = ::Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.scheme == "https" response = http.start {|http| http.request(req, options[:body]) } OpenStruct.new({ body: response.body, headers: response, status: response.code }) end endwebmock-3.18.1/test/test_webmock.rb0000644000004100000410000000063314333126774017271 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/test_helper') require File.expand_path(File.dirname(__FILE__) + '/shared_test') class TestWebMock < Test::Unit::TestCase include SharedTest def teardown # Ensure global Test::Unit teardown was called assert_empty WebMock::RequestRegistry.instance.requested_signatures.hash assert_empty WebMock::StubRegistry.instance.request_stubs end end webmock-3.18.1/test/shared_test.rb0000644000004100000410000001160314333126774017107 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/http_request') module SharedTest include HttpRequestTestHelper def setup super @stub_http = stub_http_request(:any, "http://www.example.com") @stub_https = stub_http_request(:any, "https://www.example.com") end def test_assert_requested_with_stub_and_block_raises_error assert_raises ArgumentError do assert_requested(@stub_http) {} end end def test_assert_not_requested_with_stub_and_block_raises_error assert_raises ArgumentError do assert_not_requested(@stub_http) {} end end def test_error_on_non_stubbed_request assert_raise_with_message(WebMock::NetConnectNotAllowedError, %r{Real HTTP connections are disabled. Unregistered request: GET http://www.example.net/ with headers}) do http_request(:get, "http://www.example.net/") end end def test_verification_that_expected_request_occured http_request(:get, "http://www.example.com/") assert_requested(:get, "http://www.example.com", times: 1) assert_requested(:get, "http://www.example.com") end def test_verification_that_expected_stub_occured http_request(:get, "http://www.example.com/") assert_requested(@stub_http, times: 1) assert_requested(@stub_http) end def test_verification_that_expected_request_didnt_occur expected_message = "The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times" expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================" assert_fail(expected_message) do assert_requested(:get, "http://www.example.com") end end def test_verification_that_expected_stub_didnt_occur expected_message = "The request ANY http://www.example.com/ was expected to execute 1 time but it executed 0 times" expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================" assert_fail(expected_message) do assert_requested(@stub_http) end end def test_verification_that_expected_request_occured_with_body_and_headers http_request(:get, "http://www.example.com/", body: "abc", headers: {'A' => 'a'}) assert_requested(:get, "http://www.example.com", body: "abc", headers: {'A' => 'a'}) end def test_verification_that_expected_request_occured_with_query_params stub_request(:any, "http://www.example.com").with(query: hash_including({"a" => ["b", "c"]})) http_request(:get, "http://www.example.com/?a[]=b&a[]=c&x=1") assert_requested(:get, "http://www.example.com", query: hash_including({"a" => ["b", "c"]})) end def test_verification_that_expected_request_not_occured_with_query_params stub_request(:any, 'http://www.example.com').with(query: hash_including(a: ['b', 'c'])) stub_request(:any, 'http://www.example.com').with(query: hash_excluding(a: ['b', 'c'])) http_request(:get, 'http://www.example.com/?a[]=b&a[]=c&x=1') assert_not_requested(:get, 'http://www.example.com', query: hash_excluding('a' => ['b', 'c'])) end def test_verification_that_expected_request_occured_with_excluding_query_params stub_request(:any, 'http://www.example.com').with(query: hash_excluding('a' => ['b', 'c'])) http_request(:get, 'http://www.example.com/?a[]=x&a[]=y&x=1') assert_requested(:get, 'http://www.example.com', query: hash_excluding('a' => ['b', 'c'])) end def test_verification_that_non_expected_request_didnt_occur expected_message = %r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time\n\nThe following requests were made:\n\nGET http://www.example.com/ with headers .+ was made 1 time\n\n============================================================) assert_fail(expected_message) do http_request(:get, "http://www.example.com/") assert_not_requested(:get, "http://www.example.com") end end def test_refute_requested_alias expected_message = %r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time\n\nThe following requests were made:\n\nGET http://www.example.com/ with headers .+ was made 1 time\n\n============================================================) assert_fail(expected_message) do http_request(:get, "http://www.example.com/") refute_requested(:get, "http://www.example.com") end end def test_verification_that_non_expected_stub_didnt_occur expected_message = %r(The request ANY http://www.example.com/ was not expected to execute but it executed 1 time\n\nThe following requests were made:\n\nGET http://www.example.com/ with headers .+ was made 1 time\n\n============================================================) assert_fail(expected_message) do http_request(:get, "http://www.example.com/") assert_not_requested(@stub_http) end end end webmock-3.18.1/test/test_helper.rb0000644000004100000410000000115714333126774017123 0ustar www-datawww-datarequire 'rubygems' $LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'webmock/test_unit' require 'test/unit' class Test::Unit::TestCase AssertionFailedError = Test::Unit::AssertionFailedError rescue MiniTest::Assertion def assert_raise_with_message(e, message, &block) e = assert_raises(e, &block) if message.is_a?(Regexp) assert_match(message, e.message) else assert_equal(message, e.message) end end def assert_fail(message, &block) assert_raise_with_message(AssertionFailedError, message, &block) end end webmock-3.18.1/webmock.gemspec0000644000004100000410000000462614333126774016301 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.push File.expand_path('../lib', __FILE__) require 'webmock/version' Gem::Specification.new do |s| s.name = 'webmock' s.version = WebMock::VERSION s.platform = Gem::Platform::RUBY s.authors = ['Bartosz Blimke'] s.email = ['bartosz.blimke@gmail.com'] s.homepage = 'https://github.com/bblimke/webmock' s.summary = %q{Library for stubbing HTTP requests in Ruby.} s.description = %q{WebMock allows stubbing HTTP requests and setting expectations on HTTP requests.} s.license = "MIT" s.metadata = { 'bug_tracker_uri' => 'https://github.com/bblimke/webmock/issues', 'changelog_uri' => "https://github.com/bblimke/webmock/blob/v#{s.version}/CHANGELOG.md", 'documentation_uri' => "https://www.rubydoc.info/gems/webmock/#{s.version}", 'source_code_uri' => "https://github.com/bblimke/webmock/tree/v#{s.version}", 'wiki_uri' => 'https://github.com/bblimke/webmock/wiki' } s.required_ruby_version = '>= 2.3' s.add_dependency 'addressable', '>= 2.8.0' s.add_dependency 'crack', '>= 0.3.2' s.add_dependency 'hashdiff', ['>= 0.4.0', '< 2.0.0'] unless RUBY_PLATFORM =~ /java/ s.add_development_dependency 'patron', '>= 0.4.18' s.add_development_dependency 'curb', '>= 0.7.16' s.add_development_dependency 'typhoeus', '>= 0.5.0' s.add_development_dependency 'em-http-request', '>= 1.0.2' s.add_development_dependency 'em-synchrony', '>= 1.0.0' end s.add_development_dependency 'http', '>= 0.8.0' s.add_development_dependency 'manticore', '>= 0.5.1' if RUBY_PLATFORM =~ /java/ s.add_development_dependency 'rack', ((RUBY_VERSION < '2.2.2') ? '1.6.0' : '> 1.6') s.add_development_dependency 'rspec', '>= 3.1.0' s.add_development_dependency 'httpclient', '>= 2.2.4' s.add_development_dependency 'excon', '>= 0.27.5' s.add_development_dependency 'async-http', '>= 0.48.0' s.add_development_dependency 'minitest', '>= 5.0.0' s.add_development_dependency 'test-unit', '>= 3.0.0' s.add_development_dependency 'rdoc', '> 3.5.0' s.add_development_dependency 'webrick' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ['lib'] end webmock-3.18.1/README.md0000644000004100000410000007604514333126774014570 0ustar www-datawww-dataWebMock ======= [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock) [![Build Status](https://github.com/bblimke/webmock/workflows/CI/badge.svg?branch=master)](https://github.com/bblimke/webmock/actions) [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock) [![Mentioned in Awesome Ruby](https://awesome.re/mentioned-badge.svg)](https://github.com/markets/awesome-ruby) [![Inline docs](http://inch-ci.org/github/bblimke/webmock.svg?branch=master)](http://inch-ci.org/github/bblimke/webmock) [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=webmock&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=webmock&package-manager=bundler&version-scheme=semver) Library for stubbing and setting expectations on HTTP requests in Ruby. Features -------- * Stubbing HTTP requests at low http client lib level (no need to change tests when you change HTTP library) * Setting and verifying expectations on HTTP requests * Matching requests based on method, URI, headers and body * Smart matching of the same URIs in different representations (also encoded and non encoded forms) * Smart matching of the same headers in different representations. * Support for Test::Unit * Support for RSpec * Support for MiniTest Supported HTTP libraries ------------------------ * [Async::HTTP::Client](https://github.com/socketry/async-http) * [Curb](https://github.com/taf2/curb) (currently only Curb::Easy) * [EM-HTTP-Request](https://github.com/igrigorik/em-http-request) * [Excon](https://github.com/excon/excon) * [HTTPClient](https://github.com/nahi/httpclient) * [HTTP Gem (also known as http.rb)](https://github.com/httprb/http) * [httpx](https://honeyryderchuck.gitlab.io/httpx/wiki/Webmock-Adapter) * [Manticore](https://github.com/cheald/manticore) * [Net::HTTP](https://ruby-doc.org/stdlib-2.7.0/libdoc/net/http/rdoc/Net/HTTP.html) and other libraries based on Net::HTTP, e.g.: * [HTTParty](https://github.com/jnunemaker/httparty) * [REST Client](https://github.com/rest-client/rest-client) * [Patron](https://github.com/toland/patron) * [Typhoeus](https://github.com/typhoeus/typhoeus) (currently only Typhoeus::Hydra) Supported Ruby Interpreters --------------------------- * MRI 2.5 * MRI 2.6 * MRI 2.7 * JRuby * Rubinius ## Installation ```bash gem install webmock ``` or alternatively: ```ruby # add to your Gemfile group :test do gem "webmock" end ``` ### or to install the latest development version from github master git clone http://github.com/bblimke/webmock.git cd webmock rake install ## Upgrading from v1.x to v2.x WebMock 2.x has changed somewhat since version 1.x. Changes are listed in [CHANGELOG.md](CHANGELOG.md) ### Cucumber Create a file `features/support/webmock.rb` with the following contents: ```ruby require 'webmock/cucumber' ``` ### MiniTest Add the following code to `test/test_helper`: ```ruby require 'webmock/minitest' ``` ### RSpec Add the following code to `spec/spec_helper`: ```ruby require 'webmock/rspec' ``` ### Test::Unit Add the following code to `test/test_helper.rb` ```ruby require 'webmock/test_unit' ``` ### Outside a test framework You can also use WebMock outside a test framework: ```ruby require 'webmock' include WebMock::API WebMock.enable! ``` # Examples ## Stubbing ### Stubbed request based on uri only and with the default response ```ruby stub_request(:any, "www.example.com") Net::HTTP.get("www.example.com", "/") # ===> Success ``` ### Stubbing requests based on method, uri, body and headers ```ruby stub_request(:post, "www.example.com"). with(body: "abc", headers: { 'Content-Length' => 3 }) uri = URI.parse("http://www.example.com/") req = Net::HTTP::Post.new(uri.path) req['Content-Length'] = 3 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, "abc") end # ===> Success ``` ### Matching request body and headers against regular expressions ```ruby stub_request(:post, "www.example.com"). with(body: /world$/, headers: {"Content-Type" => /image\/.+/}). to_return(body: "abc") uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Content-Type'] = 'image/png' res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'hello world') end # ===> Success ``` ### Matching request body against a hash. Body can be URL-Encoded, JSON or XML. ```ruby stub_request(:post, "www.example.com"). with(body: {data: {a: '1', b: 'five'}}) RestClient.post('www.example.com', "data[a]=1&data[b]=five", content_type: 'application/x-www-form-urlencoded') # ===> Success RestClient.post('www.example.com', '{"data":{"a":"1","b":"five"}}', content_type: 'application/json') # ===> Success RestClient.post('www.example.com', '', content_type: 'application/xml') # ===> Success ``` ### Matching request body against partial hash. ```ruby stub_request(:post, "www.example.com"). with(body: hash_including({data: {a: '1', b: 'five'}})) RestClient.post('www.example.com', "data[a]=1&data[b]=five&x=1", :content_type => 'application/x-www-form-urlencoded') # ===> Success ``` ### Matching custom request headers ```ruby stub_request(:any, "www.example.com"). with(headers:{ 'Header-Name' => 'Header-Value' }) uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Header-Name'] = 'Header-Value' res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'abc') end # ===> Success ``` ### Matching multiple headers with the same name ```ruby stub_request(:get, 'www.example.com'). with(headers: {'Accept' => ['image/jpeg', 'image/png'] }) req = Net::HTTP::Get.new("/") req['Accept'] = ['image/png'] req.add_field('Accept', 'image/jpeg') Net::HTTP.start("www.example.com") {|http| http.request(req) } # ===> Success ``` ### Matching requests against provided block ```ruby stub_request(:post, "www.example.com").with { |request| request.body == "abc" } RestClient.post('www.example.com', 'abc') # ===> Success ``` ### Request with basic authentication header ```ruby stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) # or # stub_request(:get, "www.example.com"). # with(headers: {'Authorization' => "Basic #{ Base64.strict_encode64('user:pass').chomp}"}) Net::HTTP.start('www.example.com') do |http| req = Net::HTTP::Get.new('/') req.basic_auth 'user', 'pass' http.request(req) end # ===> Success ``` ##### Important! Since version 2.0.0, WebMock does not match credentials provided in Authorization header and credentials provided in the userinfo of a url. I.e. `stub_request(:get, "user:pass@www.example.com")` does not match a request with credentials provided in the Authorization header. ### Request with basic authentication in the url ```ruby stub_request(:get, "user:pass@www.example.com") RestClient.get('user:pass@www.example.com') # ===> Success ``` ### Matching uris using regular expressions ```ruby stub_request(:any, /example/) Net::HTTP.get('www.example.com', '/') # ===> Success ``` ### Matching uris using lambda ```ruby stub_request(:any, ->(uri) { true }) ``` ### Matching uris using RFC 6570 - Basic Example ```ruby uri_template = Addressable::Template.new "www.example.com/{id}/" stub_request(:any, uri_template) Net::HTTP.get('www.example.com', '/webmock/') # ===> Success ``` ### Matching uris using RFC 6570 - Advanced Example ```ruby uri_template = Addressable::Template.new "www.example.com/thing/{id}.json{?x,y,z}{&other*}" stub_request(:any, uri_template) Net::HTTP.get('www.example.com', '/thing/5.json?x=1&y=2&z=3&anyParam=4') # ===> Success ``` ### Matching query params using hash ```ruby stub_request(:get, "www.example.com").with(query: {"a" => ["b", "c"]}) RestClient.get("http://www.example.com/?a[]=b&a[]=c") # ===> Success ``` ### Matching partial query params using hash ```ruby stub_request(:get, "www.example.com"). with(query: hash_including({"a" => ["b", "c"]})) RestClient.get("http://www.example.com/?a[]=b&a[]=c&x=1") # ===> Success ``` ### Matching partial query params using hash_excluding ```ruby stub_request(:get, "www.example.com"). with(query: hash_excluding({"a" => "b"})) RestClient.get("http://www.example.com/?a=b") # ===> Failure RestClient.get("http://www.example.com/?a=c") # ===> Success ``` ### Stubbing with custom response ```ruby stub_request(:any, "www.example.com"). to_return(body: "abc", status: 200, headers: { 'Content-Length' => 3 }) Net::HTTP.get("www.example.com", '/') # ===> "abc" ``` Set appropriate Content-Type for HTTParty's `parsed_response`. ```ruby stub_request(:any, "www.example.com").to_return body: '{}', headers: {content_type: 'application/json'} ``` ### Response with body specified as IO object ```ruby File.open('/tmp/response_body.txt', 'w') { |f| f.puts 'abc' } stub_request(:any, "www.example.com"). to_return(body: File.new('/tmp/response_body.txt'), status: 200) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" ``` ### Response with custom status message ```ruby stub_request(:any, "www.example.com"). to_return(status: [500, "Internal Server Error"]) req = Net::HTTP::Get.new("/") Net::HTTP.start("www.example.com") { |http| http.request(req) }. message # ===> "Internal Server Error" ``` ### Replaying raw responses recorded with `curl -is` ``` curl -is www.example.com > /tmp/example_curl_-is_output.txt ``` ```ruby raw_response_file = File.new("/tmp/example_curl_-is_output.txt") ``` from file ```ruby stub_request(:get, "www.example.com").to_return(raw_response_file) ``` or string ```ruby stub_request(:get, "www.example.com").to_return(raw_response_file.read) ``` ### Responses dynamically evaluated from block ```ruby stub_request(:any, 'www.example.net'). to_return { |request| {body: request.body} } RestClient.post('www.example.net', 'abc') # ===> "abc\n" ``` ### Responses dynamically evaluated from lambda ```ruby stub_request(:any, 'www.example.net'). to_return(lambda { |request| {body: request.body} }) RestClient.post('www.example.net', 'abc') # ===> "abc\n" ``` ### Dynamically evaluated raw responses recorded with `curl -is` `curl -is www.example.com > /tmp/www.example.com.txt` ```ruby stub_request(:get, "www.example.com"). to_return(lambda { |request| File.new("/tmp/#{request.uri.host.to_s}.txt") }) ``` ### Responses with dynamically evaluated parts ```ruby stub_request(:any, 'www.example.net'). to_return(body: lambda { |request| request.body }) RestClient.post('www.example.net', 'abc') # ===> "abc\n" ``` ### Rack responses ```ruby class MyRackApp def self.call(env) [200, {}, ["Hello"]] end end stub_request(:get, "www.example.com").to_rack(MyRackApp) RestClient.post('www.example.com') # ===> "Hello" ``` ### Raising errors #### Exception declared by class ```ruby stub_request(:any, 'www.example.net').to_raise(StandardError) RestClient.post('www.example.net', 'abc') # ===> StandardError ``` #### or by exception instance ```ruby stub_request(:any, 'www.example.net').to_raise(StandardError.new("some error")) ``` #### or by string ```ruby stub_request(:any, 'www.example.net').to_raise("some error") ``` ### Raising timeout errors ```ruby stub_request(:any, 'www.example.net').to_timeout RestClient.post('www.example.net', 'abc') # ===> RestClient::RequestTimeout ``` ### Multiple responses for repeated requests ```ruby stub_request(:get, "www.example.com"). to_return({body: "abc"}, {body: "def"}) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" #after all responses are used the last response will be returned infinitely Net::HTTP.get('www.example.com', '/') # ===> "def\n" ``` ### Multiple responses using chained `to_return()`, `to_raise()` or `to_timeout` declarations ```ruby stub_request(:get, "www.example.com"). to_return({body: "abc"}).then. #then() is just a syntactic sugar to_return({body: "def"}).then. to_raise(MyException) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" Net::HTTP.get('www.example.com', '/') # ===> MyException raised ``` ### Specifying number of times given response should be returned ```ruby stub_request(:get, "www.example.com"). to_return({body: "abc"}).times(2).then. to_return({body: "def"}) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" ``` ### Removing unused stubs ```ruby stub_get = stub_request(:get, "www.example.com") remove_request_stub(stub_get) ``` ### Real requests to network can be allowed or disabled ```ruby WebMock.allow_net_connect! stub_request(:any, "www.example.com").to_return(body: "abc") Net::HTTP.get('www.example.com', '/') # ===> "abc" Net::HTTP.get('www.something.com', '/') # ===> /.+Something.+/ WebMock.disable_net_connect! Net::HTTP.get('www.something.com', '/') # ===> Failure ``` ### External requests can be disabled while allowing localhost ```ruby WebMock.disable_net_connect!(allow_localhost: true) Net::HTTP.get('www.something.com', '/') # ===> Failure Net::HTTP.get('localhost:9887', '/') # ===> Allowed. Perhaps to Selenium? ``` ### External requests can be disabled while allowing specific requests Allowed requests can be specified in a number of ways. With a `String` specifying a host name: ```ruby WebMock.disable_net_connect!(allow: 'www.example.org') RestClient.get('www.something.com', '/') # ===> Failure RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('www.example.org:8080', '/') # ===> Allowed ``` With a `String` specifying a host name and a port: ```ruby WebMock.disable_net_connect!(allow: 'www.example.org:8080') RestClient.get('www.something.com', '/') # ===> Failure RestClient.get('www.example.org', '/') # ===> Failure RestClient.get('www.example.org:8080', '/') # ===> Allowed ``` With a `Regexp` matching the URI: ```ruby WebMock.disable_net_connect!(allow: %r{ample.org/foo}) RestClient.get('www.example.org', '/foo/bar') # ===> Allowed RestClient.get('sample.org', '/foo') # ===> Allowed RestClient.get('sample.org', '/bar') # ===> Failure ``` With an object that responds to `#call`, receiving a `URI` object and returning a boolean: ```ruby denylist = ['google.com', 'facebook.com', 'apple.com'] allowed_sites = lambda{|uri| denylist.none?{|site| uri.host.include?(site) } } WebMock.disable_net_connect!(allow: allowed_sites) RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('www.facebook.com', '/') # ===> Failure RestClient.get('apple.com', '/') # ===> Failure ``` With an `Array` of any of the above: ```ruby WebMock.disable_net_connect!(allow: [ lambda{|uri| uri.host.length % 2 == 0 }, /ample.org/, 'bbc.co.uk', ]) RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('bbc.co.uk', '/') # ===> Allowed RestClient.get('bbc.com', '/') # ===> Allowed RestClient.get('www.bbc.com', '/') # ===> Failure ``` ## Connecting on Net::HTTP.start HTTP protocol has 3 steps: connect, request and response (or 4 with close). Most Ruby HTTP client libraries treat connect as a part of request step, with the exception of `Net::HTTP` which allows opening connection to the server separately to the request, by using `Net::HTTP.start`. WebMock API was also designed with connect being part of request step, and it only allows stubbing requests, not connections. When `Net::HTTP.start` is called, WebMock doesn't know yet whether a request is stubbed or not. WebMock by default delays a connection until the request is invoked, so when there is no request, `Net::HTTP.start` doesn't do anything. **This means that WebMock breaks the Net::HTTP behaviour by default!** To workaround this issue, WebMock offers `:net_http_connect_on_start` option, which can be passed to `WebMock.allow_net_connect!` and `WebMock.disable_net_connect!` methods, i.e. ```ruby WebMock.allow_net_connect!(net_http_connect_on_start: true) ``` This forces WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`. ## Setting Expectations ### Setting expectations in Test::Unit ```ruby require 'webmock/test_unit' stub_request(:any, "www.example.com") uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Content-Length'] = 3 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'abc') end assert_requested :post, "http://www.example.com", headers: {'Content-Length' => 3}, body: "abc", times: 1 # ===> Success assert_not_requested :get, "http://www.something.com" # ===> Success assert_requested(:post, "http://www.example.com", times: 1) { |req| req.body == "abc" } ``` ### Expecting real (not stubbed) requests ```ruby WebMock.allow_net_connect! Net::HTTP.get('www.example.com', '/') # ===> Success assert_requested :get, "http://www.example.com" # ===> Success ``` ### Setting expectations in Test::Unit on the stub ```ruby stub_get = stub_request(:get, "www.example.com") stub_post = stub_request(:post, "www.example.com") Net::HTTP.get('www.example.com', '/') assert_requested(stub_get) assert_not_requested(stub_post) ``` ### Setting expectations in RSpec on `WebMock` module This style is borrowed from [fakeweb-matcher](http://github.com/pat/fakeweb-matcher) ```ruby require 'webmock/rspec' expect(WebMock).to have_requested(:get, "www.example.com"). with(body: "abc", headers: {'Content-Length' => 3}).twice expect(WebMock).not_to have_requested(:get, "www.something.com") expect(WebMock).to have_requested(:post, "www.example.com"). with { |req| req.body == "abc" } # Note that the block with `do ... end` instead of curly brackets won't work! # Why? See this comment https://github.com/bblimke/webmock/issues/174#issuecomment-34908908 expect(WebMock).to have_requested(:get, "www.example.com"). with(query: {"a" => ["b", "c"]}) expect(WebMock).to have_requested(:get, "www.example.com"). with(query: hash_including({"a" => ["b", "c"]})) expect(WebMock).to have_requested(:get, "www.example.com"). with(body: {"a" => ["b", "c"]}, headers: {'Content-Type' => 'application/json'}) ``` ### Setting expectations in RSpec with `a_request` ```ruby expect(a_request(:post, "www.example.com"). with(body: "abc", headers: {'Content-Length' => 3})). to have_been_made.once expect(a_request(:post, "www.something.com")).to have_been_made.times(3) expect(a_request(:post, "www.something.com")).to have_been_made.at_least_once expect(a_request(:post, "www.something.com")). to have_been_made.at_least_times(3) expect(a_request(:post, "www.something.com")).to have_been_made.at_most_twice expect(a_request(:post, "www.something.com")).to have_been_made.at_most_times(3) expect(a_request(:any, "www.example.com")).not_to have_been_made expect(a_request(:post, "www.example.com").with { |req| req.body == "abc" }). to have_been_made expect(a_request(:get, "www.example.com").with(query: {"a" => ["b", "c"]})). to have_been_made expect(a_request(:get, "www.example.com"). with(query: hash_including({"a" => ["b", "c"]}))).to have_been_made expect(a_request(:post, "www.example.com"). with(body: {"a" => ["b", "c"]}, headers: {'Content-Type' => 'application/json'})).to have_been_made ``` ### Setting expectations in RSpec on the stub ```ruby stub = stub_request(:get, "www.example.com") # ... make requests ... expect(stub).to have_been_requested ``` ## Clearing stubs and request history If you want to reset all current stubs and history of requests use `WebMock.reset!` ```ruby stub_request(:any, "www.example.com") Net::HTTP.get('www.example.com', '/') # ===> Success WebMock.reset! Net::HTTP.get('www.example.com', '/') # ===> Failure assert_not_requested :get, "www.example.com" # ===> Success ``` ## Clearing request counters If you want to reset **only** the counters of the executed requests use `WebMock.reset_executed_requests!` ```ruby stub = stub_request(:get, "www.example.com") stub2 = stub_request(:get, "www.example2.com") Net::HTTP.get('www.example.com', '/') Net::HTTP.get('www.example.com', '/') Net::HTTP.get('www.example2.com', '/') expect(stub).to have_been_requested.times(2) expect(stub2).to have_been_requested.times(1) WebMock.reset_executed_requests! expect(stub).not_to have_been_requested expect(stub2).not_to have_been_requested ``` ## Disabling and enabling WebMock or only some http client adapters ```ruby # Disable WebMock (all adapters) WebMock.disable! # Disable WebMock for all libs except Net::HTTP WebMock.disable!(except: [:net_http]) # Enable WebMock (all adapters) WebMock.enable! # Enable WebMock for all libs except Patron WebMock.enable!(except: [:patron]) ``` ## Matching requests An executed request matches stubbed request if it passes following criteria: - When request URI matches stubbed request URI string, Regexp pattern or RFC 6570 URI Template - And request method is the same as stubbed request method or stubbed request method is :any - And request body is the same as stubbed request body or stubbed request body is not specified - And request headers match stubbed request headers, or stubbed request headers match a subset of request headers, or stubbed request headers are not specified - And request matches provided block or block is not provided ## Precedence of stubs Always the last declared stub matching the request will be applied i.e: ```ruby stub_request(:get, "www.example.com").to_return(body: "abc") stub_request(:get, "www.example.com").to_return(body: "def") Net::HTTP.get('www.example.com', '/') # ====> "def" ``` ## Matching URIs WebMock will match all different representations of the same URI. I.e all the following representations of the URI are equal: ```ruby "www.example.com" "www.example.com/" "www.example.com:80" "www.example.com:80/" "http://www.example.com" "http://www.example.com/" "http://www.example.com:80" "http://www.example.com:80/" ``` The following URIs with userinfo are also equal for WebMock ```ruby "a b:pass@www.example.com" "a b:pass@www.example.com/" "a b:pass@www.example.com:80" "a b:pass@www.example.com:80/" "http://a b:pass@www.example.com" "http://a b:pass@www.example.com/" "http://a b:pass@www.example.com:80" "http://a b:pass@www.example.com:80/" "a%20b:pass@www.example.com" "a%20b:pass@www.example.com/" "a%20b:pass@www.example.com:80" "a%20b:pass@www.example.com:80/" "http://a%20b:pass@www.example.com" "http://a%20b:pass@www.example.com/" "http://a%20b:pass@www.example.com:80" "http://a%20b:pass@www.example.com:80/" ``` or these ```ruby "www.example.com/my path/?a=my param&b=c" "www.example.com/my%20path/?a=my%20param&b=c" "www.example.com:80/my path/?a=my param&b=c" "www.example.com:80/my%20path/?a=my%20param&b=c" "http://www.example.com/my path/?a=my param&b=c" "http://www.example.com/my%20path/?a=my%20param&b=c" "http://www.example.com:80/my path/?a=my param&b=c" "http://www.example.com:80/my%20path/?a=my%20param&b=c" ``` If you provide Regexp to match URI, WebMock will try to match it against every valid form of the same url. I.e `/my path/` will match `www.example.com/my%20path` because it is equivalent of `www.example.com/my path` ## Matching with URI Templates If you use [Addressable::Template](https://github.com/sporkmonger/addressable#uri-templates) for matching, then WebMock will defer the matching rules to Addressable, which complies with [RFC 6570](http://tools.ietf.org/html/rfc6570). If you use any of the WebMock methods for matching query params, then Addressable will be used to match the base URI and WebMock will match the query params. If you do not, then WebMock will let Addressable match the full URI. ## Matching headers WebMock will match request headers against stubbed request headers in the following situations: 1. Stubbed request has headers specified and request headers are the same as stubbed headers
i.e stubbed headers: `{ 'Header1' => 'Value1', 'Header2' => 'Value2' }`, requested: `{ 'Header1' => 'Value1', 'Header2' => 'Value2' }` 2. Stubbed request has headers specified and stubbed request headers are a subset of request headers
i.e stubbed headers: `{ 'Header1' => 'Value1' }`, requested: `{ 'Header1' => 'Value1', 'Header2' => 'Value2' }` 3. Stubbed request has no headers
i.e stubbed headers: `nil`, requested: `{ 'Header1' => 'Value1', 'Header2' => 'Value2' }` WebMock normalises headers and treats all forms of same headers as equal: i.e the following two sets of headers are equal: `{ "Header1" => "value1", content_length: 123, X_CuStOm_hEAder: :value }` `{ header1: "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }` ## Recording real requests and responses and replaying them later To record your application's real HTTP interactions and replay them later in tests you can use [VCR](https://github.com/vcr/vcr) with WebMock. ## Request callbacks #### WebMock can invoke callbacks stubbed or real requests: ```ruby WebMock.after_request do |request_signature, response| puts "Request #{request_signature} was made and #{response} was returned" end ``` #### invoke callbacks for real requests only and except requests made with Patron ```ruby WebMock.after_request(except: [:patron], real_requests_only: true) do |req_signature, response| puts "Request #{req_signature} was made and #{response} was returned" end ``` ## Bugs and Issues Please submit them here [http://github.com/bblimke/webmock/issues](http://github.com/bblimke/webmock/issues) ## Issue triage [![Open Source Helpers](https://www.codetriage.com/bblimke/webmock/badges/users.svg)](https://www.codetriage.com/bblimke/webmock) You can contribute by triaging issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to webmock on CodeTriage](https://www.codetriage.com/bblimke/webmock). ## Suggestions If you have any suggestions on how to improve WebMock please send an email to the mailing list [groups.google.com/group/webmock-users](http://groups.google.com/group/webmock-users) I'm particularly interested in how the DSL could be improved. ## Development In order to work on Webmock you first need to fork and clone the repo. Please do any work on a dedicated branch and rebase against master before sending a pull request. ## Credits The initial lines of this project were written during New Bamboo [Hack Day](http://blog.new-bamboo.co.uk/2009/11/13/hackday-results) Thanks to my fellow [Bambinos](http://new-bamboo.co.uk/) for all the great suggestions! People who submitted patches and new features or suggested improvements. Many thanks to these people: * Ben Pickles * Mark Evans * Ivan Vega * Piotr Usewicz * Nick Plante * Nick Quaranto * Diego E. "Flameeyes" Pettenò * Niels Meersschaert * Mack Earnhardt * Arvicco * Sergio Gil * Jeffrey Jones * Tekin Suleyman * Tom Ward * Nadim Bitar * Myron Marston * Sam Phillips * Jose Angel Cortinas * Razic * Steve Tooke * Nathaniel Bibler * Martyn Loughran * Muness Alrubaie * Charles Li * Ryan Bigg * Pete Higgins * Hans de Graaff * Alastair Brunton * Sam Stokes * Eugene Bolshakov * James Conroy-Finn * Salvador Fuentes Jr * Alex Rothenberg * Aidan Feldman * Steve Hull * Jay Adkisson * Zach Dennis * Nikita Fedyashev * Lin Jen-Shin * David Yeu * Andreas Garnæs * Roman Shterenzon * Chris McGrath * Stephen Celis * Eugene Pimenov * Albert Llop * Christopher Pickslay * Tammer Saleh * Nicolas Fouché * Joe Van Dyk * Mark Abramov * Frank Schumacher * Dimitrij Denissenko * Marnen Laibow-Koser * Evgeniy Dolzhenko * Nick Recobra * Jordan Elver * Joe Karayusuf * Paul Cortens * jugyo * aindustries * Eric Oestrich * erwanlr * Ben Bleything * Jon Leighton * Ryan Schlesinger * Julien Boyer * Kevin Glowacz * Hans Hasselberg * Andrew France * Jonathan Hyman * Rex Feng * Pavel Forkert * Jordi Massaguer Pla * Jake Benilov * Tom Beauvais * Mokevnin Kirill * Alex Grant * Lucas Dohmen * Bastien Vaucher * Joost Baaij * Joel Chippindale * Murahashi Sanemat Kenichi * Tim Kurvers * Ilya Vassilevsky * gotwalt * Leif Bladt * Alex Tomlins * Mitsutaka Mimura * Tomy Kaira * Daniel van Hoesel * Ian Asaff * Ian Lesperance * Matthew Horan * Dmitry Gutov * Florian Dütsch * Manuel Meurer * Brian D. Burns * Riley Strong * Tamir Duberstein * Stefano Uliari * Alex Stupakov * Karen Wang * Matt Burke * Jon Rowe * Aleksey V. Zapparov * Praveen Arimbrathodiyil * Bo Jeanes * Matthew Conway * Rob Olson * Max Lincoln * Oleg Gritsenko * Hwan-Joon Choi * SHIBATA Hiroshi * Caleb Thompson * Theo Hultberg * Pablo Jairala * Insoo Buzz Jung * Carlos Alonso Pérez * trlorenz * Alexander Simonov * Thorbjørn Hermanse * Mark Lorenz * tjsousa * Tasos Stathopoulos * Dan Buettner * Sven Riedel * Mark Lorenz * Dávid Kovács * fishermand46 * Franky Wahl * ChaYoung You * Simon Russell * Steve Mitchell * Mattias Putman * Zachary Anker * Emmanuel Sambo * Ramon Tayag * Johannes Schlumberger * Siôn Le Roux * Matt Palmer * Zhao Wen * Krzysztof Rygielski * Magne Land * yurivm * Mike Knepper * Charles Pence * Alexey Zapparov * Pablo Brasero * Cedric Pimenta * Michiel Karnebeek * Alex Kestner * Manfred Stienstra * Tim Diggins * Gabriel Chaney * Chris Griego * Taiki Ono * Jonathan Schatz * Jose Luis Honorato * Aaron Kromer * Pavel Jurašek * Jake Worth * Gabe Martin-Dempesy * Michael Grosser * Aleksei Maridashvili * Ville Lautanala * Koichi ITO * Jordan Harband * Tarmo Tänav * Joe Marty * Chris Thomson * Vít Ondruch * George Ulmer * Christof Koenig * Chung-Yi Chi * Olexandr Hoshylyk * Janko Marohnić * Pat Allan * Rick Song * NARUSE, Yui * Piotr Boniecki * Olia Kremmyda * Michał Matyas * Matt Brictson * Kenny Ortmann * redbar0n * Lukas Pokorny * Arkadiy Tetelman * Kazato Sugimoto * Olle Jonsson * Pavel Rosický * Geremia Taglialatela * Koichi Sasada * Yusuke Endoh * Grey Baker * SoonKhen OwYong * Pavel Valena * Adam Sokolnicki * Jeff Felchner * Eike Send * Claudio Poli * Csaba Apagyi * Frederick Cheung * Fábio D. Batista * Andriy Yanko * y-yagi * Rafael França * George Claghorn * Alex Junger * Orien Madgwick * Andrei Sidorov * Marco Costa * Ryan Davis * Brandur * Samuel Williams * Patrik Ragnarsson * Alex Coomans * Vesa Laakso * John Hawthorn * guppy0356 * Thilo Rusche * Andrew Stuntz * Lucas Uyezu * Bruno Sutic * Ryan Kerr * Adam Harwood * Ben Koshy * Jesse Bowes * Marek Kasztelnik * ce07c3 * Jun Jiang * Oleksiy Kovyrin * Matt Larraz * Tony Schneider * Niklas Hösl * Johanna Hartmann * Alex Vondrak * Will Storey * Eduardo Hernandez * ojab * Giorgio Gambino * Timmitry * Michael Fairley * Ray Zane * Go Sueyoshi * Cedric Sohrauer * Akira Matsuda * Mark Spangler For a full list of contributors you can visit the [contributors](https://github.com/bblimke/webmock/contributors) page. ## Background Thank you Fakeweb! This library was inspired by [FakeWeb](https://github.com/chrisk/fakeweb). I imported some solutions from that project to WebMock. I also copied some code i.e Net:HTTP adapter. Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed. I also preferred some things to work differently i.e request stub precedence. ## Copyright Copyright (c) 2009-2010 Bartosz Blimke. See LICENSE for details. webmock-3.18.1/minitest/0000755000004100000410000000000014333126774015131 5ustar www-datawww-datawebmock-3.18.1/minitest/test_webmock.rb0000644000004100000410000000043514333126774020146 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/test_helper') require File.expand_path(File.dirname(__FILE__) + '/../test/shared_test') test_class = defined?(MiniTest::Test) ? MiniTest::Test : MiniTest::Unit::TestCase class MiniTestWebMock < test_class include SharedTest end webmock-3.18.1/minitest/webmock_spec.rb0000644000004100000410000000436514333126774020127 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/test_helper') describe "Webmock" do include HttpRequestTestHelper before do @stub_http = stub_http_request(:any, "http://www.example.com") @stub_https = stub_http_request(:any, "https://www.example.com") end it "should update assertions count" do assert_equal 0, assertions http_request(:get, "http://www.example.com/") assert_requested(@stub_http) assert_equal 2, assertions assert_not_requested(:post, "http://www.example.com") assert_equal 4, assertions end it "should raise error on non stubbed request" do expect { http_request(:get, "http://www.example.net/") }.must_raise(WebMock::NetConnectNotAllowedError) end it "should verify that expected request occured" do http_request(:get, "http://www.example.com/") assert_requested(:get, "http://www.example.com", times: 1) assert_requested(:get, "http://www.example.com") end it "should verify that expected http stub occured" do http_request(:get, "http://www.example.com/") assert_requested(@stub_http, times: 1) assert_requested(@stub_http) end it "should verify that expected https stub occured" do http_request(:get, "https://www.example.com/") http_request(:get, "https://www.example.com/") assert_requested(@stub_https, times: 2) end it "should verify that expect request didn't occur" do expected_message = "The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times" expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================" assert_fail(expected_message) do assert_requested(:get, "http://www.example.com") end end it "should verify that expect stub didn't occur" do expected_message = "The request ANY http://www.example.com/ was expected to execute 1 time but it executed 0 times" expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================" assert_fail(expected_message) do assert_requested(@stub_http) end end end webmock-3.18.1/minitest/test_helper.rb0000644000004100000410000000143714333126774020001 0ustar www-datawww-datarequire 'rubygems' $LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require File.expand_path(File.dirname(__FILE__) + '/../test/http_request') gem 'minitest' require 'minitest/autorun' require 'webmock/minitest' test_class = defined?(MiniTest::Test) ? MiniTest::Test : MiniTest::Unit::TestCase test_class.class_eval do def assert_raise(*exp, &block) assert_raises(*exp, &block) end def assert_raise_with_message(e, message, &block) e = assert_raises(e, &block) if message.is_a?(Regexp) assert_match(message, e.message) else assert_equal(message, e.message) end end def assert_fail(message, &block) assert_raise_with_message(MiniTest::Assertion, message, &block) end end webmock-3.18.1/spec/0000755000004100000410000000000014333126774014227 5ustar www-datawww-datawebmock-3.18.1/spec/quality_spec.rb0000644000004100000410000000536214333126774017264 0ustar www-datawww-datarequire "spec_helper" # Borrowed from Bundler # https://github.com/carlhuda/bundler/blob/1-0-stable/spec/quality_spec.rb # Portions copyright (c) 2010 Andre Arko # Portions copyright (c) 2009 Engine Yard # MIT License # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. describe "The library itself" do def check_for_tab_characters(filename) failing_lines = [] File.readlines(filename).each_with_index do |line,number| failing_lines << number + 1 if line =~ /\t/ end unless failing_lines.empty? "#{filename} has tab characters on lines #{failing_lines.join(', ')}" end end def check_for_extra_spaces(filename) failing_lines = [] File.readlines(filename).each_with_index do |line,number| next if line =~ /^\s+#.*\s+\n$/ failing_lines << number + 1 if line =~ /\s+\n$/ end unless failing_lines.empty? "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}" end end RSpec::Matchers.define :be_well_formed do failure_message do |actual| actual.join("\n") end match do |actual| actual.empty? end end it "has no malformed whitespace" do error_messages = [] Dir.chdir(File.expand_path("../..", __FILE__)) do `git ls-files`.split("\n").each do |filename| next if filename =~ /\.gitmodules|fixtures/ error_messages << check_for_tab_characters(filename) error_messages << check_for_extra_spaces(filename) end end expect(error_messages.compact).to be_well_formed end it "can still be built" do Dir.chdir(File.expand_path('../../', __FILE__)) do `gem build webmock.gemspec` expect($?).to eq(0) # clean up the .gem generated system("rm webmock-#{WebMock.version}.gem") end end end webmock-3.18.1/spec/fixtures/0000755000004100000410000000000014333126774016100 5ustar www-datawww-datawebmock-3.18.1/spec/fixtures/test.txt0000644000004100000410000000000514333126774017613 0ustar www-datawww-datatest webmock-3.18.1/spec/acceptance/0000755000004100000410000000000014333126774016315 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/typhoeus/0000755000004100000410000000000014333126774020175 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb0000644000004100000410000001053114333126774024603 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/webmock_shared' unless RUBY_PLATFORM =~ /java/ require 'acceptance/typhoeus/typhoeus_hydra_spec_helper' describe "Typhoeus::Hydra" do include TyphoeusHydraSpecHelper let(:hydra) { Typhoeus::Hydra.new } before do Typhoeus::Expectation.clear end include_context "with WebMock" describe "Typhoeus::Hydra features" do before(:each) do WebMock.disable_net_connect! WebMock.reset! end describe "supposed response fields" do it "present" do stub_request(:get, "http://www.example.com").to_return(headers: {'X-Test' => '1'}) response = Typhoeus.get("http://www.example.com") expect(response.code).not_to be_nil expect(response.status_message).not_to be_nil expect(response.body).not_to be_nil expect(response.headers).not_to be_nil expect(response.effective_url).not_to be_nil end end describe "when params are used" do it "should take into account params for POST request" do stub_request(:post, "www.example.com/?hello=world").with(query: {hello: 'world'}) request = Typhoeus::Request.new("http://www.example.com", method: :post, params: {hello: 'world'}) hydra.queue(request) hydra.run end it "should take into account body for POST request" do stub_request(:post, "www.example.com").with(body: {hello: 'world'}) response = Typhoeus.post("http://www.example.com", method: :post, body: {hello: 'world'}) expect(response.code).to eq(200) end it "should take into account params for GET request" do stub_request(:get, "http://www.example.com/?hello=world").to_return({}) request = Typhoeus::Request.new("http://www.example.com/?hello=world", method: :get) hydra.queue(request) hydra.run end end describe "timeouts" do it "should support native typhoeus timeouts" do stub_request(:any, "example.com").to_timeout request = Typhoeus::Request.new("http://example.com", method: :get) hydra.queue(request) hydra.run expect(request.response).to be_timed_out end end describe "callbacks" do before(:each) do @request = Typhoeus::Request.new("http://example.com") end it "should call on_complete with 2xx response" do body = "on_success fired" stub_request(:any, "example.com").to_return(body: body) test = nil Typhoeus.on_complete do |c| test = c.body end hydra.queue @request hydra.run expect(test).to eq(body) end it "should call on_complete with 5xx response" do response_code = 599 stub_request(:any, "example.com").to_return(status: [response_code, "Server On Fire"]) test = nil Typhoeus.on_complete do |c| test = c.code end hydra.queue @request hydra.run expect(test).to eq(response_code) end it "should call on_body with 2xx response" do body = "on_body fired" stub_request(:any, "example.com").to_return(body: body) test_body = nil test_complete = nil skip("This test requires a newer version of Typhoeus") unless @request.respond_to?(:on_body) @request.on_body do |body_chunk, response| test_body = body_chunk end @request.on_complete do |response| test_complete = response.body end hydra.queue @request hydra.run expect(test_body).to eq(body) expect(test_complete).to eq("") end it "should call on_headers with 2xx response" do body = "on_headers fired" stub_request(:any, "example.com").to_return(body: body, headers: {'X-Test' => '1'}) test_headers = nil skip("This test requires a newer version of Typhoeus") unless @request.respond_to?(:on_headers) @request.on_headers do |response| test_headers = response.headers end hydra.queue @request hydra.run expect(test_headers.to_h).to include('X-Test' => '1') end end end end end webmock-3.18.1/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb0000644000004100000410000000267114333126774026150 0ustar www-datawww-datarequire 'ostruct' module TyphoeusHydraSpecHelper class FakeTyphoeusHydraTimeoutError < StandardError; end class FakeTyphoeusHydraConnectError < StandardError; end def http_request(method, uri, options = {}, &block) uri = uri.gsub(" ", "%20") #typhoeus doesn't like spaces in the uri request_options = { method: method, body: options[:body], headers: options[:headers], timeout: 25000 } if options[:basic_auth] request_options[:userpwd] = options[:basic_auth].join(':') end request = Typhoeus::Request.new(uri, request_options) hydra = Typhoeus::Hydra.new hydra.queue(request) hydra.run response = request.response raise FakeTyphoeusHydraConnectError.new if response.return_code == :couldnt_connect raise FakeTyphoeusHydraTimeoutError.new if response.timed_out? OpenStruct.new({ body: response.body, headers: WebMock::Util::Headers.normalize_headers(join_array_values(response.headers)), status: response.code.to_s, message: response.status_message }) end def join_array_values(hash) joined = {} if hash hash.each do |k,v| v = v.join(", ") if v.is_a?(Array) joined[k] = v end end joined end def client_timeout_exception_class FakeTyphoeusHydraTimeoutError end def connection_refused_exception_class FakeTyphoeusHydraConnectError end def http_library :typhoeus end end webmock-3.18.1/spec/acceptance/webmock_shared.rb0000644000004100000410000000261714333126774021625 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/shared/enabling_and_disabling_webmock' require 'acceptance/shared/returning_declared_responses' require 'acceptance/shared/callbacks' require 'acceptance/shared/request_expectations' require 'acceptance/shared/stubbing_requests' require 'acceptance/shared/allowing_and_disabling_net_connect' require 'acceptance/shared/precedence_of_stubs' require 'acceptance/shared/complex_cross_concern_behaviors' unless defined? SAMPLE_HEADERS SAMPLE_HEADERS = { "Content-Length" => "8888", "Accept" => "application/json" } ESCAPED_PARAMS = "x=ab%20c&z=%27Stop%21%27%20said%20Fred%20m" NOT_ESCAPED_PARAMS = "z='Stop!' said Fred m&x=ab c" end shared_examples "with WebMock" do |*adapter_info| describe "with WebMock" do let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"} before(:each) do WebMock.disable_net_connect! WebMock.reset! end include_context "allowing and disabling net connect", *adapter_info include_context "stubbing requests", *adapter_info include_context "declared responses", *adapter_info include_context "precedence of stubs", *adapter_info include_context "request expectations", *adapter_info include_context "callbacks", *adapter_info include_context "enabled and disabled webmock", *adapter_info include_context "complex cross-concern behaviors", *adapter_info end end webmock-3.18.1/spec/acceptance/shared/0000755000004100000410000000000014333126774017563 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/shared/complex_cross_concern_behaviors.rb0000644000004100000410000000246314333126774026546 0ustar www-datawww-datashared_context "complex cross-concern behaviors" do |*adapter_info| it 'allows a response with multiple values for the same header to be recorded and played back exactly as-is' do WebMock.allow_net_connect! recorded_response = nil WebMock.after_request { |_,r| recorded_response = r } real_response = http_request(:get, webmock_server_url) stub_request(:get, webmock_server_url).to_return( status: recorded_response.status, body: recorded_response.body, headers: recorded_response.headers ) played_back_response = http_request(:get, webmock_server_url) expect(played_back_response.headers.keys).to include('Set-Cookie') expect(played_back_response).to eq(real_response) end let(:no_content_url) { 'https://httpstat.us/204' } [nil, ''].each do |stub_val| it "returns the same value (nil or "") for a request stubbed as #{stub_val.inspect} that a real empty response has", net_connect: true do unless http_library == :curb WebMock.allow_net_connect! real_response = http_request(:get, no_content_url) stub_request(:get, no_content_url).to_return(status: 204, body: stub_val) stubbed_response = http_request(:get, no_content_url) expect(stubbed_response.body).to eq(real_response.body) end end end end webmock-3.18.1/spec/acceptance/shared/stubbing_requests.rb0000644000004100000410000007561514333126774023676 0ustar www-datawww-data# 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") expect(http_request(:get, "http://www.example.com/hello%2B/?#{ESCAPED_PARAMS}").body).to eq("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") expect(http_request(:get, "http://www.example.com/?a=1").body).to eq("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") expect(http_request(:get, "http://www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}").body).to eq("abc") end it "should return stubbed response for url with non utf query params" do param = 'aäoöuü'.encode('iso-8859-1') param = CGI.escape(param) stub_request(:get, "www.example.com/?#{param}").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/?#{param}").body).to eq("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") expect(http_request(:get, "http://www.example.com/hello/?#{ESCAPED_PARAMS}").body).to eq("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 expect(e.message).to match(/Unregistered request: GET http:\/\/www\.example\.com\/hello\+\/\?x=ab%20c&z='Stop!'%20said%20Fred%20m/m) expect(e.message).to 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") expect(http_request(:get, "http://www.example.com/?a[]=b+x&a[]=c%20d").body).to eq("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") expect(http_request(:get, "http://www.example.com/?a[]=b&a[]=c").body).to eq("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") expect(http_request(:get, "http://www.example.com/?x=3&a[]=b&a[]=c").body).to eq("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") expect(http_request(:get, "http://www.example.com/?a[]=b&a[]=c&b=1").body).to eq("abc") end it 'should return stubbed response when stub expects exclude part of query params' do stub_request(:get, 'www.example.com').with(query: hash_excluding(a: ['b', 'c'])).to_return(body: 'abc') expect(http_request(:get, 'http://www.example.com/?a[]=c&a[]=d&b=1').body).to eq('abc') end it "should return stubbed response when stub expects an empty array" do stub_request(:get, 'www.example.com').with(query: { a: [] }).to_return(body: 'abc') expect(http_request(:get, 'http://www.example.com/?a[]').body).to eq('abc') end end describe "based on method" do it "should return stubbed response" do stub_request(:get, "www.example.com") expect(http_request(:get, "http://www.example.com/").status).to eq("200") end it "should match stubbed request when http request was made with method given as string" do stub_request(:get, "www.example.com") expect(http_request('get', "http://www.example.com/").status).to eq("200") end it "should raise error if stubbed request has different method" do stub_request(:get, "www.example.com") expect(http_request(:get, "http://www.example.com/").status).to eq("200") expect { http_request(:delete, "http://www.example.com/") }.to 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") expect(http_request( :post, "http://www.example.com/", body: "abc").status).to eq("200") end it "should match requests if body is not set in the stub" do stub_request(:post, "www.example.com") expect(http_request( :post, "http://www.example.com/", body: "abc").status).to eq("200") end it "should not match requests if body is different" do stub_request(:post, "www.example.com").with(body: "abc") expect { http_request(:post, "http://www.example.com/", body: "def") }.to 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$/) expect(http_request( :post, "http://www.example.com/", body: "123abc").status).to eq("200") end it "should not match requests if body doesn't match regexp" do stub_request(:post, "www.example.com").with(body: /^abc/) expect { http_request(:post, "http://www.example.com/", body: "xabc") }.to 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 expect(http_request( :post, "http://www.example.com/", body: 'a=1&c[d][]=e&c[d][]=f&b=five+x').status).to eq("200") end it "should match request if hash matches body in different order of params" do expect(http_request( :post, "http://www.example.com/", body: 'a=1&c[d][]=e&b=five+x&c[d][]=f').status).to eq("200") end it "should not match if hash doesn't match url encoded body" do expect { http_request( :post, "http://www.example.com/", body: 'c[d][]=f&a=1&c[d][]=e') }.to 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 describe "for request with form url encoded body and content type" do it "should match if stubbed request body hash has string values matching string values in request body" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => '1'}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "foo=1").status).to eq("200") end it "should match if stubbed request body hash has NON string values matching string values in request body" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => 1}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "foo=1").status).to eq("200") end it "should match if stubbed request body is hash_included" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => hash_including("bar" => '1')}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "foo[bar]=1").status).to eq("200") end end end describe "for request with json body and content type is set to json" do it "should match if hash matches body" do expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five x\"}").status).to eq("200") end it "should match if hash matches body in different form" do expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"b\":\"five x\",\"c\":{\"d\":[\"e\",\"f\"]}}").status).to eq("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"}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":\"2010-01-01\"}").status).to eq("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"}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":\"a b c\"}").status).to eq("200") end it "should match if stubbed request body hash has NON string values matching NON string values in request body" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => 1}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":1}").status).to eq("200") end it "should not match if stubbed request body hash has string values matching NON string values in request body" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => '1'}) expect{http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":1}") }.to raise_error(WebMock::NetConnectNotAllowedError) end it "should not match if stubbed request body hash has NON string values matching string values in request body" do WebMock.reset! stub_request(:post, "www.example.com").with(body: {"foo" => 1}) expect{http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":\"1\"}") }.to raise_error(WebMock::NetConnectNotAllowedError) 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 expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n \n e\n f\n \n\n").status).to eq("200") end it "should match if hash matches body in different form" do expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n \n e\n f\n \n\n").status).to eq("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"}}) expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n\n").status).to eq("200") end end end describe "when body is declared as partial hash matcher" do subject(:request) { http_request( :post, "http://www.example.com/", body: 'a=1&c[d][]=e&c[d][]=f&b=five') } subject(:wrong_request) { http_request(:post, "http://www.example.com/", body: 'c[d][]=f&a=1&c[d][]=e').status } describe "when using 'RSpec:Mocks::ArgumentMatchers#hash_including'" do before(:each) do stub_request(:post, "www.example.com"). with(body: hash_including(:a, c: {'d' => ['e', 'f']} )) end describe "for request with url encoded body" do it "should match request if hash matches body" do expect(request.status).to eq("200") end it "should not match if hash doesn't match url encoded body" do expect { wrong_request }.to raise_error(WebMock::NetConnectNotAllowedError) end end describe "for request with json body and content type is set to json" do it "should match if hash matches body" do expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}").status).to eq("200") end end end describe "when using 'WebMock::API#hash_including'" do before(:each) do stub_request(:post, "www.example.com"). with(body: WebMock::API.hash_including(:a, c: {'d' => ['e', 'f']} )) end describe "for request with url encoded body" do it "should match request if hash matches body" do expect(request.status).to eq("200") end it "should not match if hash doesn't match url encoded body" do expect { wrong_request }.to raise_error(WebMock::NetConnectNotAllowedError) end end describe "for request with json body and content type is set to json" do it "should match if hash matches body" do expect(http_request( :post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}").status).to eq("200") end 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 ) expect(http_request( :get, "http://www.example.com/", headers: SAMPLE_HEADERS).status).to eq("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"]} ) expect(http_request( :get, "http://www.example.com/", headers: {"a" => "b"}).status).to eq("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"]} ) expect(http_request( :get, "http://www.example.com/", headers: {"a" => ["b", "c"]}).status).to eq("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"]} ) expect(http_request( :get, "http://www.example.com/", headers: {"a" => ["c", "b"]}).status).to eq("200") end it "should not match requests if headers are different" do stub_request(:get, "www.example.com").with(headers: {"a" => ["b", "c"]}) expect { http_request( :get, "http://www.example.com/", headers: {"a" => ["b", "d"]}) }.to 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") expect(http_request( :get, "http://www.example.com/", headers: SAMPLE_HEADERS).status).to eq("200") end it "should not match requests if headers are different" do stub_request(:get, "www.example.com").with(headers: SAMPLE_HEADERS) expect { http_request( :get, "http://www.example.com/", headers: { 'Content-Length' => '9999'}) }.to 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'}) expect { http_request( :get, "http://www.example.com/", headers: { 'Accept' => 'application/xml'}) }.to 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$/ }) expect(http_request( :get, "http://www.example.com/", headers: { 'some-header' => 'MyAppName' }).status).to eq("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$/ }) expect { http_request( :get, "http://www.example.com/", headers: { 'some-header' => 'xMyAppName' }) }.to 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 userinfo in url", 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") expect(http_request(:get, "http://user:pass@www.example.com/").status).to eq("200") end it "should not match if credentials are different" do stub_request(:get, "user:pass@www.example.com") expect { expect(http_request(:get, "http://user:pazz@www.example.com/").status).to eq("200") }.to 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") expect { expect(http_request(:get, "http://www.example.com/").status).to eq("200") }.to 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") expect { expect(http_request(:get, "http://user:pazz@www.example.com/").status).to eq("200") }.to 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 request has credentials provided in basic authentication herader" do stub_request(:get, "user:pass@www.example.com") expect { expect(http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']).status).to eq("200") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/ with headers)) end end describe "when stubbing request with basic authentication header" do it "should match if credentials are the same" do stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) expect(http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']).status).to eq("200") end it "should match if credentials are the same and encode to more than one line" do stub_request(:get, "www.example.com").with(basic_auth: ['user' * 5, 'pass' * 5]) expect(http_request(:get, "http://www.example.com/", basic_auth: ['user' * 5, 'pass' * 5]).status).to eq("200") end it "should match if credentials are the same and were provided directly as authentication headers in request" do stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) expect(http_request(:get, "http://www.example.com/", headers: {'Authorization'=>'Basic dXNlcjpwYXNz'}).status).to eq("200") end it "should match if credentials are the same and have been declared in the stub as encoded header" do stub_request(:get, "www.example.com").with(headers: {'Authorization'=>'Basic dXNlcjpwYXNz'}) expect(http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']).status).to eq("200") end it "should not match if credentials are different" do stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) expect { expect(http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pazz']).status).to eq("200") }.to 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 credentials are stubbed but not provided in the request" do stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) expect { expect(http_request(:get, "http://www.example.com/").status).to eq("200") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/)) end it "should match if credentials are not stubbed but exist in the request" do stub_request(:get, "www.example.com") expect(http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']).status).to eq("200") end it "should not match if request has credentials provides in userinfo", unless: (adapter_info.include?(:no_url_auth)) do stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) expect { expect(http_request(:get, "http://user:pass@www.example.com/").status).to eq("200") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://user:pass@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 expect(http_request(:get, "http://www.example.com/").body).to eq("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! expect(http_request(:get, "http://www.example.com/").body).to eq("global stub body") end it "does not stub the request if the hook does not return anything" do WebMock.globally_stub_request { |r| } expect { http_request(:get, "http://www.example.com/") }.to 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") expect(passed_request.uri.to_s).to eq("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/") expect(call_count).to eq(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 expect(http_request(:get, "http://www.example.com/").body).to eq("global stub body") expect(stub_invocation_order).to 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' } }) expect(http_request(:get, "http://www.example.com/").body).to eq("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 }) expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body") end end end context "when global stub should be invoked last" do before do WebMock.globally_stub_request(:after_local_stubs) do { body: "global stub body" } end end it "uses global stub when non-global stub is not defined" do expect(http_request(:get, "http://www.example.com/").body).to eq("global stub body") end it "uses non-global stub first" do stub_request(:get, "www.example.com").to_return(body: 'non-global stub body') expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body") 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 } expect(http_request(:get, "http://www.example.com/").status).to eq("200") end it "should not match if block returns false" do stub_request(:get, "www.example.com").with { |request| false } expect { http_request(:get, "http://www.example.com/") }.to 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" } expect(http_request( :post, "http://www.example.com/", body: "wadus").status).to eq("200") expect { http_request(:post, "http://www.example.com/", body: "jander") }.to 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 } expect(http_request(:get, "http://www.example.com/").status).to eq("200") expect(call_count).to eq(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) expect { http_request(:get, "http://www.example.com/") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/)) end end describe "in Rspec around(:each) hook" do # order goes # around(:each) # before(:each) # after(:each) # anything after example.run in around(:each) around(:each) do |example| example.run expect { http_request(:get, "http://www.example.com/") }.to_not raise_error # WebMock::NetConnectNotAllowedError end it "should still allow me to make a mocked request" do stub_request(:get, "www.example.com") end end end webmock-3.18.1/spec/acceptance/shared/enabling_and_disabling_webmock.rb0000644000004100000410000000470514333126774026242 0ustar www-datawww-datashared_context "enabled and disabled webmock" do |*adapter_info| describe "when webmock is disabled" do before(:each) do WebMock.disable! end after(:each) do WebMock.enable! end include_context "disabled WebMock" end describe "when webmock is enabled again" do before(:each) do WebMock.disable! WebMock.enable! end include_context "enabled WebMock" end describe "when webmock is disabled except this lib" do before(:each) do WebMock.disable!(except: [http_library]) end after(:each) do WebMock.enable! end include_context "enabled WebMock" end describe "when webmock is enabled except this lib" do before(:each) do WebMock.disable! WebMock.enable!(except: [http_library]) end after(:each) do WebMock.enable! end include_context "disabled WebMock" end end shared_context "disabled WebMock" do it "should not register executed requests" do http_request(:get, webmock_server_url) expect(a_request(:get, webmock_server_url)).not_to have_been_made end it "should not block unstubbed requests" do expect { http_request(:get, webmock_server_url) }.not_to raise_error end it "should return real response even if there are stubs" do stub_request(:get, /.*/).to_return(body: "x") expect(http_request(:get, webmock_server_url).body).to eq("hello world") end it "should not invoke any callbacks" do WebMock.reset_callbacks stub_request(:get, webmock_server_url) @called = nil WebMock.after_request { @called = 1 } http_request(:get, webmock_server_url) expect(@called).to eq(nil) end end shared_context "enabled WebMock" do it "should register executed requests" do WebMock.allow_net_connect! http_request(:get, webmock_server_url) expect(a_request(:get, webmock_server_url)).to have_been_made end it "should block unstubbed requests" do expect { http_request(:get, "http://www.example.com/") }.to raise_error(WebMock::NetConnectNotAllowedError) end it "should return stubbed response" do stub_request(:get, /.*/).to_return(body: "x") expect(http_request(:get, "http://www.example.com/").body).to eq("x") end it "should invoke callbacks" do WebMock.allow_net_connect! WebMock.reset_callbacks @called = nil WebMock.after_request { @called = 1 } http_request(:get, webmock_server_url) expect(@called).to eq(1) end end webmock-3.18.1/spec/acceptance/shared/precedence_of_stubs.rb0000644000004100000410000000126414333126774024114 0ustar www-datawww-datashared_context "precedence of stubs" do |*adapter_info| describe "when choosing a matching request stub" do it "should use the last declared matching request stub" do stub_request(:get, "www.example.com").to_return(body: "abc") stub_request(:get, "www.example.com").to_return(body: "def") expect(http_request(:get, "http://www.example.com/").body).to eq("def") end it "should not be affected by the type of uri or request method" do stub_request(:get, "www.example.com").to_return(body: "abc") stub_request(:any, /.*example.*/).to_return(body: "def") expect(http_request(:get, "http://www.example.com/").body).to eq("def") end end end webmock-3.18.1/spec/acceptance/shared/allowing_and_disabling_net_connect.rb0000644000004100000410000003216414333126774027147 0ustar www-datawww-datashared_context "allowing and disabling net connect" do |*adapter_info| describe "when net connect" do describe "is allowed", net_connect: true do before(:each) do WebMock.allow_net_connect! end it "should make a real web request if request is not stubbed" do expect(http_request(:get, webmock_server_url).status).to eq("200") end it "should make a real https request if request is not stubbed" do unless http_library == :httpclient result = http_request(:get, "https://www.google.com/").body if result.respond_to? :encode result = result.encode( 'UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '' ) end expect(result).to match(/.*google.*/) end end it "should return stubbed response if request was stubbed" do stub_request(:get, "www.example.com").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/").body).to eq("abc") end end describe "is not allowed" do before(:each) do WebMock.disable_net_connect! end it "should return stubbed response if request was stubbed" do stub_request(:get, "www.example.com").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/").body).to eq("abc") end it "should return stubbed response if request with path was stubbed" do stub_request(:get, "www.example.com/hello_world").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/hello_world").body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, "http://www.example.com/") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/)) end end describe "is not allowed with exception for localhost" do before(:each) do WebMock.disable_net_connect!(allow_localhost: true) end it "should return stubbed response if request was stubbed" do stub_request(:get, "www.example.com").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/").body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, "http://www.example.com/") }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/)) end it "should make a real request to localhost" do expect { http_request(:get, "http://localhost:12345/") }.to raise_error(connection_refused_exception_class) end it "should make a real request to 127.0.0.1" do expect { http_request(:get, "http://127.0.0.1:12345/") }.to raise_error(connection_refused_exception_class) end it "should make a real request to 0.0.0.0" do expect { http_request(:get, "http://0.0.0.0:12345/") }.to raise_error(connection_refused_exception_class) end end describe "is not allowed, with exceptions" do describe "allowing by host string" do before :each do WebMock.disable_net_connect!(allow: 'https://httpstat.us') end context "when the host is not allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'disallowed.example.com/foo').to_return(body: "abc") expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, 'http://disallowed.example.com/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com)) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc") expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc") end # WARNING: this makes a real HTTP request! it "should make a real request to allowed host", net_connect: true do expect(http_request(:get, "https://httpstat.us/200").status).to eq('200') end end end describe "allowing by host:port string" do def replace_with_different_port(uri) uri.sub(%r{:(\d+)}){|m0, m1| ':' + ($~[1].to_i + 1).to_s } end let(:allowed_host_with_port) { WebMockServer.instance.host_with_port } let(:disallowed_host_with_port) { replace_with_different_port(allowed_host_with_port) } before :each do WebMock.disable_net_connect!(allow: allowed_host_with_port) end context "when the host is not allowed" do it "should return stubbed response if request was stubbed" do request_url = "http://#{disallowed_host_with_port}/foo" stub_request(:get, request_url).to_return(body: "abc") expect(http_request(:get, request_url).body).to eq("abc") end it "should raise exception if request was not stubbed" do request_url = "http://#{disallowed_host_with_port}/foo" expect { http_request(:get, request_url) }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET #{request_url})) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do request_url = "http://#{allowed_host_with_port}/foo" stub_request(:get, request_url).to_return(body: "abc") expect(http_request(:get, request_url).body).to eq('abc') end it "should make a real request to allowed host", net_connect: true do request_url = "http://#{allowed_host_with_port}/foo" expect(http_request(:get, request_url).status).to eq('200') end end end describe "allowing by scheme:host string" do before :each do WebMock.disable_net_connect!(allow: 'https://www.google.pl') end context "when the host and scheme is not allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://disallowed.example.com/foo').to_return(body: "abc") expect(http_request(:get, 'https://disallowed.example.com/foo').body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, 'https://disallowed.example.com/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET https://disallowed.example.com)) end it "should raise exception if request was made to different port" do expect { http_request(:get, 'https://www.google.pl:80/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET https://www.google.pl:80)) end it "should raise exception if request was made to different scheme" do expect { http_request(:get, 'http://www.google.pl/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.google.pl)) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://www.google.pl').to_return(body: "abc") expect(http_request(:get, "https://www.google.pl/").body).to eq("abc") end it "should make a real request to allowed host with scheme", net_connect: true do method = http_library == :httpclient ? :head : :get #https://github.com/nahi/httpclient/issues/299 expect(http_request(method, "https://www.google.pl/").status).to eq('200') end it "should make a real request to allowed host with scheme and port", net_connect: true do method = http_library == :httpclient ? :head : :get expect(http_request(method, "https://www.google.pl:443/").status).to eq('200') end end end describe "allowing by regular expression" do before :each do WebMock.disable_net_connect!(allow: %r{httpstat}) end context "when the host is not allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'disallowed.example.com/foo').to_return(body: "abc") expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, 'http://disallowed.example.com/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com)) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc") expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc") end # WARNING: this makes a real HTTP request! it "should make a real request to allowed host", net_connect: true do expect(http_request(:get, "https://httpstat.us/200").status).to eq('200') end it "should make a real request if request is allowed by path regexp and url contains default port", net_connect: true do WebMock.disable_net_connect!(allow: %r{www.google.pl/webhp}) method = http_library == :httpclient ? :head : :get expect(http_request(method, 'https://www.google.pl:443/webhp').status).to eq('200') end end end describe "allowing by a callable" do before :each do WebMock.disable_net_connect!(allow: lambda{|url| url.to_str.include?('httpstat') }) end context "when the host is not allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'disallowed.example.com/foo').to_return(body: "abc") expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, 'http://disallowed.example.com/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com)) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc") expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc") end # WARNING: this makes a real HTTP request! it "should make a real request to allowed host", net_connect: true do expect(http_request(:get, "https://httpstat.us/200").status).to eq('200') end end end describe "allowing by a list of the above" do before :each do WebMock.disable_net_connect!(allow: [lambda{|_| false }, %r{foobar}, 'https://httpstat.us']) end context "when the host is not allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'disallowed.example.com/foo').to_return(body: "abc") expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc") end it "should raise exception if request was not stubbed" do expect { http_request(:get, 'http://disallowed.example.com/') }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com)) end end context "when the host is allowed" do it "should return stubbed response if request was stubbed" do stub_request(:get, 'https://httpstat.us/200').to_return(body: "abc") expect(http_request(:get, "https://httpstat.us/200").body).to eq("abc") end # WARNING: this makes a real HTTP request! it "should make a real request to allowed host", net_connect: true do expect(http_request(:get, "https://httpstat.us/200").status).to eq('200') end end end end end end webmock-3.18.1/spec/acceptance/shared/request_expectations.rb0000644000004100000410000013060014333126774024366 0ustar www-datawww-datashared_context "request expectations" do |*adapter_info| describe "when request expectations are set" do describe "when net connect is not allowed" do before(:each) do WebMock.disable_net_connect! stub_request(:any, "http://www.example.com") stub_request(:any, "https://www.example.com") end it "should satisfy expectation if request was executed with the same uri and method" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.once }.not_to raise_error end it "should satisfy expectation declared on WebMock.resuest" do expect { http_request(:get, "http://www.example.com/") expect(WebMock.request(:get, "http://www.example.com")).to have_been_made.once }.not_to raise_error end it "should satisfy expectation if request was not expected and not executed" do expect { expect(a_request(:get, "http://www.example.com")).not_to have_been_made }.not_to raise_error end it "should fail if request was not expected but executed" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).not_to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end it "should fail resulting with failure with a message and executed requests listed" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).not_to have_been_made }.to fail_with(%r{The following requests were made:\n\nGET http://www.example.com/.+was made 1 time}) end it "should fail if request was not executed" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed to different uri" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.org")).to have_been_made }.to fail_with(%r(The request GET http://www.example.org/ was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed with different method" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:get, "http://www.example.com")).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times)) end it "should satisfy expectation if request was executed with different form of uri" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "www.example.com")).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with different form of uri without port " do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "www.example.com:80")).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with different form of uri with port" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "www.example.com:80")).to have_been_made }.not_to raise_error end it "should fail if request was executed to a different port" do expect { http_request(:get, "http://www.example.com:80/") expect(a_request(:get, "www.example.com:90")).to have_been_made }.to fail_with(%r(The request GET http://www.example.com:90/ was expected to execute 1 time but it executed 0 times)) end it "should satisfy expectation if request was executed with different form of uri with https port" do expect { http_request(:get, "https://www.example.com/") expect(a_request(:get, "https://www.example.com:443/")).to have_been_made }.not_to raise_error end it "should satisfy expectations even if requests were executed in different order than expectations were declared" do stub_request(:post, "http://www.example.com") http_request(:post, "http://www.example.com/", body: "def") http_request(:post, "http://www.example.com/", body: "abc") expect(WebMock).to have_requested(:post, "www.example.com").with(body: "abc") expect(WebMock).to have_requested(:post, "www.example.com").with(body: "def") end describe "when matching requests with escaped or unescaped uris" do before(:each) do WebMock.disable_net_connect! stub_request(:any, "http://www.example.com/?#{NOT_ESCAPED_PARAMS}") end it "should satisfy expectation if request was executed with escaped params" do expect { http_request(:get, "http://www.example.com/?#{ESCAPED_PARAMS}") expect(a_request(:get, "http://www.example.com/?#{NOT_ESCAPED_PARAMS}")).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with non escaped params" do expect { http_request(:get, "http://www.example.com/?#{NOT_ESCAPED_PARAMS}") expect(a_request(:get, "http://www.example.com/?#{ESCAPED_PARAMS}")).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with escaped params and uri matching regexp was expected" do expect { http_request(:get, "http://www.example.com/?#{ESCAPED_PARAMS}") expect(a_request(:get, /.*example.*/)).to have_been_made }.not_to raise_error end end describe "when matching requests with query params" do before(:each) do stub_request(:any, /.*example.*/) end it "should satisfy expectation if the request was executed with query params declared as a hash in a query option" do expect { http_request(:get, "http://www.example.com/?a[]=b&a[]=c") expect(a_request(:get, "www.example.com").with(query: {"a" => ["b", "c"]})).to have_been_made }.not_to raise_error end it "should satisfy expectation if the request was executed with query params declared as string in query option" do expect { http_request(:get, "http://www.example.com/?a[]=b&a[]=c") expect(a_request(:get, "www.example.com").with(query: "a[]=b&a[]=c")).to have_been_made }.not_to raise_error end it "should satisfy expectation if the request was executed with query params both in uri and in query option" do expect { http_request(:get, "http://www.example.com/?x=3&a[]=b&a[]=c") expect(a_request(:get, "www.example.com/?x=3").with(query: {"a" => ["b", "c"]})).to have_been_made }.not_to raise_error end it "should satisfy expectation if the request was executed with only part query params declared as a hash in a query option" do expect { http_request(:get, "http://www.example.com/?a[]=b&a[]=c&b=1") expect(a_request(:get, "www.example.com").with(query: hash_including({"a" => ["b", "c"]}))).to have_been_made }.not_to raise_error end it 'should satisfy expectation if the request was executed with excluding part of query params declared as a hash in a query option' do expect { http_request(:get, "http://www.example.com/?a[]=d&b[]=e&b=1") expect(a_request(:get, "www.example.com").with(query: hash_excluding(a: ['b', 'c']))).to have_been_made }.not_to raise_error end it 'should satisfy expectation if the request was executed with an empty array in the query params' do expect { http_request(:get, "http://www.example.com/?a[]") expect(a_request(:get, "www.example.com").with(query: hash_including(a: []))).to have_been_made }.not_to raise_error end end context "when using flat array notation" do before :all do WebMock::Config.instance.query_values_notation = :flat_array end it "should satisfy expectation if request includes different repeated query params in flat array notation" do expect { stub_request(:get, "http://www.example.com/?a=1&a=2") http_request(:get, "http://www.example.com/?a=1&a=2") expect(a_request(:get, "http://www.example.com/?a=1&a=2")).to have_been_made }.not_to raise_error end after :all do WebMock::Config.instance.query_values_notation = nil end end describe "at_most_times" do it "fails if request was made more times than maximum" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_times(2) }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute at most 2 times but it executed 3 times)) end it "passes if request was made the maximum number of times" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_times(2) }.not_to raise_error end it "passes if request was made fewer than the maximum number of times" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_times(2) }.not_to raise_error end it "passes if request was not made at all" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_times(2) }.not_to raise_error end end describe "at_least_times" do it "fails if request was made fewer times than minimum" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_times(2) }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute at least 2 times but it executed 1 time)) end it "passes if request was made the minimum number of times" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_times(2) }.not_to raise_error end it "passes if request was made more than the minimum number of times" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_times(2) }.not_to raise_error end context "descriptive at_most_ matcher" do context "at_most_once" do it "succeeds if no request was executed" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_once }.not_to raise_error end it "satisfies expectation if request was executed with the same uri and method once" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_once }.not_to raise_error end it "fails if request was executed with the same uri and method twice" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_once }.to fail end end context "at_most_twice" do it "succeeds if no request was executed" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_twice }.not_to raise_error end it "succeeds if too few requests were executed" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_twice }.not_to raise_error end it "satisfies expectation if request was executed with the same uri and method twice" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_twice }.not_to raise_error end it "fails if request was executed with the same uri and method three times" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_most_twice }.to fail end end end context "descriptive at_least_ matcher" do context "at_least_once" do it "fails if no request was executed" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_once }.to fail end it "satisfies expectation if request was executed with the same uri and method once" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_once }.not_to raise_error end it "satisfies expectation if request was executed with the same uri and method twice" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_once }.not_to raise_error end end context "at_least_twice" do it "fails if no request was executed" do expect { expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_twice }.to fail end it "fails if too few requests were executed" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_twice }.to fail end it "satisfies expectation if request was executed with the same uri and method twice" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_twice }.not_to raise_error end it "satisfies expectation if request was executed with the same uri and method three times" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.at_least_twice }.not_to raise_error end end end end it "should fail if request was made more times than expected" do expect { http_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 1 time but it executed 2 times)) end it "should fail if request was made less times than expected" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.twice }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 2 times but it executed 1 time)) end it "should fail if request was made less times than expected when 3 times expected" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.times(3) }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 3 times but it executed 1 time)) end it "should satisfy expectation if request was executed with the same body" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:post, "www.example.com").with(body: "abc")).to have_been_made }.not_to raise_error end it "should fail if request was executed with different body" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:post, "www.example.com"). with(body: "def")).to have_been_made }.to fail_with(%r(The request POST http://www.example.com/ with body "def" was expected to execute 1 time but it executed 0 times)) end describe "when expected request body is declared as a regexp" do it "should satisfy expectation if request was executed with body matching regexp" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:post, "www.example.com").with(body: /^abc$/)).to have_been_made }.not_to raise_error end it "should fail if request was executed with body not matching regexp" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:post, "www.example.com"). with(body: /^xabc/)).to have_been_made }.to fail_with(%r(The request POST http://www.example.com/ with body /\^xabc/ was expected to execute 1 time but it executed 0 times)) end end describe "when expected reqest body is declared as a hash" do let(:body_hash) { {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}} } let(:fail_message) {%r(The request POST http://www.example.com/ with body .+ was expected to execute 1 time but it executed 0 times)} describe "when request is made with url encoded body matching hash" do it "should satisfy expectation" do expect { http_request(:post, "http://www.example.com/", body: 'a=1&c[d][]=e&c[d][]=f&b=five') expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should satisfy expectation even if url encoded params have different order" do expect { http_request(:post, "http://www.example.com/", body: 'a=1&c[d][]=e&b=five&c[d][]=f') expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should fail if request is executed with url encoded body not matching hash" do expect { http_request(:post, "http://www.example.com/", body: 'c[d][]=f&a=1&c[d][]=e') expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.to fail_with(fail_message) end end describe "when request is executed with json body matching hash and Content-Type is set to json" do it "should satisfy expectation" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}") expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should satisfy expectation even if json body is in different form" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}") expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should satisfy expectation even if json body contains date string" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/json'}, body: "{\"foo\":\"2010-01-01\"}") expect(a_request(:post, "www.example.com").with(body: {"foo" => "2010-01-01"})).to have_been_made }.not_to raise_error end end describe "when request is executed with xml body matching hash and content type is set to xml" do let(:body_hash) { { "opt" => {:a => "1", :b => 'five', 'c' => {'d' => ['e', 'f']}} }} it "should satisfy expectation" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n \n e\n f\n \n\n") expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should satisfy expectation even if xml body is in different form" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n \n e\n f\n \n\n") expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should satisfy expectation even if xml body contains date string" do expect { http_request(:post, "http://www.example.com/", headers: {'Content-Type' => 'application/xml'}, body: "\n\n") expect(a_request(:post, "www.example.com").with(body: {"opt" => {"foo" => "2010-01-01"}})).to have_been_made }.not_to raise_error end end end describe "when expected reqest body is declared as a partial hash matcher" do let(:body_hash) { hash_including({:a => '1', 'c' => {'d' => ['e', 'f']}}) } let(:fail_message) {%r(The request POST http://www.example.com/ with body hash_including(.+) was expected to execute 1 time but it executed 0 times)} describe "when request is made with url encoded body matching hash" do it "should satisfy expectation" do expect { http_request(:post, "http://www.example.com/", body: 'a=1&c[d][]=e&c[d][]=f&b=five') expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.not_to raise_error end it "should fail if request is executed with url encoded body not matching hash" do expect { http_request(:post, "http://www.example.com/", body: 'c[d][]=f&a=1&c[d][]=e') expect(a_request(:post, "www.example.com").with(body: body_hash)).to have_been_made }.to fail_with(fail_message) end end end describe "when request with headers is expected" do it "should satisfy expectation if request was executed with the same headers" do expect { http_request(:get, "http://www.example.com/", headers: SAMPLE_HEADERS) expect(a_request(:get, "www.example.com"). with(headers: SAMPLE_HEADERS)).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with the same headers but with header value declared as array" do expect { http_request(:get, "http://www.example.com/", headers: {"a" => "b"}) expect(a_request(:get, "www.example.com"). with(headers: {"a" => ["b"]})).to have_been_made }.not_to raise_error end describe "when multiple headers with the same key are passed" do it "should satisfy expectation" do expect { http_request(:get, "http://www.example.com/", headers: {"a" => ["b", "c"]}) expect(a_request(:get, "www.example.com"). with(headers: {"a" => ["b", "c"]})).to have_been_made }.not_to raise_error end it "should satisfy expectation even if request was executed with the same headers but different order" do expect { http_request(:get, "http://www.example.com/", headers: {"a" => ["b", "c"]}) expect(a_request(:get, "www.example.com"). with(headers: {"a" => ["c", "b"]})).to have_been_made }.not_to raise_error end it "should fail if request was executed with different headers" do expect { http_request(:get, "http://www.example.com/", headers: {"a" => ["b", "c"]}) expect(a_request(:get, "www.example.com"). with(headers: {"a" => ["b", "d"]})).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ with headers \{'A'=>\['b', 'd'\]\} was expected to execute 1 time but it executed 0 times)) end end it "should fail if request was executed with different headers" do expect { http_request(:get, "http://www.example.com/", headers: SAMPLE_HEADERS) expect(a_request(:get, "www.example.com"). with(headers: { 'Content-Length' => '9999'})).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ with headers \{'Content-Length'=>'9999'\} was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed with less headers" do expect { http_request(:get, "http://www.example.com/", headers: {'A' => 'a'}) expect(a_request(:get, "www.example.com"). with(headers: {'A' => 'a', 'B' => 'b'})).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ with headers \{'A'=>'a', 'B'=>'b'\} was expected to execute 1 time but it executed 0 times)) end it "should satisfy expectation if request was executed with more headers" do expect { http_request(:get, "http://www.example.com/", headers: {'A' => 'a', 'B' => 'b'} ) expect(a_request(:get, "www.example.com"). with(headers: {'A' => 'a'})).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with body and headers but they were not specified in expectantion" do expect { http_request(:post, "http://www.example.com/", body: "abc", headers: SAMPLE_HEADERS ) expect(a_request(:post, "www.example.com")).to have_been_made }.not_to raise_error end it "should satisfy expectation if request was executed with headers matching regular expressions" do expect { http_request(:get, "http://www.example.com/", headers: { 'some-header' => 'MyAppName' }) expect(a_request(:get, "www.example.com"). with(headers: { some_header: /^MyAppName$/ })).to have_been_made }.not_to raise_error end it "should fail if request was executed with headers not matching regular expression" do expect { http_request(:get, "http://www.example.com/", headers: { 'some-header' => 'xMyAppName' }) expect(a_request(:get, "www.example.com"). with(headers: { some_header: /^MyAppName$/ })).to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ with headers \{'Some-Header'=>/\^MyAppName\$/\} was expected to execute 1 time but it executed 0 times)) end end describe "when expectation contains a request matching block" do it "should satisfy expectation if request was executed and block evaluated to true" do expect { http_request(:post, "http://www.example.com/", body: "wadus") expect(a_request(:post, "www.example.com").with { |req| req.body == "wadus" }).to have_been_made }.not_to raise_error end it "should fail if request was executed and block evaluated to false" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(a_request(:post, "www.example.com").with { |req| req.body == "wadus" }).to have_been_made }.to fail_with(%r(The request POST http://www.example.com/ with given block was expected to execute 1 time but it executed 0 times)) end it "should fail if request was not expected but it executed and block matched request" do expect { http_request(:post, "http://www.example.com/", body: "wadus") expect(a_request(:post, "www.example.com").with { |req| req.body == "wadus" }).not_to have_been_made }.to fail_with(%r(The request POST http://www.example.com/ with given block was not expected to execute but it executed 1 time)) end end describe "with userinfo", unless: (adapter_info.include?(:no_url_auth)) do before(:each) do stub_request(:any, "http://user:pass@www.example.com") stub_request(:any, "http://user:pazz@www.example.com") end it "should satisfy expectation if request was executed with expected credentials" do expect { http_request(:get, "http://user:pass@www.example.com/") expect(a_request(:get, "http://user:pass@www.example.com")).to have_been_made.once }.not_to raise_error end it "should fail if request was executed with different credentials than expected" do expect { http_request(:get, "http://user:pass@www.example.com/") expect(a_request(:get, "http://user:pazz@www.example.com")).to have_been_made.once }.to fail_with(%r(The request GET http://user:pazz@www.example.com/ was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed without credentials and credentials were expected" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://user:pass@www.example.com")).to have_been_made.once }.to fail_with(%r(The request GET http://user:pass@www.example.com/ was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed with credentials but expected without credentials" do expect { http_request(:get, "http://user:pass@www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made.once }.to fail_with(%r(The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed with basic auth header but expected with credentials in userinfo" do expect { http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']) expect(a_request(:get, "http://user:pass@www.example.com")).to have_been_made.once }.to fail_with(%r(The request GET http://user:pass@www.example.com/ was expected to execute 1 time but it executed 0 times)) end end describe "with basic authentication header" do before(:each) do stub_request(:any, "http://www.example.com").with(basic_auth: ['user', 'pass']) stub_request(:any, "http://www.example.com").with(basic_auth: ['user', 'pazz']) end it "should satisfy expectation if request was executed with expected credentials" do expect { http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']) expect(a_request(:get, "http://www.example.com").with(basic_auth: ['user', 'pass'])).to have_been_made.once }.not_to raise_error end it "should satisfy expectation if request was executed with expected credentials passed directly as header" do expect { http_request(:get, "http://www.example.com/", headers: {'Authorization'=>'Basic dXNlcjpwYXNz'}) expect(a_request(:get, "http://www.example.com").with(basic_auth: ['user', 'pass'])).to have_been_made.once }.not_to raise_error end it "should fail if request was executed with different credentials than expected" do expect { http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']) expect(a_request(:get, "http://www.example.com").with(basic_auth: ['user', 'pazz'])).to have_been_made.once }.to fail_with(%r(The request GET http://www.example.com/ with headers {'Authorization'=>'Basic dXNlcjpwYXp6'} was expected to execute 1 time but it executed 0 times)) end it "should fail if request was executed without credentials and credentials were expected" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com").with(basic_auth: ['user', 'pass'])).to have_been_made.once }.to fail_with(%r(The request GET http://www.example.com/ with headers {'Authorization'=>'Basic dXNlcjpwYXNz'} was expected to execute 1 time but it executed 0 times)) end it "should not fail if request was executed with credentials but expected despite credentials" do expect { http_request(:get, "http://www.example.com/", basic_auth: ['user', 'pass']) expect(a_request(:get, "http://www.example.com")).to have_been_made.once }.not_to raise_error end it "should fail if request was executed with basic auth header and credentials were provided in url", unless: (adapter_info.include?(:no_url_auth)) do expect { stub_request(:any, "http://user:pass@www.example.com") http_request(:get, "http://user:pass@www.example.com/") expect(a_request(:get, "http://www.example.com").with(basic_auth: ['user', 'pass'])).to have_been_made.once }.to fail_with(%r(The request GET http://www.example.com/ with headers {'Authorization'=>'Basic dXNlcjpwYXNz'} was expected to execute 1 time but it executed 0 times)) end end describe "when expectations were set on WebMock object" do it "should satisfy expectation if expected request was made" do expect { http_request(:get, "http://www.example.com/") expect(WebMock).to have_requested(:get, "http://www.example.com").once }.not_to raise_error end it "should satisfy expectation if request with body and headers was expected and request was made" do expect { http_request(:post, "http://www.example.com/", body: "abc", headers: {'A' => 'a'}) expect(WebMock).to have_requested(:post, "http://www.example.com").with(body: "abc", headers: {'A' => 'a'}).once }.not_to raise_error end it "should fail if request expected not to be made was made" do expect { http_request(:get, "http://www.example.com/") expect(WebMock).not_to have_requested(:get, "http://www.example.com") }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end it "should satisfy expectation if request was executed and expectation had block which evaluated to true" do expect { http_request(:post, "http://www.example.com/", body: "wadus") expect(WebMock).to have_requested(:post, "www.example.com").with { |req| req.body == "wadus" } }.not_to raise_error end it "should fail if request was executed and expectation had block which evaluated to false" do expect { http_request(:post, "http://www.example.com/", body: "abc") expect(WebMock).to have_requested(:post, "www.example.com").with { |req| req.body == "wadus" } }.to fail_with(%r(The request POST http://www.example.com/ with given block was expected to execute 1 time but it executed 0 times)) end it "should fail if request was expected not to be made but was made and block matched request" do expect { http_request(:post, "http://www.example.com/", body: "wadus") expect(WebMock).not_to have_requested(:post, "www.example.com").with { |req| req.body == "wadus" } }.to fail_with(%r(The request POST http://www.example.com/ with given block was not expected to execute but it executed 1 time)) end end describe "when expectation is declared using assert_requested" do it "should satisfy expectation if requests was made" do expect { http_request(:get, "http://www.example.com/") assert_requested(:get, "http://www.example.com", times: 1) assert_requested(:get, "http://www.example.com") }.not_to raise_error end it "should satisfy expectation if request was made with body and headers" do expect { http_request(:post, "http://www.example.com/", body: "abc", headers: {'A' => 'a'}) assert_requested(:post, "http://www.example.com", body: "abc", headers: {'A' => 'a'}) }.not_to raise_error end it "should fail if request expected not to be made was not wade" do expect { http_request(:get, "http://www.example.com/") assert_not_requested(:get, "http://www.example.com") }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end it "should fail if request expected not to be made was made and expectation block evaluated to true" do expect { http_request(:post, "http://www.example.com/", body: "wadus") assert_not_requested(:post, "www.example.com") { |req| req.body == "wadus" } }.to fail_with(%r(The request POST http://www.example.com/ with given block was not expected to execute but it executed 1 time)) end it "should satisfy expectation if request was made and expectation block evaluated to true" do expect { http_request(:post, "http://www.example.com/", body: "wadus") assert_requested(:post, "www.example.com") { |req| req.body == "wadus" } }.not_to raise_error end it "should fail if request was made and expectation block evaluated to false" do expect { http_request(:post, "http://www.example.com/", body: "abc") assert_requested(:post, "www.example.com") { |req| req.body == "wadus" } }.to fail_with(%r(The request POST http://www.example.com/ with given block was expected to execute 1 time but it executed 0 times)) end end describe "when expectation is declared using assert_requested" do it "should satisfy expectation if requests was made" do stub_http = stub_http_request(:get, "http://www.example.com") expect { http_request(:get, "http://www.example.com/") assert_requested(stub_http, times: 1) assert_requested(stub_http) }.not_to raise_error end it "should fail if request expected not to be made was not wade" do stub_http = stub_http_request(:get, "http://www.example.com") expect { http_request(:get, "http://www.example.com/") assert_not_requested(stub_http) }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end end end describe "expectation is set on the request stub" do it "should satisfy expectation if expected request was made" do stub = stub_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(stub).to have_been_requested.once end it "should satisfy expectations if subsequent requests were made" do stub = stub_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(stub).to have_been_requested.once http_request(:get, "http://www.example.com/") expect(stub).to have_been_requested.twice end it "should satisfy expectation if expected request with body and headers was made" do stub = stub_request(:post, "http://www.example.com").with(body: "abc", headers: {'A' => 'a'}) http_request(:post, "http://www.example.com/", body: "abc", headers: {'A' => 'a'}) expect(stub).to have_been_requested.once end it "should fail if request not expected to be made was made" do expect { stub = stub_request(:get, "http://www.example.com") http_request(:get, "http://www.example.com/") expect(stub).not_to have_been_requested }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end it "should fail request not expected to be made was made and expectation block evaluated to true" do expect { stub = stub_request(:post, "www.example.com").with { |req| req.body == "wadus" } http_request(:post, "http://www.example.com/", body: "wadus") expect(stub).not_to have_been_requested }.to fail_with(%r(The request POST http://www.example.com/ with given block was not expected to execute but it executed 1 time)) end it "should satisfy expectation if request was made and expectation block evaluated to true" do stub = stub_request(:post, "www.example.com").with { |req| req.body == "wadus" } http_request(:post, "http://www.example.com/", body: "wadus") expect(stub).to have_been_requested end it "should satisfy expectation if request was made and expectation block evaluated to false" do expect { stub_request(:any, /.+/) #stub any request stub = stub_request(:post, "www.example.com").with { |req| req.body == "wadus" } http_request(:post, "http://www.example.com/", body: "abc") expect(stub).to have_been_requested }.to fail_with(%r(The request POST http://www.example.com/ with given block was expected to execute 1 time but it executed 0 times)) end end describe "when net connect is allowed", net_connect: true do before(:each) do WebMock.allow_net_connect! end it "should satisfy expectation if expected requests was made" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).to have_been_made }.not_to raise_error end it "should fail request expected not to be made, was made" do expect { http_request(:get, "http://www.example.com/") expect(a_request(:get, "http://www.example.com")).not_to have_been_made }.to fail_with(%r(The request GET http://www.example.com/ was not expected to execute but it executed 1 time)) end end end end webmock-3.18.1/spec/acceptance/shared/returning_declared_responses.rb0000644000004100000410000004237214333126774026061 0ustar www-datawww-dataclass MyException < StandardError; end; class Responder def call(request) {body: request.body} end end shared_context "declared responses" do |*adapter_info| describe "when request stub declares that request should raise exception" do it "should raise exception" do stub_request(:get, "www.example.com").to_raise(MyException) expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") end it "should raise exception if declared as and exception instance" do stub_request(:get, "www.example.com").to_raise(MyException.new("hello world")) expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "hello world") end it "should raise exception if declared as an exception instance" do stub_request(:get, "www.example.com").to_raise("hello world") expect { http_request(:get, "http://www.example.com/") }.to raise_error("hello world") end it "should raise exception after returning declared successful response first" do stub_request(:get, "www.example.com").to_return(body: "abc").then.to_raise(MyException) expect(http_request(:get, "http://www.example.com/").body).to eq("abc") expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") end end describe "when request stub declares that request should timeout" do it "should timeout" do stub_request(:get, "www.example.com").to_timeout expect { http_request(:get, "http://www.example.com/") }.to raise_error(client_timeout_exception_class) end it "should timeout after returning declared successful response" do stub_request(:get, "www.example.com").to_return(body: "abc").then.to_timeout expect(http_request(:get, "http://www.example.com/").body).to eq("abc") expect { http_request(:get, "http://www.example.com/") }.to raise_error(client_timeout_exception_class) end end describe "when request stub declares that request should return a response" do it "should return response with declared body" do stub_request(:get, "www.example.com").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/").body).to eq("abc") end it "should return response with declared headers" do stub_request(:get, "www.example.com").to_return(headers: SAMPLE_HEADERS) response = http_request(:get, "http://www.example.com/") expect(response.headers["Accept"]).to eq("application/json") unless adapter_info.include?(:no_content_length_header) expect(response.headers["Content-Length"]).to eq("8888") end end it "should return response with declared headers even if there are multiple headers with the same key" do stub_request(:get, "www.example.com").to_return(headers: {"a" => ["b", "c"]}) response = http_request(:get, "http://www.example.com/") expect(response.headers["A"]).to eq("b, c") end it "should return response with declared status code" do stub_request(:get, "www.example.com").to_return(status: 500) expect(http_request(:get, "http://www.example.com/").status).to eq("500") end it "should return response with declared status message", unless: (adapter_info.include?(:no_status_message)) do stub_request(:get, "www.example.com").to_return(status: [500, "Internal Server Error"]) response = http_request(:get, "http://www.example.com/") expect(response.message).to eq("Internal Server Error") end it "should return response with a default status code" do stub_request(:get, "www.example.com") expect(http_request(:get, "http://www.example.com/").status).to eq("200") end it "should return default response with empty message if response was not declared", unless: (adapter_info.include?(:no_status_message)) do stub_request(:get, "www.example.com") response = http_request(:get, "http://www.example.com/") expect(response.message).to eq("") end describe "when response body was declared as IO" do it "should return response body" do stub_request(:get, "www.example.com").to_return(body: File.new(__FILE__)) expect(http_request(:get, "http://www.example.com/").body).to eq(File.read(__FILE__)) end it "should return response body if requested many times" do stub_request(:get, "www.example.com").to_return(body: File.new(__FILE__)) 2.times do expect(http_request(:get, "http://www.example.com/").body).to eq(File.read(__FILE__)) end end it "should close IO after request" do stub_request(:get, "www.example.com").to_return(body: @file = File.new(__FILE__)) expect(@file).to be_closed end end describe "when response parts were declared as lambdas" do it "should return evaluated response body" do stub_request(:post, "www.example.com").to_return(body: lambda { |request| request.body }) expect(http_request(:post, "http://www.example.com/", body: "echo").body).to eq("echo") end it "should return evaluated response headers" do stub_request(:post, "www.example.com").to_return(headers: lambda { |request| request.headers }) expect(http_request(:post, "http://www.example.com/", body: "abc", headers: {'A' => 'B'}).headers['A']).to eq('B') expect(http_request(:post, "http://www.example.com/", body: "abc", headers: {'A' => 'C'}).headers['A']).to eq('C') end it "should evaluate response body for each request" do stub_request(:post, "www.example.com").to_return(body: lambda { |request| request.body }) expect(http_request(:post, "http://www.example.com/", body: "echo").body).to eq("echo") expect(http_request(:post, "http://www.example.com/", body: "foxtrot").body).to eq("foxtrot") end end describe "when response was declared as lambda" do it "should return evaluated response body" do stub_request(:post, "www.example.com").to_return(lambda {|request| {body: request.body} }) expect(http_request(:post, "http://www.example.com/", body: "echo").body).to eq("echo") expect(http_request(:post, "http://www.example.com/", body: "foxtrot").body).to eq("foxtrot") end it "should return evaluated response headers" do stub_request(:get, "www.example.com").to_return(lambda { |request| {headers: request.headers} }) expect(http_request(:get, "http://www.example.com/", headers: {'A' => 'B'}).headers['A']).to eq('B') end it "should return dynamic response declared as a block" do stub_request(:post, "www.example.com").to_return do |request| {body: request.body} end expect(http_request(:post, "http://www.example.com/", body: "echo").body).to eq("echo") end it "should return dynamic response declared as an object responding to call" do stub_request(:post, "www.example.com").to_return(Responder.new) expect(http_request(:post, "http://www.example.com/", body: "echo").body).to eq("echo") end end describe "when response was declared as a file with a raw response" do before(:each) do @file = File.new(CURL_EXAMPLE_OUTPUT_PATH) stub_request(:get, "www.example.com").to_return(@file) @response = http_request(:get, "http://www.example.com/") end it "should return recorded headers" do if adapter_info.include?(:no_content_length_header) expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) else expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"419", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) end end it "should return recorded body" do expect(@response.body.size).to eq(419) end it "should return recorded status" do expect(@response.status).to eq("202") end it "should return recorded status message", unless: (adapter_info.include?(:no_status_message)) do expect(@response.message).to eq("OK") end it "should ensure file is closed" do expect(@file).to be_closed end end describe "when response was declared as a string with a raw response" do before(:each) do @input = File.read(CURL_EXAMPLE_OUTPUT_PATH) stub_request(:get, "www.example.com").to_return(@input) @response = http_request(:get, "http://www.example.com/") end it "should return recorded headers" do if adapter_info.include?(:no_content_length_header) expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) else expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"419", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) end end it "should return recorded body" do expect(@response.body.size).to eq(419) end it "should return recorded status" do expect(@response.status).to eq("202") end it "should return recorded status message", unless: (adapter_info.include?(:no_status_message)) do expect(@response.message).to eq("OK") end end describe "when response was declared as lambda evaluating to a string with a raw response" do before(:each) do @files = { "www.example.com" => File.new(CURL_EXAMPLE_OUTPUT_PATH) } end it "should return response from evaluated file" do stub_request(:get, "www.example.com").to_return(lambda {|request| @files[request.uri.host.to_s] }) expect(http_request(:get, "http://www.example.com/").body.size).to eq(419) end it "should return response from evaluated string" do stub_request(:get, "www.example.com").to_return(lambda {|request| @files[request.uri.host.to_s].read }) expect(http_request(:get, "http://www.example.com/").body.size).to eq(419) end end describe "when response is declared as an Rack app" do it "should return response returned by the rack app" do stub_request(:any, "http://www.example.com/greet").to_rack(MyRackApp) expect(http_request(:post, 'http://www.example.com/greet', body: 'name=Jimmy').body).to eq('Good to meet you, Jimmy!') end it "should pass along the port number to the rack app" do stub_request(:get, "http://www.example.com/compute").to_rack(MyRackApp) expect(http_request(:get, "http://www.example.com/compute").status).to eq("200") end it "preserves content-type header when proxying to a rack app" do stub_request(:any, //).to_rack(lambda {|req| [200, {}, ["OK"]] }) url = "https://google.com/hi/there" headers = { "Accept" => "application/json", "Content-Type" => "application/json" } http_request(:get, url, headers: headers) expect(WebMock).to have_requested(:get, url).with(headers: headers) end end describe "when sequences of responses are declared" do it "should return responses one by one if declared in array" do stub_request(:get, "www.example.com").to_return([ {body: "1"}, {body: "2"}, {body: "3"} ]) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("3") end it "should repeat returning last declared response from a sequence after all responses were returned" do stub_request(:get, "www.example.com").to_return([ {body: "1"}, {body: "2"} ]) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("2") end it "should return responses one by one if declared as comma separated params" do stub_request(:get, "www.example.com").to_return({body: "1"}, {body: "2"}, {body: "3"}) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("3") end it "should return responses one by one if declared with several to_return invokations" do stub_request(:get, "www.example.com"). to_return({body: "1"}). to_return({body: "2"}). to_return({body: "3"}) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("3") end it "should return responses one by one if declared with to_return invocations separated with then syntactic sugar" do stub_request(:get, "www.example.com").to_return({body: "1"}).then. to_return({body: "2"}).then.to_return({body: "3"}) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("3") end end describe "when responses are declared to return more than once" do it "should repeat one response declared number of times" do stub_request(:get, "www.example.com"). to_return({body: "1"}).times(2). to_return({body: "2"}) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") end it "should repeat sequence of response declared number of times" do stub_request(:get, "www.example.com"). to_return({body: "1"}, {body: "2"}).times(2). to_return({body: "3"}) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("2") expect(http_request(:get, "http://www.example.com/").body).to eq("3") end it "should repeat infinitely last response even if number of declared times is lower" do stub_request(:get, "www.example.com"). to_return({body: "1"}).times(2) expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("1") expect(http_request(:get, "http://www.example.com/").body).to eq("1") end it "should give error if times is declared without specifying response" do expect { stub_request(:get, "www.example.com").times(3) }.to raise_error("Invalid WebMock stub declaration. times(N) can be declared only after response declaration.") end end describe "when exception is declared to be raised more than once" do it "should repeat raising exception declared number of times" do stub_request(:get, "www.example.com"). to_raise(MyException).times(2). to_return({body: "2"}) expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") expect(http_request(:get, "http://www.example.com/").body).to eq("2") end it "should repeat raising sequence of exceptions declared number of times" do stub_request(:get, "www.example.com"). to_raise(MyException, ArgumentError).times(2). to_return({body: "2"}) expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") expect { http_request(:get, "http://www.example.com/") }.to raise_error(ArgumentError) expect { http_request(:get, "http://www.example.com/") }.to raise_error(MyException, "Exception from WebMock") expect { http_request(:get, "http://www.example.com/") }.to raise_error(ArgumentError) expect(http_request(:get, "http://www.example.com/").body).to eq("2") end end end end webmock-3.18.1/spec/acceptance/shared/callbacks.rb0000644000004100000410000001167414333126774022040 0ustar www-datawww-datashared_context "callbacks" do |*adapter_info| describe "when after_request callback is declared" do before(:each) do @called = nil WebMock.reset_callbacks stub_request(:get, "http://www.example.com") end it "should not invoke callback unless request is made" do WebMock.after_request { @called = true } expect(@called).to eq(nil) end it "should invoke a callback after request is made" do WebMock.after_request { @called = true } http_request(:get, "http://www.example.com/") expect(@called).to eq(true) end it "should not invoke a callback if this http library should be ignored" do WebMock.after_request(except: [http_library()]) { @called = true } http_request(:get, "http://www.example.com/") expect(@called).to eq(nil) end it "should invoke a callback even if other http libraries should be ignored" do WebMock.after_request(except: [:other_lib]) { @called = true } http_request(:get, "http://www.example.com/") expect(@called).to eq(true) end it "should pass request signature to the callback" do WebMock.after_request(except: [:other_lib]) do |request_signature, _| @request_signature = request_signature end http_request(:get, "http://www.example.com/") expect(@request_signature.uri.to_s).to eq("http://www.example.com:80/") end after(:each) do WebMock::StubRegistry.instance.global_stubs.clear end it 'passes the same request signature instance to the callback that was passed to the global stub callback' do global_stub_request_sig = after_request_request_sig = nil WebMock.globally_stub_request do |request_sig| global_stub_request_sig = request_sig nil end WebMock.after_request do |request_sig, _| after_request_request_sig = request_sig end http_request(:get, "http://www.example.com/") expect(global_stub_request_sig).to be(after_request_request_sig) end context "passing response to callback" do context "when request is stubbed" do before(:each) do stub_request(:get, "http://www.example.com"). to_return( status: [200, "hello"], headers: {'Content-Length' => '666', 'Hello' => 'World'}, body: "foo bar" ) WebMock.after_request(except: [:other_lib]) do |_, response| @response = response end http_request(:get, "http://www.example.com/") end it "should pass response to callback with the status and message" do expect(@response.status).to eq([200, "hello"]) end it "should pass response to callback with headers" do expect(@response.headers).to eq({ 'Content-Length' => '666', 'Hello' => 'World' }) end it "should pass response to callback with body" do expect(@response.body).to eq("foo bar") end end describe "when request is not stubbed", net_connect: true do before(:each) do WebMock.reset! WebMock.allow_net_connect! WebMock.after_request(except: [:other_lib]) do |_, response| @response = response end http_request(:get, "https://httpstat.us/201", headers: { "Accept" => "*" }) end it "should pass real response to callback with status and message" do expect(@response.status[0]).to eq(201) expect(@response.status[1]).to eq("Created") unless adapter_info.include?(:no_status_message) end it "should pass real response to callback with headers" do expect(@response.headers["Server"]).to eq( "Kestrel") expect(@response.headers["Content-Length"]).to eq("11") unless adapter_info.include?(:no_content_length_header) end it "should pass response to callback with body" do expect(@response.body.size).to eq(11) end end end it "should invoke multiple callbacks in order of their declarations" do WebMock.after_request { @called = 1 } WebMock.after_request { @called += 1 } http_request(:get, "http://www.example.com/") expect(@called).to eq(2) end it "should invoke callbacks only for real requests if requested", net_connect: true do WebMock.after_request(real_requests_only: true) { @called = true } http_request(:get, "http://www.example.com/") expect(@called).to eq(nil) WebMock.allow_net_connect! http_request(:get, "http://www.example.net/") expect(@called).to eq(true) end it "should not invoke any callbacks after callbacks were reset" do WebMock.after_request { @called = 1 } WebMock.reset_callbacks stub_request(:get, "http://www.example.com/") http_request(:get, "http://www.example.com/") expect(@called).to eq(nil) end end end webmock-3.18.1/spec/acceptance/patron/0000755000004100000410000000000014333126774017620 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/patron/patron_spec_helper.rb0000644000004100000410000000253014333126774024021 0ustar www-datawww-datarequire 'ostruct' module PatronSpecHelper def http_request(method, uri, options = {}, &block) method = method.to_sym uri = Addressable::URI.heuristic_parse(uri) sess = Patron::Session.new sess.base_url = "#{uri.omit(:path, :query).normalize.to_s}".gsub(/\/$/,"") if options[:basic_auth] sess.username = options[:basic_auth][0] sess.password = options[:basic_auth][1] end sess.connect_timeout = 30 sess.timeout = 30 sess.max_redirects = 0 uri = "#{uri.path}#{uri.query ? '?' : ''}#{uri.query}" uri = uri.gsub(' ','%20') response = sess.request(method, uri, options[:headers] || {}, { data: options[:body] }) headers = {} if response.headers response.headers.each do |k,v| v = v.join(", ") if v.is_a?(Array) headers[k] = v end end status_line_pattern = %r(\AHTTP/(\d+(\.\d+)?)\s+(\d\d\d)\s*([^\r\n]+)?) message = response.status_line.match(status_line_pattern)[4] || "" OpenStruct.new({ body: response.body, headers: WebMock::Util::Headers.normalize_headers(headers), status: response.status.to_s, message: message }) end def client_timeout_exception_class Patron::TimeoutError end def connection_refused_exception_class Patron::ConnectionFailed end def http_library :patron end end webmock-3.18.1/spec/acceptance/patron/patron_spec.rb0000644000004100000410000001002414333126774022457 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' require 'acceptance/webmock_shared' unless RUBY_PLATFORM =~ /java/ require 'acceptance/patron/patron_spec_helper' require 'tmpdir' require 'fileutils' describe "Patron" do include PatronSpecHelper include_examples "with WebMock" describe "when custom functionality is used" do before(:each) do @sess = Patron::Session.new @sess.base_url = "http://www.example.com" end it "should allow stubbing PATCH request with body" do stub_request(:patch, "http://www.example.com/") .with(body: "abc") @sess.patch('/', "abc") end describe "file requests" do before(:each) do @dir_path = Dir.mktmpdir('webmock-') @file_path = File.join(@dir_path, "webmock_temp_test_file") FileUtils.rm_rf(@file_path) if File.exist?(@file_path) end after(:each) do FileUtils.rm_rf(@dir_path) if File.exist?(@dir_path) end it "should work with get_file" do stub_request(:get, "www.example.com").to_return(body: "abc") @sess.get_file("/", @file_path) expect(File.read(@file_path)).to eq("abc") end it "should raise same error as Patron if file is not readable for get request" do stub_request(:get, "www.example.com") File.open("/tmp/read_only_file", "w") do |tmpfile| tmpfile.chmod(0400) end begin expect { @sess.get_file("/", "/tmp/read_only_file") }.to raise_error(ArgumentError, "Unable to open specified file.") ensure File.unlink("/tmp/read_only_file") end end it "should work with put_file" do File.open(@file_path, "w") {|f| f.write "abc"} stub_request(:put, "www.example.com").with(body: "abc") @sess.put_file("/", @file_path) end it "should work with post_file" do File.open(@file_path, "w") {|f| f.write "abc"} stub_request(:post, "www.example.com").with(body: "abc") @sess.post_file("/", @file_path) end it "should raise same error as Patron if file is not readable for post request" do stub_request(:post, "www.example.com").with(body: "abc") expect { @sess.post_file("/", "/path/to/non/existing/file") }.to raise_error(ArgumentError, "Unable to open specified file.") end end describe "handling errors same way as patron" do it "should raise error if put request has neither upload_data nor file_name" do stub_request(:post, "www.example.com") expect { @sess.post("/", nil) }.to raise_error(ArgumentError, "Must provide either data or a filename when doing a PUT or POST") end end it "should work with WebDAV copy request" do stub_request(:copy, "www.example.com/abc").with(headers: {'Destination' => "/def"}) @sess.copy("/abc", "/def") end describe "handling encoding same way as patron" do around(:each) do |example| @encoding = Encoding.default_internal Encoding.default_internal = "UTF-8" example.run Encoding.default_internal = @encoding end it "should not encode body with default encoding" do stub_request(:get, "www.example.com"). to_return(body: "Øl") expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT) expect(@sess.get("").inspectable_body.encoding).to eq(Encoding::UTF_8) end it "should not encode body to default internal" do stub_request(:get, "www.example.com"). to_return(headers: {'Content-Type' => 'text/html; charset=iso-8859-1'}, body: "Øl".encode("iso-8859-1")) expect(@sess.get("").body.encoding).to eq(Encoding::ASCII_8BIT) expect(@sess.get("").decoded_body.encoding).to eq(Encoding.default_internal) end end end end end webmock-3.18.1/spec/acceptance/net_http/0000755000004100000410000000000014333126774020142 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/net_http/net_http_spec.rb0000644000004100000410000003442714333126774023340 0ustar www-datawww-datarequire 'spec_helper' require 'ostruct' require 'acceptance/webmock_shared' require 'acceptance/net_http/net_http_spec_helper' require 'acceptance/net_http/net_http_shared' include NetHTTPSpecHelper describe "Net:HTTP" do include_examples "with WebMock", :no_url_auth let(:port) { WebMockServer.instance.port } describe "marshalling" do class TestMarshalingInWebMockNetHTTP attr_accessor :r end before(:each) do @b = TestMarshalingInWebMockNetHTTP.new end after(:each) do WebMock.enable! end it "should be possible to load object marshalled when webmock was disabled" do WebMock.disable! original_constants = [ Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete, Net::HTTP::Head, Net::HTTP::Options ] @b.r = original_constants original_serialized = Marshal.dump(@b) Marshal.load(original_serialized) WebMock.enable! Marshal.load(original_serialized) end it "should be possible to load object marshalled when webmock was enabled" do WebMock.enable! new_constants = [ Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete, Net::HTTP::Head, Net::HTTP::Options ] @b.r = new_constants new_serialized = Marshal.dump(@b) Marshal.load(new_serialized) WebMock.disable! Marshal.load(new_serialized) end end describe "constants" do it "should still have const Get defined on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").const_defined?("Get")).to be_truthy end it "should still have const Get within constants on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").constants.map(&:to_s)).to include("Get") end it "should still have const Get within constants on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").const_get("Get")).not_to be_nil end if Module.method(:const_defined?).arity != 1 it "should still have const Get defined (and not inherited) on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").const_defined?("Get", false)).to be_truthy end end if Module.method(:const_get).arity != 1 it "should still be able to get non inherited constant Get on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").const_get("Get", false)).not_to be_nil end end if Module.method(:constants).arity != 0 it "should still Get within non inherited constants on replaced Net::HTTP" do expect(Object.const_get("Net").const_get("HTTP").constants(false).map(&:to_s)).to include("Get") end end describe "after WebMock is disabled" do after(:each) do WebMock.enable! end it "Net::HTTP should have the same constants" do orig_consts_number = WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP.constants.size Net::HTTP.send(:const_set, "TEST_CONST", 10) expect(Net::HTTP.constants.size).to eq(orig_consts_number + 1) WebMock.disable! expect(Net::HTTP.constants.size).to eq(orig_consts_number + 1) end end end it "should work with block provided" do stub_http_request(:get, "www.example.com").to_return(body: "abc"*100000) expect(Net::HTTP.start("www.example.com") { |query| query.get("/") }.body).to eq("abc"*100000) end it "should handle requests with raw binary data" do body = "\x14\x00\x00\x00\x70\x69\x6e\x67\x00\x00" stub_http_request(:post, "www.example.com").with(body: body).to_return(body: "abc") req = Net::HTTP::Post.new("/") req.body = body req.content_type = "application/octet-stream" expect(Net::HTTP.start("www.example.com") { |http| http.request(req)}.body).to eq("abc") end it "raises an ArgumentError if passed headers as symbols" do uri = URI.parse("http://google.com/") http = Net::HTTP.new(uri.host, uri.port) request = Net::HTTP::Get.new(uri.request_uri) request[:InvalidHeaderSinceItsASymbol] = "this will not be valid" stub_http_request(:get, "google.com").with(headers: { InvalidHeaderSinceItsASymbol: "this will not be valid" }) expect do http.request(request) end.not_to raise_error end it "should handle multiple values for the same response header" do stub_http_request(:get, "www.example.com").to_return(headers: { 'Set-Cookie' => ['foo=bar', 'bar=bazz'] }) response = Net::HTTP.get_response(URI.parse("http://www.example.com/")) expect(response.get_fields('Set-Cookie')).to eq(['bar=bazz', 'foo=bar']) end it "should yield block on response" do stub_http_request(:get, "www.example.com").to_return(body: "abc") response_body = "" http_request(:get, "http://www.example.com/") do |response| response_body = response.body end expect(response_body).to eq("abc") end it "should handle Net::HTTP::Post#body" do stub_http_request(:post, "www.example.com").with(body: "my_params").to_return(body: "abc") req = Net::HTTP::Post.new("/") req.body = "my_params" expect(Net::HTTP.start("www.example.com") { |http| http.request(req)}.body).to eq("abc") end it "should handle Net::HTTP::Post#body_stream" do stub_http_request(:post, "www.example.com").with(body: "my_params").to_return(body: "abc") req = Net::HTTP::Post.new("/") req.body_stream = StringIO.new("my_params") expect(Net::HTTP.start("www.example.com") { |http| http.request(req)}.body).to eq("abc") end it "should behave like Net::HTTP and raise error if both request body and body argument are set" do stub_http_request(:post, "www.example.com").with(body: "my_params").to_return(body: "abc") req = Net::HTTP::Post.new("/") req.body = "my_params" expect { Net::HTTP.start("www.example.com") { |http| http.request(req, "my_params")} }.to raise_error("both of body argument and HTTPRequest#body set") end it "should return a Net::ReadAdapter from response.body when a stubbed request is made with a block and #read_body" do WebMock.stub_request(:get, 'http://example.com/').to_return(body: "the body") response = Net::HTTP.new('example.com', 80).request_get('/') { |r| r.read_body { } } expect(response.body).to be_a(Net::ReadAdapter) end it "should have request 1 time executed in registry after 1 real request", net_connect: true do WebMock.allow_net_connect! http = Net::HTTP.new('localhost', port) http.get('/') {} expect(WebMock::RequestRegistry.instance.requested_signatures.hash.size).to eq(1) expect(WebMock::RequestRegistry.instance.requested_signatures.hash.values.first).to eq(1) end it "should work with Addressable::URI passed to Net::HTTP.get_response" do stub_request(:get, 'http://www.example.com/hello?a=1').to_return(body: "abc") expect(Net::HTTP.get_response(Addressable::URI.parse('http://www.example.com/hello?a=1')).body).to eq("abc") end it "should support method calls on stubbed socket" do WebMock.allow_net_connect! stub_request(:get, 'www.google.com')#.with(headers: {"My-Header" => 99}) req = Net::HTTP::Get.new('/') Net::HTTP.start('www.google.com') do |http| http.request(req, '') socket = http.instance_variable_get(:@socket) expect(socket).to be_a(StubSocket) expect { socket.io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) }.to_not raise_error end end if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0') it "uses the StubSocket to provide IP address" do Net::HTTP.start("http://example.com") do |http| expect(http.ipaddr).to eq("127.0.0.1") end end end it "defines common socket methods" do Net::HTTP.start("http://example.com") do |http| socket = http.instance_variable_get(:@socket) expect(socket.io.ssl_version).to eq("TLSv1.3") expect(socket.io.cipher).to eq(["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128]) end end describe "connecting on Net::HTTP.start" do before(:each) do @http = Net::HTTP.new('www.google.com', 443) @http.use_ssl = true @http.verify_mode = OpenSSL::SSL::VERIFY_NONE end describe "when net http is allowed" do it "should not connect to the server until the request", net_connect: true do WebMock.allow_net_connect! @http.start {|conn| expect(conn.peer_cert).to be_nil } end it "should connect to the server on start", net_connect: true do WebMock.allow_net_connect!(net_http_connect_on_start: true) @http.start {|conn| cert = OpenSSL::X509::Certificate.new conn.peer_cert expect(cert).to be_a(OpenSSL::X509::Certificate) } end end describe "when net http is disabled and allowed only for some hosts" do it "should not connect to the server until the request", net_connect: true do WebMock.disable_net_connect!(allow: "www.google.com") @http.start {|conn| expect(conn.peer_cert).to be_nil } end it "should connect to the server on start", net_connect: true do WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: true) @http.start {|conn| cert = OpenSSL::X509::Certificate.new conn.peer_cert expect(cert).to be_a(OpenSSL::X509::Certificate) } end it "should connect to the server on start when allowlisted", net_connect: true do WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.google.com") @http.start {|conn| cert = OpenSSL::X509::Certificate.new conn.peer_cert expect(cert).to be_a(OpenSSL::X509::Certificate) } end it "should not connect to the server on start when not allowlisted", net_connect: true do WebMock.disable_net_connect!(allow: "www.google.com", net_http_connect_on_start: "www.yahoo.com") @http.start {|conn| expect(conn.peer_cert).to be_nil } end it "should connect to the server if the URI matches an regex", net_connect: true do WebMock.disable_net_connect!(allow: /google.com/) Net::HTTP.get('www.google.com','/') end it "should connect to the server if the URI matches any regex the array", net_connect: true do WebMock.disable_net_connect!(allow: [/google.com/, /yahoo.com/]) Net::HTTP.get('www.google.com','/') end end end describe "when net_http_connect_on_start is true" do before(:each) do WebMock.allow_net_connect!(net_http_connect_on_start: true) end it_should_behave_like "Net::HTTP" end describe "when net_http_connect_on_start is false" do before(:each) do WebMock.allow_net_connect!(net_http_connect_on_start: false) end it_should_behave_like "Net::HTTP" end describe "when net_http_connect_on_start is a specific host" do before(:each) do WebMock.allow_net_connect!(net_http_connect_on_start: "localhost") end it_should_behave_like "Net::HTTP" end describe 'after_request callback support', net_connect: true do let(:expected_body_regex) { /hello world/ } before(:each) do WebMock.allow_net_connect! @callback_invocation_count = 0 WebMock.after_request do |_, response| @callback_invocation_count += 1 @callback_response = response end end after(:each) do WebMock.reset_callbacks end def perform_get_with_returning_block http_request(:get, "http://localhost:#{port}/") do |response| return response.body end end it "should support the after_request callback on an request with block and read_body" do response_body = ''.dup http_request(:get, "http://localhost:#{port}/") do |response| response.read_body { |fragment| response_body << fragment } end expect(response_body).to match(expected_body_regex) expect(@callback_response.body).to eq(response_body) end it "should support the after_request callback on a request with a returning block" do response_body = perform_get_with_returning_block expect(response_body).to match(expected_body_regex) expect(@callback_response).to be_instance_of(WebMock::Response) expect(@callback_response.body).to eq(response_body) end it "should only invoke the after_request callback once, even for a recursive post request" do Net::HTTP.new('localhost', port).post('/', nil) expect(@callback_invocation_count).to eq(1) end end it "should match http headers, even if their values have been set in a request as numbers" do WebMock.disable_net_connect! stub_request(:post, "www.example.com").with(headers: {"My-Header" => 99}) uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['My-Header'] = 99 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, '') end end describe "hostname handling" do it "should set brackets around the hostname if it is an IPv6 address" do net_http = Net::HTTP.new('b2dc:5bdf:4f0d::3014:e0ca', 80) path = '/example.jpg' expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg') end it "should not set brackets around the hostname if it is already wrapped by brackets" do net_http = Net::HTTP.new('[b2dc:5bdf:4f0d::3014:e0ca]', 80) path = '/example.jpg' expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg') end it "should not set brackets around the hostname if it is an IPv4 address" do net_http = Net::HTTP.new('181.152.137.168', 80) path = '/example.jpg' expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://181.152.137.168:80/example.jpg') end it "should not set brackets around the hostname if it is a domain" do net_http = Net::HTTP.new('www.example.com', 80) path = '/example.jpg' expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg') end it "does not require a path" do net_http = Net::HTTP.new('www.example.com', 80) expect(WebMock::NetHTTPUtility.get_uri(net_http)).to eq('http://www.example.com:80') end end end webmock-3.18.1/spec/acceptance/net_http/real_net_http_spec.rb0000644000004100000410000000073114333126774024332 0ustar www-datawww-datarequire 'rubygems' require 'rspec' require 'net/http' require 'net/https' require 'stringio' require 'acceptance/net_http/net_http_shared' require 'support/webmock_server' describe "Real Net:HTTP without webmock", without_webmock: true do before(:all) do raise "WebMock has no access here!!!" if defined?(WebMock::NetHTTPUtility) WebMockServer.instance.start end after(:all) do WebMockServer.instance.stop end it_should_behave_like "Net::HTTP" end webmock-3.18.1/spec/acceptance/net_http/net_http_shared.rb0000644000004100000410000001366314333126774023653 0ustar www-datawww-datarequire 'set' shared_examples_for "Net::HTTP" do describe "when making real requests", net_connect: true do let(:port){ WebMockServer.instance.port } before(:each) do @http = Net::HTTP.new("localhost", port) end it "should return a Net::ReadAdapter from response.body when a real request is made with a block and #read_body", net_connect: true do response = Net::HTTP.new("localhost", port).request_get('/') { |r| r.read_body { } } expect(response.body).to be_a(Net::ReadAdapter) end it "should handle requests with block passed to read_body", net_connect: true do body = "".dup req = Net::HTTP::Get.new("/") Net::HTTP.start("localhost", port) do |http| http.request(req) do |res| res.read_body do |str| body << str end end end expect(body).to match(/hello world/) end it "should connect only once when connected on start", net_connect: true do @http = Net::HTTP.new('localhost', port) socket_before_request = socket_after_request = nil @http.start {|conn| socket_before_request = conn.instance_variable_get(:@socket) conn.request(Net::HTTP::Get.new("/")) socket_after_request = conn.instance_variable_get(:@socket) } if !defined?(WebMock::NetHTTPUtility) || WebMock::Config.instance.net_http_connect_on_start expect(socket_before_request).to be_a(Net::BufferedIO) expect(socket_after_request).to be_a(Net::BufferedIO) expect(socket_after_request).to be(socket_before_request) else expect(socket_before_request).to be_a(StubSocket) expect(socket_after_request).to be_a(Net::BufferedIO) end end it "should allow sending multiple requests when persisted", net_connect: true do @http = Net::HTTP.new('example.org') @http.start expect(@http.get("/")).to be_a(Net::HTTPSuccess) expect(@http.get("/")).to be_a(Net::HTTPSuccess) expect(@http.get("/")).to be_a(Net::HTTPSuccess) @http.finish end it "should not leak file descriptors", net_connect: true do sockets = Set.new @http = Net::HTTP.new('example.org') @http.start sockets << @http.instance_variable_get(:@socket) @http.get("/") sockets << @http.instance_variable_get(:@socket) @http.get("/") sockets << @http.instance_variable_get(:@socket) @http.get("/") sockets << @http.instance_variable_get(:@socket) @http.finish if !defined?(WebMock::NetHTTPUtility) || WebMock.net_http_connect_on_start?(Addressable::URI.parse("http://example.com/")) expect(sockets.length).to eq(1) expect(sockets.to_a[0]).to be_a(Net::BufferedIO) else expect(sockets.length).to eq(2) expect(sockets.to_a[0]).to be_a(StubSocket) expect(sockets.to_a[1]).to be_a(Net::BufferedIO) end expect(sockets.all?(&:closed?)).to be(true) end it "should pass the read_timeout value on", net_connect: true do @http = Net::HTTP.new('localhost', port) read_timeout = @http.read_timeout + 1 @http.read_timeout = read_timeout @http.start {|conn| conn.request(Net::HTTP::Get.new("/")) socket = conn.instance_variable_get(:@socket) expect(socket.read_timeout).to eq(read_timeout) } end describe "without start" do it "should close connection after a real request" do @http.get('/') { } expect(@http).not_to be_started end it "should execute block exactly once" do times = 0 @http.get('/') { times += 1 } expect(times).to eq(1) end it "should have socket open during a real request" do socket_id = nil @http.get('/') { socket_id = @http.instance_variable_get(:@socket).object_id } expect(socket_id).not_to be_nil end it "should be started during a real request" do started = nil @http.get('/') { started = @http.started? } expect(started).to eq(true) expect(@http.started?).to eq(false) end end describe "with start" do it "should close connection after a real request" do @http.start {|conn| conn.get('/') { } } expect(@http).not_to be_started end it "should execute block exactly once" do times = 0 @http.start {|conn| conn.get('/') { times += 1 }} expect(times).to eq(1) end it "should have socket open during a real request" do socket_id = nil @http.start {|conn| conn.get('/') { socket_id = conn.instance_variable_get(:@socket).object_id } } expect(socket_id).not_to be_nil end it "should be started during a real request" do started = nil @http.start {|conn| conn.get('/') { started = conn.started? } } expect(started).to eq(true) expect(@http.started?).to eq(false) end end describe "with start without request block" do it "should close connection after a real request" do @http.start {|conn| conn.get('/') } expect(@http).not_to be_started end it "should have socket open during a real request" do socket_id = nil @http.start {|conn| socket_id = conn.instance_variable_get(:@socket).object_id } expect(socket_id).not_to be_nil end it "should be started during a real request" do started = nil @http.start {|conn| started = conn.started? } expect(started).to eq(true) expect(@http.started?).to eq(false) end end describe "with start without a block and finish" do it "should gracefully start and close connection" do @http.start @http.get("/") expect(@http).to be_started @http.finish expect(@http).not_to be_started end end end end webmock-3.18.1/spec/acceptance/net_http/net_http_spec_helper.rb0000644000004100000410000000322614333126774024670 0ustar www-datawww-datamodule NetHTTPSpecHelper def http_request(method, uri, options = {}, &block) begin uri = URI.parse(uri) rescue uri = Addressable::URI.heuristic_parse(uri) end response = nil clazz = Net::HTTP.const_get("#{method.to_s.capitalize}") req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", nil) options[:headers].each do |k,v| if v.is_a?(Array) v.each_with_index do |e,i| i == 0 ? (req[k] = e) : req.add_field(k, e) end else req[k] = v end end if options[:headers] if options[:basic_auth] req.basic_auth(options[:basic_auth][0], options[:basic_auth][1]) end http = Net::HTTP.new(uri.host, uri.port) if uri.scheme == "https" http.use_ssl = true #1.9.1 has a bug with ssl_timeout http.ssl_timeout = 20 unless RUBY_PLATFORM =~ /java/ http.open_timeout = 60 http.read_timeout = 60 end http.verify_mode = OpenSSL::SSL::VERIFY_NONE response = http.start {|open_http| open_http.request(req, options[:body], &block) } headers = {} response.each_header {|name, value| headers[name] = value} OpenStruct.new({ body: response.body, headers: WebMock::Util::Headers.normalize_headers(headers), status: response.code, message: response.message }) end def client_timeout_exception_class if defined?(Net::OpenTimeout) Net::OpenTimeout elsif defined?(Net::HTTP::OpenTimeout) Net::HTTP::OpenTimeout else Timeout::Error end end def connection_refused_exception_class Errno::ECONNREFUSED end def http_library :net_http end end webmock-3.18.1/spec/acceptance/http_rb/0000755000004100000410000000000014333126774017757 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/http_rb/http_rb_spec_helper.rb0000644000004100000410000000254314333126774024323 0ustar www-datawww-datarequire "ostruct" module HttpRbSpecHelper def http_request(method, uri, options = {}) chain = HTTP if basic_auth = options.delete(:basic_auth) chain = chain.basic_auth(user: basic_auth[0], pass: basic_auth[1]) end ssl_ctx = OpenSSL::SSL::SSLContext.new ssl_ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE response = chain.request(method, normalize_uri(uri), options.merge(ssl_context: ssl_ctx)) OpenStruct.new({ body: response.body.to_s, headers: normalize_headers(response.headers.to_h), status: response.code.to_s, message: response.reason }) end def client_timeout_exception_class return Errno::ETIMEDOUT if HTTP::VERSION < "1.0.0" HTTP::TimeoutError end def connection_refused_exception_class return Errno::ECONNREFUSED if HTTP::VERSION < "1.0.0" HTTP::ConnectionError end def http_library :http_rb end def normalize_uri(uri) Addressable::URI.heuristic_parse(uri).normalize.to_s end def normalize_headers(headers) headers = Hash[headers.map { |k, v| [k, Array(v).join(", ")] }] WebMock::Util::Headers.normalize_headers headers end def stub_simple_request(host, status = 200, headers = {}, body = nil) stub_request(:any, host).to_return({ status: status, headers: headers.merge({ "Host" => host }), body: body }) end end webmock-3.18.1/spec/acceptance/http_rb/http_rb_spec.rb0000644000004100000410000000525714333126774022771 0ustar www-datawww-data# encoding: utf-8 require "spec_helper" require "acceptance/webmock_shared" require "acceptance/http_rb/http_rb_spec_helper" describe "HTTP.rb" do include HttpRbSpecHelper include_examples "with WebMock", :no_status_message context "streaming body" do let(:response) { HTTP.get "http://example.com" } before { stub_simple_request "example.com", 302, {}, "abc" } it "works as if it was streamed from socket" do expect(response.body.readpartial 1).to eq "a" end it "fails if body was already streamed" do response.body.to_s expect { response.body.readpartial 1 }.to raise_error(HTTP::StateError) end end context "without following redirects" do let(:response) { http_request(:get, "http://example.com") } let(:headers) { response.headers } it "stops on first request" do stub_simple_request("example.com", 302, "Location" => "http://www.example.com") stub_simple_request("www.example.com") expect(headers).to include "Host" => "example.com" end end context "following redirects" do let(:options) { { follow: true } } let(:response) { http_request(:get, "http://example.com", options) } let(:headers) { response.headers } it "returns response of destination" do stub_simple_request("example.com", 302, "Location" => "http://www.example.com") stub_simple_request("www.example.com") expect(headers).to include "Host" => "www.example.com" end end context "restored request uri on replayed response object" do it "keeps non-default port" do stub_request :get, "example.com:1234/foo" response = HTTP.get "http://example.com:1234/foo" expect(response.uri.to_s).to eq "http://example.com:1234/foo" end it "does not injects default port" do stub_request :get, "example.com/foo" response = HTTP.get "http://example.com/foo" expect(response.uri.to_s).to eq "http://example.com/foo" end it "strips out default port even if it was explicitly given" do stub_request :get, "example.com/foo" response = HTTP.get "http://example.com:80/foo" expect(response.uri.to_s).to eq "http://example.com/foo" end end context "streamer" do it "can be read to a provided buffer" do stub_request(:get, "example.com/foo") .to_return(status: 200, body: "Hello world! ") response = HTTP.get "http://example.com/foo" buffer = "" response.body.readpartial(1024, buffer) expect(buffer).to eq "Hello world! " end it "can be closed" do stub_request :get, "example.com/foo" response = HTTP.get "http://example.com/foo" response.connection.close end end end webmock-3.18.1/spec/acceptance/curb/0000755000004100000410000000000014333126774017250 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/curb/curb_spec.rb0000644000004100000410000004007214333126774021545 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/webmock_shared' unless RUBY_PLATFORM =~ /java/ require 'acceptance/curb/curb_spec_helper' shared_examples_for "Curb" do include CurbSpecHelper include_examples "with WebMock" describe "when doing PUTs" do it "should stub them" do stub_request(:put, "www.example.com").with(body: "01234") expect(http_request(:put, "http://www.example.com", body: "01234"). status).to eq("200") end end end describe "Curb features" do before(:each) do WebMock.disable_net_connect! WebMock.reset! end describe "callbacks" do before(:each) do @curl = Curl::Easy.new @curl.url = "http://example.com" end describe 'on_debug' do it "should call on_debug" do stub_request(:any, "example.com"). to_return(status: 200, headers: { 'Server' => 'nginx' }, body: { hello: :world }.to_json) test = [] @curl.on_debug do |message, operation| test << "#{operation} -> #{message}" end @curl.headers['Content-Type'] = 'application/json' @curl.http_post({ hello: :world }.to_json) expect(test).to_not be_empty end end it "should call on_success with 2xx response" do body = "on_success fired" stub_request(:any, "example.com").to_return(body: body) test = nil @curl.on_success do |c| test = c.body_str end @curl.http_get expect(test).to eq(body) end it "should call on_missing with 4xx response" do response_code = 403 stub_request(:any, "example.com"). to_return(status: [response_code, "None shall pass"]) test = nil @curl.on_missing do |c, code| test = code end @curl.http_get expect(test).to eq(response_code) end it "should call on_failure with 5xx response" do response_code = 599 stub_request(:any, "example.com"). to_return(status: [response_code, "Server On Fire"]) test = nil @curl.on_failure do |c, code| test = code end @curl.http_get expect(test).to eq(response_code) end it "should call on_body when response body is read" do body = "on_body fired" stub_request(:any, "example.com"). to_return(body: body) test = nil @curl.on_body do |data| test = data end @curl.http_get expect(test).to eq(body) end it "should call on_body for each chunk with chunked response" do stub_request(:any, "example.com"). to_return(body: ["first_chunk", "second_chunk"], headers: {"Transfer-Encoding" => "chunked"}) test = [] @curl.on_body do |data| test << data end @curl.http_get expect(test).to eq(["first_chunk", "second_chunk"]) end it "should call on_header when response headers are read" do stub_request(:any, "example.com"). to_return(headers: {one: 1}) test = [] @curl.on_header do |data| test << data end @curl.http_get expect(test).to eq([ "HTTP/1.1 200 \r\n", 'One: 1' ]) end it "should call on_complete when request is complete" do body = "on_complete fired" stub_request(:any, "example.com").to_return(body: body) test = nil @curl.on_complete do |curl| test = curl.body_str end @curl.http_get expect(test).to eq(body) end it "should call on_progress when portion of response body is read" do stub_request(:any, "example.com").to_return(body: "01234") test = nil @curl.on_progress do |*args| expect(args.length).to eq(4) args.each {|arg| expect(arg.is_a?(Float)).to eq(true) } test = true end @curl.http_get expect(test).to eq(true) end it "should call callbacks in correct order on successful request" do stub_request(:any, "example.com") order = [] @curl.on_success {|*args| order << :on_success } @curl.on_missing {|*args| order << :on_missing } @curl.on_failure {|*args| order << :on_failure } @curl.on_header {|*args| order << :on_header } @curl.on_body {|*args| order << :on_body } @curl.on_complete {|*args| order << :on_complete } @curl.on_progress {|*args| order << :on_progress } @curl.http_get expect(order).to eq([:on_progress,:on_header,:on_body,:on_complete,:on_success]) end it "should call callbacks in correct order on failed request" do stub_request(:any, "example.com").to_return(status: [500, ""]) order = [] @curl.on_success {|*args| order << :on_success } @curl.on_missing {|*args| order << :on_missing } @curl.on_failure {|*args| order << :on_failure } @curl.on_header {|*args| order << :on_header } @curl.on_body {|*args| order << :on_body } @curl.on_complete {|*args| order << :on_complete } @curl.on_progress {|*args| order << :on_progress } @curl.http_get expect(order).to eq([:on_progress,:on_header,:on_body,:on_complete,:on_failure]) end it "should call callbacks in correct order on missing request" do stub_request(:any, "example.com").to_return(status: [403, ""]) order = [] @curl.on_success {|*args| order << :on_success } @curl.on_missing {|*args| order << :on_missing } @curl.on_failure {|*args| order << :on_failure } @curl.on_header {|*args| order << :on_header } @curl.on_body {|*args| order << :on_body } @curl.on_complete {|*args| order << :on_complete } @curl.on_progress {|*args| order << :on_progress } @curl.http_get expect(order).to eq([:on_progress,:on_header,:on_body,:on_complete,:on_missing]) end end describe '#last_effective_url' do before(:each) do @curl = Curl::Easy.new @curl.url = "http://example.com" end context 'when not following redirects' do before { @curl.follow_location = false } it 'should be the same as #url even with a location header' do stub_request(:any, 'example.com'). to_return(body: "abc", status: 302, headers: { 'Location' => 'http://www.example.com' }) @curl.http_get expect(@curl.last_effective_url).to eq('http://example.com') end end context 'when following redirects' do before { @curl.follow_location = true } it 'should be the same as #url when no location header is present' do stub_request(:any, "example.com") @curl.http_get expect(@curl.last_effective_url).to eq('http://example.com') end it 'should be the value of the location header when present' do stub_request(:any, 'example.com'). to_return(headers: { 'Location' => 'http://www.example.com' }) stub_request(:any, 'www.example.com') @curl.http_get expect(@curl.last_effective_url).to eq('http://www.example.com') end it 'should work with more than one redirect' do stub_request(:any, 'example.com'). to_return(headers: { 'Location' => 'http://www.example.com' }) stub_request(:any, 'www.example.com'). to_return(headers: { 'Location' => 'http://blog.example.com' }) stub_request(:any, 'blog.example.com') @curl.http_get expect(@curl.last_effective_url).to eq('http://blog.example.com') end it 'should maintain the original url' do stub_request(:any, 'example.com'). to_return(headers: { 'Location' => 'http://www.example.com' }) stub_request(:any, 'www.example.com') @curl.http_get expect(@curl.url).to eq('http://example.com') end it 'should have the redirected-to attrs (body, response code)' do stub_request(:any, 'example.com'). to_return(body: 'request A', status: 302, headers: { 'Location' => 'http://www.example.com' }) stub_request(:any, 'www.example.com').to_return(body: 'request B') @curl.http_get expect(@curl.body_str).to eq('request B') expect(@curl.response_code).to eq(200) end it 'should follow more than one redirect' do stub_request(:any, 'example.com'). to_return(headers: { 'Location' => 'http://www.example.com' }) stub_request(:any, 'www.example.com'). to_return(headers: { 'Location' => 'http://blog.example.com' }) stub_request(:any, 'blog.example.com').to_return(body: 'blog post') @curl.http_get expect(@curl.url).to eq('http://example.com') expect(@curl.body_str).to eq('blog post') end end end describe "#content_type" do before(:each) do @curl = Curl::Easy.new @curl.url = "http://example.com" end context "when response includes Content-Type header" do it "returns correct content_type" do content_type = "application/json" stub_request(:any, 'example.com'). to_return(body: "abc", status: 200, headers: { 'Content-Type' => content_type }) @curl.http_get expect(@curl.content_type).to eq(content_type) end end context "when response does not include Content-Type header" do it "returns nil for content_type" do stub_request(:any, 'example.com'). to_return(body: "abc", status: 200 ) @curl.http_get expect(@curl.content_type).to be_nil end end end describe "#chunked_response?" do before(:each) do @curl = Curl::Easy.new @curl.url = "http://example.com" end it "is true when Transfer-Encoding is 'chunked' and body responds to each" do stub_request(:any, 'example.com'). to_return(body: ["abc", "def"], status: 200, headers: { 'Transfer-Encoding' => 'chunked' }) @curl.http_get expect(@curl).to be_chunked_response end it "is false when Transfer-Encoding is not 'chunked'" do stub_request(:any, 'example.com'). to_return(body: ["abc", "def"], status: 200) @curl.http_get expect(@curl).not_to be_chunked_response end it "is false when Transfer-Encoding is 'chunked' but body does not respond to each" do stub_request(:any, 'example.com'). to_return(body: "abc", status: 200) @curl.http_get expect(@curl).not_to be_chunked_response end end end describe "Webmock with Curb" do describe "using #http for requests" do it_should_behave_like "Curb" include CurbSpecHelper::DynamicHttp it "should work with uppercase arguments" do stub_request(:get, "www.example.com").to_return(body: "abc") c = Curl::Easy.new c.url = "http://www.example.com" c.http(:GET) expect(c.body_str).to eq("abc") end it "should alias body to body_str" do stub_request(:get, "www.example.com").to_return(body: "abc") c = Curl::Easy.new c.url = "http://www.example.com" c.http(:GET) expect(c.body).to eq("abc") end it "supports array headers passed to Curl::Easy" do stub_request(:get, "www.example.com").with(headers: {'X-One' => '1'}).to_return(body: "abc") c = Curl::Easy.new c.url = "http://www.example.com" c.headers = ["X-One: 1"] c.http(:GET) expect(c.body).to eq("abc") end it "supports headers containing the ':' character" do stub_request(:get, "www.example.com").with(headers: {'Referer'=>'http://www.example.com'}).to_return(body: "abc") c = Curl::Easy.new c.url = "http://www.example.com" c.headers = ["Referer: http://www.example.com"] c.http(:GET) expect(c.body).to eq("abc") expect(c.headers).to eq(["Referer: http://www.example.com"]) end describe 'match request body' do it 'for post' do stub_request(:post, "www.example.com").with(body: 'foo=nhe').to_return(body: "abc") response = Curl.post("http://www.example.com", {foo: :nhe}) expect(response.body_str).to eq("abc") end it 'for patch' do stub_request(:patch, "www.example.com").with(body: 'foo=nhe').to_return(body: "abc") response = Curl.patch("http://www.example.com", {foo: :nhe}) expect(response.body_str).to eq("abc") end it 'for put' do stub_request(:put, "www.example.com").with(body: 'foo=nhe').to_return(body: "abc") response = Curl.put("http://www.example.com", {foo: :nhe}) expect(response.body_str).to eq("abc") end end end describe "using #http_* methods for requests" do it_should_behave_like "Curb" include CurbSpecHelper::NamedHttp it "should reset @webmock_method after each call" do stub_request(:post, "www.example.com").with(body: "01234") c = Curl::Easy.new c.url = "http://www.example.com" c.post_body = "01234" c.http_post expect { c.perform }.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com)) end it "should work with blank arguments for post" do stub_request(:post, "www.example.com").with(body: "01234") c = Curl::Easy.new c.url = "http://www.example.com" c.post_body = "01234" c.http_post expect(c.response_code).to eq(200) end it "should work with several body arguments for post using the class method" do stub_request(:post, "www.example.com").with(body: {user: {first_name: 'Bartosz', last_name: 'Blimke'}}) c = Curl::Easy.http_post "http://www.example.com", 'user[first_name]=Bartosz', 'user[last_name]=Blimke' expect(c.response_code).to eq(200) end it "should work with blank arguments for put" do stub_request(:put, "www.example.com").with(body: "01234") c = Curl::Easy.new c.url = "http://www.example.com" c.put_data = "01234" c.http_put expect(c.response_code).to eq(200) end it "should work with multiple arguments for post" do data = { name: "john", address: "111 example ave" } stub_request(:post, "www.example.com").with(body: data) c = Curl::Easy.new c.url = "http://www.example.com" c.http_post Curl::PostField.content('name', data[:name]), Curl::PostField.content('address', data[:address]) expect(c.response_code).to eq(200) end end describe "using #perform for requests" do it_should_behave_like "Curb" include CurbSpecHelper::Perform end describe "using .http_* methods for requests" do it_should_behave_like "Curb" include CurbSpecHelper::ClassNamedHttp end describe "using .perform for requests" do it_should_behave_like "Curb" include CurbSpecHelper::ClassPerform end describe "using #reset" do before do @curl = Curl::Easy.new @curl.url = "http://example.com" stub_request(:any, "example.com"). to_return(body: "abc", headers: { "Content-Type" => "application/json" }) @curl.http_get end it "should clear all memoized response fields" do @curl.reset expect(@curl).to have_attributes( body_str: nil, content_type: nil, header_str: nil, last_effective_url: nil, response_code: 0, ) end end end end webmock-3.18.1/spec/acceptance/curb/curb_spec_helper.rb0000644000004100000410000000631714333126774023110 0ustar www-datawww-datarequire 'ostruct' module CurbSpecHelper def http_request(method, uri, options = {}, &block) uri = Addressable::URI.heuristic_parse(uri) body = options[:body] curl = curb_http_request(uri, method, body, options) status, response_headers = WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(curl.header_str) # Deal with the fact that the HTTP spec allows multi-values headers # to either be a single entry with a comma-separated listed of # values, or multiple separate entries response_headers.keys.each do |k| v = response_headers[k] if v.is_a?(Array) response_headers[k] = v.join(', ') end end OpenStruct.new( body: curl.body_str, headers: WebMock::Util::Headers.normalize_headers(response_headers), status: curl.response_code.to_s, message: status ) end def setup_request(uri, curl, options={}) curl ||= Curl::Easy.new curl.url = uri.to_s if options[:basic_auth] curl.http_auth_types = :basic curl.username = options[:basic_auth][0] curl.password = options[:basic_auth][1] end curl.timeout = 30 curl.connect_timeout = 30 if headers = options[:headers] headers.each {|k,v| curl.headers[k] = v } end curl end def client_timeout_exception_class Curl::Err::TimeoutError end def connection_refused_exception_class Curl::Err::ConnectionFailedError end def http_library :curb end module DynamicHttp def curb_http_request(uri, method, body, options) curl = setup_request(uri, nil, options) case method when :post curl.post_body = body when :put curl.put_data = body end curl.http(method.to_s.upcase) curl end end module NamedHttp def curb_http_request(uri, method, body, options) curl = setup_request(uri, nil, options) case method when :put, :post curl.send( "http_#{method}", body ) else curl.send( "http_#{method}" ) end curl end end module Perform def curb_http_request(uri, method, body, options) curl = setup_request(uri, nil, options) case method when :post curl.post_body = body when :put curl.put_data = body when :head curl.head = true when :delete curl.delete = true end curl.perform curl end end module ClassNamedHttp def curb_http_request(uri, method, body, options) args = ["http_#{method}", uri] args << body if method == :post || method == :put c = Curl::Easy.send(*args) do |curl| setup_request(uri, curl, options) end c end end module ClassPerform def curb_http_request(uri, method, body, options) args = ["http_#{method}", uri] args << body if method == :post || method == :put c = Curl::Easy.send(*args) do |curl| setup_request(uri, curl, options) case method when :post curl.post_body = body when :put curl.put_data = body when :head curl.head = true when :delete curl.delete = true end end c end end end webmock-3.18.1/spec/acceptance/excon/0000755000004100000410000000000014333126774017431 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/excon/excon_spec_helper.rb0000644000004100000410000000263014333126774023444 0ustar www-datawww-datarequire 'ostruct' module ExconSpecHelper def http_request(method, uri, options = {}, &block) Excon.defaults[:ssl_verify_peer] = false Excon.defaults[:ciphers] = 'DEFAULT' uri = Addressable::URI.heuristic_parse(uri) uri = uri.to_s.gsub(' ', '%20') excon_options = {} if basic_auth = options.delete(:basic_auth) excon_options = {user: basic_auth[0], password: basic_auth[1]} end if Gem::Version.new(Excon::VERSION) < Gem::Version.new("0.29.0") options = options.merge(method: method, nonblock: false) # Dup and merge response = Excon.new(uri, excon_options).request(options, &block) else options = options.merge(method: method) # Dup and merge response = Excon.new(uri, excon_options.merge(nonblock: false)).request(options, &block) end headers = WebMock::Util::Headers.normalize_headers(response.headers) headers = headers.inject({}) do |res, (name, value)| res[name] = value.is_a?(Array) ? value.flatten.join(', ') : value res end Excon.set_raise_on_warnings!(true) OpenStruct.new \ body: response.body, headers: headers, status: response.status.to_s, message: response.reason_phrase end def client_timeout_exception_class Excon::Errors::Timeout end def connection_refused_exception_class Excon::Errors::SocketError end def http_library :excon end end webmock-3.18.1/spec/acceptance/excon/excon_spec.rb0000644000004100000410000000517514333126774022114 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/webmock_shared' require 'acceptance/excon/excon_spec_helper' describe "Excon" do include ExconSpecHelper include_context "with WebMock", :no_url_auth it 'should allow Excon requests to use query hash paramters' do stub_request(:get, "http://example.com/resource/?a=1&b=2").to_return(body: "abc") expect(Excon.new('http://example.com').get(path: "resource/", query: {a: 1, b: 2}).body).to eq("abc") end it 'should support Excon :expects options' do stub_request(:get, "http://example.com/").to_return(body: 'a') expect { Excon.new('http://example.com').get(expects: 204) }.to raise_error(Excon::Errors::OK) end context "with response_block" do it "should support excon response_block for real requests", net_connect: true do a = [] WebMock.allow_net_connect! r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }). get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1) expect(a).to eq(["2", "0", "0", " ", "O", "K"]) expect(r.body).to eq("") end it "should support excon response_block" do a = [] stub_request(:get, "http://example.com/").to_return(body: "abc") r = Excon.new('http://example.com').get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1) expect(a).to eq(['a', 'b', 'c']) expect(r.body).to eq("") end it "should invoke callbacks with response body even if a real request is made", net_connect: true do a = [] WebMock.allow_net_connect! response = nil WebMock.after_request { |_, res| response = res } r = Excon.new('https://httpstat.us/200', headers: { "Accept" => "*" }). get(response_block: lambda {|e, remaining, total| a << e}, chunk_size: 1) expect(response.body).to eq("200 OK") expect(a).to eq(["2", "0", "0", " ", "O", "K"]) expect(r.body).to eq("") end end let(:file) { File.new(__FILE__) } let(:file_contents) { File.read(__FILE__) } it 'handles file uploads correctly' do stub_request(:put, "http://example.com/upload").with(body: file_contents) yielded_request_body = nil WebMock.after_request do |req, res| yielded_request_body = req.body end Excon.new("http://example.com").put(path: "upload", body: file) expect(yielded_request_body).to eq(file_contents) end describe '.request_params_from' do it 'rejects invalid request keys' do request_params = WebMock::HttpLibAdapters::ExconAdapter.request_params_from(body: :keep, fake: :reject) expect(request_params).to eq(body: :keep) end end end webmock-3.18.1/spec/acceptance/em_http_request/0000755000004100000410000000000014333126774021525 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/em_http_request/em_http_request_spec_helper.rb0000644000004100000410000000330414333126774027633 0ustar www-datawww-datamodule EMHttpRequestSpecHelper def failed EventMachine.stop fail end def http_request(method, uri, options = {}, &block) @http = nil head = options[:headers] || {} if options[:basic_auth] head.merge!('authorization' => options[:basic_auth]) end response = nil error = nil error_set = false uri = Addressable::URI.heuristic_parse(uri) EventMachine.run { request = EventMachine::HttpRequest.new("#{uri.normalize.to_s}", ssl: {verify_peer: true}) http = request.send(method, { timeout: 30, body: options[:body], file: options[:file], query: options[:query], head: head, compressed: false }, &block) http.errback { error_set = true error = if http.respond_to?(:errors) http.errors else http.error end failed } http.callback { response = OpenStruct.new({ body: http.response, headers: WebMock::Util::Headers.normalize_headers(extract_response_headers(http)), message: http.response_header.http_reason, status: http.response_header.status.to_s }) EventMachine.stop } @http = http } raise error.to_s if error_set response end def client_timeout_exception_class 'Errno::ETIMEDOUT' end def connection_refused_exception_class RuntimeError end def http_library :em_http_request end private def extract_response_headers(http) headers = {} if http.response_header http.response_header.each do |k,v| v = v.join(", ") if v.is_a?(Array) headers[k] = v end end headers end end webmock-3.18.1/spec/acceptance/em_http_request/em_http_request_spec.rb0000644000004100000410000003561414333126774026305 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' require 'acceptance/webmock_shared' require 'ostruct' unless RUBY_PLATFORM =~ /java/ require 'acceptance/em_http_request/em_http_request_spec_helper' describe "EM::HttpRequest" do include EMHttpRequestSpecHelper include_context "with WebMock", :no_status_message #functionality only supported for em-http-request 1.x if defined?(EventMachine::HttpConnection) context 'when a real request is made and redirects are followed', net_connect: true do before { WebMock.allow_net_connect! } # This url redirects to the https URL. let(:http_url) { "http://raw.github.com:80/gist/fb555cb593f3349d53af/6921dd638337d3f6a51b0e02e7f30e3c414f70d6/vcr_gist" } let(:https_url) { http_url.gsub('http', 'https').gsub('80', '443') } def make_request EM.run do request = EM::HttpRequest.new(http_url, ssl: {verify_peer: true}).get(redirects: 1) request.callback { EM.stop } end end it "invokes the globally_stub_request hook with both requests" do urls = [] WebMock.globally_stub_request { |r| urls << r.uri.to_s; nil } make_request expect(urls).to eq([http_url, https_url]) end it 'invokes the after_request hook with both requests' do urls = [] WebMock.after_request { |req, res| urls << req.uri.to_s } make_request expect(urls).to eq([http_url, https_url]) end end describe "with middleware" do it "should work with request middleware" do stub_request(:get, "www.example.com").with(body: 'bar') middleware = Class.new do def request(client, head, body) [{}, 'bar'] end end EM.run do conn = EventMachine::HttpRequest.new('http://www.example.com/') conn.use middleware http = conn.get(body: 'foo') http.callback do expect(WebMock).to have_requested(:get, "www.example.com").with(body: 'bar') EM.stop end end end it "only calls request middleware once" do stub_request(:get, "www.example.com") middleware = Class.new do def self.called! @called = called + 1 end def self.called @called || 0 end def request(client, head, body) self.class.called! [head, body] end end EM.run do conn = EventMachine::HttpRequest.new('http://www.example.com/') conn.use middleware http = conn.get http.callback do expect(middleware.called).to eq(1) EM.stop end end end let(:response_middleware) do Class.new do def response(resp) resp.response = 'bar' end end end it "should work with response middleware" do stub_request(:get, "www.example.com").to_return(body: 'foo') EM.run do conn = EventMachine::HttpRequest.new('http://www.example.com/') conn.use response_middleware http = conn.get http.callback do expect(http.response).to eq('bar') EM.stop end end end let(:webmock_server_url) { "http://#{WebMockServer.instance.host_with_port}/" } shared_examples_for "em-http-request middleware/after_request hook integration" do it 'yields the original raw body to the after_request hook even if a response middleware modifies the body' do yielded_response_body = nil ::WebMock.after_request do |request, response| yielded_response_body = response.body end EM::HttpRequest.use response_middleware EM.run do http = EventMachine::HttpRequest.new(webmock_server_url).get http.callback { EM.stop } end expect(yielded_response_body).to eq("hello world") end end context 'making a real request', net_connect: true do before { WebMock.allow_net_connect! } include_examples "em-http-request middleware/after_request hook integration" it "only calls request middleware once" do middleware = Class.new do def self.called! @called = called + 1 end def self.called @called || 0 end def request(client, head, body) self.class.called! [head, body] end end EM.run do conn = EventMachine::HttpRequest.new(webmock_server_url) conn.use middleware http = conn.get http.callback do expect(middleware.called).to eq(1) EM.stop end end end end context 'when the request is stubbed' do before { stub_request(:get, webmock_server_url).to_return(body: 'hello world') } include_examples "em-http-request middleware/after_request hook integration" end end it 'should trigger error callbacks asynchronously' do stub_request(:get, 'www.example.com').to_timeout called = false EM.run do conn = EventMachine::HttpRequest.new('http://www.example.com/') http = conn.get http.errback do called = true EM.stop end expect(called).to eq(false) end expect(called).to eq(true) end # not pretty, but it works if defined?(EventMachine::Synchrony) describe "with synchrony" do let(:webmock_em_http) { File.expand_path(File.join(File.dirname(__FILE__), "../lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb")) } before(:each) do # need to reload the webmock em-http adapter after we require synchrony WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable! $".delete webmock_em_http $".delete File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb")) require 'em-synchrony' require 'em-synchrony/em-http' require File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb")) end it "should work" do stub_request(:post, /.*.testserver.com*/).to_return(status: 200, body: 'ok') expect { EM.run do fiber = Fiber.new do EM::HttpRequest.new("http://www.testserver.com").post body: "foo=bar&baz=bang", timeout: 60 EM.stop end fiber.resume end }.not_to raise_error end after(:each) do EM.send(:remove_const, :Synchrony) EM.send(:remove_const, :HTTPMethods) WebMock::HttpLibAdapters::EmHttpRequestAdapter.disable! $".reject! {|path| path.include? "em-http-request"} $".delete webmock_em_http $".delete File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb")) require 'em-http-request' require File.expand_path(File.join(File.dirname(__FILE__), "../../../lib/webmock/http_lib_adapters/em_http_request_adapter.rb")) end end end end it "should work with streaming" do stub_request(:get, "www.example.com").to_return(body: "abc") response = "" EM.run { http = EventMachine::HttpRequest.new('http://www.example.com/').get http.stream { |chunk| response = chunk; EM.stop } } expect(response).to eq("abc") end it "should work with responses that use chunked transfer encoding" do stub_request(:get, "www.example.com").to_return(body: "abc", headers: { 'Transfer-Encoding' => 'chunked' }) expect(http_request(:get, "http://www.example.com").body).to eq("abc") end it "should work with optional query params" do stub_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/?x=3", query: {"a" => ["b", "c"]}).body).to eq("abc") end it "should work with optional query params declared as string" do stub_request(:get, "www.example.com/?x=3&a[]=b&a[]=c").to_return(body: "abc") expect(http_request(:get, "http://www.example.com/?x=3", query: "a[]=b&a[]=c").body).to eq("abc") end it "should work when the body is passed as a Hash" do stub_request(:post, "www.example.com").with(body: {a: "1", b: "2"}).to_return(body: "ok") expect(http_request(:post, "http://www.example.com", body: {a: "1", b: "2"}).body).to eq("ok") end if defined?(EventMachine::HttpConnection) it "should work when a file is passed as body" do stub_request(:post, "www.example.com").with(body: File.read(__FILE__)).to_return(body: "ok") expect(http_request(:post, "http://www.example.com", file: __FILE__).body).to eq("ok") end end it "should work with UTF-8 strings" do body = "Привет, Мир!" stub_request(:post, "www.example.com").to_return(body: body) expect(http_request(:post, "http://www.example.com").body.bytesize).to eq(body.bytesize) end it "should work with multiple requests to the same connection" do stub_request(:get, "www.example.com/foo").to_return(body: "bar") stub_request(:get, "www.example.com/baz").to_return(body: "wombat") err1 = nil err2 = nil body1 = nil body2 = nil i = 0 EM.run do conn = EM::HttpRequest.new("http://www.example.com") conn.get(path: "/foo").callback do |resp| body1 = resp.response i += 1; EM.stop if i == 2 end.errback do |resp| err1 = resp.error i += 1; EM.stop if i == 2 end conn.get(path: "/baz").callback do |resp| body2 = resp.response i += 1; EM.stop if i == 2 end.errback do |resp| err2 = resp.error i += 1; EM.stop if i == 2 end end expect(err1).to be(nil) expect(err2).to be(nil) expect(body1).to eq("bar") expect(body2).to eq("wombat") end it "should work with multiple requests to the same connection when the first request times out" do stub_request(:get, "www.example.com/foo").to_timeout.then.to_return(status: 200, body: "wombat") err = nil body = nil EM.run do conn = EM::HttpRequest.new("http://www.example.com") conn.get(path: "/foo").callback do |resp| err = :success_from_timeout EM.stop end.errback do |resp| conn.get(path: "/foo").callback do |retry_resp| expect(retry_resp.response_header.status).to eq(200) body = retry_resp.response EM.stop end.errback do |retry_resp| err = retry_resp.error EM.stop end end end expect(err).to be(nil) expect(body).to eq("wombat") end describe "mocking EM::HttpClient API" do let(:uri) { "http://www.example.com/" } before do stub_request(:get, uri) WebMock::HttpLibAdapters::EmHttpRequestAdapter.enable! end def client(uri, options = {}) client = nil EM.run do client = EventMachine::HttpRequest.new(uri).get(options) client.callback { EM.stop } client.errback { failed } end client end subject { client(uri) } it 'should support #uri' do expect(subject.uri).to eq(Addressable::URI.parse(uri)) end it 'should support #last_effective_url' do expect(subject.last_effective_url).to eq(Addressable::URI.parse(uri)) end context "with a query" do let(:uri) { "http://www.example.com/?a=1&b=2" } subject { client("http://www.example.com/?a=1", query: { 'b' => 2 }) } it "#request_signature doesn't mutate the original uri" do expect(subject.uri).to eq(Addressable::URI.parse("http://www.example.com/?a=1")) signature = WebMock::RequestRegistry.instance.requested_signatures.hash.keys.first expect(signature.uri).to eq(Addressable::URI.parse(uri)) end end describe 'get_response_cookie' do before(:each) do stub_request(:get, "http://example.org/"). to_return( status: 200, body: "", headers: { 'Set-Cookie' => cookie_string } ) end describe 'success' do context 'with only one cookie' do let(:cookie_name) { 'name_of_the_cookie' } let(:cookie_value) { 'value_of_the_cookie' } let(:cookie_string) { "#{cookie_name}=#{cookie_value}" } it 'successfully gets the cookie' do EM.run { http = EventMachine::HttpRequest.new('http://example.org').get http.errback { fail(http.error) } http.callback { expect(http.get_response_cookie(cookie_name)).to eq(cookie_value) EM.stop } } end end context 'with several cookies' do let(:cookie_name) { 'name_of_the_cookie' } let(:cookie_value) { 'value_of_the_cookie' } let(:cookie_2_name) { 'name_of_the_2nd_cookie' } let(:cookie_2_value) { 'value_of_the_2nd_cookie' } let(:cookie_string) { %W(#{cookie_name}=#{cookie_value} #{cookie_2_name}=#{cookie_2_value}) } it 'successfully gets both cookies' do EM.run { http = EventMachine::HttpRequest.new('http://example.org').get http.errback { fail(http.error) } http.callback { expect(http.get_response_cookie(cookie_name)).to eq(cookie_value) expect(http.get_response_cookie(cookie_2_name)).to eq(cookie_2_value) EM.stop } } end end end describe 'failure' do let(:cookie_string) { 'a=b' } it 'returns nil when no cookie is found' do EM.run { http = EventMachine::HttpRequest.new('http://example.org').get http.errback { fail(http.error) } http.callback { expect(http.get_response_cookie('not_found_cookie')).to eq(nil) EM.stop } } end end end end end end webmock-3.18.1/spec/acceptance/httpclient/0000755000004100000410000000000014333126774020473 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/httpclient/httpclient_spec.rb0000644000004100000410000001574114333126774024220 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/webmock_shared' require 'ostruct' require 'acceptance/httpclient/httpclient_spec_helper' describe "HTTPClient" do include HTTPClientSpecHelper before(:each) do WebMock.reset_callbacks HTTPClientSpecHelper.async_mode = false end include_examples "with WebMock" it "should raise a clearly readable error if request with multipart body is sent" do stub_request(:post, 'www.example.com').with(body: {type: 'image'}) expect { HTTPClient.new.post_content('www.example.com', type: 'image', file: File.new('spec/fixtures/test.txt')) }.to raise_error(ArgumentError, "WebMock does not support matching body for multipart/form-data requests yet :(") end it "should yield block on response if block provided" do stub_request(:get, "www.example.com").to_return(body: "abc") response_body = "" http_request(:get, "http://www.example.com/") do |body| response_body = body end expect(response_body).to eq("abc") end it "should not yield block on empty response if block provided" do stub_request(:get, "www.example.com").to_return(body: "") response_body = "" http_request(:get, "http://www.example.com/"){ raise } expect(response_body).to eq("") 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"]} ) expect(http_request( :get, "http://www.example.com/", headers: {"a" => ["c", "b"]}).status).to eq("200") end describe "when using async requests" do before(:each) do HTTPClientSpecHelper.async_mode = true end include_examples "with WebMock" end it "should work with get_content" do stub_request(:get, 'www.example.com').to_return(status: 200, body: 'test', headers: {}) str = ''.dup HTTPClient.get_content('www.example.com') do |content| str << content end expect(str).to eq('test') end it "should work via JSONClient subclass" do stub_request(:get, 'www.example.com').to_return( status: 200, body: '{"test": "foo"}', headers: {'Content-Type' => 'application/json'} ) content = JSONClient.get('www.example.com').content expect(content).to eq("test" => "foo") end context "multipart bodies" do let(:header) {{ 'Accept' => 'application/json', 'Content-Type' => 'multipart/form-data' }} let(:body) {[ { 'Content-Type' => 'application/json', 'Content-Disposition' => 'form-data', :content => '{"foo": "bar", "baz": 2}' } ]} let(:make_request) {HTTPClient.new.post("http://www.example.com", body: body, header: header)} before do stub_request(:post, "www.example.com") end it "should work with multipart bodies" do make_request end end context "Filters" do class Filter def filter_request(request) request.header["Authorization"] = "Bearer 0123456789" end def filter_response(request, response) response.header.set('X-Powered-By', 'webmock') end end before do @client = HTTPClient.new @client.request_filter << Filter.new stub_request(:get, 'www.example.com').with(headers: {'Authorization' => 'Bearer 0123456789'}) end it "supports request filters" do expect(@client.request(:get, 'http://www.example.com/').status).to eq(200) end it "supports response filters" do res = @client.request(:get, 'http://www.example.com/') expect(res.header['X-Powered-By'].first).to eq('webmock') end end context 'when a client instance is re-used for another identical request' do let(:client) { HTTPClient.new } let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"} before { WebMock.allow_net_connect! } it 'invokes the global_stub_request hook for each request' do # Mock time to ensure that date headers match now = Time.now allow(Time).to receive(:now).and_return(now) request_signatures = [] WebMock.globally_stub_request do |request_sig| request_signatures << request_sig nil # to let the request be made for real end http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" }) if defined? HTTP::CookieJar http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" }) else # If http-cookie is not present, then the cookie headers will saved between requests http_request(:get, webmock_server_url, client: client) end expect(request_signatures.size).to eq(2) # Verify the request signatures were identical as needed by this example expect(request_signatures.first).to eq(request_signatures.last) end end context 'session headers' do it "client sends a User-Agent header when given an agent_name explicitly to the client" do user_agent = "Client/0.1" stub_request(:get, "www.example.com").with(headers: { 'User-agent' => "#{user_agent} #{HTTPClient::LIB_NAME}" }) HTTPClient.new(agent_name: user_agent).get("www.example.com") end it "client sends the Accept, User-Agent, and Date by default" do WebMock.disable_net_connect! stub_request(:get, "www.example.com").with do |req| req.headers["Accept"] == "*/*" && req.headers["User-Agent"] == "#{HTTPClient::DEFAULT_AGENT_NAME} #{HTTPClient::LIB_NAME}" && req.headers["Date"] end http_request(:get, "www.example.com") end it "explicitly defined headers take precedence over session defaults" do headers = { 'Accept' => 'foo/bar', 'User-Agent' => 'custom', 'Date' => 'today' } stub_request(:get, "www.example.com").with(headers: headers) HTTPClient.new.get("www.example.com", nil, headers) end end context 'httpclient response header' do it 'receives request_method, request_uri, and request_query from the request header' do stub_request :get, 'www.example.com' message = HTTPClient.new.get 'www.example.com' expect(message.header.request_uri.to_s).to eq('www.example.com') end end context 'httpclient streams response', net_connect: true do before do WebMock.allow_net_connect! WebMock.after_request(except: [:other_lib]) do |_, response| @response = response end end it 'sets the full body on the webmock response' do body = '' HTTPClient.new.request(:get, 'http://www.example.com/') do |http_res, chunk| body += chunk end expect(@response.body).to eq body end end context 'credentials' do it 'are detected when manually specifying Authorization header' do stub_request(:get, "http://www.example.com/").with(basic_auth: ['username', 'password']).to_return(status: 200) headers = {'Authorization' => 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='} expect(http_request(:get, 'http://www.example.com/', {headers: headers}).status).to eql('200') end end end webmock-3.18.1/spec/acceptance/httpclient/httpclient_spec_helper.rb0000644000004100000410000000306214333126774025550 0ustar www-datawww-datamodule HTTPClientSpecHelper class << self attr_accessor :async_mode end def http_request(method, uri, options = {}, &block) uri = Addressable::URI.heuristic_parse(uri) c = options.fetch(:client) { HTTPClient.new } c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE c.reset_all if options[:basic_auth] c.force_basic_auth = true c.set_basic_auth(nil, options[:basic_auth][0], options[:basic_auth][1]) end params = [method, uri.normalize.to_s, WebMock::Util::QueryMapper.query_to_values(uri.query, notation: WebMock::Config.instance.query_values_notation), options[:body], options[:headers] || {}] if HTTPClientSpecHelper.async_mode connection = c.request_async(*params) connection.join response = connection.pop else response = c.request(*params, &block) end headers = merge_headers(response) OpenStruct.new({ body: HTTPClientSpecHelper.async_mode ? response.content.read : response.content, headers: headers, status: response.code.to_s, message: response.reason }) end def client_timeout_exception_class HTTPClient::TimeoutError end def connection_refused_exception_class Errno::ECONNREFUSED end def http_library :httpclient end private def merge_headers(response) response.header.all.inject({}) do |headers, header| if !headers.has_key?(header[0]) headers[header[0]] = header[1] else headers[header[0]] = [headers[header[0]], header[1]].join(', ') end headers end end end webmock-3.18.1/spec/acceptance/async_http_client/0000755000004100000410000000000014333126774022027 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/async_http_client/async_http_client_spec.rb0000644000004100000410000002244714333126774027111 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' require 'acceptance/webmock_shared' require_relative './async_http_client_spec_helper' require 'protocol/http/body/file' Async.logger.debug! if ENV['ASYNC_LOGGER_DEBUG'] unless RUBY_PLATFORM =~ /java/ describe 'Async::HTTP::Client' do include AsyncHttpClientSpecHelper include_context "with WebMock", :no_status_message, :no_url_auth, :no_content_length_header it 'works' do stub_request(:get, 'http://www.example.com') expect(make_request(:get, 'http://www.example.com')).to eq( status: 200, headers: {}, body: nil ) end it 'works with request path' do stub_request(:get, 'http://www.example.com/foo') expect(make_request(:get, 'http://www.example.com/foo')).to eq( status: 200, headers: {}, body: nil ) end it 'works with request query' do stub_request(:get, 'http://www.example.com/').with( query: { 'foo' => 'bar' } ) expect(make_request(:get, 'http://www.example.com/?foo=bar')).to eq( status: 200, headers: {}, body: nil ) end it 'works with request headers' do stub_request(:get, 'http://www.example.com').with( headers: { 'X-Token' => 'Token' } ) expect( make_request :get, 'http://www.example.com', headers: { 'X-Token' => 'Token' } ).to eq( status: 200, headers: {}, body: nil ) end it 'works with request body as text' do stub_request(:post, 'http://www.example.com').with( body: 'x'*10_000 ) expect( make_request :post, 'http://www.example.com', body: 'x'*10_000 ).to eq( status: 200, headers: {}, body: nil ) end it 'works with request body as file' do stub_request(:post, "www.example.com").with( body: File.read(__FILE__) ) expect( make_request :post, "http://www.example.com", body: ::Protocol::HTTP::Body::File.open(__FILE__, block_size: 32) ).to eq( status: 200, headers: {}, body: nil ) end it 'works with response status' do stub_request(:get, 'http://www.example.com').to_return( status: 400 ) expect(make_request(:get, 'http://www.example.com')).to eq( status: 400, headers: {}, body: nil ) end it 'works with response headers' do stub_request(:get, 'http://www.example.com').to_return( headers: { 'X-Token' => 'TOKEN' } ) expect(make_request(:get, 'http://www.example.com')).to eq( status: 200, headers: { 'x-token' => ['TOKEN'] }, body: nil ) end it 'works with response body' do stub_request(:get, 'http://www.example.com').to_return( body: 'abc' ) expect(make_request(:get, 'http://www.example.com')).to eq( status: 200, headers: {}, body: 'abc' ) end it 'works with to_timeout' do stub_request(:get, 'http://www.example.com').to_timeout expect { make_request(:get, 'http://www.example.com') }.to raise_error Async::TimeoutError end it 'does not invoke "after real request" callbacks for stubbed requests' do WebMock.allow_net_connect! stub_request(:get, 'http://www.example.com').to_return(body: 'abc') callback_invoked = false WebMock.after_request(real_requests_only: true) { |_| callback_invoked = true } make_request(:get, 'http://www.example.com') expect(callback_invoked).to eq(false) end it 'does invoke "after request" callbacks for stubbed requests' do WebMock.allow_net_connect! stub_request(:get, 'http://www.example.com').to_return(body: 'abc') callback_invoked = false WebMock.after_request(real_requests_only: false) { |_| callback_invoked = true } make_request(:get, 'http://www.example.com') expect(callback_invoked).to eq(true) end context 'scheme and protocol' do let(:default_response_headers) { {} } before do stub_request( :get, "#{scheme}://www.example.com" ).and_return( body: 'BODY' ) end subject do make_request(:get, "#{scheme}://www.example.com", protocol: protocol) end shared_examples :common do specify do expect(subject).to eq( status: 200, headers: default_response_headers, body: 'BODY' ) end end context 'http scheme' do let(:scheme) { 'http' } context 'default protocol' do let(:protocol) { nil } include_examples :common end context 'HTTP10 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP10 } let(:default_response_headers) { {"connection"=>["keep-alive"]} } include_examples :common end context 'HTTP11 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP11 } include_examples :common end context 'HTTP2 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP2 } include_examples :common end end context 'https scheme' do let(:scheme) { 'https' } context 'default protocol' do let(:protocol) { nil } include_examples :common end context 'HTTP10 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP10 } let(:default_response_headers) { {"connection"=>["keep-alive"]} } include_examples :common end context 'HTTP11 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP11 } include_examples :common end context 'HTTP2 protocol' do let(:protocol) { Async::HTTP::Protocol::HTTP2 } include_examples :common end context 'HTTPS protocol' do let(:protocol) { Async::HTTP::Protocol::HTTPS } include_examples :common end end end context 'multiple requests' do let!(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') } let(:requests_count) { 3 } shared_examples :common do before do requests_count.times do |index| stub_request( :get, "http://www.example.com/foo#{index}" ).to_return( status: 200 + index, headers: {'X-Token' => "foo#{index}"}, body: "FOO#{index}" ) end end specify do expect(subject).to eq( 0 => { status: 200, headers: {'x-token' => ['foo0']}, body: 'FOO0' }, 1 => { status: 201, headers: {'x-token' => ['foo1']}, body: 'FOO1' }, 2 => { status: 202, headers: {'x-token' => ['foo2']}, body: 'FOO2' } ) end end context 'sequential' do subject do responses = {} Async do |task| Async::HTTP::Client.open(endpoint, protocol) do |client| requests_count.times do |index| response = client.get "/foo#{index}" responses[index] = response_to_hash(response) end end end responses end context 'HTTP1 protocol' do let!(:protocol) { Async::HTTP::Protocol::HTTP1 } include_examples :common end context 'HTTP2 protocol' do let!(:protocol) { Async::HTTP::Protocol::HTTP2 } include_examples :common end end context 'asynchronous' do subject do responses = {} Async do |task| Async::HTTP::Client.open(endpoint, protocol) do |client| tasks = requests_count.times.map do |index| task.async do response = client.get "/foo#{index}" responses[index] = response_to_hash(response) end end tasks.map(&:wait) end end responses end context 'HTTP1 protocol' do let!(:protocol) { Async::HTTP::Protocol::HTTP1 } include_examples :common end context 'HTTP2 protocol' do let!(:protocol) { Async::HTTP::Protocol::HTTP2 } include_examples :common end end end def make_request(method, url, protocol: nil, headers: {}, body: nil) Async do endpoint = Async::HTTP::Endpoint.parse(url) begin Async::HTTP::Client.open(endpoint, protocol || endpoint.protocol) do |client| response = client.send( method, endpoint.path, headers, body ) response_to_hash(response) end rescue Async::TimeoutError => e e end end.wait end def response_to_hash(response) { status: response.status, headers: response.headers.to_h, body: response.read } end end end webmock-3.18.1/spec/acceptance/async_http_client/async_http_client_spec_helper.rb0000644000004100000410000000303514333126774030440 0ustar www-datawww-datamodule AsyncHttpClientSpecHelper def http_request(method, url, options = {}, &block) endpoint = Async::HTTP::Endpoint.parse(url) path = endpoint.path path = path + "?" + options[:query] if options[:query] headers = (options[:headers] || {}).each_with_object([]) do |(k, v), o| Array(v).each do |v| o.push [k, v] end end headers.push( ['authorization', 'Basic ' + Base64.strict_encode64(options[:basic_auth].join(':'))] ) if options[:basic_auth] body = options[:body] Async do begin Async::HTTP::Client.open(endpoint) do |client| response = client.send( method, path, headers, body ) OpenStruct.new( build_hash_response(response) ) end rescue Exception => e e end end.wait end def client_timeout_exception_class Async::TimeoutError end def connection_refused_exception_class Errno::ECONNREFUSED end def http_library :async_http_client end private def build_hash_response(response) { status: response.status.to_s, message: Protocol::HTTP1::Reason::DESCRIPTIONS[response.status], headers: build_response_headers(response), body: response.read } end def build_response_headers(response) response.headers.each.each_with_object({}) do |(k, v), o| o[k] ||= [] o[k] << v end.tap do |o| o.each do |k, v| o[k] = v.join(', ') end end end end webmock-3.18.1/spec/acceptance/manticore/0000755000004100000410000000000014333126774020276 5ustar www-datawww-datawebmock-3.18.1/spec/acceptance/manticore/manticore_spec_helper.rb0000644000004100000410000000146614333126774025164 0ustar www-datawww-datamodule ManticoreSpecHelper def http_request(method, uri, options = {}) client = Manticore::Client.new if basic_auth = options[:basic_auth] options = options.merge(auth: {user: basic_auth[0], pass: basic_auth[1]}) end response = client.http(method, uri, options) OpenStruct.new({ body: response.body || '', headers: WebMock::Util::Headers.normalize_headers(join_array_values(response.headers)), status: response.code.to_s }) end def join_array_values(hash) hash.reduce({}) do |h, (k,v)| v = v.join(', ') if v.is_a?(Array) h.merge(k => v) end end def client_timeout_exception_class Manticore::ConnectTimeout end def connection_refused_exception_class Manticore::SocketException end def http_library :manticore end end webmock-3.18.1/spec/acceptance/manticore/manticore_spec.rb0000644000004100000410000000710714333126774023623 0ustar www-datawww-datarequire 'spec_helper' require 'acceptance/webmock_shared' if RUBY_PLATFORM =~ /java/ require 'acceptance/manticore/manticore_spec_helper' describe "Manticore" do include ManticoreSpecHelper include_context "with WebMock", :no_status_message context "calling http methods on Manticore directly using Manticore's facade" do it "handles GET" do stub_request(:get, "http://example-foo.com").to_return(status: 301) response = Manticore.get("http://example-foo.com") expect(response.code).to eq(301) end it "handles POST" do stub_request(:post, "http://example-foo.com").to_return(status: 201) response = Manticore.post("http://example-foo.com", {hello: "world"}) expect(response.code).to eq(201) end it "handles PUT" do stub_request(:put, "http://example-foo.com").to_return(status: 409) response = Manticore.put("http://example-foo.com", {hello: "world"}) expect(response.code).to eq(409) end it "handles PATCH" do stub_request(:patch, "http://example-foo.com").to_return(status: 409) response = Manticore.patch("http://example-foo.com", {hello: "world"}) expect(response.code).to eq(409) end it "handles DELETE" do stub_request(:delete, "http://example-foo.com").to_return(status: 204) response = Manticore.delete("http://example-foo.com", {id: 1}) expect(response.code).to eq(204) end it "handles OPTIONS" do stub_request(:options, "http://example-foo.com").to_return(status: 200) response = Manticore.options("http://example-foo.com") expect(response.code).to eq(200) end it "handles HEAD" do stub_request(:head, "http://example-foo.com").to_return(status: 204) response = Manticore.head("http://example-foo.com") expect(response.code).to eq(204) end context "when a custom failure handler is defined" do let(:failure_handler) { proc {} } before do allow(failure_handler).to receive(:call).with(kind_of(Manticore::Timeout)) do |ex| raise ex end end it "handles timeouts by invoking the failure handler" do stub_request(:get, "http://example-foo.com").to_timeout request = Manticore.get("http://example-foo.com").tap do |req| req.on_failure(&failure_handler) end expect { request.call }.to raise_error(Manticore::Timeout) expect(failure_handler).to have_received(:call) end end context 'when used in a streaming mode' do let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"} let(:result_chunks) { [] } def manticore_streaming_get Manticore.get(webmock_server_url).tap do |req| req.on_success do |response| response.body do |chunk| result_chunks << chunk end end end end context 'when connections are allowed' do it 'works' do WebMock.allow_net_connect! expect { manticore_streaming_get.call }.to_not raise_error expect(result_chunks).to_not be_empty end end context 'when stubbed' do it 'works' do stub_body = 'hello!' stub_request(:get, webmock_server_url).to_return(body: stub_body) expect { manticore_streaming_get.call }.to_not raise_error expect(result_chunks).to eq [stub_body] end end end end end end webmock-3.18.1/spec/unit/0000755000004100000410000000000014333126774015206 5ustar www-datawww-datawebmock-3.18.1/spec/unit/request_execution_verifier_spec.rb0000644000004100000410000002101214333126774024207 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::RequestExecutionVerifier do before(:each) do @verifier = WebMock::RequestExecutionVerifier.new @request_pattern = double(WebMock::RequestPattern, to_s: "www.example.com") @verifier.request_pattern = @request_pattern allow(WebMock::RequestRegistry.instance).to receive(:to_s).and_return("executed requests") @executed_requests_info = "\n\nThe following requests were made:\n\nexecuted requests\n" + "="*60 end describe "description" do it "reports the description" do @verifier.expected_times_executed = 2 expect(@verifier.description).to eq "request www.example.com 2 times" end it "reports description correctly when expectation is 1 time" do @verifier.expected_times_executed = 1 expect(@verifier.description).to eq "request www.example.com 1 time" end context "at_least_times_executed is set" do it "reports description correctly when expectation at least 2 times" do @verifier.at_least_times_executed = 2 expect(@verifier.description).to eq "request www.example.com at least 2 times" end it "reports description correctly when expectation is at least 3 times" do @verifier.at_least_times_executed = 3 expect(@verifier.description).to eq "request www.example.com at least 3 times" end end context "at_most_times_executed is set" do it "reports description correctly when expectation is at most 2 times" do @verifier.at_most_times_executed = 2 expect(@verifier.description).to eq "request www.example.com at most 2 times" end it "reports description correctly when expectation is at most 1 time" do @verifier.at_most_times_executed = 1 expect(@verifier.description).to eq "request www.example.com at most 1 time" end end end describe "failure message" do it "reports the failure message" do @verifier.times_executed = 0 @verifier.expected_times_executed = 2 expected_text = "The request www.example.com was expected to execute 2 times but it executed 0 times" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end it "reports failure message correctly when executed times is one" do @verifier.times_executed = 1 @verifier.expected_times_executed = 1 expected_text = "The request www.example.com was expected to execute 1 time but it executed 1 time" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end context "at_least_times_executed is set" do it "reports failure message correctly when executed times is one" do @verifier.times_executed = 1 @verifier.at_least_times_executed = 2 expected_text = "The request www.example.com was expected to execute at least 2 times but it executed 1 time" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end it "reports failure message correctly when executed times is two" do @verifier.times_executed = 2 @verifier.at_least_times_executed = 3 expected_text = "The request www.example.com was expected to execute at least 3 times but it executed 2 times" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end end context "at_most_times_executed is set" do it "reports failure message correctly when executed times is three" do @verifier.times_executed = 3 @verifier.at_most_times_executed = 2 expected_text = "The request www.example.com was expected to execute at most 2 times but it executed 3 times" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end it "reports failure message correctly when executed times is two" do @verifier.times_executed = 2 @verifier.at_most_times_executed = 1 expected_text = "The request www.example.com was expected to execute at most 1 time but it executed 2 times" expected_text += @executed_requests_info expect(@verifier.failure_message).to eq(expected_text) end end end describe "negative failure message" do it "reports failure message if it executed number of times specified" do @verifier.times_executed = 2 @verifier.expected_times_executed = 2 expected_text = "The request www.example.com was not expected to execute 2 times but it executed 2 times" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end it "reports failure message when not expected request but it executed" do @verifier.times_executed = 1 expected_text = "The request www.example.com was not expected to execute but it executed 1 time" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end context "at_least_times_executed is set" do it "reports failure message correctly when executed times is one" do @verifier.times_executed = 3 @verifier.at_least_times_executed = 2 expected_text = "The request www.example.com was not expected to execute at least 2 times but it executed 3 times" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end it "reports failure message correctly when executed times is two" do @verifier.times_executed = 2 @verifier.at_least_times_executed = 2 expected_text = "The request www.example.com was not expected to execute at least 2 times but it executed 2 times" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end end context "at_most_times_executed is set" do it "reports failure message correctly when executed times is three" do @verifier.times_executed = 2 @verifier.at_most_times_executed = 3 expected_text = "The request www.example.com was not expected to execute at most 3 times but it executed 2 times" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end it "reports failure message correctly when executed times is one" do @verifier.times_executed = 1 @verifier.at_most_times_executed = 2 expected_text = "The request www.example.com was not expected to execute at most 2 times but it executed 1 time" expected_text += @executed_requests_info expect(@verifier.failure_message_when_negated).to eq(expected_text) end end end describe "matches?" do it "succeeds if request was executed expected number of times" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(10) @verifier.expected_times_executed = 10 expect(@verifier.matches?).to be_truthy end it "fails if request was not executed expected number of times" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(10) @verifier.expected_times_executed = 5 expect(@verifier.matches?).to be_falsey end end describe "does_not_match?" do it "fails if request executed expected number of times" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(10) @verifier.expected_times_executed = 10 expect(@verifier.does_not_match?).to be_falsey end it "succeeds if request was not executed at all and expected number of times was not set" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(0) expect(@verifier.does_not_match?).to be_truthy end it "fails if request was executed and expected number of times was not set" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(1) expect(@verifier.does_not_match?).to be_falsey end it "succeeds if request was not executed expected number of times" do expect(WebMock::RequestRegistry.instance). to receive(:times_executed).with(@request_pattern).and_return(10) @verifier.expected_times_executed = 5 expect(@verifier.does_not_match?).to be_truthy end end end webmock-3.18.1/spec/unit/request_body_diff_spec.rb0000644000004100000410000000457014333126774022250 0ustar www-datawww-datarequire 'spec_helper' RSpec.describe WebMock::RequestBodyDiff do subject { WebMock::RequestBodyDiff.new(request_signature, request_stub) } let(:uri) { "http://example.com" } let(:method) { "GET" } let(:request_stub) { WebMock::RequestStub.new(method, uri) } let(:request_signature) { WebMock::RequestSignature.new(method, uri) } let(:request_stub_body) { { "key" => "value"} } let(:request_signature_body) { {"key" => "different value"}.to_json } let(:request_pattern) { WebMock::RequestPattern.new( method, uri, {body: request_stub_body} ) } before :each do request_stub.request_pattern = request_pattern request_signature.headers = {"Content-Type" => "application/json"} request_signature.body = request_signature_body end describe "#body_diff" do context "request signature is unparseable json" do let(:request_signature_body) { "youcan'tparsethis!" } it "returns an empty hash" do expect(subject.body_diff).to eq({}) end end context "request stub body as unparseable json" do let(:request_stub_body) { "youcan'tparsethis!" } it "returns an empty hash" do expect(subject.body_diff).to eq({}) end end context "request stub body pattern is hash" do let(:request_stub_body) { { "key" => "value"} } it "generates a diff" do expect(subject.body_diff).to eq( [["~", "key", "different value", "value"]] ) end end context "request signature doesn't have json headers" do before :each do request_signature.headers = {"Content-Type" => "application/xml"} end it "returns an empty hash" do expect(subject.body_diff).to eq({}) end end context "request stub body pattern is a string" do let(:request_stub_body) { { "key" => "value"}.to_json } it "generates a diff" do expect(subject.body_diff).to eq( [["~", "key", "different value", "value"]] ) end end context "stub request has no request pattern" do let(:request_signature_body) { nil } it "returns an empty hash" do expect(subject.body_diff).to eq({}) end end context "stub request has no body pattern" do let(:request_stub_body) { nil } it "returns an empty hash" do expect(subject.body_diff).to eq({}) end end end end webmock-3.18.1/spec/unit/api_spec.rb0000644000004100000410000001264514333126774017326 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::API do describe '#hash_including' do subject { klass.new.hash_including(args) } let(:args) { { data: :one } } context 'when mixed into a class that does not define `hash_including`' do let(:klass) do Class.new do include WebMock::API end end it 'uses WebMock::Matchers::HashIncludingMatcher' do expect(subject).to be_a(WebMock::Matchers::HashIncludingMatcher) end # by testing equality for HashIncludingMatcher (which stringifies the passed hash) we are # testing HashIncludingMatcher.initialize behavior as well context "when args correspond to an hash" do it "creates 'HashIncludingMatcher'" do expect(subject).to eq("data" => :one) end end context "when args are one or many keys" do subject {klass.new.hash_including(:foo, :bar)} let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) } it "creates 'HashIncludingMatcher' with keys anythingized" do expect(subject).to eq("foo" => anything, "bar" => anything ) end end context "when args are both keys and key/value pairs" do subject {klass.new.hash_including(:foo, :bar, data: :one)} let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) } it "creates 'HashIncludingMatcher' with keys anythingized" do expect(subject).to eq("foo" => anything, "bar" => anything, "data" => :one) end end context "when args are an empty hash" do subject {klass.new.hash_including({})} it "creates 'HashIncludingMatcher' with an empty hash" do expect(subject).to eq({}) end end end context 'when mixed into a class with a parent that defines `hash_including`' do subject { klass.new.hash_including(*args) } let(:args) { %w(:foo, :bar, {:data => :one}) } let(:klass) do Class.new( Class.new do def hash_including(*args) args end end ) { include WebMock::API } end it 'uses super and passes the args untampered' do expect(subject).to eq(args) end end end describe '#hash_excluding' do subject { klass.new.hash_excluding(args) } let(:args) { { data: :one } } context 'when mixed into a class that does not define `hash_including`' do let(:klass) do Class.new do include WebMock::API end end it 'uses WebMock::Matchers::HashIncludingMatcher' do expect(subject).to be_a(WebMock::Matchers::HashExcludingMatcher) end # by testing equality for HashIncludingMatcher (which stringifies the passed hash) we are # testing HashIncludingMatcher.initialize behavior as well context 'when args correspond to an hash' do context 'creates "HashExcludingMatcher"' do it 'equals hash with similar key but different value' do expect(subject).to eq('data' => :two) end it 'equals hash with similar value but different key' do expect(subject).to eq('data2' => :one) end it 'equals hash with defferent value and key' do expect(subject).to eq('data2' => :two) end it 'not equals with similar value and key' do expect(subject).not_to eq('data' => :one) end end end context 'when args are one or many keys' do subject { klass.new.hash_excluding(:foo, :bar) } let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) } it "creates 'HashExcludingMatcher' with keys anythingized" do expect(subject).not_to eq('foo' => anything, 'bar' => anything ) end end context 'when args are both keys and key/value pairs' do subject { klass.new.hash_excluding(:foo, :bar, data: :one) } let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) } it 'creates "HashExcludingMatcher" with keys anythingized' do expect(subject).not_to eq('foo' => anything, 'bar' => anything, 'data' => :one) end end context 'when args are an empty hash' do subject { klass.new.hash_excluding({}) } it 'creates "HashExcludingMatcher" with an empty hash' do expect(subject).to eq({}) end end end context 'when mixed into a class with a parent that defines `hash_excluding`' do subject { klass.new.hash_excluding(*args) } let(:args) { %w(:foo, :bar, {:data => :one}) } let(:klass) do Class.new( Class.new do def hash_excluding(*args) args end end ) { include WebMock::API } end it 'uses super and passes the args untampered' do expect(subject).to eq(args) end end end describe '#reset_executed_requests!' do subject { WebMock::API.reset_executed_requests! } let(:request_signature) { WebMock::RequestSignature.new(:get, "www.example.com") } let(:request_pattern) { WebMock::RequestPattern.new(:get, "www.example.com") } before do WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) end it 'resets request registry counter' do expect{ subject }.to change{ WebMock::RequestRegistry.instance.times_executed(request_pattern) }.from(1).to(0) end end end webmock-3.18.1/spec/unit/rack_response_spec.rb0000644000004100000410000000745414333126774021415 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe WebMock::RackResponse do before :each do @rack_response = WebMock::RackResponse.new(MyRackApp) end it "should hook up to a rack appliance" do request = WebMock::RequestSignature.new(:get, 'www.example.com') response = @rack_response.evaluate(request) expect(response.status.first).to eq(200) expect(response.body).to include('This is my root!') end it "should set the reason phrase based on the status code" do request = WebMock::RequestSignature.new(:get, 'www.example.com') response = @rack_response.evaluate(request) expect(response.status).to eq([200, "OK"]) request = WebMock::RequestSignature.new(:get, 'www.example.com/error') response = @rack_response.evaluate(request) expect(response.status).to eq([500, "Internal Server Error"]) end it "should behave correctly when the rack response is not a simple array of strings" do request = WebMock::RequestSignature.new(:get, 'www.example.com/non_array_response') response = @rack_response.evaluate(request) expect(response.status.first).to eq(200) expect(response.body).to include('This is not in an array!') end it "should shouldn't blow up when hitting a locked resource twice" do @locked_rack_response = WebMock::RackResponse.new(MyLockedRackApp) request = WebMock::RequestSignature.new(:get, 'www.example.com/locked') @locked_rack_response.evaluate(request) response2 = @locked_rack_response.evaluate(request) expect(response2.body).to include('Single threaded response.') expect(response2.status.first).to eq(200) end it "should send along params" do request = WebMock::RequestSignature.new(:get, 'www.example.com/greet?name=Johnny') response = @rack_response.evaluate(request) expect(response.status.first).to eq(200) expect(response.body).to include('Hello, Johnny') end it "should send along POST params" do request = WebMock::RequestSignature.new(:post, 'www.example.com/greet', body: 'name=Jimmy' ) response = @rack_response.evaluate(request) expect(response.body).to include('Good to meet you, Jimmy!') end it "should send params with proper content length if params have non-ascii symbols" do request = WebMock::RequestSignature.new(:post, 'www.example.com/greet', body: 'name=Олег' ) response = @rack_response.evaluate(request) expect(response.body).to include('Good to meet you, Олег!') end describe 'rack error output' do before :each do @original_stderr = $stderr $stderr = StringIO.new end after :each do $stderr = @original_stderr end it 'should behave correctly when an app uses rack.errors' do request = WebMock::RequestSignature.new(:get, 'www.example.com/error') expect { @rack_response.evaluate(request) }.to_not raise_error expect($stderr.length).to_not eq 0 end end describe 'basic auth request' do before :each do @rack_response_with_basic_auth = WebMock::RackResponse.new( Rack::Auth::Basic.new(MyRackApp) do |username, password| username == 'username' && password == 'password' end ) end it 'should be failure when wrong credentials' do request = WebMock::RequestSignature.new(:get, 'foo:bar@www.example.com') response = @rack_response_with_basic_auth.evaluate(request) expect(response.status.first).to eq(401) expect(response.body).not_to include('This is my root!') end it 'should be success when valid credentials' do request = WebMock::RequestSignature.new(:get, 'username:password@www.example.com') response = @rack_response_with_basic_auth.evaluate(request) expect(response.status.first).to eq(200) expect(response.body).to include('This is my root!') end end end webmock-3.18.1/spec/unit/matchers/0000755000004100000410000000000014333126774017014 5ustar www-datawww-datawebmock-3.18.1/spec/unit/matchers/hash_excluding_matcher_spec.rb0000644000004100000410000000363314333126774025050 0ustar www-datawww-datarequire 'spec_helper' module WebMock module Matchers describe HashExcludingMatcher do it 'stringifies the given hash keys' do expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('a' => 1, 'b' => 2) end it 'sorts elements in the hash' do expect(HashExcludingMatcher.new(b: 2, a: 1)).not_to eq('a' => 1, 'b' => 2) end it 'describes itself properly' do expect(HashExcludingMatcher.new(a: 1).inspect).to eq 'hash_excluding({"a"=>1})' end describe 'success' do it 'match with hash with a missing key' do expect(HashExcludingMatcher.new(a: 1)).to eq('b' => 2) end it 'match an empty hash with a given key' do expect(HashExcludingMatcher.new(a: 1)).to eq({}) end it 'match when values are nil but keys are different' do expect(HashExcludingMatcher.new(a: nil)).to eq('b' => nil) end describe 'when matching an empty hash' do it 'does not matches against any hash' do expect(HashExcludingMatcher.new({})).to eq(a: 1, b: 2, c: 3) end end end describe 'failing' do it 'does not match a hash with a one missing key when one pair is matching' do expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('b' => 2) end it 'match a hash with an incorrect value' do expect(HashExcludingMatcher.new(a: 1, b: 2)).not_to eq('a' => 1, 'b' => 3) end it 'does not matches the same hash' do expect(HashExcludingMatcher.new('a' => 1, 'b' => 2)).not_to eq('a' => 1, 'b' => 2) end it 'does not matches a hash with extra stuff' do expect(HashExcludingMatcher.new(a: 1)).not_to eq('a' => 1, 'b' => 2) end it 'does not match a non-hash' do expect(HashExcludingMatcher.new(a: 1)).not_to eq 1 end end end end end webmock-3.18.1/spec/unit/matchers/hash_including_matcher_spec.rb0000644000004100000410000000562214333126774025042 0ustar www-datawww-datarequire 'spec_helper' module WebMock module Matchers describe HashIncludingMatcher do it "stringifies the given hash keys" do expect(HashIncludingMatcher.new(a: 1, b: 2)).to eq("a" => 1, "b" => 2) end it "sorts elements in the hash" do expect(HashIncludingMatcher.new(b: 2, a: 1)).to eq("a" => 1, "b" => 2) end it "describes itself properly" do expect(HashIncludingMatcher.new(a: 1).inspect).to eq "hash_including({\"a\"=>1})" end describe "success" do it "matches the same hash" do expect(HashIncludingMatcher.new("a" => 1, "b" => 2)).to eq("a" => 1, "b" => 2) end it "matches a hash with extra stuff" do expect(HashIncludingMatcher.new(a: 1)).to eq("a" => 1, "b" => 2) end describe "when matching anythingized keys" do let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) } it "matches an int against anything()" do expect(HashIncludingMatcher.new(a: anything, b: 2)).to eq({'a' => 1, 'b' => 2}) end it "matches a string against anything()" do expect(HashIncludingMatcher.new(a: anything, b: 2)).to eq({'a' => "1", 'b' => 2}) end it "matches if the key is present" do expect(HashIncludingMatcher.new(a: anything)).to eq({'a' => 1, 'b' => 2}) end it "matches if more keys are present" do expect(HashIncludingMatcher.new(a: anything, b: anything)).to eq({'a' => 1, 'b' => 2, 'c' => 3}) end it "matches if passed many keys and many key/value pairs" do expect(HashIncludingMatcher.new(a: anything, b: anything, c: 3, e: 5)).to eq({'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}) end end describe "when matching an empty hash" do it "matches against any hash" do expect(HashIncludingMatcher.new({})).to eq({a: 1, b: 2, c: 3}) end end end describe "failing" do it "does not match a non-hash" do expect(HashIncludingMatcher.new(a: 1)).not_to eq 1 end it "does not match a hash with a missing key" do expect(HashIncludingMatcher.new(a: 1)).not_to eq('b' => 2) end it "does not match an empty hash with a given key" do expect(HashIncludingMatcher.new(a: 1)).not_to eq({}) end it "does not match a hash with a missing key when one pair is matching" do expect(HashIncludingMatcher.new(a: 1, b: 2)).not_to eq('b' => 2) end it "does not match a hash with an incorrect value" do expect(HashIncludingMatcher.new(a: 1, b: 2)).not_to eq('a' => 1, 'b' => 3) end it "does not match when values are nil but keys are different" do expect(HashIncludingMatcher.new(a: nil)).not_to eq('b' => nil) end end end end end webmock-3.18.1/spec/unit/request_signature_spec.rb0000644000004100000410000001537214333126774022326 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::RequestSignature do describe "initialization" do it "assign the uri to be the normalized uri" do expect(WebMock::Util::URI).to receive(:normalize_uri).and_return("www.example.kom") signature = WebMock::RequestSignature.new(:get, "www.example.com") expect(signature.uri).to eq("www.example.kom") end it "assigns the uri without normalization if uri is already a URI" do expect(WebMock::Util::URI).not_to receive(:normalize_uri) uri = Addressable::URI.parse("www.example.com") signature = WebMock::RequestSignature.new(:get, uri) expect(signature.uri).to eq(uri) end it "assigns normalized headers" do allow(WebMock::Util::Headers).to receive(:normalize_headers).with({'A' => 'a'}.freeze).and_return('B' => 'b') expect( WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'}).headers ).to eq({'B' => 'b'}) end it "assign the body" do expect(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc").body).to eq("abc") end it "symbolizes the method" do expect(WebMock::RequestSignature.new('get', "www.example.com", body: "abc").method).to eq(:get) end end describe "#to_s" do it "describes itself" do expect(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}).to_s).to eq( "GET http://www.example.com/ with body 'abc' with headers {'A'=>'a', 'B'=>'b'}" ) end end describe "#hash" do it "reporst same hash for two signatures with the same values" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}) signature2 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}) expect(signature1.hash).to eq(signature2.hash) end it "reports different hash for two signatures with different method" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com") signature2 = WebMock::RequestSignature.new(:put, "www.example.com") expect(signature1.hash).not_to eq(signature2.hash) end it "reports different hash for two signatures with different uri" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com") signature2 = WebMock::RequestSignature.new(:get, "www.example.org") expect(signature1.hash).not_to eq(signature2.hash) end it "reports different hash for two signatures with different body" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc") signature2 = WebMock::RequestSignature.new(:get, "www.example.com", body: "def") expect(signature1.hash).not_to eq(signature2.hash) end it "reports different hash for two signatures with different headers" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'}) signature2 = WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'A'}) expect(signature1.hash).not_to eq(signature2.hash) end end [:==, :eql?].each do |method| describe method do it "is true for two signatures with the same values" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}) signature2 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}) expect(signature1.send(method, signature2)).to be_truthy end it "is false for two signatures with different method" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com") signature2 = WebMock::RequestSignature.new(:put, "www.example.com") expect(signature1.send(method, signature2)).to be_falsey end it "is false for two signatures with different uri" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com") signature2 = WebMock::RequestSignature.new(:get, "www.example.org") expect(signature1.send(method, signature2)).to be_falsey end it "is false for two signatures with different body" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", body: "abc") signature2 = WebMock::RequestSignature.new(:get, "www.example.com", body: "def") expect(signature1.send(method, signature2)).to be_falsey end it "is false for two signatures with different headers" do signature1 = WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'}) signature2 = WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'A'}) expect(signature1.send(method, signature2)).to be_falsey end end end subject { WebMock::RequestSignature.new(:get, "www.example.com") } describe "#url_encoded?" do it "returns true if the headers are urlencoded" do subject.headers = { "Content-Type" => "application/x-www-form-urlencoded" } expect(subject.url_encoded?).to be true end it "returns true if the headers are urlencoded with a specified charset" do subject.headers = { "Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8" } expect(subject.url_encoded?).to be true end it "returns false if the headers are NOT urlencoded" do subject.headers = { "Content-Type" => "application/made-up-format" } expect(subject.url_encoded?).to be false end it "returns false when no content type header is present" do subject.headers = { "Some-Header" => "some-value" } expect(subject.url_encoded?).to be false end it "returns false when no headers are set" do subject.headers = nil expect(subject.url_encoded?).to be false end end describe "#json_headers?" do it "returns true if the headers are json" do subject.headers = { "Content-Type" => "application/json" } expect(subject.json_headers?).to be true end it "returns true if the headers are json with a specified charset" do subject.headers = { "Content-Type" => "application/json; charset=UTF-8" } expect(subject.json_headers?).to be true end it "returns false if the headers are NOT json" do subject.headers = { "Content-Type" => "application/made-up-format" } expect(subject.json_headers?).to be false end it "returns false when no content type header is present" do subject.headers = { "Some-Header" => "some-value" } expect(subject.json_headers?).to be false end it "returns false when no headers are set" do subject.headers = nil expect(subject.json_headers?).to be false end end end webmock-3.18.1/spec/unit/util/0000755000004100000410000000000014333126774016163 5ustar www-datawww-datawebmock-3.18.1/spec/unit/util/headers_spec.rb0000644000004100000410000000165514333126774021144 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::Util::Headers do it "should decode_userinfo_from_header handles basic auth" do authorization_header = "Basic dXNlcm5hbWU6c2VjcmV0" userinfo = WebMock::Util::Headers.decode_userinfo_from_header(authorization_header) expect(userinfo).to eq("username:secret") end describe "sorted_headers_string" do it "should return nice string for hash with string values" do expect(WebMock::Util::Headers.sorted_headers_string({"a" => "b"})).to eq("{'A'=>'b'}") end it "should return nice string for hash with array values" do expect(WebMock::Util::Headers.sorted_headers_string({"a" => ["b", "c"]})).to eq("{'A'=>['b', 'c']}") end it "should return nice string for hash with array values and string values" do expect(WebMock::Util::Headers.sorted_headers_string({"a" => ["b", "c"], "d" => "e"})).to eq("{'A'=>['b', 'c'], 'D'=>'e'}") end end end webmock-3.18.1/spec/unit/util/json_spec.rb0000644000004100000410000000177314333126774020503 0ustar www-datawww-data# encoding: utf-8 require 'spec_helper' describe WebMock::Util::JSON do describe ".parse" do it "should parse json without parsing dates" do expect(WebMock::Util::JSON.parse("\"a\":\"2011-01-01\"")).to eq( {"a" => "2011-01-01"} ) end it "can parse json with multibyte characters" do expect(WebMock::Util::JSON.parse( "{\"name\":\"山田太郎\"\,\"job\":\"会社員\"}" )).to eq({"name" => "山田太郎", "job" => "会社員"}) end it "rescues ArgumentError's from YAML.load" do allow(YAML).to receive(:load).and_raise(ArgumentError) expect { WebMock::Util::JSON.parse("Bad JSON") }.to raise_error WebMock::Util::JSON::ParseError end end describe ".convert_json_to_yaml" do it "parses multibyte characters" do expect(WebMock::Util::JSON.convert_json_to_yaml( "{\"name\":\"山田太郎\"\,\"job\":\"会社員\"}" )).to eq "{\"name\": \"山田太郎\", \"job\": \"会社員\"}" end end end webmock-3.18.1/spec/unit/util/version_checker_spec.rb0000644000004100000410000000554314333126774022702 0ustar www-datawww-datarequire 'spec_helper' module WebMock describe VersionChecker do it 'prints a warning if the major version is too low' do checker = VersionChecker.new('foo', '0.7.3', '1.0.0', '1.1') expect(Kernel).to receive(:warn).with("\e[31mYou are using foo 0.7.3. WebMock supports version >= 1.0.0, < 1.2.\e[0m") checker.check_version! end it 'prints a warning if the minor version is too low' do checker = VersionChecker.new('foo', '1.0.99', '1.1.3', '1.2') expect(Kernel).to receive(:warn).with("\e[31mYou are using foo 1.0.99. WebMock supports version >= 1.1.3, < 1.3.\e[0m") checker.check_version! end it 'prints a warning if the patch version is too low' do checker = VersionChecker.new('foo', '1.0.8', '1.0.10', '1.2') expect(Kernel).to receive(:warn).with("\e[31mYou are using foo 1.0.8. WebMock supports version >= 1.0.10, < 1.3.\e[0m") checker.check_version! end it 'prints a warning if the patch version is too low and max version is not specified' do checker = VersionChecker.new('foo', '1.0.8', '1.0.10') expect(Kernel).to receive(:warn).with("\e[31mYou are using foo 1.0.8. WebMock supports version >= 1.0.10.\e[0m") checker.check_version! end it 'prints a warning if the major version is too high' do checker = VersionChecker.new('foo', '2.0.0', '1.0.0', '1.1') expect(Kernel).to receive(:warn).with(/may not work with this version/) checker.check_version! end it 'prints a warning if the minor version is too high' do checker = VersionChecker.new('foo', '1.2.0', '1.0.0', '1.1') expect(Kernel).to receive(:warn).with(/may not work with this version/) checker.check_version! end it 'does not raise an error or print a warning when the major version is between the min and max' do checker = VersionChecker.new('foo', '2.0.0', '1.0.0', '3.0') expect(Kernel).not_to receive(:warn) checker.check_version! end it 'does not raise an error or print a warning when the min_patch is 0.6.5, the max_minor is 0.7 and the version is 0.7.3' do checker = VersionChecker.new('foo', '0.7.3', '0.6.5', '0.7') expect(Kernel).not_to receive(:warn) checker.check_version! end it 'does not raise an error or print a warning when the min_patch is 0.6.5, the max_minor is not specified and the version is 0.8.3' do checker = VersionChecker.new('foo', '0.8.3', '0.6.5') expect(Kernel).not_to receive(:warn) checker.check_version! end it "prints warning if version is unsupported" do checker = VersionChecker.new('foo', '2.0.0', '1.0.0', '3.0', ['2.0.0']) expect(Kernel).to receive(:warn).with(%r{You are using foo 2.0.0. WebMock does not support this version. WebMock supports versions >= 1.0.0, < 3.1, except versions 2.0.0.}) checker.check_version! end end end webmock-3.18.1/spec/unit/util/hash_keys_stringifier_spec.rb0000644000004100000410000000074214333126774024110 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::Util::HashKeysStringifier do it "should recursively stringify all symbol keys" do hash = { a: { b: [ { c: [{d: "1"}] } ] } } stringified = { 'a' => { 'b' => [ { 'c' => [{'d' => "1"}] } ] } } expect(WebMock::Util::HashKeysStringifier.stringify_keys!(hash, deep: true)).to eq(stringified) end end webmock-3.18.1/spec/unit/util/uri_spec.rb0000644000004100000410000003172114333126774020325 0ustar www-datawww-datarequire 'spec_helper' URIS_WITHOUT_PATH_OR_PARAMS = [ "www.example.com", "www.example.com/", "www.example.com:80", "www.example.com:80/", "http://www.example.com", "http://www.example.com/", "http://www.example.com:80", "http://www.example.com:80/" ].sort URIS_WITHOUT_PATH_BUT_WITH_PARAMS = [ "www.example.com?a=b", "www.example.com/?a=b", "www.example.com:80?a=b", "www.example.com:80/?a=b", "http://www.example.com?a=b", "http://www.example.com/?a=b", "http://www.example.com:80?a=b", "http://www.example.com:80/?a=b" ].sort URIS_WITH_AUTH = [ "a b:pass@www.example.com", "a b:pass@www.example.com/", "a b:pass@www.example.com:80", "a b:pass@www.example.com:80/", "http://a b:pass@www.example.com", "http://a b:pass@www.example.com/", "http://a b:pass@www.example.com:80", "http://a b:pass@www.example.com:80/", "a%20b:pass@www.example.com", "a%20b:pass@www.example.com/", "a%20b:pass@www.example.com:80", "a%20b:pass@www.example.com:80/", "http://a%20b:pass@www.example.com", "http://a%20b:pass@www.example.com/", "http://a%20b:pass@www.example.com:80", "http://a%20b:pass@www.example.com:80/" ].sort URIS_WITH_PATH_AND_PARAMS = [ "www.example.com/my path/?a=my param&b=c d", "www.example.com/my%20path/?a=my%20param&b=c%20d", "www.example.com:80/my path/?a=my param&b=c d", "www.example.com:80/my%20path/?a=my%20param&b=c%20d", "http://www.example.com/my path/?a=my param&b=c d", "http://www.example.com/my%20path/?a=my%20param&b=c%20d", "http://www.example.com:80/my path/?a=my param&b=c d", "http://www.example.com:80/my%20path/?a=my%20param&b=c%20d", ].sort URIS_WITH_DIFFERENT_PORT = [ "www.example.com:88", "www.example.com:88/", "http://www.example.com:88", "http://www.example.com:88/" ].sort URIS_FOR_HTTPS = [ "https://www.example.com", "https://www.example.com/", "https://www.example.com:443", "https://www.example.com:443/" ].sort URIS_FOR_LOCALHOST = [ "localhost", "localhost/", "localhost:80", "localhost:80/", "http://localhost", "http://localhost/", "http://localhost:80", "http://localhost:80/" ].sort URIS_WITH_SCHEME = [ "http://www.example.com", "http://www.example.com/", "http://www.example.com:80", "http://www.example.com:80/" ].sort URIS_WITH_COLON_IN_PATH = [ [ "https://example.com/a/b:80", "https://example.com:443/a/b:80", ].sort, [ "https://example.com:443/a/b:443", "https://example.com/a/b:443", ].sort, [ "http://example.com/a/b:443", "example.com/a/b:443", "http://example.com:80/a/b:443", "example.com:80/a/b:443", ].sort, [ "http://example.com/a/b:80", "example.com/a/b:80", "http://example.com:80/a/b:80", "example.com:80/a/b:80", ].sort ] describe WebMock::Util::URI do describe "reporting variations of uri" do it "should find all variations of the same uri for all variations of uri with params and path" do URIS_WITH_PATH_AND_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_PATH_AND_PARAMS) end end it "should find all variations of the same uri for all variations of uri with params but without path" do URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITHOUT_PATH_BUT_WITH_PARAMS) end end it "should find all variations of the same uri for all variations of uri without params or path" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITHOUT_PATH_OR_PARAMS) end end it "should find all variations of the same uri for all variations of uri with auth" do URIS_WITH_AUTH.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_AUTH) end end it "should find all variations of the same uri for all variations of uri with different port" do URIS_WITH_DIFFERENT_PORT.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_WITH_DIFFERENT_PORT) end end it "should find all variations of the same uri for all variations of https uris" do URIS_FOR_HTTPS.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_FOR_HTTPS) end end it "should find all variations of the same uri for all variations of host names uris without a period" do URIS_FOR_LOCALHOST.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(URIS_FOR_LOCALHOST) end end it "should find all variations of the same uri with scheme for all variations when only_with_scheme is true" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri| variations_of_uri_with_scheme = WebMock::Util::URI.variations_of_uri_as_strings(uri, only_with_scheme: true) expect(variations_of_uri_with_scheme.sort).to eq(URIS_WITH_SCHEME) end end it "should not replace :80 or :443 in path" do URIS_WITH_COLON_IN_PATH.each do |uris| uris.each do |uri| expect(WebMock::Util::URI.variations_of_uri_as_strings(uri).sort).to eq(uris) end end end it "should find all variations of uris with https, basic auth, a non-standard port and a path" do uri = "https://~%8A:pass@www.example.com:9000/foo" variations = [ "https://~%8A:pass@www.example.com:9000/foo", "https://~\x8A:pass@www.example.com:9000/foo".force_encoding(Encoding::ASCII_8BIT) ] expect(WebMock::Util::URI.variations_of_uri_as_strings(uri)).to eq(variations) end end describe "normalized uri equality" do it "should successfully compare all variations of the same uri with path and params" do URIS_WITH_PATH_AND_PARAMS.each do |uri_a| URIS_WITH_PATH_AND_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri with path but with params" do URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri_a| URIS_WITHOUT_PATH_BUT_WITH_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri without path or params" do URIS_WITHOUT_PATH_OR_PARAMS.each do |uri_a| URIS_WITHOUT_PATH_OR_PARAMS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri with authority" do URIS_WITH_AUTH.each do |uri_a| URIS_WITH_AUTH.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same uri custom port" do URIS_WITH_DIFFERENT_PORT.each do |uri_a| URIS_WITH_DIFFERENT_PORT.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully compare all variations of the same https uri" do URIS_FOR_HTTPS.each do |uri_a| URIS_FOR_HTTPS.each do |uri_b| expect(WebMock::Util::URI.normalize_uri(uri_a)).to be === WebMock::Util::URI.normalize_uri(uri_b) end end end it "should successfully handle array parameters" do uri_string = 'http://www.example.com:80/path?a[]=b&a[]=c' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"a"=>["b", "c"]}) end it "should successfully handle hash parameters" do uri_string = 'http://www.example.com:80/path?a[d]=b&a[e]=c&a[b][c]=1' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"a"=>{"d"=>"b", "e"=>"c", "b"=>{"c"=>"1"}}}) end it "should successfully handle nested hash parameters" do uri_string = 'http://www.example.com:80/path?one[two][three][]=four&one[two][three][]=five' uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"one"=>{"two"=>{"three" => ["four", "five"]}}}) end it "should successfully handle mixed array and hash parameters" do # derived from an elasticsearch query: # load => { # :include => [ # { :staff => :email }, # :business_name # ] # } uri_string = "http://www.example.com:80/path?load[include][][staff]=email&load[include][]=business_name" uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query)).to eq({"load"=>{"include"=>[{"staff"=>"email"},"business_name"]}}) end context "when query notation is set to :flat_array" do before :all do WebMock::Config.instance.query_values_notation = :flat_array end it "should successfully handle repeated paramters" do uri_string = "http://www.example.com:80/path?target=host1&target=host2" uri = WebMock::Util::URI.normalize_uri(uri_string) expect(WebMock::Util::QueryMapper.query_to_values(uri.query, notation: WebMock::Config.instance.query_values_notation)).to eq([['target', 'host1'], ['target', 'host2']]) end end end describe "sorting query values" do context "when query values is a Hash" do it "returns an alphabetically sorted hash" do sorted_query = WebMock::Util::URI.sort_query_values({"b"=>"one", "a"=>"two"}) expect(sorted_query).to eq({"a"=>"two", "b"=>"one"}) end end context "when query values is an Array" do it "returns an alphabetically sorted array" do sorted_query = WebMock::Util::URI.sort_query_values([["b","two"],["a","one_b"],["a","one_a"]]) expect(sorted_query).to eq([["a","one_a"],["a","one_b"],["b","two"]]) end end end describe "stripping default port" do it "should strip_default_port_from_uri strips 80 from http with path" do uri = "http://example.com:80/foo/bar" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("http://example.com/foo/bar") end it "should strip_default_port_from_uri strips 80 from http without path" do uri = "http://example.com:80" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("http://example.com") end it "should strip_default_port_from_uri strips 443 from https without path" do uri = "https://example.com:443" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("https://example.com") end it "should strip_default_port_from_uri strips 443 from https" do uri = "https://example.com:443/foo/bar" stripped_uri = WebMock::Util::URI.strip_default_port_from_uri_string(uri) expect(stripped_uri).to eq("https://example.com/foo/bar") end it "should strip_default_port_from_uri does not strip 8080 from http" do uri = "http://example.com:8080/foo/bar" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not strip 443 from http" do uri = "http://example.com:443/foo/bar" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not strip 80 from query string" do uri = "http://example.com/?a=:80&b=c" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end it "should strip_default_port_from_uri does not modify strings that do not start with http or https" do uri = "httpz://example.com:80/" expect(WebMock::Util::URI.strip_default_port_from_uri_string(uri)).to eq(uri) end end describe "encoding userinfo" do it "should encode unsafe chars in userinfo does not encode userinfo safe punctuation" do userinfo = "user;&=+$,:secret" expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(userinfo) end it "should encode unsafe chars in userinfo does not encode rfc 3986 unreserved characters" do userinfo = "-.!~*'()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:secret" expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(userinfo) end it "should encode unsafe chars in userinfo does encode other characters" do userinfo, safe_userinfo = 'us#rn@me:sec//ret?"', 'us%23rn%40me:sec%2F%2Fret%3F%22' expect(WebMock::Util::URI.encode_unsafe_chars_in_userinfo(userinfo)).to eq(safe_userinfo) end end end webmock-3.18.1/spec/unit/util/query_mapper_spec.rb0000644000004100000410000001267314333126774022244 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::Util::QueryMapper do subject { described_class } context '#query_to_values' do it 'should raise on invalid notation' do query = 'a=&b=c' expect { subject.query_to_values(query, {notation: 'foo'}) }.to raise_error( ArgumentError, 'Invalid notation. Must be one of: [:flat, :dot, :subscript, :flat_array].' ) end it 'should parse hash queries' do # {"one" => {"two" => {"three" => ["four", "five"]}}} query = 'one%5Btwo%5D%5Bthree%5D%5B%5D=four&one%5Btwo%5D%5Bthree%5D%5B%5D=five' hsh = subject.query_to_values(query) expect(hsh['one']['two']['three']).to eq(%w(four five)) end it 'should parse one nil value queries' do # {'a' => nil, 'b' => 'c'} query = 'a=&b=c' hsh = subject.query_to_values(query) expect(hsh['a']).to be_empty expect(hsh['b']).to eq('c') end it 'should parse array queries' do # {"one" => ["foo", "bar"]} query = 'one%5B%5D=foo&one%5B%5D=bar' hsh = subject.query_to_values(query) expect(hsh['one']).to eq(%w(foo bar)) end it 'should parse string queries' do # {"one" => "two", "three" => "four"} query = 'one=two&three=four' hsh = subject.query_to_values(query) expect(hsh).to eq({'one' => 'two', 'three' => 'four'}) end it 'should parse nested queries' do # [{"b"=>[{"c"=>[{"d"=>["1", {"e"=>"2"}]}]}]}] query = 'a%5B%5D%5Bb%5D%5B%5D%5Bc%5D%5B%5D%5Bd%5D%5B%5D=1&a%5B%5D%5Bb%5D%5B%5D%5Bc%5D%5B%5D%5Bd%5D%5B%5D%5Be%5D=2' hsh = subject.query_to_values(query) expect(hsh['a'][0]['b'][0]['c'][0]['d'][0]).to eq('1') expect(hsh['a'][0]['b'][0]['c'][0]['d'][1]['e']).to eq('2') end it "should parse nested repeated correctly" do query = "a[][b][]=one&a[][b][]=two" hsh = subject.query_to_values(query) expect(hsh['a']).to be_a(Array) expect(hsh['a'][0]).to eq({"b" => ['one']}) expect(hsh['a'][1]).to eq({"b" => ['two']}) end it "should parse nested non-repeated correctly" do query = "a[][b][]=one&a[][c][]=two" hsh = subject.query_to_values(query) expect(hsh['a']).to be_a(Array) expect(hsh['a'][0]['b']).to eq(['one']) expect(hsh['a'][0]['c']).to eq(['two']) end it 'should not attempt to mutate its query argument' do query = "a=foo".freeze hsh = subject.query_to_values(query) expect(hsh['a']).to eq('foo') end it "should parse hash query with key starting with non word character" do query = "a[$in]=1".freeze hsh = subject.query_to_values(query) expect(hsh).to eql({'a' => {'$in' => '1'}}) end end context '#to_query' do it 'should transform nil value' do expect(subject.to_query('a', nil)).to eq('a') end it 'should transform string value' do expect(subject.to_query('a', 'b')).to eq('a=b') end it 'should transform hash value' do expect(subject.to_query('a', {'key' => 'value'})).to eq('a[key]=value') end it 'should transform hash value with keys that are symbols' do expect(subject.to_query('a', {key: 'value'})).to eq('a[key]=value') end it 'should transform array value' do expect(subject.to_query('a', ['b', 'c'])).to eq('a[0]=b&a[1]=c') end it 'should transform boolean values' do expect(subject.to_query('a', true)).to eq('a=true') expect(subject.to_query('a', false)).to eq('a=false') end end context '#values_to_query' do it 'converts values to a query string' do query = "key=value&other_key=other_value" values = [['key','value'],['other_key','other_value']] expect(subject.values_to_query values).to eq query end it 'converts values with missing keys to a query string' do query = "=value" values = { '' => 'value' } expect(subject.values_to_query values).to eq query end it 'converts values with nil keys to a query string' do query = "=value" values = { nil => 'value' } expect(subject.values_to_query values).to eq query end end it 'converts array values, vice versa' do query = "one%5B%5D=1&one%5B%5D=2" # one[]=1&one[]=2 values = {"one" => ["1","2"]} expect(subject.values_to_query values).to eq query expect(subject.query_to_values query).to eq values end it 'converts hash values, vice versa' do query = "one%5Ba%5D=1&one%5Bb%5D=2" # one[a]=1&one[b]=2 values = {"one" => {"a" => "1", "b" => "2"}} expect(subject.values_to_query values).to eq query expect(subject.query_to_values query).to eq values end it 'converts complex nested hashes, vice versa' do query = "one%5B%5D[foo]=bar&one%5B%5D[zoo]=car" # one[][foo]=bar&one[][zoo]=car values = {"one" => [{"foo" => "bar", "zoo" => "car"}]} expect(subject.values_to_query values).to eq query expect(subject.query_to_values query).to eq values end it 'converts complex nested array of hashes, vice versa' do query = "one%5B%5D[foo]=bar&one%5B%5D[foo]=bar&one%5B%5D[zoo]=car" # one[][foo]=bar&one[][foo]=bar&one[][zoo]=car values = {"one" => [{"foo" => "bar"}, {"foo" => "bar", "zoo" => "car"}]} expect(subject.values_to_query values).to eq query expect(subject.query_to_values query).to eq values end it 'converts an empty array to ?' do query = "one%5B%5D" values = {"one" => []} expect(subject.values_to_query values).to eq query expect(subject.query_to_values query).to eq values end end webmock-3.18.1/spec/unit/util/hash_counter_spec.rb0000644000004100000410000000205114333126774022202 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::Util::HashCounter do it "should return 0 for non existing key" do expect(WebMock::Util::HashCounter.new.get(:abc)).to eq(0) end it "should increase the returned value on every put with the same key" do counter = WebMock::Util::HashCounter.new counter.put(:abc) expect(counter.get(:abc)).to eq(1) counter.put(:abc) expect(counter.get(:abc)).to eq(2) end it "should only increase value for given key provided to put" do counter = WebMock::Util::HashCounter.new counter.put(:abc) expect(counter.get(:abc)).to eq(1) expect(counter.get(:def)).to eq(0) end describe "each" do it "should provide elements in order of the last modified" do counter = WebMock::Util::HashCounter.new counter.put(:a) counter.put(:b) counter.put(:c) counter.put(:b) counter.put(:a) counter.put(:d) elements = [] counter.each {|k,v| elements << [k,v]} expect(elements).to eq([[:c, 1], [:b, 2], [:a, 2], [:d, 1]]) end end end webmock-3.18.1/spec/unit/errors_spec.rb0000644000004100000410000001452214333126774020065 0ustar www-datawww-datarequire 'spec_helper' describe "errors" do describe WebMock::NetConnectNotAllowedError do describe "message" do it "should have message with request signature and snippet" do allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\nYou can stub this request with the following snippet:" \ "\n\n#{stub_result}" \ "\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end it "should have message with registered stubs if available" do allow(WebMock::StubRegistry.instance).to receive(:request_stubs).and_return([request_stub]) allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) allow_any_instance_of(WebMock::RequestBodyDiff).to receive(:body_diff).and_return({}) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\nYou can stub this request with the following snippet:" \ "\n\n#{stub_result}" \ "\n\nregistered request stubs:" \ "\n\n#{stub_result}" \ "\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end it "should not be caught by a rescue block without arguments" do allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) exception = WebMock::NetConnectNotAllowedError.new(request_signature) expect do begin raise exception rescue raise "exception should not be caught" end end.to raise_exception exception end it "should print body diff if available" do allow(WebMock::StubRegistry.instance).to receive(:request_stubs).and_return([request_stub]) allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) allow_any_instance_of(WebMock::RequestBodyDiff).to receive(:body_diff).and_return(body_diff) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\nYou can stub this request with the following snippet:" \ "\n\n#{stub_result}" \ "\n\nregistered request stubs:" \ "\n\n#{stub_result}" \ "\n\nBody diff:\n [[\"+\", \"test\", \"test2\"], [\"-\", \"test3\"], [\"~\", \"test5\", \"test6\"]]" \ "\n\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end context "WebMock.show_body_diff? is false" do before do WebMock.hide_body_diff! end it "should not show body diff" do allow(WebMock::StubRegistry.instance).to receive(:request_stubs).and_return([request_stub]) allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) expect_any_instance_of(WebMock::RequestBodyDiff).to_not receive(:body_diff) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\nYou can stub this request with the following snippet:" \ "\n\n#{stub_result}" \ "\n\nregistered request stubs:" \ "\n\n#{stub_result}" \ "\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end end context "WebMock.show_stubbing_instructions? is false" do before do WebMock.hide_stubbing_instructions! end it "should have message with request signature and snippet" do allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end it "should have message with registered stubs if available" do allow(WebMock::StubRegistry.instance).to receive(:request_stubs).and_return([request_stub]) allow(WebMock::RequestStub).to receive(:from_request_signature).and_return(request_stub) allow(WebMock::StubRequestSnippet).to receive(:new). with(request_stub).and_return(stub_result) allow(request_stub).to receive(:request_pattern).and_return(body_pattern) expected = \ "Real HTTP connections are disabled. Unregistered request: #{request_signature}" \ "\n\nregistered request stubs:" \ "\n\n#{stub_result}" \ "\n\n============================================================" expect(WebMock::NetConnectNotAllowedError.new(request_signature).message).to eq(expected) end end end let(:request_signature) { double(:request_signature, to_s: rand(10**20).to_s) } let(:stub_result) { double(:stub_result, to_s: rand(10**20).to_s) } let(:request_stub) { double(:request_stub) } let(:body_pattern) { double(:body_pattern, body_pattern: nil)} let(:body_diff) { [["+", "test", "test2"], ["-", "test3"], ["~", "test5", "test6"]] } end end webmock-3.18.1/spec/unit/stub_request_snippet_spec.rb0000644000004100000410000001265014333126774023040 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::StubRequestSnippet do describe "to_s" do describe "GET" do before(:each) do @request_signature = WebMock::RequestSignature.new(:get, "www.example.com/?a=b&c=d", headers: {}) end it "should print stub request snippet with url with params and method and empty successful response" do expected = %Q(stub_request(:get, "http://www.example.com/?a=b&c=d").\n to_return(status: 200, body: "", headers: {})) @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected) end it "should print stub request snippet with body if available" do @request_signature.body = "abcdef" expected = %Q(stub_request(:get, "http://www.example.com/?a=b&c=d").)+ "\n with(\n body: \"abcdef\")." + "\n to_return(status: 200, body: \"\", headers: {})" @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected) end it "should print stub request snippet with multiline body" do @request_signature.body = "abc\ndef" expected = %Q(stub_request(:get, "http://www.example.com/?a=b&c=d").)+ "\n with(\n body: \"abc\\ndef\")." + "\n to_return(status: 200, body: \"\", headers: {})" @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected) end it "should print stub request snippet with headers if any" do @request_signature.headers = {'B' => 'b', 'A' => 'a'} expected = 'stub_request(:get, "http://www.example.com/?a=b&c=d").'+ "\n with(\n headers: {\n\t\ 'A\'=>\'a\',\n\t \'B\'=>\'b\'\n })." + "\n to_return(status: 200, body: \"\", headers: {})" @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected) end it "should print stub request snippet with body and headers" do @request_signature.body = "abcdef" @request_signature.headers = {'B' => 'b', 'A' => 'a'} expected = 'stub_request(:get, "http://www.example.com/?a=b&c=d").'+ "\n with(\n body: \"abcdef\",\n headers: {\n\t \'A\'=>\'a\',\n\t \'B\'=>\'b\'\n })." + "\n to_return(status: 200, body: \"\", headers: {})" @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected) end it "should not print to_return part if not wanted" do expected = 'stub_request(:get, "http://www.example.com/").'+ "\n with(\n body: \"abcdef\")" stub = WebMock::RequestStub.new(:get, "www.example.com").with(body: "abcdef").to_return(body: "hello") expect(WebMock::StubRequestSnippet.new(stub).to_s(false)).to eq(expected) end end describe "POST" do let(:form_body) { 'user%5bfirst_name%5d=Bartosz' } let(:multipart_form_body) { 'complicated stuff--ABC123--goes here' } it "should print stub request snippet with body as a hash using rails conventions on form posts" do @request_signature = WebMock::RequestSignature.new(:post, "www.example.com", headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: form_body) @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expected = <<-STUB stub_request(:post, "http://www.example.com/"). with( body: {"user"=>{"first_name"=>"Bartosz"}}, headers: { \t 'Content-Type'=>'application/x-www-form-urlencoded' }). to_return(status: 200, body: \"\", headers: {}) STUB expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected.strip) end it "should print stub request snippet leaving body as string when not a urlencoded form" do @request_signature = WebMock::RequestSignature.new(:post, "www.example.com", headers: {'Content-Type' => 'multipart/form-data; boundary=ABC123'}, body: multipart_form_body) @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expected = <<-STUB stub_request(:post, "http://www.example.com/"). with( body: "#{multipart_form_body}", headers: { \t 'Content-Type'=>'multipart/form-data; boundary=ABC123' }). to_return(status: 200, body: \"\", headers: {}) STUB expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected.strip) end it "should print stub request snippet with valid JSON body when request header contains 'Accept'=>'application/json' " do @request_signature = WebMock::RequestSignature.new(:post, "www.example.com", headers: {'Accept' => 'application/json'}) @request_stub = WebMock::RequestStub.from_request_signature(@request_signature) expected = <<-STUB stub_request(:post, "http://www.example.com/"). with( headers: { \t 'Accept'=>'application/json' }). to_return(status: 200, body: \"{}\", headers: {}) STUB expect(WebMock::StubRequestSnippet.new(@request_stub).to_s).to eq(expected.strip) end end end end webmock-3.18.1/spec/unit/request_stub_spec.rb0000644000004100000410000002061014333126774021271 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::RequestStub do before(:each) do @request_stub = WebMock::RequestStub.new(:get, "www.example.com") end it "should have request pattern with method and uri" do expect(@request_stub.request_pattern.to_s).to eq("GET http://www.example.com/") end it "should have response" do expect(@request_stub.response).to be_a(WebMock::Response) end describe "with" do it "should assign body to request pattern" do @request_stub.with(body: "abc") expect(@request_stub.request_pattern.to_s).to eq(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc").to_s) end it "should assign normalized headers to request pattern" do @request_stub.with(headers: {'A' => 'a'}) expect(@request_stub.request_pattern.to_s).to eq( WebMock::RequestPattern.new(:get, "www.example.com", headers: {'A' => 'a'}).to_s ) end it "should assign given block to request profile" do @request_stub.with { |req| req.body == "abc" } expect(@request_stub.request_pattern.matches?(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc"))).to be_truthy end end describe "to_return" do it "should assign response with provided options" do @request_stub.to_return(body: "abc", status: 500) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.status).to eq([500, ""]) end it "should assign responses with provided options" do @request_stub.to_return([{body: "abc"}, {body: "def"}]) expect([@request_stub.response.body, @request_stub.response.body]).to eq(["abc", "def"]) end end describe "to_return_json" do it "should raise if a block is given" do expect { @request_stub.to_return_json(body: "abc", status: 500) { puts "don't call me" } }.to raise_error(ArgumentError, '#to_return_json does not support passing a block') end it "should assign responses normally" do @request_stub.to_return_json([{body: "abc"}, {body: "def"}]) expect([@request_stub.response.body, @request_stub.response.body]).to eq(["abc", "def"]) end it "should json-ify a Hash body" do @request_stub.to_return_json(body: {abc: "def"}, status: 500) expect(@request_stub.response.body).to eq({abc: "def"}.to_json) expect(@request_stub.response.status).to eq([500, ""]) end it "should apply the content_type header" do @request_stub.to_return_json(body: {abc: "def"}, status: 500) expect(@request_stub.response.headers).to eq({"Content-Type"=>"application/json"}) end it "should preserve existing headers" do @request_stub.to_return_json(headers: {"A" => "a"}, body: "") expect(@request_stub.response.headers).to eq({"A"=>"a", "Content-Type"=>"application/json"}) end it "should allow callsites to override content_type header" do @request_stub.to_return_json(headers: {content_type: 'application/super-special-json'}) expect(@request_stub.response.headers).to eq({"Content-Type"=>"application/super-special-json"}) end end describe "then" do it "should return stub without any modifications, acting as syntactic sugar" do expect(@request_stub.then).to eq(@request_stub) end end describe "response" do it "should return responses in a sequence passed as array" do @request_stub.to_return([{body: "abc"}, {body: "def"}]) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") end it "should repeat returning last response" do @request_stub.to_return([{body: "abc"}, {body: "def"}]) @request_stub.response @request_stub.response expect(@request_stub.response.body).to eq("def") end it "should return responses in a sequence passed as comma separated params" do @request_stub.to_return({body: "abc"}, {body: "def"}) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") end it "should return responses declared in multiple to_return declarations" do @request_stub.to_return({body: "abc"}).to_return({body: "def"}) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") end end describe "to_raise" do it "should assign response with exception to be thrown" do @request_stub.to_raise(ArgumentError) expect { @request_stub.response.raise_error_if_any }.to raise_error(ArgumentError, "Exception from WebMock") end it "should assign sequence of responses with response with exception to be thrown" do @request_stub.to_return(body: "abc").then.to_raise(ArgumentError) expect(@request_stub.response.body).to eq("abc") expect { @request_stub.response.raise_error_if_any }.to raise_error(ArgumentError, "Exception from WebMock") end it "should assign a list responses to be thrown in a sequence" do @request_stub.to_raise(ArgumentError, IndexError) expect { @request_stub.response.raise_error_if_any }.to raise_error(ArgumentError, "Exception from WebMock") expect { @request_stub.response.raise_error_if_any }.to raise_error(IndexError, "Exception from WebMock") end it "should raise exceptions declared in multiple to_raise declarations" do @request_stub.to_raise(ArgumentError).then.to_raise(IndexError) expect { @request_stub.response.raise_error_if_any }.to raise_error(ArgumentError, "Exception from WebMock") expect { @request_stub.response.raise_error_if_any }.to raise_error(IndexError, "Exception from WebMock") end end describe "to_timeout" do it "should assign response with timeout" do @request_stub.to_timeout expect(@request_stub.response.should_timeout).to be_truthy end it "should assign sequence of responses with response with timeout" do @request_stub.to_return(body: "abc").then.to_timeout expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.should_timeout).to be_truthy end it "should allow multiple timeouts to be declared" do @request_stub.to_timeout.then.to_timeout.then.to_return(body: "abc") expect(@request_stub.response.should_timeout).to be_truthy expect(@request_stub.response.should_timeout).to be_truthy expect(@request_stub.response.body).to eq("abc") end end describe "times" do it "should give error if declared before any response declaration is declared" do expect { @request_stub.times(3) }.to raise_error("Invalid WebMock stub declaration. times(N) can be declared only after response declaration.") end it "should repeat returning last declared response declared number of times" do @request_stub.to_return({body: "abc"}).times(2).then.to_return({body: "def"}) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") end it "should repeat raising last declared exception declared number of times" do @request_stub.to_return({body: "abc"}).times(2).then.to_return({body: "def"}) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") end it "should repeat returning last declared sequence of responses declared number of times" do @request_stub.to_return({body: "abc"}, {body: "def"}).times(2).then.to_return({body: "ghj"}) expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") expect(@request_stub.response.body).to eq("abc") expect(@request_stub.response.body).to eq("def") expect(@request_stub.response.body).to eq("ghj") end it "should return self" do expect(@request_stub.to_return({body: "abc"}).times(1)).to eq(@request_stub) end it "should raise error if argument is not integer" do expect { @request_stub.to_return({body: "abc"}).times("not number") }.to raise_error("times(N) accepts integers >= 1 only") end it "should raise error if argument is < 1" do expect { @request_stub.to_return({body: "abc"}).times(0) }.to raise_error("times(N) accepts integers >= 1 only") end end end webmock-3.18.1/spec/unit/webmock_spec.rb0000644000004100000410000000734514333126774020205 0ustar www-datawww-datarequire 'spec_helper' describe "WebMock" do describe ".version" do it "should report version" do expect(WebMock.version).to eq(WebMock::VERSION) end it "should not require safe_yaml" do expect(defined?SafeYAML).to eq(nil) end it "should alias enable_net_connect! to allow_net_connect!" do expect(WebMock.method(:enable_net_connect!)).to eq(WebMock.method(:allow_net_connect!)) end it "should alias disallow_net_connect! to disable_net_connect!" do expect(WebMock.method(:disallow_net_connect!)).to eq(WebMock.method(:disable_net_connect!)) end end describe ".net_connect_allowed?" do context 'enabled globally' do before do WebMock.enable_net_connect! end context 'without arguments' do it 'returns WebMock::Config.instance.allow_net_connect' do expect(WebMock.net_connect_allowed?).to eql(true) end end end context 'disabled with allowed remote string' do before do WebMock.disable_net_connect!(allow: "http://192.168.64.2:20031") end context 'without arguments' do it 'returns WebMock::Config.instance.allow_net_connect' do expect(WebMock.net_connect_allowed?).to eql(false) end end end context 'disabled globally' do before do WebMock.disable_net_connect! end context 'without arguments' do it 'returns WebMock::Config.instance.allow_net_connect' do expect(WebMock.net_connect_allowed?).to eql(false) end end end end describe ".net_http_connect_on_start?" do let(:uri) { Addressable::URI.parse("http://example.org:5432") } it "will not connect on start when false" do WebMock.disable_net_connect! expect(WebMock.net_http_connect_on_start?(uri)).to be(false) end it "will connect on start when true" do WebMock.disable_net_connect!(net_http_connect_on_start: true) expect(WebMock.net_http_connect_on_start?(uri)).to be(true) end it "will connect on start when regexp matches" do WebMock.disable_net_connect!(net_http_connect_on_start: /example/) expect(WebMock.net_http_connect_on_start?(uri)).to be(true) end it "will not connect on start when regexp does not match" do WebMock.disable_net_connect!(net_http_connect_on_start: /nope/) expect(WebMock.net_http_connect_on_start?(uri)).to be(false) end it "will connect on start when host matches" do WebMock.disable_net_connect!(net_http_connect_on_start: "example.org") expect(WebMock.net_http_connect_on_start?(uri)).to be(true) end it "will not connect on start when host does not match" do WebMock.disable_net_connect!(net_http_connect_on_start: "localhost") expect(WebMock.net_http_connect_on_start?(uri)).to be(false) end it "will connect on start when host + port matches" do WebMock.disable_net_connect!(net_http_connect_on_start: "example.org:5432") expect(WebMock.net_http_connect_on_start?(uri)).to be(true) end it "will not connect on start when host + port does not match" do WebMock.disable_net_connect!(net_http_connect_on_start: "example.org:80") expect(WebMock.net_http_connect_on_start?(uri)).to be(false) end it "will connect on start when scheme + host + port matches" do WebMock.disable_net_connect!(net_http_connect_on_start: "http://example.org:5432") expect(WebMock.net_http_connect_on_start?(uri)).to be(true) end it "will not connect on start when scheme + host + port does not match" do WebMock.disable_net_connect!(net_http_connect_on_start: "https://example.org:5432") expect(WebMock.net_http_connect_on_start?(uri)).to be(false) end end end webmock-3.18.1/spec/unit/request_pattern_spec.rb0000644000004100000410000011562114333126774022000 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::RequestPattern do describe "describing itself" do it "should report string describing itself" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}).to_s).to eq( "GET http://www.example.com/ with body \"abc\" with headers {'A'=>'a', 'B'=>'b'}" ) end it "should report string describing itself with block" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc", headers: {'A' => 'a', 'B' => 'b'}).with {|req| true}.to_s).to eq( "GET http://www.example.com/ with body \"abc\" with headers {'A'=>'a', 'B'=>'b'} with given block" ) end it "should report string describing itself with query params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: {'a' => ['b', 'c']}).to_s).to eq( "GET /.*example.*/ with query params {\"a\"=>[\"b\", \"c\"]}" ) end it "should report string describing itself with query params as hash including matcher" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: WebMock::Matchers::HashIncludingMatcher.new({'a' => ['b', 'c']})).to_s).to eq( "GET /.*example.*/ with query params hash_including({\"a\"=>[\"b\", \"c\"]})" ) end it "should report string describing itself with body as hash including matcher" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, body: WebMock::Matchers::HashIncludingMatcher.new({'a' => ['b', 'c']})).to_s).to eq( "GET /.*example.*/ with body hash_including({\"a\"=>[\"b\", \"c\"]})" ) end end describe "with" do before(:each) do @request_pattern =WebMock::RequestPattern.new(:get, "www.example.com") end it "should have assigned body pattern" do @request_pattern.with(body: "abc") expect(@request_pattern.to_s).to eq(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc").to_s) end it "should have assigned normalized headers pattern" do @request_pattern.with(headers: {'A' => 'a'}) expect(@request_pattern.to_s).to eq(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'A' => 'a'}).to_s) end it "should raise an error if options passed to `with` are invalid" do expect { @request_pattern.with(foo: "bar") }.to raise_error('Unknown key: "foo". Valid keys are: "body", "headers", "query", "basic_auth"') end it "should raise an error if neither options or block is provided" do expect { @request_pattern.with() }.to raise_error('#with method invoked with no arguments. Either options hash or block must be specified. Created a block with do..end? Try creating it with curly braces {} instead.') end end class WebMock::RequestPattern def match(request_signature) self.matches?(request_signature) end end describe "when matching" do it "should match if uri matches and method matches" do expect(WebMock::RequestPattern.new(:get, "www.example.com")). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri matches and method pattern is any" do expect(WebMock::RequestPattern.new(:any, "www.example.com")). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should not match if request has different method" do expect(WebMock::RequestPattern.new(:post, "www.example.com")). not_to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri matches request uri" do expect(WebMock::RequestPattern.new(:get, "www.example.com")). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if request has unescaped uri" do expect(WebMock::RequestPattern.new(:get, "www.example.com/my%20path")). to match(WebMock::RequestSignature.new(:get, "www.example.com/my path")) end it "should match if request has escaped uri" do expect(WebMock::RequestPattern.new(:get, "www.example.com/my path")). to match(WebMock::RequestSignature.new(:get, "www.example.com/my%20path")) end it "should match if uri regexp pattern matches unescaped form of request uri" do expect(WebMock::RequestPattern.new(:get, /.*my path.*/)). to match(WebMock::RequestSignature.new(:get, "www.example.com/my%20path")) end it "should match if uri regexp pattern matches request uri" do expect(WebMock::RequestPattern.new(:get, /.*example.*/)). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri matches requesst uri as URI object" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"))). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri proc pattern returning true" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true })). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should not match if uri proc pattern returns false" do expect(WebMock::RequestPattern.new(:get, ->(uri) { false })). not_to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri Addressable::Template pattern matches unescaped form of request uri" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/{any_path}"))). to match(WebMock::RequestSignature.new(:get, "www.example.com/my%20path")) end it "should match if uri Addressable::Template pattern matches request uri" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"))). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should match if uri Addressable::Template pattern matches request uri without TLD" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("localhost"))). to match(WebMock::RequestSignature.new(:get, "localhost")) end it "should match if Addressable::Template pattern that has ip address host matches request uri" do signature = WebMock::RequestSignature.new(:get, "127.0.0.1:3000/1234") uri = Addressable::Template.new("127.0.0.1:3000/{id}") expect(WebMock::RequestPattern.new(:get, uri)).to match(signature) end it "should match if Addressable::Template pattern that has ip address host without port matches request uri" do signature = WebMock::RequestSignature.new(:get, "127.0.0.1/1234") uri = Addressable::Template.new("127.0.0.1/{id}") expect(WebMock::RequestPattern.new(:get, uri)).to match(signature) end it "should match if Addressable::Template pattern host matches request uri" do signature = WebMock::RequestSignature.new(:get, "www.example.com") uri = Addressable::Template.new("{subdomain}.example.com") expect(WebMock::RequestPattern.new(:get, uri)).to match(signature) end it "should not match if Addressable::Template pattern host does not match request uri" do signature = WebMock::RequestSignature.new(:get, "www.bad-example.com") uri = Addressable::Template.new("{subdomain}.example.com") expect(WebMock::RequestPattern.new(:get, uri)).not_to match(signature) end it "should match if uri Addressable::Template pattern matches request uri without a schema and a path " do signature = WebMock::RequestSignature.new(:get, "127.0.0.1:3000") uri = Addressable::Template.new("127.0.0.1:3000") expect(WebMock::RequestPattern.new(:get, uri)).to match(signature) end it "should match for uris with same parameters as pattern" do expect(WebMock::RequestPattern.new(:get, "www.example.com?a=1&b=2")). to match(WebMock::RequestSignature.new(:get, "www.example.com?a=1&b=2")) end it "should not match for uris with different parameters" do expect(WebMock::RequestPattern.new(:get, "www.example.com?a=1&b=2")). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a=2&b=1")) end it "should match for uri parameters in different order" do expect(WebMock::RequestPattern.new(:get, "www.example.com?b=2&a=1")). to match(WebMock::RequestSignature.new(:get, "www.example.com?a=1&b=2")) end describe "when parameters are escaped" do it "should match if uri pattern has escaped parameters and request has unescaped parameters" do expect(WebMock::RequestPattern.new(:get, "www.example.com/?a=a%20b")). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a b")) end it "should match if uri pattern has unescaped parameters and request has escaped parameters" do expect(WebMock::RequestPattern.new(:get, "www.example.com/?a=a b")). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a%20b")) end it "should match if uri regexp pattern matches uri with unescaped parameters and request has escaped parameters" do expect(WebMock::RequestPattern.new(:get, /.*a=a b.*/)). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a%20b")) end it "should match if uri regexp pattern matches uri with escaped parameters and request has unescaped parameters" do expect(WebMock::RequestPattern.new(:get, /.*a=a%20b.*/)). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a b")) end it "should match if uri Addressable::Template pattern matches uri without parameter value and request has escaped parameters" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/{?a}"))). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a%20b")) end it "should match if uri Addressable::Template pattern matches uri without parameter value and request has unescaped parameters" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/{?a}"))). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a b")) end it "should match if uri Addressable::Template pattern matches uri with unescaped parameter value and request has unescaped parameters" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/?a=a b"))). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a b")) end it "should match if uri Addressable::Template pattern matches uri with escaped parameter value and request has escaped parameters" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com/?a=a%20b"))). to match(WebMock::RequestSignature.new(:get, "www.example.com/?a=a%20b")) end end describe "when matching requests on query params" do describe "when uri is described as regexp" do it "should match request query params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: {"a" => ["b", "c"]})). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should not match request query params if params don't match" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: {"x" => ["b", "c"]})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, /.*example.*/, query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end end describe "when uri is described as URI" do it "should match request query params" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: {"a" => ["b", "c"]})). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should not match request query params if params don't match" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: {"x" => ["b", "c"]})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, URI.parse("www.example.com"), query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end end describe "when uri is described as a proc" do it "should match request query params" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: {"a" => ["b", "c"]})). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should not match request query params if params don't match" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: {"x" => ["b", "c"]})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, ->(uri) { true }, query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end end describe "when uri is described as Addressable::Template" do it "should raise error if query params are specified" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: {"a" => ["b", "c"]})). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should not match request query params if params don't match" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: {"x" => ["b", "c"]})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, Addressable::Template.new("www.example.com"), query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end end describe "when uri is described as string" do it "should match when query params are the same as declared in hash" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: {"a" => ["b", "c"]})). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should not match when query params are different than the declared in hash" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: {"a" => ["b", "c"]})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?x[]=b&a[]=c")) end it "should match when query params are the same as declared as string" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: "a[]=b&a[]=c")). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c")) end it "should match when query params are the same as declared both in query option or url" do expect(WebMock::RequestPattern.new(:get, "www.example.com/?x=3", query: "a[]=b&a[]=c")). to match(WebMock::RequestSignature.new(:get, "www.example.com/?x=3&a[]=b&a[]=c")) end it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: WebMock::Matchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: WebMock::Matchers::HashIncludingMatcher.new({"x" => ["b", "c"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "c"]}))). to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]}))). not_to match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1")) end context "when using query values notation as flat array" do before :all do WebMock::Config.instance.query_values_notation = :flat_array end it "should not match when repeated query params are not the same as declared as string" do expect(WebMock::RequestPattern.new(:get, "www.example.com", query: "a=b&a=c")). to match(WebMock::RequestSignature.new(:get, "www.example.com?a=b&a=c")) end after :all do WebMock::Config.instance.query_values_notation = nil end end end end describe "when matching requests with body" do it "should match if request body and body pattern are the same" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc")). to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should match if request body matches regexp" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: /^abc$/)). to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should not match if body pattern is different than request body" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "def")). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should not match if request body doesn't match regexp pattern" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: /^abc$/)). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "xabc")) end it "should match if pattern doesn't have specified body" do expect(WebMock::RequestPattern.new(:get, "www.example.com")). to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should not match if pattern has body specified as nil but request body is not empty" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: nil)). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should not match if pattern has empty body but request body is not empty" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "")). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", body: "abc")) end it "should not match if pattern has body specified but request has no body" do expect(WebMock::RequestPattern.new(:get, "www.example.com", body: "abc")). not_to match(WebMock::RequestSignature.new(:get, "www.example.com")) end describe "when body in pattern is declared as a hash" do let(:body_hash) { {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}} } describe "for request with url encoded body" do it "should match when hash matches body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a=1&c[d][]=e&c[d][]=f&b=five')) end it "should match when hash matches body in different order of params" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a=1&c[d][]=e&b=five&c[d][]=f')) end it "should not match when hash doesn't match url encoded body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'c[d][]=f&a=1&c[d][]=e')) end it "should not match when body is not url encoded" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'foo bar')) end it "should match when hash contains regex values" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: {a: /^\w{5}$/, b: {c: /^\d{3}$/}})). to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a=abcde&b[c]=123')) end it "should not match when hash does not contains regex values" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: {a: /^\d+$/, b: {c: /^\d{3}$/}})). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a=abcde&b[c]=123')) end context 'body is an hash with an array of hashes' do let(:body_hash) { {a: [{'b' => '1'}, {'b' => '2'}]} } it "should match when hash matches body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a[][b]=1&a[][b]=2')) end end context 'body is an hash with an array of hashes with multiple keys' do let(:body_hash) { {a: [{'b' => '1', 'a' => '2'}, {'b' => '3'}]} } it "should match when hash matches body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", body: 'a[][b]=1&a[][a]=2&a[][b]=3')) end end end describe "for request with json body and content type is set to json" do shared_examples "a json body" do it "should match when hash matches body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "{\"a\":\"1\",\"c\":{\"d\":[\"e\",\"f\"]},\"b\":\"five\"}")) end it "should match if hash matches body in different form" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}")) end it "should match if the request body has a top level array" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: [{a: 1}])). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "[{\"a\":1}]")) end it "should not match if the request body has a different top level array" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: ["a", "b"])). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "[\"a\", \"c\"]")) end it "should not match when body is not json" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "foo bar")) end it "should not match if request body is different" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "{\"a\":1,\"c\":null}")) end it "should not match if request body is has less params than pattern" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1, b: 2})). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "{\"a\":1}")) end it "should not match if request body is has more params than pattern" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: {a: 1})). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "{\"a\":1,\"c\":1}")) end end context "standard application/json" do let(:content_type) { 'application/json' } it_behaves_like "a json body" end context "custom json content type" do let(:content_type) { 'application/vnd.api+json' } it_behaves_like "a json body" end end describe "for request with xml body and content type is set to xml" do let(:body_hash) { {"opt" => {:a => '1', :b => 'five', 'c' => {'d' => ['e', 'f']}}} } shared_examples "a xml body" do it "should match when hash matches body" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "\n \n e\n f\n \n\n")) end it "should match if hash matches body in different form" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "\n \n e\n f\n \n\n")) end it "should not match when body is not xml" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). not_to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: content_type}, body: "foo bar")) end it "matches when the content type include a charset" do expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_hash)). to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: "#{content_type};charset=UTF-8"}, body: "\n \n e\n f\n \n\n")) end end context "standard application/xml" do let(:content_type) { 'application/xml' } it_behaves_like "a xml body" end context "custom xml content type" do let(:content_type) { 'application/atom+xml' } it_behaves_like "a xml body" end end end describe "when body in a pattern is declared as a partial hash matcher" do let(:signature) { WebMock::RequestSignature.new(:post, "www.example.com", body: 'a=1&c[d][]=e&c[d][]=f&b=five') } it "should match when query params are declared as HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: WebMock::Matchers::HashIncludingMatcher.new({:a => '1', 'c' => {'d' => ['e', 'f']}}))). to match(signature) end it "should not match when query params are declared as HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: WebMock::Matchers::HashIncludingMatcher.new({:x => '1', 'c' => {'d' => ['e', 'f']}}))). not_to match(signature) end it "should match when query params are declared as RSpec HashIncluding matcher matching params" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({:a => '1', 'c' => {'d' => ['e', 'f']}}))). to match(signature) end it "should not match when query params are declared as RSpec HashIncluding matcher not matching params" do expect(WebMock::RequestPattern.new(:post, "www.example.com", body: RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({:x => '1', 'c' => {'d' => ['e', 'f']}}))). not_to match(signature) end end end it "should match if pattern and request have the same headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})). to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})) end it "should match if pattern headers values are regexps matching request header values" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => %r{^image/jpeg$}})). to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})) end it "should not match if pattern has different value of header than request" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => 'image/png'})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})) end it "should not match if pattern header value regexp doesn't match request header value" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => %r{^image\/jpeg$}})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpegx'})) end it "should match if request has more headers than request pattern" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})). to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg', 'Content-Length' => '8888'})) end it "should not match if request has less headers than the request pattern" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg', 'Content-Length' => '8888'})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'Content-Type' => 'image/jpeg'})) end it "should match even is header keys are declared in different form" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'ContentLength' => '8888', 'Content-type' => 'image/png'})). to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {:ContentLength => 8888, 'content_type' => 'image/png'})) end it "should match is pattern doesn't have specified headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com")). to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'})) end it "should not match if pattern has nil headers but request has headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: nil)). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'})) end it "should not match if pattern has empty headers but request has headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {'A' => 'a'})) end it "should not match if pattern has specified headers but request has nil headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'A'=>'a'})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should not match if pattern has specified headers but request has empty headers" do expect(WebMock::RequestPattern.new(:get, "www.example.com", headers: {'A'=>'a'})). not_to match(WebMock::RequestSignature.new(:get, "www.example.com", headers: {})) end it "should match if block given in pattern evaluates request to true" do expect(WebMock::RequestPattern.new(:get, "www.example.com").with { |request| true }). to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should not match if block given in pattrn evaluates request to false" do expect(WebMock::RequestPattern.new(:get, "www.example.com").with { |request| false }). not_to match(WebMock::RequestSignature.new(:get, "www.example.com")) end it "should yield block with request signature" do signature = WebMock::RequestSignature.new(:get, "www.example.com") expect(WebMock::RequestPattern.new(:get, "www.example.com").with { |request| request == signature }). to match(signature) end end end webmock-3.18.1/spec/unit/response_spec.rb0000644000004100000410000002447114333126774020413 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::ResponseFactory do describe "response_for" do it "should create response with options passed as arguments" do options = {body: "abc", headers: {a: :b}} expect(WebMock::Response).to receive(:new).with(options).and_return(@response = double(WebMock::Response)) expect(WebMock::ResponseFactory.response_for(options)).to eq(@response) end it "should create dynamic response for argument responding to call" do callable = double(call: {body: "abc"}) expect(WebMock::DynamicResponse).to receive(:new).with(callable).and_return(@response = double(WebMock::Response)) expect(WebMock::ResponseFactory.response_for(callable)).to eq(@response) end end end describe WebMock::Response do before(:each) do @response = WebMock::Response.new(headers: {'A' => 'a'}) end it "should raise an error when initialized with unknown option" do expect { WebMock::Response.new(foo: "bar") }.to raise_error('Unknown key: "foo". Valid keys are: "headers", "status", "body", "exception", "should_timeout"') end it "should report normalized headers" do allow(WebMock::Util::Headers).to receive(:normalize_headers).with({'A' => 'a'}.freeze).and_return('B' => 'b') @response = WebMock::Response.new(headers: {'A' => 'a'}) expect(@response.headers).to eq({'B' => 'b'}) end describe "status" do it "should have 200 code and empty message by default" do expect(@response.status).to eq([200, ""]) end it "should return assigned status" do @response = WebMock::Response.new(status: 500) expect(@response.status).to eq([500, ""]) end it "should return assigned message" do @response = WebMock::Response.new(status: [500, "Internal Server Error"]) expect(@response.status).to eq([500, "Internal Server Error"]) end end describe "raising error" do it "should raise error if any assigned" do @response = WebMock::Response.new(exception: ArgumentError) expect { @response.raise_error_if_any }.to raise_error(ArgumentError, "Exception from WebMock") end it "should raise error if any assigned as instance" do @response = WebMock::Response.new(exception: ArgumentError.new("hello world")) expect { @response.raise_error_if_any }.to raise_error(ArgumentError, "hello world") end it "should raise error if any assigned as string" do @response = WebMock::Response.new(exception: "hello world") expect { @response.raise_error_if_any }.to raise_error("hello world") end it "should not raise error if no error assigned" do @response.raise_error_if_any end end describe "timeout" do it "should know if it should timeout" do @response = WebMock::Response.new(should_timeout: true) expect(@response.should_timeout).to be_truthy end it "should not timeout by default" do @response = WebMock::Response.new expect(@response.should_timeout).to be_falsey end end describe "body" do it "should return empty body by default" do expect(@response.body).to eq('') end it "should report body if assigned" do @response = WebMock::Response.new(body: "abc") expect(@response.body).to eq("abc") end it "should report string even if existing file path was provided" do @response = WebMock::Response.new(body: __FILE__) expect(@response.body).to eq(__FILE__) end it "should report content of a IO object if provided" do @response = WebMock::Response.new(body: File.new(__FILE__)) expect(@response.body).to eq(File.read(__FILE__)) end it "should report many times content of a IO object if provided" do @response = WebMock::Response.new(body: File.new(__FILE__)) expect(@response.body).to eq(File.read(__FILE__)) expect(@response.body).to eq(File.read(__FILE__)) end it "should work with Pathnames" do @response = WebMock::Response.new(body: Pathname.new(__FILE__)) expect(@response.body).to eq(File.read(__FILE__)) end # Users of webmock commonly make the mistake of stubbing the response # body to return a hash, to prevent this: # it "should error if given a non-allowed type: a hash" do expect { WebMock::Response.new(body: Hash.new) }.to \ raise_error(WebMock::Response::InvalidBody) end it "should error if given a non-allowed type: something that is not a hash" do expect { WebMock::Response.new(body: 123) }.to \ raise_error(WebMock::Response::InvalidBody) end end describe "from raw response" do describe "when input is a StringIO" do before(:each) do @io = StringIO.new(File.read(CURL_EXAMPLE_OUTPUT_PATH)) @response = WebMock::Response.new(@io) end it "should read status" do expect(@response.status).to eq([202, "OK"]) end it "should read headers" do expect(@response.headers).to eq( "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"419", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" ) end it "should read body" do expect(@response.body.size).to eq(419) end it "should close IO" do expect(@io).to be_closed end end describe "when input is IO" do before(:each) do @file = File.new(CURL_EXAMPLE_OUTPUT_PATH) @response = WebMock::Response.new(@file) end it "should read status" do expect(@response.status).to eq([202, "OK"]) end it "should read headers" do expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"419", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) end it "should read body" do expect(@response.body.size).to eq(419) end it "should close IO" do expect(@file).to be_closed end end describe "when input is String" do before(:each) do @input = File.read(CURL_EXAMPLE_OUTPUT_PATH) @response = WebMock::Response.new(@input) end it "should read status" do expect(@response.status).to eq([202, "OK"]) end it "should read headers" do expect(@response.headers).to eq({ "Date"=>"Sat, 23 Jan 2010 01:01:05 GMT", "Content-Type"=>"text/html; charset=UTF-8", "Content-Length"=>"419", "Connection"=>"Keep-Alive", "Accept"=>"image/jpeg, image/png" }) end it "should read body" do expect(@response.body.size).to eq(419) end it "should work with transfer-encoding set to chunked" do @input.gsub!("Content-Length: 419", "Transfer-Encoding: chunked") @response = WebMock::Response.new(@input) expect(@response.body.size).to eq(419) end end describe "with dynamically evaluated options" do before(:each) do @request_signature = WebMock::RequestSignature.new(:post, "www.example.com", body: "abc", headers: {'A' => 'a'}) end it "should have evaluated body" do @response = WebMock::Response.new(body: lambda {|request| request.body}) expect(@response.evaluate(@request_signature).body).to eq("abc") end it "should have evaluated headers" do @response = WebMock::Response.new(headers: lambda {|request| request.headers}) expect(@response.evaluate(@request_signature).headers).to eq({'A' => 'a'}) end it "should have evaluated status" do @response = WebMock::Response.new(status: lambda {|request| 302}) expect(@response.evaluate(@request_signature).status).to eq([302, ""]) end end end describe WebMock::DynamicResponse do describe "evaluating response options" do it "should evaluate new response with evaluated options" do request_signature = WebMock::RequestSignature.new(:post, "www.example.com", body: "abc", headers: {'A' => 'a'}) response = WebMock::DynamicResponse.new(lambda {|request| { body: request.body, headers: request.headers, status: 302 } }) evaluated_response = response.evaluate(request_signature) expect(evaluated_response.body).to eq("abc") expect(evaluated_response.headers).to eq({'A' => 'a'}) expect(evaluated_response.status).to eq([302, ""]) end it "should be equal to static response after evaluation" do request_signature = WebMock::RequestSignature.new(:post, "www.example.com", body: "abc") response = WebMock::DynamicResponse.new(lambda {|request| {body: request.body}}) evaluated_response = response.evaluate(request_signature) expect(evaluated_response).to eq(WebMock::Response.new(body: "abc")) end describe "when raw response is evaluated" do before(:each) do @files = { "www.example.com" => File.new(CURL_EXAMPLE_OUTPUT_PATH) } @request_signature = WebMock::RequestSignature.new(:get, "www.example.com") end describe "as a file" do it "should return response" do response = WebMock::DynamicResponse.new(lambda {|request| @files[request.uri.host.to_s] }) expect(response.evaluate(@request_signature).body.size).to eq(419) end end describe "as a string" do it "should return response" do response = WebMock::DynamicResponse.new(lambda {|request| @files[request.uri.host.to_s].read }) expect(response.evaluate(@request_signature).body.size).to eq(419) end end end end end end webmock-3.18.1/spec/unit/request_registry_spec.rb0000644000004100000410000001010114333126774022156 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::RequestRegistry do before(:each) do WebMock::RequestRegistry.instance.reset! @request_pattern = WebMock::RequestPattern.new(:get, "www.example.com") @request_signature = WebMock::RequestSignature.new(:get, "www.example.com") end describe "reset!" do before(:each) do WebMock::RequestRegistry.instance.requested_signatures.put(@request_signature) end it "should clean list of executed requests" do expect(WebMock::RequestRegistry.instance.times_executed(@request_pattern)).to eq(1) WebMock::RequestRegistry.instance.reset! expect(WebMock::RequestRegistry.instance.times_executed(@request_pattern)).to eq(0) end end describe "times executed" do before(:each) do @request_stub1 = WebMock::RequestStub.new(:get, "www.example.com") @request_stub2 = WebMock::RequestStub.new(:get, "www.example.net") @request_stub3 = WebMock::RequestStub.new(:get, "www.example.org") WebMock::RequestRegistry.instance.requested_signatures.put(WebMock::RequestSignature.new(:get, "www.example.com")) WebMock::RequestRegistry.instance.requested_signatures.put(WebMock::RequestSignature.new(:get, "www.example.com")) WebMock::RequestRegistry.instance.requested_signatures.put(WebMock::RequestSignature.new(:get, "www.example.org")) end it "should report 0 if no request matching pattern was requested" do expect(WebMock::RequestRegistry.instance.times_executed(WebMock::RequestPattern.new(:get, "www.example.net"))).to eq(0) end it "should report number of times matching pattern was requested" do expect(WebMock::RequestRegistry.instance.times_executed(WebMock::RequestPattern.new(:get, "www.example.com"))).to eq(2) end it "should report number of times all matching pattern were requested" do expect(WebMock::RequestRegistry.instance.times_executed(WebMock::RequestPattern.new(:get, /.*example.*/))).to eq(3) end describe "multithreading" do let(:request_pattern) { WebMock::RequestPattern.new(:get, "www.example.com") } # Reproduce a multithreading issue that causes a RuntimeError: # can't add a new key into hash during iteration. it "works normally iterating on the requested signature hash while another thread is setting it" do thread_injected = false allow(request_pattern).to receive(:matches?).and_wrap_original do |m, *args| unless thread_injected thread_injected = true Thread.new { WebMock::RequestRegistry.instance.requested_signatures.put(:abc) }.join(0.1) end m.call(*args) end expect(WebMock::RequestRegistry.instance.times_executed(request_pattern)).to eq(2) sleep 0.1 while !WebMock::RequestRegistry.instance.requested_signatures.hash.key?(:abc) end end end describe "request_signatures" do it "should return hash of unique request signatures with accumulated number" do WebMock::RequestRegistry.instance.requested_signatures.put(WebMock::RequestSignature.new(:get, "www.example.com")) WebMock::RequestRegistry.instance.requested_signatures.put(WebMock::RequestSignature.new(:get, "www.example.com")) expect(WebMock::RequestRegistry.instance.requested_signatures. get(WebMock::RequestSignature.new(:get, "www.example.com"))).to eq(2) end end describe "to_s" do it "should output string with all executed requests and numbers of executions" do [ WebMock::RequestSignature.new(:get, "www.example.com"), WebMock::RequestSignature.new(:get, "www.example.com"), WebMock::RequestSignature.new(:put, "www.example.org"), ].each do |s| WebMock::RequestRegistry.instance.requested_signatures.put(s) end expect(WebMock::RequestRegistry.instance.to_s).to eq( "GET http://www.example.com/ was made 2 times\nPUT http://www.example.org/ was made 1 time\n" ) end it "should output info if no requests were executed" do expect(WebMock::RequestRegistry.instance.to_s).to eq("No requests were made.") end end end webmock-3.18.1/spec/unit/request_signature_snippet_spec.rb0000644000004100000410000000470214333126774024063 0ustar www-datawww-datarequire "spec_helper" RSpec.describe WebMock::RequestSignatureSnippet do it("is real"){expect{subject}.not_to(raise_error)} subject { WebMock::RequestSignatureSnippet.new(request_signature) } let(:uri) { "http://example.com" } let(:method) { "GET" } let(:request_signature) { WebMock::RequestSignature.new(method, uri) } let(:request_signature_body) { {"key" => "different value"}.to_json } let(:request_pattern) { WebMock::RequestPattern.new( method, uri, {body: request_signature_body} ) } before :each do request_signature.headers = {"Content-Type" => "application/json"} request_signature.body = request_signature_body end describe "#stubbing_instructions" do context "with stubbing instructions turned off" do before :each do WebMock.hide_stubbing_instructions! end it "returns nil" do expect(subject.stubbing_instructions).to be nil end after :each do WebMock.show_stubbing_instructions! end end context "with stubbing instructions turned on" do it "returns a stub snippet" do expect(subject.stubbing_instructions).to include( "You can stub this request with the following snippet:" ) end end end describe "#request_stubs" do before :each do WebMock.stub_request(:get, "https://www.example.com").with(body: {"a" => "b"}) end context "when showing the body diff is turned off" do before :each do WebMock.hide_body_diff! end it "returns does not show the body diff" do result = subject.request_stubs result.sub!("registered request stubs:\n\n", "") expect(result).to eq( "stub_request(:get, \"https://www.example.com/\").\n with(\n body: {\"a\"=>\"b\"})" ) end after :each do WebMock.show_body_diff! end end context "when showing the body diff is turned on" do it "shows the body diff" do result = subject.request_stubs result.sub!("registered request stubs:\n\n", "") expect(result).to eq( "stub_request(:get, \"https://www.example.com/\").\n with(\n body: {\"a\"=>\"b\"})\n\nBody diff:\n [[\"-\", \"key\", \"different value\"], [\"+\", \"a\", \"b\"]]\n" ) end end context "with no request stubs" do it "returns nil" do WebMock.reset! expect(subject.request_stubs).to be nil end end end end webmock-3.18.1/spec/unit/http_lib_adapters/0000755000004100000410000000000014333126774020676 5ustar www-datawww-datawebmock-3.18.1/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb0000644000004100000410000000054414333126774025545 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::HttpLibAdapter do describe "adapter_for" do it "should add adapter to adapter registry" do class MyAdapter < WebMock::HttpLibAdapter; end expect(WebMock::HttpLibAdapterRegistry.instance). to receive(:register).with(:my_lib, MyAdapter) MyAdapter.adapter_for(:my_lib) end end endwebmock-3.18.1/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb0000644000004100000410000000105714333126774027475 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::HttpLibAdapterRegistry do describe "each_adapter" do it "should yield block over each adapter" do class MyAdapter < WebMock::HttpLibAdapter; end WebMock::HttpLibAdapterRegistry.instance.register(:my_lib, MyAdapter) adapters = [] WebMock::HttpLibAdapterRegistry.instance.each_adapter {|n,a| adapters << [n, a] } expect(adapters).to include([:my_lib, MyAdapter]) WebMock::HttpLibAdapterRegistry.instance. http_lib_adapters.delete(:my_lib) end end endwebmock-3.18.1/spec/unit/stub_registry_spec.rb0000644000004100000410000001051014333126774021447 0ustar www-datawww-datarequire 'spec_helper' describe WebMock::StubRegistry do before(:each) do WebMock::StubRegistry.instance.reset! @request_pattern = WebMock::RequestPattern.new(:get, "www.example.com") @request_signature = WebMock::RequestSignature.new(:get, "www.example.com") @request_stub = WebMock::RequestStub.new(:get, "www.example.com") end describe "remove_request_stub" do it "should remove stub from registry" do WebMock::StubRegistry.instance.register_request_stub(@request_stub) expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(@request_stub) WebMock::StubRegistry.instance.remove_request_stub(@request_stub) expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(nil) end end describe "reset!" do before(:each) do WebMock::StubRegistry.instance.register_request_stub(@request_stub) end it "should clean request stubs" do expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(@request_stub) WebMock::StubRegistry.instance.reset! expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(nil) end end describe "registering and reporting registered requests" do it "should return registered stub" do expect(WebMock::StubRegistry.instance.register_request_stub(@request_stub)).to eq(@request_stub) end it "should report if request stub is not registered" do expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(nil) end it "should register and report registered stub" do WebMock::StubRegistry.instance.register_request_stub(@request_stub) expect(WebMock::StubRegistry.instance.registered_request?(@request_signature)).to eq(@request_stub) end end describe "response for request" do it "should report registered evaluated response for request pattern" do @request_stub.to_return(body: "abc") WebMock::StubRegistry.instance.register_request_stub(@request_stub) expect(WebMock::StubRegistry.instance.response_for_request(@request_signature)). to eq(WebMock::Response.new(body: "abc")) end it "should report evaluated response" do @request_stub.to_return {|request| {body: request.method.to_s} } WebMock::StubRegistry.instance.register_request_stub(@request_stub) response1 = WebMock::StubRegistry.instance.response_for_request(@request_signature) expect(response1).to eq(WebMock::Response.new(body: "get")) end it "should report clone of the response" do @request_stub.to_return(body: lambda{|r| r.method.to_s}) WebMock::StubRegistry.instance.register_request_stub(@request_stub) response1 = WebMock::StubRegistry.instance.response_for_request(@request_signature) response2 = WebMock::StubRegistry.instance.response_for_request(@request_signature) expect(response1).not_to be(response2) end it "should report clone of the dynamic response" do @request_stub.to_return {|request| {body: request.method.to_s} } WebMock::StubRegistry.instance.register_request_stub(@request_stub) response1 = WebMock::StubRegistry.instance.response_for_request(@request_signature) response2 = WebMock::StubRegistry.instance.response_for_request(@request_signature) expect(response1).not_to be(response2) end it "should report nothing if no response for request is registered" do expect(WebMock::StubRegistry.instance.response_for_request(@request_signature)).to eq(nil) end it "should always return last registered matching response" do @request_stub1 = WebMock::RequestStub.new(:get, "www.example.com") @request_stub1.to_return(body: "abc") @request_stub2 = WebMock::RequestStub.new(:get, "www.example.com") @request_stub2.to_return(body: "def") @request_stub3 = WebMock::RequestStub.new(:get, "www.example.org") @request_stub3.to_return(body: "ghj") WebMock::StubRegistry.instance.register_request_stub(@request_stub1) WebMock::StubRegistry.instance.register_request_stub(@request_stub2) WebMock::StubRegistry.instance.register_request_stub(@request_stub3) expect(WebMock::StubRegistry.instance.response_for_request(@request_signature)). to eq(WebMock::Response.new(body: "def")) end end end webmock-3.18.1/spec/spec_helper.rb0000644000004100000410000000230714333126774017047 0ustar www-datawww-datarequire 'rubygems' require 'httpclient' unless RUBY_PLATFORM =~ /java/ require 'curb' require 'patron' require 'em-http' require 'typhoeus' end if RUBY_PLATFORM =~ /java/ require 'manticore' end $LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'rspec' require 'webmock/rspec' require 'support/network_connection' require 'support/webmock_server' require 'support/my_rack_app' require 'support/failures' CURL_EXAMPLE_OUTPUT_PATH = File.expand_path('../support/example_curl_output.txt', __FILE__) RSpec.configure do |config| no_network_connection = ENV["NO_CONNECTION"] || ! NetworkConnection.is_network_available? if no_network_connection warn("No network connectivity. Only examples which do not make real network connections will run.") config.filter_run_excluding net_connect: true end config.filter_run_excluding without_webmock: true config.before(:suite) do WebMockServer.instance.start unless WebMockServer.instance.started end config.after(:suite) do WebMockServer.instance.stop end config.filter_run focus: true config.run_all_when_everything_filtered = true config.include Failures end webmock-3.18.1/spec/support/0000755000004100000410000000000014333126774015743 5ustar www-datawww-datawebmock-3.18.1/spec/support/network_connection.rb0000644000004100000410000000050114333126774022174 0ustar www-datawww-datarequire 'timeout' require 'socket' module NetworkConnection def self.connect_to(host, port, timeout=10) Timeout.timeout(timeout) do TCPSocket.new(host, port) end end def self.is_network_available? begin self.connect_to("8.8.8.8", 53, 5) true rescue false end end end webmock-3.18.1/spec/support/my_rack_app.rb0000644000004100000410000000301214333126774020551 0ustar www-datawww-datarequire 'rack' class MyRackApp class NonArrayResponse # The rack response body need not implement #join, # but it must implement #each. It need not be an Array. # ActionDispatch::Response, for example, exercises that fact. # See: http://rack.rubyforge.org/doc/SPEC.html def each(*args, &blk) ["This is not in an array!"].each(*args, &blk) end end def self.call(env) case env.values_at('REQUEST_METHOD', 'PATH_INFO') when ['GET', '/'] [200, {}, ["This is my root!"]] when ['GET', '/greet'] name = env['QUERY_STRING'][/name=([^&]*)/, 1] || "World" [200, {}, ["Hello, #{name}"]] when ['GET', '/non_array_response'] [200, {}, NonArrayResponse.new] when ['GET', '/locked'] [200, {}, ["Single threaded response."]] when ['POST', '/greet'] name = env["rack.input"].read(env["CONTENT_LENGTH"]) name = name.force_encoding("UTF-8") if name.respond_to? :force_encoding name = name[/name=([^&]*)/, 1] || "World" [200, {}, ["Good to meet you, #{name}!"]] when ['GET', '/compute'] if env['SERVER_PORT'] == 80 && env["SCRIPT_NAME"] == "" [200, {}, [""]] else [401, {}, [""]] end when ['GET', '/error'] env['rack.errors'].puts('Error!') [500, {}, ['']] else [404, {}, ['']] end end end class MyLockedRackApp MUTEX = Mutex.new def self.call(env) lock = Rack::Lock.new(MyRackApp, MUTEX) lock.call(env) end end webmock-3.18.1/spec/support/example_curl_output.txt0000644000004100000410000000111714333126774022604 0ustar www-datawww-dataHTTP/1.1 202 OK Content-Type: text/html; charset=UTF-8 Connection: Keep-Alive Date: Sat, 23 Jan 2010 01:01:05 GMT Content-Length: 419 Accept: image/jpeg Accept: image/png Example Web Page

You have reached this web page by typing "example.com", "example.net", or "example.org" into your web browser.

These domain names are reserved for use in documentation and are not available for registration. See RFC 2606, Section 3.

webmock-3.18.1/spec/support/failures.rb0000644000004100000410000000031014333126774020074 0ustar www-datawww-datamodule Failures def fail() raise_error(RSpec::Expectations::ExpectationNotMetError) end def fail_with(message) raise_error(RSpec::Expectations::ExpectationNotMetError, message) end end webmock-3.18.1/spec/support/webmock_server.rb0000644000004100000410000000242514333126774021310 0ustar www-datawww-datarequire 'webrick' require 'logger' require 'singleton' class WebMockServer include Singleton attr_reader :port, :started def host_with_port "localhost:#{port}" end def concurrent unless RUBY_PLATFORM =~ /java/ @pid = Process.fork do yield end else Thread.new { yield } end end def start @started = true server = WEBrick::GenericServer.new(Port: 0, Logger: Logger.new("/dev/null")) server.logger.level = 0 @port = server.config[:Port] concurrent do ['TERM', 'INT'].each do |signal| trap(signal) do Thread.new do server.shutdown end end end server.start do |socket| socket.read(1) socket.puts <<-EOT.gsub(/^\s+\|/, '') |HTTP/1.1 200 OK\r |Date: Fri, 31 Dec 1999 23:59:59 GMT\r |Content-Type: text/html\r |Content-Length: 11\r |Set-Cookie: bar\r |Set-Cookie: foo\r |\r |hello world EOT end end loop do begin TCPSocket.new("localhost", port) sleep 0.1 break rescue Errno::ECONNREFUSED sleep 0.1 end end end def stop if @pid Process.kill('INT', @pid) end end end webmock-3.18.1/CHANGELOG.md0000644000004100000410000020365214333126774015116 0ustar www-datawww-data# Changelog # 3.18.1 * Reverted simplified connection handing in Net::HTTP adapter due to https://github.com/bblimke/webmock/issues/999 # 3.18.0 * Net::BufferedIO is not replaced anymore. Thanks to [Ray Zane](https://github.com/rzane) * Simplified connection handing in Net::HTTP adapter. Thanks to [Ray Zane](https://github.com/rzane) # 3.17.1 * Fixed Syntax Error Thanks to [Mark Spangler](https://github.com/mspangler) # 3.17.0 * Minimum required Ruby version is 2.3 Thanks to [Go Sueyoshi](https://github.com/sue445) * When using Net::HTTP, stubbed socket StubSocket#close and StubSocket#closed? behave more like the real sockets. Thanks to [Ray Zane](https://github.com/rzane) * Added `peeraddr`, `ssl_version` and `cipher` methods to stubbed sockets used by Net::HTTP. Thanks to [Ray Zane](https://github.com/rzane) * Added support for matching top-level array in JSON request body. E.g. ```` stub_request(:post, 'www.example.com').with(body: [{a: 1}]) ```` Thanks to [Cedric Sohrauer](https://github.com/cedrics) # 3.16.2 * Minimum required Ruby version is 2.0. # 3.16.0 (yanked) * Fix leaky file descriptors and reuse socket for persistent connections. Thanks to [Ray Zane](https://github.com/rzane) * Allow specifying for what URIs or hosts, Net::HTTP should connect on start. Thanks to [Ray Zane](https://github.com/rzane) # 3.15.2 * Minimum required Ruby version is 2.0. # 3.15.0 (yanked) * fixed async-http adapter on Windows Thanks to [Pavel Rosický](https://github.com/ahorek) * Support for http.rb >= 5.0.2 Thanks to [ojab](https://github.com/ojab) * Curb adapter supports headers with `:` character in the header value Thanks to [Giorgio Gambino](https://github.com/mrbuzz) * Support for matching body of JSON or application/x-www-form-urlencoded requests with content type header including charset. Thanks to [Timmitry](https://github.com/Timmitry) * Prevent double-wrapping http.rb features on non-stubbed requests Thanks to [Michael Fairley](https://github.com/michaelfairley) # 3.14.0 * Bump Addressable from 2.3.6 to 2.8.0 Thanks to [Eduardo Hernandez](https://github.com/EduardoGHdez) # 3.13.0 * Support http.rb 5.x Thanks to [Will Storey](https://github.com/horgh) # 3.12.2 * Fixed em-http-request adapter to avoid calling middleware twice. Thanks to [Alex Vondrak](https://github.com/ajvondrak) # 3.12.1 * Fixed handling of URIs with IPv6 addresses with square brackets when in Net::HTTP adapter. Thanks to [Johanna Hartmann](https://github.com/JohannaHartmann) # 3.12.0 * Added support for handling custom JSON and XML content types e.g. 'application/vnd.api+json' # 3.11.3 * Fixed async-http adapter to only considered requests as real if they are real. Thanks to Thanks to [Tony Schneider](https://github.com/tonywok) and [Samuel Williams](https://github.com/ioquatix) # 3.11.2 * Fix for Manticore streaming mode Thanks to [Oleksiy Kovyrin](https://github.com/kovyrin) # 3.11.1 * Compatibility with async-http 0.54+ Thanks to [Jun Jiang](https://github.com/jasl) # 3.11.0 * Added support for `features` in http.rb adapter. Thanks to [Carl (ce07c3)](https://github.com/ce07c3) # 3.10.0 * Added option to global stubs to have lower priority than local stubs. WebMock.globally_stub_request(:after_local_stubs) do { body: "global stub body" } end stub_request(:get, "www.example.com").to_return(body: 'non-global stub body') expect(http_request(:get, "http://www.example.com/").body).to eq("non-global stub body") Thanks to [Marek Kasztelnik](https://github.com/mkasztelnik) # 3.9.5 * Prevent overwriting `teardown` method in Test::Unit Thanks to [Jesse Bowes](https://github.com/jessebs) # 3.9.4 * More intuitive error message when stubbed response body was provided as Hash Thanks to [Ben Koshy](https://github.com/BKSpurgeon) # 3.9.3 * Make httpclient_adapter thread-safe Thanks to [Adam Harwood](https://github.com/adam-harwood) # 3.9.2 * Made global stubs thread-safe Thanks to [Adam Harwood](https://github.com/adam-harwood) # 3.9.1 * Fixed support for passing `URI` objects as second argument of `stub_request` Thanks to [Ryan Kerr](https://github.com/leboshi) ## 3.9.0 * Allow using a "callable" (like a proc) as URI pattern stub_request(:any, ->(uri) { true }) Thanks to [John Hawthorn](https://github.com/jhawthorn) * Added stubbed IO on stubbed socket in Net::HTTP adapter. Thanks to [Thilo Rusche](https://github.com/trusche) * When 'webmock/rspec' is required, reset WebMock after all after(:each/example) hooks Thanks to [Andrew Stuntz](https://github.com/drews256) * Fixed `net_connect_allowed?` when invoked with no arguments, when there were any allowed URIs passed to `disable_net_connect?`. Thanks to [Lucas Uyezu](https://github.com/lucasuyezu) * Fixed async-http adapter which caused Async::HTTP::Client or Async::HTTP::Internet to hang and never return a response. Thanks to [Bruno Sutic](https://github.com/bruno-) and [Samuel Williams](https://github.com/ioquatix) * Fixed warning when using async-http adapter Thanks to [Bruno Sutic](https://github.com/bruno-) * Dropped support for Ruby 2.3 - EOL date: 2019-03-31 * Dropped support for Ruby 2.4 - EOL date: 2020-03-31 * Handling matching of Addressable::Template patterns that have an ip address without port and patterns that have ip address and don’t have schema and path. Thanks to [Rafael França](https://github.com/rafaelfranca) and [guppy0356](https://github.com/guppy0356) ## 3.8.3 * Fixed problem introduced in version 3.4.2, which caused matching against Addressable::Template representing host part of the URI to raise an error. Thanks to [Vesa Laakso](https://github.com/valscion) ## 3.8.2 * Support correct encoding parameter for HTTP.rb 2.x and earlier Thanks to [Alex Coomans](https://github.com/drcapulet) ## 3.8.1 * Added support for mocking non-ASCII bodies when making requests with HTTP.rb Thanks to [Patrik Ragnarsson](https://github.com/dentarg) ## 3.8.0 * Fixed options handling when initialising Async::HTTP::Client Thanks to [Samuel Williams](https://github.com/ioquatix) * Ruby 2.7 support. Thanks to [Ryan Davis](https://github.com/zenspider) and [Brandur](https://github.com/brandur) ## 3.7.6 * Suppressed keyword argument warnings in Ruby 2.7 in async-http adapter. Thanks to [Koichi ITO](https://github.com/koic) ## 3.7.5 * Suppress Excon warning generated by extra key Thanks to [Marco Costa](https://github.com/marcotc) ## 3.7.4 * Resetting memoized response fields in Curb adapter. Thanks to [Andrei Sidorov](https://github.com/heretge) ## 3.7.3 * Fix for http.rb. Allow passing an output buffer to HTTP::Response::Body#readpartial Thanks to [George Claghorn](https://github.com/georgeclaghorn) * Fixed Manticore adapter to invoke Manticore failure handler on stubbed timeout Thanks to [Alex Junger](https://github.com/alexJunger) * Added project metadata to the gemspec Thanks to [Orien Madgwick](https://github.com/orien) ## 3.7.2 * Fixed handling of non UTF-8 encoded urls Thanks to [Rafael França](https://github.com/rafaelfranca) * Fixed "shadowing outer local variable" warning Thanks to [y-yagi](https://github.com/y-yagi) ## 3.7.1 * Fixed Async::HTTP::Client adapter code to not cause Ruby warning Thanks to [y-yagi](https://github.com/y-yagi) ## 3.7.0 * Support for Async::HTTP::Client Thanks to [Andriy Yanko](https://github.com/ayanko) ## 3.6.2 * Fixed Patron adapter to handle HTTP/2 status line. Thanks to [Fábio D. Batista](https://github.com/fabiob) ## 3.6.1 * Fixed issue with matching Addressable::Template without a period in the domain Thanks to [Eike Send](https://github.com/eikes) * Support for `write_timeout` in Net::HTTP Thanks to [Claudio Poli](https://github.com/masterkain) * Fixed issue with handling urls with ":80" or ":443" in the path. Thanks to [Csaba Apagyi](https://github.com/thisismydesign) for reporting and to [Frederick Cheung](https://github.com/fcheung) for fixing the issue. ## 3.6.0 * Compatibility with the latest version of hashdiff gem, with constant changed from HashDiff to Hashdiff Thanks to [Jeff Felchner](https://github.com/jfelchner) * Added a hint to the error message raised when `with` method is called without args or a block. Thanks to [Adam Sokolnicki](https://github.com/asok) * Resetting configured HTTP method in Curb adapter after each request Thanks to [tiendo1011](https://github.com/tiendo1011) * Added `WebMock.enable_net_connect!` as an alias for `WebMock.allow_net_connect!` and `WebMock.disallow_net_connect!` as an alias for `WebMock.disable_net_connect!` Thanks to [SoonKhen OwYong](https://github.com/owyongsk) * Fixed handling of empty arrays as query params when using Faraday Thanks to [Ryan Moret](https://github.com/rcmoret) ## 3.5.1 * Disabling TracePoint defined in Net::BufferedIO in case of exception being raised. Thanks to [Koichi Sasada](https://github.com/ko1) ## 3.5.0 * Ruby 2.6.0 support Thanks to [Arkadiy Tetelman](https://github.com/arkadiyt) * Added `WebMock.reset_executed_requests!` method. stub_get = stub_request(:get, "www.example.com") Net::HTTP.get('www.example.com', '/') WebMock::RequestRegistry.instance.times_executed(stub_get.request_pattern) # => 1 reset_executed_requests! WebMock::RequestRegistry.instance.times_executed(stub_get.request_pattern) # => 0 Thanks to [Olia Kremmyda](https://github.com/oliakremmyda) * Performance improvements Thanks to [Pavel Rosický](https://github.com/ahorek) ## 3.4.2 * Fixed `rbuf_fill` in Net::HTTP adapter to be thread-safe Thanks to [Arkadiy Tetelman](https://github.com/arkadiyt) * Fix invalid scheme error with Addressable::Template Thanks to [Kazato Sugimoto](https://github.com/uiureo) ## 3.4.1 * When comparing url encoded body to a body from request stub, which was declared as hash, only String, Numeric and boolean hash values are stringified before the comparison. Thanks to [Lukas Pokorny](https://github.com/luk4s) ## 3.4.0 * Ruby 2.6 support. Prevent `Net/ReadTimeout` error in Ruby 2.6 Thanks to [Koichi ITO](https://github.com/koic) * Handling query params, which represent nested hashes with keys starting with non word characters. Thanks to [rapides](https://github.com/rapides) for reporting the issue. * Patron adapter handles PATCH requests with body. Thanks to [Mattia](https://github.com/iMacTia) for reporting the issue. * Allowing requests with url encoded body to be matched by request stubs declared with hash body with non-string values. stub_request(:post, "www.example.com").with(body: {"a" => 1, "b" => false}) RestClient.post('www.example.com', 'a=1&b=false', :content_type => 'application/x-www-form-urlencoded') # ===> Success Thanks to [Kenny Ortmann](https://github.com/yairgo) for suggesting this feature. * When request headers contain 'Accept'=>'application/json' and no registered stub matches the request, WebMock prints a suggested stub code with to_return body set to '{}'. Thanks to [redbar0n](https://github.com/redbar0n) * Improved suggested stub output when the request stub only contains headers declaration. Thanks to [Olia Kremmyda](https://github.com/oliakremmyda) * Fixed Curb adapter to handle `reset` method. Thanks tp [dinhhuydh](https://github.com/dinhhuydh) for reporting the issue. Thanks to [Olia Kremmyda](https://github.com/oliakremmyda) for fixing it. ## 3.3.0 * Better formatting of outputted request stub snippets, displayed on failures due to unstubbed requests. Thanks to [Olia Kremmyda](https://github.com/oliakremmyda) ## 3.2.1 * Fixed Ruby warning under Ruby 2.5 Thanks to [Matt Brictson](https://github.com/mattbrictson) ## 3.2.0 * Automatically disable WebMock after Rspec suite Thanks to [Michał Matyas](https://github.com/d4rky-pl) * Fixed bug when handling redirection using Curb. Thanks to [Olia Kremmyda](https://github.com/oliakremmyda) ## 3.1.1 * Warning message is displayed only once when adding query params to URIAddressablePattern. ## 3.1.0 * http.rb 3.0.0 compatibility Thanks to [Piotr Boniecki](https://github.com/Bonias) * Typhoeus 1.3.0 support Thanks to [NARUSE, Yui](https://github.com/nurse) * Added support for matching partial query params using hash_excluding stub_request(:get, "www.example.com"). with(query: hash_excluding({"a" => "b"})) RestClient.get("http://www.example.com/?a=b") # ===> Failure RestClient.get("http://www.example.com/?a=c") # ===> Success Thanks to [Olexandr Hoshylyk](https://github.com/Warrior109) * Added MRI 2.3+ frozen string literal compatibility Thanks to [Pat Allan](https://github.com/pat) * Ensured that HTTPClient adapter does not yield block on empty response body if a block is provided Thanks to [NARUSE, Yui](https://github.com/nurse) * Fixed issue with `to_timeout` incorrectly raising `HTTP::ConnectionError` instead of `HTTP::TimeoutError` when using http.rb Thanks to [Rick Song](https://github.com/RickCSong) * Fixed problem with `response.connection.close` method being undefined when using http.rb Thanks to [Janko Marohnić](https://github.com/janko-m) * Fixed problem with matching Net::HTTP request header values assigned as numbers. Thanks to [Felipe Constantino de Oliveira](https://github.com/felipecdo) for reporting the issue. * Fixed problem with Net::HTTP adapter converting empty response body to nil for non 204 responses. Thanks to [Jeffrey Charles](https://github.com/jeffcharles) for reporting the issue. ## 3.0.1 * Suppressed \`warning: \`&' interpreted as argument prefix\` Thanks to [Koichi ITO](https://github.com/koic) ## 3.0.0 * Dropped support for Ruby 1.9.3 * Using Ruby >= 1.9 hash key syntax in stub suggestions Thanks to [Tarmo Tänav](https://github.com/tarmo) * Add at_least matchers for fakeweb-style expectations Thanks to [Joe Marty](https://github.com/mltsy) * Fix against "can't modify frozen String' error when Ruby option `frozen_string_literal` is enabled. Thanks to [Chris Thomson](https://github.com/christhomson) * Handling `read_timeout` option in Net::HTTP in Ruby >= 2.4 Thanks to [Christof Koenig](https://github.com/ckoenig) * `RequestRegistry` fix for `RuntimeError - can't add a new key into hash during iteration` Thanks to [Chung-Yi Chi](https://github.com/starsirius) ## 2.3.2 * Restored support for Ruby 1.9.3 to comply with semantic versioning. Thanks to [Jordan Harband](https://github.com/ljharb) for reporting the problem. ## 2.3.1 * Added support for Ruby 2.4 Thanks to [Koichi ITO](https://github.com/koic) * Dropped support for Ruby 1.9.3 ## 2.2.0 * Added `refute_requested` as an alias for `assert_not_requested` Thanks to [Michael Grosser](https://github.com/grosser) * Raising `Net::OpenTimeout` instead of `Timeout::Error` if available when a request stub is declared `to_timeout` Thanks to [Gabe Martin-Dempesy](https://github.com/gabetax) ## 2.1.1 * Added support for handling status messages in Excon responses. Thanks to [Tero Marttila](https://github.com/SpComb) for reporting the issue. ## 2.1.0 * Added support for `on_debug` callback in Curb. Thanks to [Pavel Jurašek](https://github.com/pavel-jurasek-bcgdv-com) * Added support for PATCH requests using Curb. Thanks to [Pavel Jurašek](https://github.com/pavel-jurasek-bcgdv-com) ## 2.0.3 * Handling headers passed as an Array to Curl::Easy Thanks to [Chelsea](https://github.com/grosscr) for reporting the issue. * Removed Ruby warnings. Thanks to [Aaron Kromer](https://github.com/cupakromer) ## 2.0.2 * Using `Base64.strict_encode64` instead of `Base64.encode64` to handle long user:pass basic auth credentials Thanks to [Jonathan Schatz](https://github.com/modosc) * Fixed handling of Authorisation header provided as string instead of array when using em-http-request. Thanks to [Michael Richardson](https://github.com/TTransmit) for reporing the issue. * Ensured `WebMock.net_connect_explicit_allowed?` always returns boolean. Thanks tp [Jose Luis Honorato](https://github.com/jlhonora) ## 2.0.1 * Added code responsible for loading em-http-request if available, which has been removed by mistake. Thanks to [Vasiliy](https://github.com/304) * WebMock loads "base64" if it's not yet loaded. Thanks to [Taiki Ono](https://github.com/taiki45). ## 2.0.0 * `require 'webmock'` does not enable WebMock anymore. `gem 'webmock'` can now be safely added to a Gemfile and no http client libs will be modified when it's loaded. Call `WebMock.enable!` to enable WebMock. Please note that `require 'webmock/rspec'`, `require 'webmock/test_unit'`, `require 'webmock/minitest'` and `require 'webmock/cucumber'` still do enable WebMock. * Dropped support for Ruby < 1.9.3 * Dropped support for em-http-request < 1.0.0 * WebMock 2.0 does not match basic authentication credentials in the userinfo part of the url, with credentials passed in `Authorization: Basic ...` header anymore. It now treats the Authorization header and credentials in the userinfo part of a url as two completely separate attributes of a request. The following stub declaration, which used to work in WebMock 1.x, is not going to work anymore stub_request(:get, "user:pass@www.example.com") Net::HTTP.start('www.example.com') do |http| req = Net::HTTP::Get.new('/') req.basic_auth 'user', 'pass' http.request(req) end # ===> Failure In order to stub a request with basic authentication credentials provided in the Authorization header, please use the following code: stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass']) or stub_request(:get, "www.example.com"). with(headers: 'Authorization' => "Basic #{ Base64.strict_encode64('user:pass').chomp}") In order to stub a request with basic authentication credentials provided in the url, please use the following code: stub_request(:get, "user:pass@www.example.com") RestClient.get('user:pass@www.example.com') # ===> Success ## 1.24.6 * Fixed issue with RUBY_VERSION comparison using old RubyGems. Thanks to [Chris Griego](https://github.com/cgriego). * Support for http.rb >= 2.0.0 ## 1.24.4 * Fixed the issue with parsing query to a hash with nested array i.e. `a[][b][]=one&a[][c][]=two` Thanks to [Tim Diggins](https://github.com/timdiggins) for reporting the issue. Thanks to [Cedric Pimenta](https://github.com/cedricpim) for finding the solution. ## 1.24.3 * Allow Net:HTTP headers keys to be provided as symbols if `RUBY_VERSION` >= 2.3.0 Thanks to [Alex Kestner](https://github.com/akestner) * Added a clear message on an attempt to match a multipart encoded request body. WebMock doesn't support requests with multipart body... yet. * `WebMock.disable_net_connect` `:allow` option, provided as regexp, matches https URIs correctly. * `WebMock.disable_net_connect` `:allow` option can be set as a url string with scheme, host and port. WebMock.disable_net_connect!(:allow => 'https://www.google.pl') Thanks to [Gabriel Chaney](https://github.com/gabrieljoelc) for reporting the issue. ## 1.24.2 * Improve parsing of params on request Thanks to [Cedric Pimenta](https://github.com/cedricpim) ## 1.24.1 * HTTPClient adapter supports reading basic authentication credentials directly from Authorization header. Thanks to [Michiel Karnebeek](https://github.com/mkarnebeek) ## 1.24.0 * Enabled support for Curb > 0.8.6 ## 1.23.0 * `WebMock.disable_net_connect` accepts `:allow` option with an object that responds to `#call`, receiving a `URI` object and returning a boolean: denylist = ['google.com', 'facebook.com', 'apple.com'] allowed_sites = lambda{|uri| denylist.none?{|site| uri.host.include?(site) } } WebMock.disable_net_connect!(:allow => allowed_sites) RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('www.facebook.com', '/') # ===> Failure RestClient.get('apple.com', '/') # ===> Failure Thanks to [Pablo Brasero](https://github.com/pablobm) * Support for HTTPClient stream responses with body chunks Thanks to [Cedric Pimenta](https://github.com/cedricpim) ## 1.22.6 * Fixes [issue](https://github.com/bblimke/webmock/issues/568) around WebMock restricting [Addressable](https://github.com/sporkmonger/addressable) version, based on Ruby 1.8.7 for all versions of Ruby. This change inverts that, and forces Ruby 1.8.7 users to specify in thier Gemfile an Addressable version < 2.4.0. Thanks to [PikachuEXE](https://github.com/PikachuEXE) and [Matthew Rudy Jacobs](https://github.com/matthewrudy). ## 1.22.5 * Fixes [bug](https://github.com/bblimke/webmock/issues/565) where WebMock tries to alias a method that is deprecated in Ruby Versions > 1.9.2 ('sysread' for class 'StringIO') Thanks to [Marcos Acosta](https://github.com/mmaa) for discovering this bug. ## 1.22.4 * Adds support for JSONClient (a subclass of HTTPClient) Thanks to [Andrew Kozin](https://github.com/nepalez) * Adds support for Ruby 2.3.0 Thanks to [Charles Pence](https://github.com/cpence) * Adds support for [http](https://github.com/httprb/http) versions >= 1.0.0 Thanks to [Alexey Zapparov](https://github.com/ixti) * Fixes support for Ruby 1.8.7 by restrciting Addressable version < 2.4.0 Thanks to [Matthew Rudy Jacobs](https://github.com/matthewrudy) ## 1.22.3 * Return "effective_url" attribute in Typhoeus::Response Thanks to [Senya](https://github.com/cmrd-senya) ## 1.22.2 * Fix: prevents adding an extra =true to urls with parameters without values Thanks to [David Begin](https://github.com/davidbegin) ## 1.22.1 * Adds Rack as a development dependency and removes require rack/utils in main lib. Thanks to [Keenan Brock](https://github.com/kbrock) ## 1.22.0 All the credit for preparing this release go to [David Begin](https://github.com/davidbegin)! * Adds [Manticore](https://github.com/cheald/manticore) support. Thanks to [Mike Knepper](https://github.com/mikeknep), [David Abdemoulaie](https://github.com/hobodave) * Update to Show a hash diff for requests that have stubs with a body. Thanks to [yurivm](https://github.com/yurivm) * Update to mirror Net::HTTP handling of headers as symbols * Update to ignore non-comparable-values error when sorting query values, because sorting is just a convience. Thanks to [Magne Land](https://github.com/magneland) * Covert Boolean values to Strings when using them to define the body of a request. Thanks to [Krzysztof Rygielski](https://github.com/riggy) * Fixes WebMock's parsing Multibyte characters Thanks to [Zhao Wen](https://github.com/VincentZhao) * Updates to be compatible with httpclient 2.6.0 * Converts keys from symbols to strings when for QueryMapper.to_query Thanks to [Ramon Tayag](https://github.com/ramontayag) * Restricts http.rb version to 0.7.3 for Ruby 1.8.7 * Fixes issue emulating em-http-request's handling of multiple requests. Thanks to [Matt Palmer](https://github.com/mpalmer) * WebMock requires only the necessary parts of crack to avoid pulling in safe_yaml Thanks to [Johannes Schlumberger](https://github.com/spjsschl) ## 1.21.0 * Support for http.rb >= 0.8.0 Thanks to [Zachary Anker](https://github.com/zanker), [Aleksey V. Zapparov](https://github.com/ixti) * Support for http.rb 0.7.0 Thanks to [Mattias Putman](https://github.com/challengee) * Added support for RSpec3-like `and_return`, `and_raise`, `and_timeout` syntax. Thanks to [Franky Wahl](https://github.com/frankywahl) * Restricted Curb support up to version 0.8.6. WebMock specs fail with Curb 0.8.7. ## 1.20.4 * Fixed support for `hash_including` matcher in RSpec 3 ## 1.20.3 * `with` method raises error if provided without options hash and without block * `with` and `to_return` raise an error if invoked with invalid keys in options hash. ## 1.20.2 * WebMock provides a helpful error message if an incompatible object is given as response body. Thanks to [Mark Lorenz](https://github.com/dapplebeforedawn) ## 1.20.1 * `assert_requested` and `assert_not_requested` accept `at_least_times` and `at_most_times` options Thanks to [Dan Buettner](https://github.com/Capncavedan) * Silenced `instance variable undefined` warnings in Curb adapted. Thanks to [Sven Riedel](https://github.com/sriedel) ## 1.20.0 * Add support for on_missing callback of Curb::Easy Thanks to [Tasos Stathopoulos](https://github.com/astathopoulos) * Add at_least_times and at_most_times matchers Thanks to [Dan Buettner](https://github.com/Capncavedan) ## 1.19.0 * Fixed issue with Excon adapter giving warning message when redirects middleware was enabled. Thanks to [Theo Hultberg](https://github.com/iconara) for reporting that. * Fixed issue with `undefined method 'valid_request_keys' for Excon::Utils:Module` Thanks to [Pablo Jairala](https://github.com/davidjairala) * Fixed query mapper to encode `'one' => ['1','2']` as `'one[]=1&one[]=2'`. Thanks to [Insoo Buzz Jung](https://github.com/insoul) * Improved cookies support for em-http-request Thanks to [Carlos Alonso Pérez](https://github.com/calonso) * Fix HTTP Gem adapter to ensure uri attribute is set on response object. Thanks to [Aleksey V. Zapparov](https://github.com/ixti) * Fixed HTTPClient adapter. The response header now receives `request_method`, `request_uri`, and `request_query` transferred from request header Thanks to [trlorenz](https://github.com/trlorenz) * Query mapper supports nested data structures i.e. `{"first" => [{"two" => [{"three" => "four"}, "five"]}]}` Thanks to [Alexander Simonov](https://github.com/simonoff) * Fixed compatibility with latest versions of Excon which don't define `VALID_REQUEST_KEYS` anymore. Thanks to [Pablo Jairala](https://github.com/davidjairala) * Request method is always a symbol is request signatures. This fixes the issue of WebMock not matching Typhoeus requests with request method defined as string. Thanks to [Thorbjørn Hermanse](https://github.com/thhermansen) * Stubbing instructions which are displayed when no matching stub is found, can be disabled with `Config.instance.show_stubbing_instructions = false` Thanks to [Mark Lorenz](https://github.com/dapplebeforedawn) * Notation used for mapping query strings to data structure can be configured i.e. `WebMock::Config.instance.query_values_notation = :subscript`. This allows setting `:flat_array` notation which supports duplicated parameter names in query string. Thanks to [tjsousa](https://github.com/tjsousa) ## 1.18.0 * Updated dependency on Addressable to versions >= 2.3.6 * Added support for matching uris using RFC 6570 (URI Templates) uri_template = Addressable::Template.new "www.example.com/{id}/" stub_request(:any, uri_template) Thanks to [Max Lincoln](https://github.com/maxlinc) * Fixed content length calculation for Rack responses with UTF8 body Thanks to [Oleg Gritsenko](https://github.com/Claster) * Add missing Curl::Easy aliases Thanks to [Hwan-Joon Choi](https://github.com/hc5duke) * HTTP Gem >= 0.6.0 compatibility Thanks to [Aleksey V. Zapparov](https://github.com/ixti) * Minitest 4 and 5 compatibility. Thanks to [SHIBATA Hiroshi](https://github.com/hsbt) ## 1.17.4 * Update matchers for RSpec 3's matcher protocol Thanks to [Rob Olson](https://github.com/robolson) ## 1.17.3 * Fixed issue with Rack response removing 'Content-Type' header Thanks to [Bo Jeanes](https://github.com/bjeanes) and [Matthew Conway](https://github.com/mattonrails) ## 1.17.2 * Support for chunked responses in Curb Thanks to [Zachary Belzer](https://github.com/zbelzer) * Fixed handling of request body passed as a hash to `Typhoeus.post` Thanks to [Mason Chang](https://github.com/changmason) for reporting. ## 1.17.1 * Added missing license statements. Thanks to [Praveen Arimbrathodiyil](https://github.com/pravi) ## 1.17.0 * HTTP gem support! Thanks to [Aleksey V. Zapparov](https://github.com/ixti) * Limited Excon gem requirement to version < 0.30 until the compatibility with version > 0.30.0 is fixed. Thanks to [Aleksey V. Zapparov](https://github.com/ixti) * Fixed issue where empty query key caused a `TypeError` Thanks to [Jon Rowe](https://github.com/JonRowe) * Handling Typhoeus `on_headers` and `on_body` params. Thanks to [Matt Burke](https://github.com/spraints) ## 1.16.1 * Fixed "NameError: uninitialized constant WebMock::Response::Pathname" issue. Thanks to [Alex Stupakow and Karen Wang](https://github.com/stupakov) for the fix. ## 1.16.0 * Allow a Pathname to be passed as a Response body stub_request(:get, /example.com/).to_return( body: Rails.root.join('test/fixtures/foo.txt') ) Thanks to [Ben Pickles](https://github.com/benpickles) * `hash_including` matcher can be initialized with empty keys to match any values. stub_request(:post, "www.example.com").with(:body => hash_including(:a, :b => {'c'})) RestClient.post('www.example.com', '{"a":"1","b":"c"}', :content_type => 'application/json') Thanks to [Stefano Uliari](https://github.com/steookk) ## 1.15.2 * Fixed `hash_including` to accept a splat of solitary keys. Thanks to [Tamir Duberstein](https://github.com/tamird) and [https://github.com/strongriley](https://github.com/strongriley) ## 1.15.0 * Excon >= 0.27.5 compatibility. Thanks to [Brian D. Burns](https://github.com/burns) ## 1.14.0 * Handling non UTF-8 characters in query params. Thanks to [Florian Dütsch](https://github.com/der-flo) for reporting the issue. * Added support for `request_block` param in Excon Thanks to [Dmitry Gutov](https://github.com/dgutov) for reporting the issue. * Fixed compatibility with latest Curb Thanks to [Ian Lesperance](https://github.com/elliterate) and [Matthew Horan](https://github.com/mhoran) * Triggering errbacks assynchronously in em-http-request adapter. Thanks to [Ian Lesperance](https://github.com/elliterate) and [Matthew Horan](https://github.com/mhoran) * Handling query params with a hashes nested inside arrays. Thanks to [Ian Asaff](https://github.com/montague) * Changed NetConnectNotAllowedError to inherit from Exception to allow it to bubble up into a test suite. Thanks to [Daniel van Hoesel](https://github.com/s0meone) * HTTPClient adapter is thread safe. Thanks to [Tom Beauvais](https://github.com/tbeauvais) ## 1.13.0 * Net::HTTP::Persistent compatibility. WebMock doesn't disconnect previously started connections upon a request anymore. ## 1.12.3 * Fixed issue with handling Addressable::URI with query params passed to `Net::HTTP.get_response` Thanks to [Leif Bladt](https://github.com/leifbladt) * Fixed HTTPClient adapter to not raise an error if a request with multipart body is executed. ## 1.12.2 * Fixed issue with handling request.path when Addressable::URI is passed to #request instead of URI with Ruby 2.0. Thanks to [Leif Bladt](https://github.com/leifbladt) * Accept integers as query param values in request stubs i.e. `stub_request(:get, /.*/).with(:query => {"a" => 1})` Thanks to [Mitsutaka Mimura](https://github.com/takkanm) ## 1.12.1 * Fixed Minitest < 5.0 compatibility Thanks to [Alex Tomlins](https://github.com/alext) for reporting the issue. ## 1.12.0 * Not using Gem spec anymore to check loaded Curb version. * `WebMock.disable_net_connect!` now accepts array of regexps as allow param: i.e. `WebMock.disable_net_connect!(:allow => [/google.com/, /yahoo.com/])` Thanks to [Bastien Vaucher](https://github.com/bastien) * Fixed `on_header` Curb callback behaviour in Curb adapter Thanks to [Joel Chippindale](https://github.com/mocoso) * Fixed aws-sdk compatibility with Ruby 2.0, by supporting `continue_timeout` accessor on Net::HTTP socket. Thanks to [Lin Jen-Shin](https://github.com/godfat) * Fixed WebMock::Server to not give "log writing failed. can't be called from trap context" warning with Ruby 2.0 Thanks to [Murahashi Sanemat Kenichi](https://github.com/sanemat) * Added support for EM-HTTP-Request streaming data off disk feature. Thanks to [Lin Jen-Shin](https://github.com/godfat) * Added compatibility with Minitest 5 Thanks to [Tim Kurvers](https://github.com/timkurvers) * Excon >= 0.22 compatibility. * README has nice sytnax hightlighting and fixed code styling! Thanks to [Ilya Vassilevsky](https://github.com/vassilevsky) * Compatibility with Rails 4 `rack.session.options` Thanks to [gotwalt](https://github.com/gotwalt) ## 1.11.0 * Excon >= 0.17 support. Thanks to [Nathan Sutton](https://github.com/nate) for reporting this issue and to [Wesley Beary](https://github.com/geemus) and [Myron Marston](https://github.com/myronmarston) for help. ## 1.10.2 * '+' in request path is treated as plus, but in query params always as a space. ## 1.10.1 * '+' in request body is still treated as a space. This fixes a bug introduced in previous version. Thanks to [Erik Michaels-Ober](https://github.com/sferik) for reporting this problem. * Fixed issue: response body declared as Proc was not evaluated again on subsequent requests. Thanks to [Rick Fletcher](https://github.com/rfletcher) for reporting this issue. ## 1.10.0 * '+' in query params is not treated as space anymore and is encoded as %2B Thanks to [goblin](https://github.com/goblin) for reporting this issue. * added `remove_request_stub` method to the api to allow removing unused stubs i.e. stub_get = stub_request(:get, "www.example.com") remove_request_stub(stub_get) * `assert_requested` and `assert_not_requested` raise an error if a stub object is provided together with a block. ## 1.9.3 * Fixed issue with unavailable constant Mutex in Ruby < 1.9 Thanks to [Lucas Dohmen](https://github.com/moonglum) for reporting this issue. ## 1.9.2 * Added support for Excon's :response_block parameter Thanks to [Myron Marston](https://github.com/myronmarston) for reporting this issue. ## 1.9.1 * Fix 'rack.errors' not being set for Rack apps Thanks to [Alex Grant](https://github.com/grantovich) * Added support for minitest assertions count Thanks to [Mokevnin Kirill](https://github.com/mokevnin) * Fixed issues with registering http requests in multi-threaded environments Thanks to [Tom Beauvais](https://github.com/tbeauvais) * Bumped Crack version to >=0.3.2 Thanks to [Jake Benilov](https://github.com/benilovj) * Fixed issues in Typhoeus 0.6. Defaulted method to GET when no method specified. Thanks to [Hans Hasselberg](https://github.com/i0rek) * Add license information to the gemspec Thanks to [Jordi Massaguer Pla](https://github.com/jordimassaguerpla) and [Murahashi Sanemat Kenichi](https://github.com/sanemat) * Added support for :expects option in Excon adapter Thanks to [Evgeniy Dolzhenko](https://github.com/dolzenko) * Fixed Faye compatibility by treating StringIO in Net::HTTP adapter properly Thanks to [Pavel Forkert](https://github.com/fxposter) * Updated VCR link Thanks to [Rex Feng](https://github.com/xta) ## 1.9.0 * Added support for Typhoeus >= 0.5.0 and removed support for Typhoeus < 0.5.0. Thanks to [Hans Hasselberg](https://github.com/i0rek) ## 1.8.11 * Fix excon adapter to handle `:body => some_file_object` Thanks to [Myron Marston](https://github.com/myronmarston) ## 1.8.10 * em-http-request fix. After request callbacks are correctly invoked for 3xx responses, when :redirects option is set. Thanks to [Myron Marston](https://github.com/myronmarston) for reporting that issue. * Fixed compatibility with Net::HTTP::DigestAuth Thanks to [Jonathan Hyman](https://github.com/jonhyman) for reporting that issue. * Fixed problem in em-http-request 0.x appending the query to the client URI twice. Thanks to [Paweł Pierzchała](https://github.com/wrozka) ## 1.8.9 * Fixed problem with caching nil responses when the same HTTPClient instance is used. Thanks to [Myron Marston](https://github.com/myronmarston) * Added support for Addressable >= 2.3.0. Addressable 2.3.0 removed support for multiple query value notations and broke backwards compatibility. https://github.com/sporkmonger/addressable/commit/f51e290b5f68a98293327a7da84eb9e2d5f21c62 https://github.com/sporkmonger/addressable/issues/77 ## 1.8.8 * Fixed Net::HTTP adapter so that it returns `nil` for an empty body response. Thanks to [Myron Marston](https://github.com/myronmarston) * Gemspec defines compatibility with Addressable ~> 2.2.8, not >= 2.3.0 * Specs compatibility with Typhoeus 0.4.0 Thanks to [Hans Hasselberg](https://github.com/i0rek) * Handling content types that specify a charset Thanks to [Kevin Glowacz](https://github.com/kjg) * Fixed em-http-request adapter to correctly fetch authorization header from a request Thanks to [Julien Boyer](https://github.com/chatgris) * Fixing travis-ci image to report master's status Thanks to [Ryan Schlesinger](https://github.com/ryansch) * Fixed problem with em-http-request callback triggering if there were other EM::Deferred callbacks registered Thanks to [Jon Leighton](https://github.com/jonleighton) * Fixed problem with em-http-request appending the query to the URI a second time, and the parameters are repeated. Thanks to [Jon Leighton](https://github.com/jonleighton) ## 1.8.7 * Compatibility with RSpec >= 2.10 Thanks to [erwanlr](https://github.com/erwanlr) for reporting this issue. * Add missing required rack environment variable SCRIPT_NAME Thanks to [Eric Oestrich](https://github.com/oestrich) * Fixed warnings due to @query_params not being initialized Thanks to [Ben Bleything](https://github.com/bleything) ## 1.8.6 * Pass through SERVER_PORT when stubbing to rack Thanks to [Eric Oestrich](https://github.com/oestrich) * Fixed problem with missing parenthesis in `WebMock#net_connect_allowed?` conditions. Thanks to [aindustries](https://github.com/aindustries) ## 1.8.5 * WebMock::RackResponse supports basic auth Thanks to [jugyo](https://github.com/jugyo) ## 1.8.4 * Warning message is printed when an unsupported version of a http library is loaded. Thanks to [Alexander Staubo](https://github.com/alexstaubo) for reporting the problem and to [Myron Marston](https://github.com/myronmarston) for a help with solution. ## 1.8.3 * Fixed compatibility with latest em-http-request Thanks to [Paul Cortens](https://github.com/thoughtless) ## 1.8.2 * Prevent Webmock `hash_including` from overriding RSpec version 1 `hash_including` method. Thanks to [Joe Karayusuf](https://github.com/karayusuf) * Ensured WebMock handles RSpec 1 `hash_including` matcher for matching query params and body. ## 1.8.1 * Ensured WebMock doesn't interfere with `em-synchrony`, when `em-synchrony/em-http` is not included. Thanks to [Nick Recobra](https://github.com/oruen) * Improved README Thanks to [Jordan Elver](https://github.com/jordelver) ## 1.8.0 * Matching request body against partial hash. stub_http_request(:post, "www.example.com"). with(:body => hash_including({:data => {:a => '1', :b => 'five'}})) RestClient.post('www.example.com', "data[a]=1&data[b]=five&x=1", :content_type => 'application/x-www-form-urlencoded') # ===> Success request(:post, "www.example.com"). with(:body => hash_including({:data => {:a => '1', :b => 'five'}}), :headers => 'Content-Type' => 'application/json').should have_been_made # ===> Success Thanks to [Marnen Laibow-Koser](https://github.com/marnen) for help with this solution * Matching request query params against partial hash. stub_http_request(:get, "www.example.com").with(:query => hash_including({"a" => ["b", "c"]})) RestClient.get("http://www.example.com/?a[]=b&a[]=c&x=1") # ===> Success request(:get, "www.example.com"). with(:query => hash_including({"a" => ["b", "c"]})).should have_been_made # ===> Success * Added support for Excon. Thanks to [Dimitrij Denissenko](https://github.com/dim) * Added support for setting expectations on the request stub with `assert_requested` stub_get = stub_request(:get, "www.example.com") stub_post = stub_request(:post, "www.example.com") Net::HTTP.get('www.example.com', '/') assert_requested(stub_get) assert_not_requested(stub_post) Thanks to [Nicolas Fouché](https://github.com/nfo) * `WebMock.disable_net_connect!` accepts `RegExp` as `:allow` parameter Thanks to [Frank Schumacher](https://github.com/thenoseman) * Ensure multiple values for the same header can be recorded and played back Thanks to [Myron Marston](https://github.com/myronmarston) * Updated dependency on Addressable to version >= 2.2.7 to handle nested hash query values. I.e. `?one[two][three][]=four&one[two][three][]=five` * Fixed compatibility with Curb >= 0.7.16 This breaks compatibility with Curb < 0.7.16 * Fix #to_rack to handle non-array response bodies. Thanks to [Tammer Saleh](https://github.com/tsaleh) * Added `read_timeout` accessor to StubSocket which fixes compatibility with aws-sdk Thanks to [Lin Jen-Shin](https://github.com/godfat) * Fix warning "instance variable @query_params not initialized" Thanks to [Joe Van Dyk](https://github.com/joevandyk) * Using bytesize of message instead of its length for content-length header in em-http-request adapter. This fixes a problem with messages getting truncated in Ruby >= 1.9 Thanks to [Mark Abramov](https://github.com/markiz) * Fixed problem with body params being matched even if params were different. Thanks to [Evgeniy Dolzhenko](https://github.com/dolzenko) for reporting this issue. ## 1.7.10 * Yanked 1.7.9 and rebuilt gem on 1.8.7 to deal with syck/psych incompatibilties in gemspec. ## 1.7.9 * Fixed support for native Typhoeus timeouts. Thanks to [Albert Llop](https://github.com/mrsimo) * Fixed problem with WebMock and RSpec compatibility on TeamCity servers. See [this article](http://www.coding4streetcred.com/blog/post/Issue-RubyMine-31-Webmock-162-and-%E2%80%9CSpecconfigure%E2%80%9D-curse.aspx) for more details. Thanks to [Christopher Pickslay](https://github.com/chrispix) from [Two Bit Labs](https://github.com/twobitlabs) ## 1.7.8 * Fix each adapter so that it calls a `stub.with` block only once per request. Previously, the block would be called two or three times per request [Myron Marston](https://github.com/myronmarston). ## 1.7.7 - RuPy 2011 release * Passing response object to a block passed to `HTTPClient#do_get_block`. This fixes `HTTPClient.get_content` failures. [issue 130](https://github.com/bblimke/webmock/pull/130) Thanks to [Chris McGrath](https://github.com/chrismcg) * Cleaned up ruby warnings when running WebMock code with `-w`. Thanks to [Stephen Celis](https://github.com/stephencelis) * Curb adapter now correctly calls on_failure for 4xx response codes. Thanks to [Eugene Pimenov](https://github.com/libc) ## 1.7.6 * Support for the HTTPClient's request_filter feature Thanks to [Roman Shterenzon](https://github.com/romanbsd) ## 1.7.5 * Added support for Patron 0.4.15. This change is not backward compatible so please upgrade Patron to version >= 0.4.15 if you want to use it with WebMock. Thanks to [Andreas Garnæs](https://github.com/andreas) ## 1.7.4 * Added support for matching EM-HTTP-Request requests with body declared as a Hash Thanks to [David Yeu](https://github.com/daveyeu) ## 1.7.3 * Added `Get`, `Post`, `Delete`, `Put`, `Head`, `Option` constants to replaced `Net::HTTP` to make it possible to marshal objects with these constants assigned to properties. This fixed problem with `tvdb_party` gem which serializes HTTParty responses. Thanks to [Klaus Hartl](https://github.com/carhartl) for reporting this issue. ## 1.7.2 * Redefined `const_get` and `constants` methods on the replaced `Net::HTTP` to return same values as original `Net::HTTP` ## 1.7.1 * Redefined `const_defined?` on the replaced `Net::HTTP` so that it returns true if constant is defined on the original `Net::HTTP`. This fixes problems with `"Net::HTTP::Get".constantize`. Thanks to [Cássio Marques](https://github.com/cassiomarques) for reporting the issue and to [Myron Marston](https://github.com/myronmarston) for help with the solution. ## 1.7.0 * Fixed Net::HTTP adapter to not break normal Net::HTTP behaviour when network connections are allowed. This fixes **selenium-webdriver compatibility**!!! * Added support for EM-HTTP-Request 1.0.x and EM-Synchrony. Thanks to [Steve Hull](https://github.com/sdhull) * Added support for setting expectations to on a stub itself i.e. stub = stub_request(:get, "www.example.com") # ... make requests ... stub.should have_been_requested Thanks to [Aidan Feldman](https://github.com/afeld) * Minitest support! Thanks to [Peter Higgins](https://github.com/phiggins) * Added support for Typhoeus::Hydra * Added support for `Curb::Easy#http_post` and `Curb::Easy#http_post` with multiple arguments. Thanks to [Salvador Fuentes Jr](https://github.com/fuentesjr) and [Alex Rothenberg](https://github.com/alexrothenberg) * Rack support. Requests can be stubbed to respond with a Rack app i.e. class MyRackApp def self.call(env) [200, {}, ["Hello"]] end end stub_request(:get, "www.example.com").to_rack(MyRackApp) RestClient.get("www.example.com") # ===> "Hello" Thanks to [Jay Adkisson](https://github.com/jayferd) * Added support for selective disabling and enabling of http lib adapters WebMock.disable! #disable WebMock (all adapters) WebMock.disable!(:except => [:net_http]) #disable WebMock for all libs except Net::HTTP WebMock.enable! #enable WebMock (all adapters) WebMock.enable!(:except => [:patron]) #enable WebMock for all libs except Patron * The error message on an unstubbed request shows a code snippet with body as a hash when it was in url encoded form. > RestClient.post('www.example.com', "data[a]=1&data[b]=2", :content_type => 'application/x-www-form-urlencoded') WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled.... You can stub this request with the following snippet: stub_request(:post, "http://www.example.com/"). with(:body => {"data"=>{"a"=>"1", "b"=>"2"}}, :headers => { 'Content-Type'=>'application/x-www-form-urlencoded' }). to_return(:status => 200, :body => "", :headers => {}) Thanks to [Alex Rothenberg](https://github.com/alexrothenberg) * The error message on an unstubbed request shows currently registered request stubs. > stub_request(:get, "www.example.net") > stub_request(:get, "www.example.org") > RestClient.get("www.example.com") WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled.... You can stub this request with the following snippet: stub_request(:get, "http://www.example.com/"). to_return(:status => 200, :body => "", :headers => {}) registered request stubs: stub_request(:get, "http://www.example.net/") stub_request(:get, "http://www.example.org/") Thanks to [Lin Jen-Shin](https://github.com/godfat) for suggesting this feature. * Fixed problem with matching requests with json body, when json strings have date format. Thanks to [Joakim Ekberg](https://github.com/kalasjocke) for reporting this issue. * WebMock now attempts to require each http library before monkey patching it. This is to avoid problem when http library is required after WebMock is required. Thanks to [Myron Marston](https://github.com/myronmarston) for suggesting this change. * External requests can be disabled while allowing selected ports on selected hosts WebMock.disable_net_connect!(:allow => "www.example.com:8080") RestClient.get("www.example.com:80") # ===> Failure RestClient.get("www.example.com:8080") # ===> Allowed. Thanks to [Zach Dennis](https://github.com/zdennis) * Fixed syntax error in README examples, showing the ways of setting request expectations. Thanks to [Nikita Fedyashev](https://github.com/nfedyashev) **Many thanks to WebMock co-maintainer [James Conroy-Finn](https://github.com/jcf) who did a great job maintaining WebMock on his own for the last couple of months.** ## 1.6.4 This is a quick slip release to regenerate the gemspec. Apparently jeweler inserts dependencies twice if you use the `gemspec` method in your Gemfile and declare gem dependencies in your gemspec. https://github.com/technicalpickles/jeweler/issues/154 josevalim: > This just bit me. I just released a gem with the wrong dependencies > because I have updated jeweler. This should have been opt-in, > otherwise a bunch of people using jeweler are going to release gems > with the wrong dependencies because you are automatically importing > from the Gemfile. ## 1.6.3 * Update the dependency on addressable to get around an issue in v2.2.5. Thanks to [Peter Higgins](https://github.com/phiggins). * Add support for matching parameter values using a regular expression as well as a string. Thanks to [Oleg M Prozorov](https://github.com/oleg). * Fix integration with httpclient as the internal API has changed. Thanks to [Frank Prößdorf](https://github.com/endor). * Ensure Curl::Easy#content_type is always set. Thanks to [Peter Higgins](https://github.com/phiggins). * Fix bug with em-http-request adapter stubbing responses that have a chunked transfer encoding. Thanks to [Myron Marston](https://github.com/myronmarston). * Fix a load of spec failures with Patron, httpclient, and specs that depended on the behaviour of example.com. Thanks to [Alex Grigorovich](https://github.com/grig). ## 1.6.2 * Em-http-request adapter sets `last_effective_url` property. Thanks to [Sam Stokes](https://github.com/samstokes). * Curb adapter supports `Curb::Easy#http_post` and `Curb::Easy#http_put` without arguments (by setting `post_body` or `put_data` beforehand). Thanks to [Eugene Bolshakov](https://github.com/eugenebolshakov) ## 1.6.1 * Fixed issue with `webmock/rspec` which didn't load correctly if `rspec/core` was already required but `rspec/expectations` not. ## 1.6.0 * Simplified integration with Test::Unit, RSpec and Cucumber. Now only a single file has to be required i.e. require 'webmock/test_unit' require 'webmock/rspec' require 'webmock/cucumber' * The error message on unstubbed request now contains code snippet which can be used to stub this request. Thanks to Martyn Loughran for suggesting this feature. * The expectation failure message now contains a list of made requests. Thanks to Martyn Loughran for suggesting this feature. * Added `WebMock.print_executed_requests` method which can be useful to find out what requests were made until a given point. * em-http-request adapter is now activated by replacing EventMachine::HttpRequest constant, instead of monkeypatching the original class. This technique is borrowed from em-http-request native mocking module. It allows switching WebMock adapter on an off, and using it interchangeably with em-http-request native mocking i.e: EventMachine::WebMockHttpRequest.activate! EventMachine::WebMockHttpRequest.deactivate! Thanks to Martyn Loughran for suggesting this feature. * `WebMock.reset_webmock` is deprecated in favour of new `WebMock.reset!` * Fixed integration with Cucumber. Previously documented example didn't work with new versions of Cucumber. * Fixed stubbing requests with body declared as a hash. Thanks to Erik Michaels-Ober for reporting the issue. * Fixed issue with em-http-request adapter which didn't work when :query option value was passed as a string, not a hash. Thanks to Chee Yeo for reporting the issue. * Fixed problem with assert_requested which didn't work if used outside rspec or test/unit * Removed dependency on json gem ## 1.5.0 * Support for dynamically evaluated raw responses recorded with `curl -is`
i.e. `curl -is www.example.com > /tmp/www.example.com.txt` stub_request(:get, "www.example.com").to_return(lambda { |request| File.new("/tmp/#{request.uri.host.to_s}.txt" })) * `:net_http_connect_on_start` option can be passed to `WebMock.allow_net_connect!` and `WebMock.disable_net_connect!` methods, i.e. WebMock.allow_net_connect!(:net_http_connect_on_start => true) This forces WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`. Check 'Connecting on Net::HTTP.start' in README for more information. Thanks to Alastair Brunton for reporting the issue and for fix suggestions. * Fixed an issue where Patron spec tried to remove system temporary directory. Thanks to Hans de Graaff * WebMock specs now use RSpec 2 * `rake spec NO_CONNECTION=true` can now be used to only run WebMock specs which do not make real network connections ## 1.4.0 * Curb support!!! Thanks to the awesome work of Pete Higgins! * `include WebMock` is now deprecated to avoid method and constant name conflicts. Please `include WebMock::API` instead. * `WebMock::API#request` is renamed to `WebMock::API#a_request` to prevent method name conflicts with i.e. Rails controller specs. WebMock.request is still available. * Deprecated `WebMock#request`, `WebMock#allow_net_connect!`, `WebMock#net_connect_allowed?`, `WebMock#registered_request?`, `WebMock#reset_callbacks`, `WebMock#after_request` instance methods. These methods are still available, but only as WebMock class methods. * Removed `WebMock.response_for_request` and `WebMock.assertion_failure` which were only used internally and were not documented. * :allow_localhost => true' now permits 0.0.0.0 in addition to 127.0.0.1 and 'localhost'. Thanks to Myron Marston and Mike Gehard for suggesting this. * Fixed issue with both RSpec 1.x and 2.x being available. WebMock now tries to use already loaded version of RSpec (1.x or 2.x). Previously it was loading RSpec 2.0 if available, even if RSpec 1.3 was already loaded. Thanks to Hans de Graaff for reporting this. * Changed runtime dependency on Addressable version 2.2.2 which fixes handling of percent-escaped '+' ## 1.3.5 * External requests can be disabled while allowing selected hosts. Thanks to Charles Li and Ryan Bigg This feature was available before only for localhost with `:allow_localhost => true` WebMock.disable_net_connect!(:allow => "www.example.org") Net::HTTP.get('www.something.com', '/') # ===> Failure Net::HTTP.get('www.example.org', '/') # ===> Allowed. * Fixed Net::HTTP adapter so that it preserves the original behavior of Net::HTTP. When making a request with a block that calls #read_body on the request, Net::HTTP causes the body to be set to a Net::ReadAdapter, but WebMock was causing the body to be set to a string. ## 1.3.4 * Fixed Net::HTTP adapter to handle cases where a block with `read_body` call is passed to `request`. This fixes compatibility with `open-uri`. Thanks to Mark Evans for reporting the issue. ## 1.3.3 * Fixed handling of multiple values for the same response header for Net::HTTP. Thanks to Myron Marston for reporting the issue. ## 1.3.2 * Fixed compatibility with EM-HTTP-Request >= 0.2.9. Thanks to Myron Marston for reporting the issue. ## 1.3.1 * The less hacky way to get the stream behaviour working for em-http-request. Thanks to Martyn Loughran * Fixed issues where Net::HTTP was not accepting valid nil response body. Thanks to Muness Alrubaie ## 1.3.0 * Added support for [em-http-request](http://github.com/igrigorik/em-http-request) * Matching query params using a hash stub_http_request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}) RestClient.get("http://www.example.com/?a[]=b&a[]=c") # ===> Success request(:get, "www.example.com").with(:query => {"a" => ["b", "c"]}).should have_been_made # ===> Success * Matching request body against a hash. Body can be URL-Encoded, JSON or XML. (Thanks to Steve Tooke for the idea and a solution for url-encoded bodies) stub_http_request(:post, "www.example.com"). with(:body => {:data => {:a => '1', :b => 'five'}}) RestClient.post('www.example.com', "data[a]=1&data[b]=five", :content_type => 'application/x-www-form-urlencoded') # ===> Success RestClient.post('www.example.com', '{"data":{"a":"1","b":"five"}}', :content_type => 'application/json') # ===> Success RestClient.post('www.example.com', '', :content_type => 'application/xml' ) # ===> Success request(:post, "www.example.com"). with(:body => {:data => {:a => '1', :b => 'five'}}, :headers => 'Content-Type' => 'application/json').should have_been_made # ===> Success * Request callbacks (Thanks to Myron Marston for all suggestions) WebMock can now invoke callbacks for stubbed or real requests: WebMock.after_request do |request_signature, response| puts "Request #{request_signature} was made and #{response} was returned" end invoke callbacks for real requests only and except requests made with Patron client WebMock.after_request(:except => [:patron], :real_requests_only => true) do |request_signature, response| puts "Request #{request_signature} was made and #{response} was returned" end * `to_raise()` now accepts an exception instance or a string as argument in addition to an exception class stub_request(:any, 'www.example.net').to_raise(StandardError.new("some error")) stub_request(:any, 'www.example.net').to_raise("some error") * Matching requests based on a URI is 30% faster * Fixed constant namespace issues in HTTPClient adapter. Thanks to Nathaniel Bibler for submitting a patch. ## 1.2.2 * Fixed problem where ArgumentError was raised if query params were made up of an array e.g. data[]=a&data[]=b. Thanks to Steve Tooke ## 1.2.1 * Changed license from GPL to MIT * Fixed gemspec file. Thanks to Razic ## 1.2.0 * RSpec 2 compatibility. Thanks to Sam Phillips! * :allow_localhost => true' now permits 127.0.0.1 as well as 'localhost'. Thanks to Mack Earnhardt * Request URI matching in now 2x faster! ## 1.1.0 * [VCR](http://github.com/myronmarston/vcr/) compatibility. Many thanks to Myron Marston for all suggestions. * Support for stubbing requests and returning responses with multiple headers with the same name. i.e multiple Accept headers. stub_http_request(:get, 'www.example.com'). with(:headers => {'Accept' => ['image/png', 'image/jpeg']}). to_return(:body => 'abc') RestClient.get('www.example.com', {"Accept" => ['image/png', 'image/jpeg']}) # ===> "abc\n" * When real net connections are disabled and unstubbed request is made, WebMock throws WebMock::NetConnectNotAllowedError instead of assertion error or StandardError. * Added WebMock.version() ## 1.0.0 * Added support for [Patron](http://toland.github.com/patron/) * Responses dynamically evaluated from block (idea and implementation by Tom Ward) stub_request(:any, 'www.example.net'). to_return { |request| {:body => request.body} } RestClient.post('www.example.net', 'abc') # ===> "abc\n" * Responses dynamically evaluated from lambda (idea and implementation by Tom Ward) stub_request(:any, 'www.example.net'). to_return(lambda { |request| {:body => request.body} }) RestClient.post('www.example.net', 'abc') # ===> "abc\n" * Response with custom status message stub_request(:any, "www.example.com").to_return(:status => [500, "Internal Server Error"]) req = Net::HTTP::Get.new("/") Net::HTTP.start("www.example.com") { |http| http.request(req) }.message # ===> "Internal Server Error" * Raising timeout errors (suggested by Jeffrey Jones) (compatibility with Ruby 1.8.6 by Mack Earnhardt) stub_request(:any, 'www.example.net').to_timeout RestClient.post('www.example.net', 'abc') # ===> RestClient::RequestTimeout * External requests can be disabled while allowing localhost (idea and implementation by Mack Earnhardt) WebMock.disable_net_connect!(:allow_localhost => true) Net::HTTP.get('www.something.com', '/') # ===> Failure Net::HTTP.get('localhost:9887', '/') # ===> Allowed. Perhaps to Selenium? ### Bug fixes * Fixed issue where Net::HTTP adapter didn't work for requests with body responding to read (reported by Tekin Suleyman) * Fixed issue where request stub with headers declared as nil was matching requests with non empty headers ## 0.9.1 * Fixed issue where response status code was not read from raw (curl -is) responses ## 0.9.0 * Matching requests against provided block (by Sergio Gil) stub_request(:post, "www.example.com").with { |request| request.body == "abc" }.to_return(:body => "def") RestClient.post('www.example.com', 'abc') # ===> "def\n" request(:post, "www.example.com").with { |req| req.body == "abc" }.should have_been_made #or assert_requested(:post, "www.example.com") { |req| req.body == "abc" } * Matching request body against regular expressions (suggested by Ben Pickles) stub_request(:post, "www.example.com").with(:body => /^.*world$/).to_return(:body => "abc") RestClient.post('www.example.com', 'hello world') # ===> "abc\n" * Matching request headers against regular expressions (suggested by Ben Pickles) stub_request(:post, "www.example.com").with(:headers => {"Content-Type" => /image\/.+/}).to_return(:body => "abc") RestClient.post('www.example.com', '', {'Content-Type' => 'image/png'}) # ===> "abc\n" * Replaying raw responses recorded with `curl -is` `curl -is www.example.com > /tmp/example_curl_-is_output.txt` raw_response_file = File.new("/tmp/example_curl_-is_output.txt") from file stub_request(:get, "www.example.com").to_return(raw_response_file) or string stub_request(:get, "www.example.com").to_return(raw_response_file.read) * Multiple responses for repeated requests stub_request(:get, "www.example.com").to_return({:body => "abc"}, {:body => "def"}) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" * Multiple responses using chained `to_return()` or `to_raise()` declarations stub_request(:get, "www.example.com"). to_return({:body => "abc"}).then. #then() just is a syntactic sugar to_return({:body => "def"}).then. to_raise(MyException) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" Net::HTTP.get('www.example.com', '/') # ===> MyException raised * Specifying number of times given response should be returned stub_request(:get, "www.example.com"). to_return({:body => "abc"}).times(2).then. to_return({:body => "def"}) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" * Added support for `Net::HTTP::Post#body_stream` This fixes compatibility with new versions of RestClient * WebMock doesn't suppress default request headers added by http clients anymore. i.e. Net::HTTP adds `'Accept'=>'*/*'` to all requests by default ## 0.8.2 * Fixed issue where WebMock was not closing IO object passed as response body after reading it. * Ruby 1.9.2 compat: Use `File#expand_path` for require path because "." is not be included in LOAD_PATH since Ruby 1.9.2 ## 0.8.1 * Fixed HTTPClient adapter compatibility with Ruby 1.8.6 (reported by Piotr Usewicz) * Net:HTTP adapter now handles request body assigned as Net::HTTP::Post#body attribute (fixed by Mack Earnhardt) * Fixed issue where requests were not matching stubs with Accept header set.(reported by Piotr Usewicz) * Fixed compatibility with Ruby 1.9.1, 1.9.2 and JRuby 1.3.1 (reported by Diego E. “Flameeyes” Pettenò) * Fixed issue with response body declared as IO object and multiple requests (reported by Niels Meersschaert) * Fixed "undefined method `assertion_failure'" error (reported by Nick Plante) ## 0.8.0 * Support for HTTPClient (sync and async requests) * Support for dynamic responses. Response body and headers can be now declared as lambda. (Thanks to Ivan Vega ( @ivanyv ) for suggesting this feature) * Support for stubbing and expecting requests with empty body * Executing non-stubbed request leads to failed expectation instead of error ### Bug fixes * Basic authentication now works correctly * Fixed problem where WebMock didn't call a block with the response when block was provided * Fixed problem where uris with single slash were not matching uris without path provided ## 0.7.3 * Clarified documentation * Fixed some issues with loading of Webmock classes * Test::Unit and RSpec adapters have to be required separately ## 0.7.2 * Added support for matching escaped and non escaped URLs webmock-3.18.1/.gitignore0000644000004100000410000000043414333126774015266 0ustar www-datawww-data## MAC OS .DS_Store ## TEXTMATE *.tmproj tmtags ## EMACS *~ \#* .\#* ## VIM .*.sw[a-z] ## RubyMine and related .idea ## PROJECT::GENERAL coverage rdoc pkg ## PROJECT::SPECIFIC *.gem .bundle Gemfile.lock gemfiles/*.gemfile.lock pkg/* tmp/* *.rbc *.rbx .ruby-gemset .ruby-version webmock-3.18.1/LICENSE0000644000004100000410000000204714333126774014305 0ustar www-datawww-dataCopyright (c) 2009-2010 Bartosz Blimke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. webmock-3.18.1/.gemtest0000644000004100000410000000000014333126774014734 0ustar www-datawww-datawebmock-3.18.1/Rakefile0000644000004100000410000000175414333126774014751 0ustar www-datawww-datarequire 'bundler' Bundler::GemHelper.install_tasks require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = %w[ --force-color --format progress --require ./spec/spec_helper.rb ] t.pattern = 'spec/**/*_spec.rb' end RSpec::Core::RakeTask.new(:spec_http_without_webmock) do |t| t.rspec_opts = %w[ --force-color --format progress --require ./spec/acceptance/net_http/real_net_http_spec.rb ] t.pattern = 'spec/acceptance/net_http/real_net_http_spec.rb' end require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb") test.options = "--use-color" test.verbose = false test.warning = false end Rake::TestTask.new(:minitest) do |test| test.test_files = FileList["minitest/**/*.rb"].exclude("test/test_helper.rb") test.options = "--pride" test.verbose = false test.warning = false end task default: [:spec, :spec_http_without_webmock, :test, :minitest] webmock-3.18.1/lib/0000755000004100000410000000000014333126774014043 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/0000755000004100000410000000000014333126774015472 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/version.rb0000644000004100000410000000011414333126774017500 0ustar www-datawww-datamodule WebMock VERSION = '3.18.1' unless defined?(::WebMock::VERSION) end webmock-3.18.1/lib/webmock/deprecation.rb0000644000004100000410000000024314333126774020313 0ustar www-datawww-datamodule WebMock class Deprecation class << self def warning(message) warn "WebMock deprecation warning: #{message}" end end end end webmock-3.18.1/lib/webmock/assertion_failure.rb0000644000004100000410000000033214333126774021533 0ustar www-datawww-datamodule WebMock class AssertionFailure @error_class = RuntimeError class << self attr_accessor :error_class def failure(message) raise @error_class.new(message) end end end end webmock-3.18.1/lib/webmock/stub_request_snippet.rb0000644000004100000410000000216114333126774022306 0ustar www-datawww-datamodule WebMock class StubRequestSnippet def initialize(request_stub) @request_stub = request_stub end def body_pattern request_pattern.body_pattern end def to_s(with_response = true) request_pattern = @request_stub.request_pattern string = "stub_request(:#{request_pattern.method_pattern.to_s},".dup string << " \"#{request_pattern.uri_pattern.to_s}\")" with = "".dup if (request_pattern.body_pattern) with << "\n body: #{request_pattern.body_pattern.to_s}" end if (request_pattern.headers_pattern) with << "," unless with.empty? with << "\n headers: #{request_pattern.headers_pattern.pp_to_s}" end string << ".\n with(#{with})" unless with.empty? if with_response if request_pattern.headers_pattern && request_pattern.headers_pattern.matches?({ 'Accept' => "application/json" }) string << ".\n to_return(status: 200, body: \"{}\", headers: {})" else string << ".\n to_return(status: 200, body: \"\", headers: {})" end end string end end end webmock-3.18.1/lib/webmock/request_execution_verifier.rb0000644000004100000410000000440114333126774023464 0ustar www-datawww-datamodule WebMock class RequestExecutionVerifier attr_accessor :request_pattern, :expected_times_executed, :times_executed, :at_least_times_executed, :at_most_times_executed def initialize(request_pattern = nil, expected_times_executed = nil, at_least_times_executed = nil, at_most_times_executed = nil) @request_pattern = request_pattern @expected_times_executed = expected_times_executed @at_least_times_executed = at_least_times_executed @at_most_times_executed = at_most_times_executed end def matches? @times_executed = RequestRegistry.instance.times_executed(@request_pattern) if @at_least_times_executed @times_executed >= @at_least_times_executed elsif @at_most_times_executed @times_executed <= @at_most_times_executed else @times_executed == (@expected_times_executed || 1) end end def does_not_match? @times_executed = RequestRegistry.instance.times_executed(@request_pattern) if @expected_times_executed @times_executed != @expected_times_executed else @times_executed == 0 end end def description "request #{request_pattern} #{quantity_phrase.strip}" end def failure_message failure_message_phrase(false) end def failure_message_when_negated failure_message_phrase(true) end def self.executed_requests_message "\n\nThe following requests were made:\n\n#{RequestRegistry.instance}\n" + "="*60 end private def failure_message_phrase(is_negated=false) negation = is_negated ? "was not" : "was" "The request #{request_pattern} #{negation} expected to execute #{quantity_phrase(is_negated)}but it executed #{times(times_executed)}" + self.class.executed_requests_message end def quantity_phrase(is_negated=false) if @at_least_times_executed "at least #{times(@at_least_times_executed)} " elsif @at_most_times_executed "at most #{times(@at_most_times_executed)} " elsif @expected_times_executed "#{times(@expected_times_executed)} " else is_negated ? "" : "#{times(1)} " end end def times(times) "#{times} time#{ (times == 1) ? '' : 's'}" end end end webmock-3.18.1/lib/webmock/stub_registry.rb0000644000004100000410000000440714333126774020731 0ustar www-datawww-datamodule WebMock class StubRegistry include Singleton attr_accessor :request_stubs def initialize reset! end def global_stubs @global_stubs ||= Hash.new { |h, k| h[k] = [] } end def reset! self.request_stubs = [] end def register_global_stub(order = :before_local_stubs, &block) unless %i[before_local_stubs after_local_stubs].include?(order) raise ArgumentError.new("Wrong order. Use :before_local_stubs or :after_local_stubs") end # This hash contains the responses returned by the block, # keyed by the exact request (using the object_id). # That way, there's no race condition in case #to_return # doesn't run immediately after stub.with. responses = {} response_lock = Mutex.new stub = ::WebMock::RequestStub.new(:any, ->(uri) { true }).with { |request| update_response = -> { responses[request.object_id] = yield(request) } # The block can recurse, so only lock if we don't already own it if response_lock.owned? update_response.call else response_lock.synchronize(&update_response) end }.to_return(lambda { |request| response_lock.synchronize { responses.delete(request.object_id) } }) global_stubs[order].push stub end def register_request_stub(stub) request_stubs.insert(0, stub) stub end def remove_request_stub(stub) if not request_stubs.delete(stub) raise "Request stub \n\n #{stub.to_s} \n\n is not registered." end end def registered_request?(request_signature) request_stub_for(request_signature) end def response_for_request(request_signature) stub = request_stub_for(request_signature) stub ? evaluate_response_for_request(stub.response, request_signature) : nil end private def request_stub_for(request_signature) (global_stubs[:before_local_stubs] + request_stubs + global_stubs[:after_local_stubs]) .detect { |registered_request_stub| registered_request_stub.request_pattern.matches?(request_signature) } end def evaluate_response_for_request(response, request_signature) response.dup.evaluate(request_signature) end end end webmock-3.18.1/lib/webmock/matchers/0000755000004100000410000000000014333126774017300 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/matchers/hash_argument_matcher.rb0000644000004100000410000000107714333126774024162 0ustar www-datawww-datamodule WebMock module Matchers # Base class for Hash matchers # https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb class HashArgumentMatcher def initialize(expected) @expected = Hash[WebMock::Util::HashKeysStringifier.stringify_keys!(expected, deep: true).sort] end def ==(_actual, &block) @expected.all?(&block) rescue NoMethodError false end def self.from_rspec_matcher(matcher) new(matcher.instance_variable_get(:@expected)) end end end end webmock-3.18.1/lib/webmock/matchers/hash_excluding_matcher.rb0000644000004100000410000000070614333126774024320 0ustar www-datawww-datamodule WebMock module Matchers # this is a based on RSpec::Mocks::ArgumentMatchers::HashExcludingMatcher # https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb class HashExcludingMatcher < HashArgumentMatcher def ==(actual) super { |key, value| !actual.key?(key) || value != actual[key] } end def inspect "hash_excluding(#{@expected.inspect})" end end end end webmock-3.18.1/lib/webmock/matchers/hash_including_matcher.rb0000644000004100000410000000075714333126774024320 0ustar www-datawww-datamodule WebMock module Matchers # this is a based on RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher # https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/argument_matchers.rb class HashIncludingMatcher < HashArgumentMatcher def ==(actual) super { |key, value| actual.key?(key) && value === actual[key] } rescue NoMethodError false end def inspect "hash_including(#{@expected.inspect})" end end end end webmock-3.18.1/lib/webmock/matchers/any_arg_matcher.rb0000644000004100000410000000034514333126774022752 0ustar www-datawww-datamodule WebMock module Matchers # this is a based on RSpec::Mocks::ArgumentMatchers::AnyArgMatcher class AnyArgMatcher def initialize(ignore) end def ==(other) true end end end end webmock-3.18.1/lib/webmock/responses_sequence.rb0000644000004100000410000000124314333126774021730 0ustar www-datawww-datamodule WebMock class ResponsesSequence attr_accessor :times_to_repeat def initialize(responses) @times_to_repeat = 1 @responses = responses @current_position = 0 end def end? @times_to_repeat == 0 end def next_response if @times_to_repeat > 0 response = @responses[@current_position] increase_position response else @responses.last end end private def increase_position if @current_position == (@responses.length - 1) @current_position = 0 @times_to_repeat -= 1 else @current_position += 1 end end end end webmock-3.18.1/lib/webmock/errors.rb0000644000004100000410000000073214333126774017335 0ustar www-datawww-datamodule WebMock class NetConnectNotAllowedError < Exception def initialize(request_signature) request_signature_snippet = RequestSignatureSnippet.new(request_signature) text = [ "Real HTTP connections are disabled. Unregistered request: #{request_signature}", request_signature_snippet.stubbing_instructions, request_signature_snippet.request_stubs, "="*60 ].compact.join("\n\n") super(text) end end end webmock-3.18.1/lib/webmock/request_signature_snippet.rb0000644000004100000410000000312014333126774023326 0ustar www-datawww-datarequire "pp" module WebMock class RequestSignatureSnippet attr_reader :request_signature, :request_stub def initialize(request_signature) @request_signature = request_signature @request_stub = RequestStub.from_request_signature(request_signature) end def stubbing_instructions return unless WebMock.show_stubbing_instructions? "You can stub this request with the following snippet:\n\n" + WebMock::StubRequestSnippet.new(request_stub).to_s end def request_stubs return if WebMock::StubRegistry.instance.request_stubs.empty? text = "registered request stubs:\n".dup WebMock::StubRegistry.instance.request_stubs.each do |stub| text << "\n#{WebMock::StubRequestSnippet.new(stub).to_s(false)}" add_body_diff(stub, text) if WebMock.show_body_diff? end text end private def add_body_diff(stub, text) body_diff_str = signature_stub_body_diff(stub) text << "\n\n#{body_diff_str}" unless body_diff_str.empty? end def signature_stub_body_diff(stub) diff = RequestBodyDiff.new(request_signature, stub).body_diff diff.empty? ? "" : "Body diff:\n #{pretty_print_to_string(diff)}" end def request_params @request_params ||= if request_signature.json_headers? JSON.parse(request_signature.body) else "" end end def pretty_print_to_string(string_to_print) StringIO.open("".dup) do |stream| PP.pp(string_to_print, stream) stream.rewind stream.read end end end end webmock-3.18.1/lib/webmock/util/0000755000004100000410000000000014333126774016447 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/util/version_checker.rb0000644000004100000410000000761514333126774022156 0ustar www-datawww-data# This code was created based on https://github.com/myronmarston/vcr/blob/master/lib/vcr/util/version_checker.rb # Thanks to @myronmarston # Copyright (c) 2010-2012 Myron Marston # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module WebMock class VersionChecker def initialize(library_name, library_version, min_patch_level, max_minor_version = nil, unsupported_versions = []) @library_name, @library_version = library_name, library_version @min_patch_level, @max_minor_version = min_patch_level, max_minor_version @unsupported_versions = unsupported_versions || [] @major, @minor, @patch = parse_version(library_version) @min_major, @min_minor, @min_patch = parse_version(min_patch_level) if max_minor_version @max_major, @max_minor = parse_version(max_minor_version) else @max_major, @max_minor = nil, nil end @comparison_result = compare_version end def check_version! warn_about_too_low if too_low? warn_about_too_high if too_high? warn_about_unsupported_version if unsupported_version? end private def too_low? @comparison_result == :too_low end def too_high? @comparison_result == :too_high end def unsupported_version? @unsupported_versions.include?(@library_version) end def warn_about_too_low warn_in_red "You are using #{@library_name} #{@library_version}. " + "WebMock supports version #{version_requirement}." end def warn_about_too_high warn_in_red "You are using #{@library_name} #{@library_version}. " + "WebMock is known to work with #{@library_name} #{version_requirement}. " + "It may not work with this version." end def warn_about_unsupported_version warn_in_red "You are using #{@library_name} #{@library_version}. " + "WebMock does not support this version. " + "WebMock supports versions #{version_requirement}." end def warn_in_red(text) Kernel.warn colorize(text, "\e[31m") end def compare_version case when @major < @min_major then :too_low when @max_major && @major > @max_major then :too_high when @major > @min_major then :ok when @minor < @min_minor then :too_low when @max_minor && @minor > @max_minor then :too_high when @minor > @min_minor then :ok when @patch < @min_patch then :too_low end end def version_requirement req = ">= #{@min_patch_level}" req += ", < #{@max_major}.#{@max_minor + 1}" if @max_minor req += ", except versions #{@unsupported_versions.join(',')}" unless @unsupported_versions.empty? req end def parse_version(version) version.split('.').map { |v| v.to_i } end def colorize(text, color_code) "#{color_code}#{text}\e[0m" end end end webmock-3.18.1/lib/webmock/util/uri.rb0000644000004100000410000000713714333126774017603 0ustar www-datawww-datamodule WebMock module Util class URI module CharacterClasses USERINFO = Addressable::URI::CharacterClasses::UNRESERVED + Addressable::URI::CharacterClasses::SUB_DELIMS + "\\:" end ADDRESSABLE_URIS = Hash.new do |hash, key| hash[key] = Addressable::URI.heuristic_parse(key) end NORMALIZED_URIS = Hash.new do |hash, uri| normalized_uri = WebMock::Util::URI.heuristic_parse(uri) if normalized_uri.query_values sorted_query_values = sort_query_values(WebMock::Util::QueryMapper.query_to_values(normalized_uri.query, notation: Config.instance.query_values_notation) || {}) normalized_uri.query = WebMock::Util::QueryMapper.values_to_query(sorted_query_values, notation: WebMock::Config.instance.query_values_notation) end normalized_uri = normalized_uri.normalize #normalize! is slower normalized_uri.query = normalized_uri.query.gsub("+", "%2B") if normalized_uri.query normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port hash[uri] = normalized_uri end def self.heuristic_parse(uri) ADDRESSABLE_URIS[uri].dup end def self.normalize_uri(uri) return uri if uri.is_a?(Regexp) uri = 'http://' + uri unless uri.match('^https?://') if uri.is_a?(String) NORMALIZED_URIS[uri].dup end def self.variations_of_uri_as_strings(uri_object, only_with_scheme: false) normalized_uri = normalize_uri(uri_object.dup).freeze uris = [ normalized_uri ] if normalized_uri.path == '/' uris = uris_with_trailing_slash_and_without(uris) end if normalized_uri.port == Addressable::URI.port_mapping[normalized_uri.scheme] uris = uris_with_inferred_port_and_without(uris) end uris = uris_encoded_and_unencoded(uris) if normalized_uri.scheme == "http" && !only_with_scheme uris = uris_with_scheme_and_without(uris) end uris.map {|uri| uri.to_s.gsub(/^\/\//,'') }.uniq end def self.strip_default_port_from_uri_string(uri_string) case uri_string when %r{^http://} then uri_string.sub(%r{:80(/|$)}, '\1') when %r{^https://} then uri_string.sub(%r{:443(/|$)}, '\1') else uri_string end end def self.encode_unsafe_chars_in_userinfo(userinfo) Addressable::URI.encode_component(userinfo, WebMock::Util::URI::CharacterClasses::USERINFO) end def self.is_uri_localhost?(uri) uri.is_a?(Addressable::URI) && %w(localhost 127.0.0.1 0.0.0.0).include?(uri.host) end private def self.sort_query_values(query_values) sorted_query_values = query_values.sort query_values.is_a?(Hash) ? Hash[*sorted_query_values.inject([]) { |values, pair| values + pair}] : sorted_query_values end def self.uris_with_inferred_port_and_without(uris) uris.map { |uri| [ uri, uri.omit(:port)] }.flatten end def self.uris_encoded_and_unencoded(uris) uris.map do |uri| [ uri.to_s.force_encoding(Encoding::ASCII_8BIT), Addressable::URI.unencode(uri, String).force_encoding(Encoding::ASCII_8BIT).freeze ] end.flatten end def self.uris_with_scheme_and_without(uris) uris.map { |uri| [ uri, uri.gsub(%r{^https?://},"").freeze ] }.flatten end def self.uris_with_trailing_slash_and_without(uris) uris.map { |uri| [ uri, uri.omit(:path).freeze ] }.flatten end end end end webmock-3.18.1/lib/webmock/util/values_stringifier.rb0000644000004100000410000000057214333126774022704 0ustar www-datawww-dataclass WebMock::Util::ValuesStringifier def self.stringify_values(value) case value when String, Numeric, TrueClass, FalseClass value.to_s when Hash Hash[ value.map do |k, v| [k, stringify_values(v)] end ] when Array value.map do |v| stringify_values(v) end else value end end end webmock-3.18.1/lib/webmock/util/hash_validator.rb0000644000004100000410000000076614333126774021775 0ustar www-datawww-datamodule WebMock class HashValidator def initialize(hash) @hash = hash end #This code is based on https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/keys.rb def validate_keys(*valid_keys) valid_keys.flatten! @hash.each_key do |k| unless valid_keys.include?(k) raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}") end end end end end webmock-3.18.1/lib/webmock/util/json.rb0000644000004100000410000000542114333126774017747 0ustar www-datawww-data# This is a copy of https://github.com/jnunemaker/crack/blob/master/lib/crack/json.rb # with date parsing removed # Copyright (c) 2004-2008 David Heinemeier Hansson # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module WebMock module Util class JSON class ParseError < StandardError; end def self.parse(json) yaml = unescape(convert_json_to_yaml(json)) YAML.load(yaml) rescue ArgumentError => e raise ParseError, "Invalid JSON string: #{yaml}, Error: #{e.inspect}" end protected def self.unescape(str) str.gsub(/\\u([0-9a-f]{4})/) { [$1.hex].pack("U") } end # Ensure that ":" and "," are always followed by a space def self.convert_json_to_yaml(json) #:nodoc: scanner, quoting, marks, times = StringScanner.new(json), false, [], [] while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/) case char = scanner[1] when '"', "'" if !quoting quoting = char elsif quoting == char quoting = false end when ":","," marks << scanner.pos - 1 unless quoting when "\\" scanner.skip(/\\/) end end if marks.empty? json.gsub(/\\\//, '/') else left_pos = [-1].push(*marks) right_pos = marks << json.bytesize output = [] left_pos.each_with_index do |left, i| if json.respond_to?(:byteslice) output << json.byteslice(left.succ..right_pos[i]) else output << json[left.succ..right_pos[i]] end end output = output * " " times.each { |i| output[i-1] = ' ' } output.gsub!(/\\\//, '/') output end end end end end webmock-3.18.1/lib/webmock/util/query_mapper.rb0000644000004100000410000002367414333126774021521 0ustar www-datawww-datamodule WebMock::Util class QueryMapper class << self #This class is based on Addressable::URI pre 2.3.0 ## # Converts the query component to a Hash value. # # @option [Symbol] notation # May be one of :flat, :dot, or # :subscript. The :dot notation is not # supported for assignment. Default value is :subscript. # # @return [Hash, Array] The query string parsed as a Hash or Array object. # # @example # WebMock::Util::QueryMapper.query_to_values("?one=1&two=2&three=3") # #=> {"one" => "1", "two" => "2", "three" => "3"} # WebMock::Util::QueryMapper("?one[two][three]=four").query_values # #=> {"one" => {"two" => {"three" => "four"}}} # WebMock::Util::QueryMapper.query_to_values("?one.two.three=four", # :notation => :dot # ) # #=> {"one" => {"two" => {"three" => "four"}}} # WebMock::Util::QueryMapper.query_to_values("?one[two][three]=four", # :notation => :flat # ) # #=> {"one[two][three]" => "four"} # WebMock::Util::QueryMapper.query_to_values("?one.two.three=four", # :notation => :flat # ) # #=> {"one.two.three" => "four"} # WebMock::Util::QueryMapper( # "?one[two][three][]=four&one[two][three][]=five" # ) # #=> {"one" => {"two" => {"three" => ["four", "five"]}}} # WebMock::Util::QueryMapper.query_to_values( # "?one=two&one=three").query_values(:notation => :flat_array) # #=> [['one', 'two'], ['one', 'three']] def query_to_values(query, options={}) return nil if query.nil? query = query.dup.force_encoding('utf-8') if query.respond_to?(:force_encoding) options[:notation] ||= :subscript if ![:flat, :dot, :subscript, :flat_array].include?(options[:notation]) raise ArgumentError, 'Invalid notation. Must be one of: ' + '[:flat, :dot, :subscript, :flat_array].' end empty_accumulator = :flat_array == options[:notation] ? [] : {} query_array = collect_query_parts(query) query_hash = collect_query_hash(query_array, empty_accumulator, options) normalize_query_hash(query_hash, empty_accumulator, options) end def normalize_query_hash(query_hash, empty_accumulator, options) query_hash.inject(empty_accumulator.dup) do |accumulator, (key, value)| if options[:notation] == :flat_array accumulator << [key, value] else accumulator[key] = value.kind_of?(Hash) ? dehash(value) : value end accumulator end end def collect_query_parts(query) query_parts = query.split('&').map do |pair| pair.split('=', 2) if pair && !pair.empty? end query_parts.compact end def collect_query_hash(query_array, empty_accumulator, options) query_array.compact.inject(empty_accumulator.dup) do |accumulator, (key, value)| value = if value.nil? nil else ::Addressable::URI.unencode_component(value.tr('+', ' ')) end key = Addressable::URI.unencode_component(key) key = key.dup.force_encoding(Encoding::ASCII_8BIT) if key.respond_to?(:force_encoding) self.__send__("fill_accumulator_for_#{options[:notation]}", accumulator, key, value) accumulator end end def fill_accumulator_for_flat(accumulator, key, value) if accumulator[key] raise ArgumentError, "Key was repeated: #{key.inspect}" end accumulator[key] = value end def fill_accumulator_for_flat_array(accumulator, key, value) accumulator << [key, value] end def fill_accumulator_for_dot(accumulator, key, value) array_value = false subkeys = key.split(".") current_hash = accumulator subkeys[0..-2].each do |subkey| current_hash[subkey] = {} unless current_hash[subkey] current_hash = current_hash[subkey] end if array_value if current_hash[subkeys.last] && !current_hash[subkeys.last].is_a?(Array) current_hash[subkeys.last] = [current_hash[subkeys.last]] end current_hash[subkeys.last] = [] unless current_hash[subkeys.last] current_hash[subkeys.last] << value else current_hash[subkeys.last] = value end end def fill_accumulator_for_subscript(accumulator, key, value) current_node = accumulator subkeys = key.split(/(?=\[[^\[\]]+)/) subkeys[0..-2].each do |subkey| node = subkey =~ /\[\]\z/ ? [] : {} subkey = subkey.gsub(/[\[\]]/, '') if current_node.is_a? Array container = current_node.find { |n| n.is_a?(Hash) && n.has_key?(subkey) } if container current_node = container[subkey] else current_node << {subkey => node} current_node = node end else current_node[subkey] = node unless current_node[subkey] current_node = current_node[subkey] end end last_key = subkeys.last array_value = !!(last_key =~ /\[\]$/) last_key = last_key.gsub(/[\[\]]/, '') if current_node.is_a? Array last_container = current_node.select { |n| n.is_a?(Hash) }.last if last_container && !last_container.has_key?(last_key) if array_value last_container[last_key] ||= [] last_container[last_key] << value else last_container[last_key] = value end else if array_value current_node << {last_key => [value]} else current_node << {last_key => value} end end else if array_value current_node[last_key] ||= [] current_node[last_key] << value unless value.nil? else current_node[last_key] = value end end end ## # Sets the query component for this URI from a Hash object. # This method produces a query string using the :subscript notation. # An empty Hash will result in a nil query. # # @param [Hash, #to_hash, Array] new_query_values The new query values. def values_to_query(new_query_values, options = {}) options[:notation] ||= :subscript return if new_query_values.nil? unless new_query_values.is_a?(Array) unless new_query_values.respond_to?(:to_hash) raise TypeError, "Can't convert #{new_query_values.class} into Hash." end new_query_values = new_query_values.to_hash new_query_values = new_query_values.inject([]) do |object, (key, value)| key = key.to_s if key.is_a?(::Symbol) || key.nil? if value.is_a?(Array) && value.empty? object << [key.to_s + '[]'] elsif value.is_a?(Array) value.each { |v| object << [key.to_s + '[]', v] } elsif value.is_a?(Hash) value.each { |k, v| object << ["#{key.to_s}[#{k}]", v]} else object << [key.to_s, value] end object end # Useful default for OAuth and caching. # Only to be used for non-Array inputs. Arrays should preserve order. begin new_query_values.sort! # may raise for non-comparable values rescue NoMethodError, ArgumentError # ignore end end buffer = ''.dup new_query_values.each do |parent, value| encoded_parent = ::Addressable::URI.encode_component( parent.dup, ::Addressable::URI::CharacterClasses::UNRESERVED ) buffer << "#{to_query(encoded_parent, value, options)}&" end buffer.chop end def dehash(hash) hash.each do |(key, value)| if value.is_a?(::Hash) hash[key] = self.dehash(value) end end if hash != {} && hash.keys.all? { |key| key =~ /^\d+$/ } hash.sort.inject([]) do |accu, (_, value)| accu << value; accu end else hash end end ## # Joins and converts parent and value into a properly encoded and # ordered URL query. # # @private # @param [String] parent an URI encoded component. # @param [Array, Hash, Symbol, #to_str] value # # @return [String] a properly escaped and ordered URL query. # new_query_values have form [['key1', 'value1'], ['key2', 'value2']] def to_query(parent, value, options = {}) options[:notation] ||= :subscript case value when ::Hash value = value.map do |key, val| [ ::Addressable::URI.encode_component(key.to_s.dup, ::Addressable::URI::CharacterClasses::UNRESERVED), val ] end value.sort! buffer = ''.dup value.each do |key, val| new_parent = options[:notation] != :flat_array ? "#{parent}[#{key}]" : parent buffer << "#{to_query(new_parent, val, options)}&" end buffer.chop when ::Array buffer = ''.dup value.each_with_index do |val, i| new_parent = options[:notation] != :flat_array ? "#{parent}[#{i}]" : parent buffer << "#{to_query(new_parent, val, options)}&" end buffer.chop when NilClass parent else encoded_value = Addressable::URI.encode_component( value.to_s.dup, Addressable::URI::CharacterClasses::UNRESERVED ) "#{parent}=#{encoded_value}" end end end end end webmock-3.18.1/lib/webmock/util/headers.rb0000644000004100000410000000327614333126774020417 0ustar www-datawww-datarequire 'base64' module WebMock module Util class Headers def self.normalize_headers(headers) return nil unless headers array = headers.map { |name, value| [name.to_s.split(/_|-/).map { |segment| segment.capitalize }.join("-"), case value when Regexp then value when Array then (value.size == 1) ? value.first.to_s : value.map {|v| v.to_s}.sort else value.to_s end ] } Hash[*array.inject([]) {|r,x| r + x}] end def self.sorted_headers_string(headers) headers = WebMock::Util::Headers.normalize_headers(headers) str = '{'.dup str << headers.map do |k,v| v = case v when Regexp then v.inspect when Array then "["+v.map{|w| "'#{w.to_s}'"}.join(", ")+"]" else "'#{v.to_s}'" end "'#{k}'=>#{v}" end.sort.join(", ") str << '}' end def self.pp_headers_string(headers) headers = WebMock::Util::Headers.normalize_headers(headers) seperator = "\n\t " str = "{#{seperator} ".dup str << headers.map do |k,v| v = case v when Regexp then v.inspect when Array then "["+v.map{|w| "'#{w.to_s}'"}.join(", ")+"]" else "'#{v.to_s}'" end "'#{k}'=>#{v}" end.sort.join(",#{seperator} ") str << "\n }" end def self.decode_userinfo_from_header(header) header.sub(/^Basic /, "").unpack("m").first end def self.basic_auth_header(*credentials) "Basic #{Base64.strict_encode64(credentials.join(':')).chomp}" end end end end webmock-3.18.1/lib/webmock/util/hash_keys_stringifier.rb0000644000004100000410000000110414333126774023353 0ustar www-datawww-datamodule WebMock module Util class HashKeysStringifier def self.stringify_keys!(arg, options = {}) case arg when Array arg.map { |elem| options[:deep] ? stringify_keys!(elem, options) : elem } when Hash Hash[ *arg.map { |key, value| k = key.is_a?(Symbol) ? key.to_s : key v = (options[:deep] ? stringify_keys!(value, options) : value) [k,v] }.inject([]) {|r,x| r + x}] else arg end end end end end webmock-3.18.1/lib/webmock/util/hash_counter.rb0000644000004100000410000000137214333126774021461 0ustar www-datawww-datarequire 'thread' module WebMock module Util class HashCounter attr_accessor :hash def initialize self.hash = {} @order = {} @max = 0 @lock = ::Mutex.new end def put key, num=1 @lock.synchronize do hash[key] = (hash[key] || 0) + num @order[key] = @max = @max + 1 end end def get key @lock.synchronize do hash[key] || 0 end end def select(&block) return unless block_given? @lock.synchronize do hash.select(&block) end end def each(&block) @order.to_a.sort_by { |a| a[1] }.each do |a| yield(a[0], hash[a[0]]) end end end end end webmock-3.18.1/lib/webmock/minitest.rb0000644000004100000410000000177414333126774017664 0ustar www-datawww-databegin require 'minitest/test' test_class = Minitest::Test assertions = "assertions" rescue LoadError require "minitest/unit" test_class = MiniTest::Unit::TestCase assertions = "_assertions" end require 'webmock' WebMock.enable! test_class.class_eval do include WebMock::API alias_method :teardown_without_webmock, :teardown def teardown_with_webmock teardown_without_webmock WebMock.reset! end alias_method :teardown, :teardown_with_webmock [:assert_request_requested, :assert_request_not_requested].each do |name| alias_method :"#{name}_without_assertions_count", name define_method :"#{name}_with_assertions_count" do |*args| self.send("#{assertions}=", self.send("#{assertions}") + 1) send :"#{name}_without_assertions_count", *args end alias_method name, :"#{name}_with_assertions_count" end end begin error_class = MiniTest::Assertion rescue NameError error_class = Minitest::Assertion end WebMock::AssertionFailure.error_class = error_class webmock-3.18.1/lib/webmock/api.rb0000644000004100000410000000730614333126774016576 0ustar www-datawww-datamodule WebMock module API extend self def stub_request(method, uri) WebMock::StubRegistry.instance. register_request_stub(WebMock::RequestStub.new(method, uri)) end alias_method :stub_http_request, :stub_request def a_request(method, uri) WebMock::RequestPattern.new(method, uri) end class << self alias :request :a_request end def assert_requested(*args, &block) if not args[0].is_a?(WebMock::RequestStub) args = convert_uri_method_and_options_to_request_and_options(args[0], args[1], args[2], &block) elsif block raise ArgumentError, "assert_requested with a stub object, doesn't accept blocks" end assert_request_requested(*args) end def assert_not_requested(*args, &block) if not args[0].is_a?(WebMock::RequestStub) args = convert_uri_method_and_options_to_request_and_options(args[0], args[1], args[2], &block) elsif block raise ArgumentError, "assert_not_requested with a stub object, doesn't accept blocks" end assert_request_not_requested(*args) end alias refute_requested assert_not_requested # Similar to RSpec::Mocks::ArgumentMatchers#hash_including() # # Matches a hash that includes the specified key(s) or key/value pairs. # Ignores any additional keys. # # @example # # object.should_receive(:message).with(hash_including(:key => val)) # object.should_receive(:message).with(hash_including(:key)) # object.should_receive(:message).with(hash_including(:key, :key2 => val2)) def hash_including(*args) if defined?(super) super else WebMock::Matchers::HashIncludingMatcher.new(anythingize_lonely_keys(*args)) end end def hash_excluding(*args) if defined?(super) super else WebMock::Matchers::HashExcludingMatcher.new(anythingize_lonely_keys(*args)) end end def remove_request_stub(stub) WebMock::StubRegistry.instance.remove_request_stub(stub) end def reset_executed_requests! WebMock::RequestRegistry.instance.reset! end private def convert_uri_method_and_options_to_request_and_options(method, uri, options, &block) options ||= {} options_for_pattern = options.dup [:times, :at_least_times, :at_most_times].each { |key| options_for_pattern.delete(key) } request = WebMock::RequestPattern.new(method, uri, options_for_pattern) request = request.with(&block) if block [request, options] end def assert_request_requested(request, options = {}) times = options.delete(:times) at_least_times = options.delete(:at_least_times) at_most_times = options.delete(:at_most_times) times = 1 if times.nil? && at_least_times.nil? && at_most_times.nil? verifier = WebMock::RequestExecutionVerifier.new(request, times, at_least_times, at_most_times) WebMock::AssertionFailure.failure(verifier.failure_message) unless verifier.matches? end def assert_request_not_requested(request, options = {}) times = options.delete(:times) at_least_times = options.delete(:at_least_times) at_most_times = options.delete(:at_most_times) verifier = WebMock::RequestExecutionVerifier.new(request, times, at_least_times, at_most_times) WebMock::AssertionFailure.failure(verifier.failure_message_when_negated) unless verifier.does_not_match? end #this is a based on RSpec::Mocks::ArgumentMatchers#anythingize_lonely_keys def anythingize_lonely_keys(*args) hash = args.last.class == Hash ? args.delete_at(-1) : {} args.each { | arg | hash[arg] = WebMock::Matchers::AnyArgMatcher.new(nil) } hash end end end webmock-3.18.1/lib/webmock/request_registry.rb0000644000004100000410000000146614333126774021446 0ustar www-datawww-datamodule WebMock class RequestRegistry include Singleton attr_accessor :requested_signatures def initialize reset! end def reset! self.requested_signatures = Util::HashCounter.new end def times_executed(request_pattern) self.requested_signatures.select do |request_signature| request_pattern.matches?(request_signature) end.inject(0) { |sum, (_, times_executed)| sum + times_executed } end def to_s if requested_signatures.hash.empty? "No requests were made." else text = "".dup self.requested_signatures.each do |request_signature, times_executed| text << "#{request_signature} was made #{times_executed} time#{times_executed == 1 ? '' : 's' }\n" end text end end end end webmock-3.18.1/lib/webmock/rspec/0000755000004100000410000000000014333126774016606 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/rspec/matchers.rb0000644000004100000410000000113114333126774020735 0ustar www-datawww-datarequire 'webmock' require 'webmock/rspec/matchers/request_pattern_matcher' require 'webmock/rspec/matchers/webmock_matcher' module WebMock module Matchers def have_been_made WebMock::RequestPatternMatcher.new end def have_been_requested WebMock::RequestPatternMatcher.new end def have_not_been_made WebMock::RequestPatternMatcher.new.times(0) end def have_requested(method, uri) WebMock::WebMockMatcher.new(method, uri) end def have_not_requested(method, uri) WebMock::WebMockMatcher.new(method, uri).times(0) end end end webmock-3.18.1/lib/webmock/rspec/matchers/0000755000004100000410000000000014333126774020414 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/rspec/matchers/request_pattern_matcher.rb0000644000004100000410000000340614333126774025674 0ustar www-datawww-datamodule WebMock class RequestPatternMatcher def initialize @request_execution_verifier = RequestExecutionVerifier.new end def once @request_execution_verifier.expected_times_executed = 1 self end def twice @request_execution_verifier.expected_times_executed = 2 self end def times(times) @request_execution_verifier.expected_times_executed = times.to_i self end def at_least_once @request_execution_verifier.at_least_times_executed = 1 self end def at_least_twice @request_execution_verifier.at_least_times_executed = 2 self end def at_least_times(times) @request_execution_verifier.at_least_times_executed = times.to_i self end def at_most_once @request_execution_verifier.at_most_times_executed = 1 self end def at_most_twice @request_execution_verifier.at_most_times_executed = 2 self end def at_most_times(times) @request_execution_verifier.at_most_times_executed = times.to_i self end def matches?(request_pattern) @request_execution_verifier.request_pattern = request_pattern @request_execution_verifier.matches? end def does_not_match?(request_pattern) @request_execution_verifier.request_pattern = request_pattern @request_execution_verifier.does_not_match? end def failure_message @request_execution_verifier.failure_message end def failure_message_when_negated @request_execution_verifier.failure_message_when_negated end def description @request_execution_verifier.description end # RSpec 2 compatibility: alias_method :negative_failure_message, :failure_message_when_negated end end webmock-3.18.1/lib/webmock/rspec/matchers/webmock_matcher.rb0000644000004100000410000000277614333126774024107 0ustar www-datawww-datamodule WebMock class WebMockMatcher def initialize(method, uri) @request_execution_verifier = RequestExecutionVerifier.new @request_execution_verifier.request_pattern = RequestPattern.new(method, uri) end def once @request_execution_verifier.expected_times_executed = 1 self end def twice @request_execution_verifier.expected_times_executed = 2 self end def at_least_once @request_execution_verifier.at_least_times_executed = 1 self end def at_least_twice @request_execution_verifier.at_least_times_executed = 2 self end def at_least_times(times) @request_execution_verifier.at_least_times_executed = times self end def with(options = {}, &block) @request_execution_verifier.request_pattern.with(options, &block) self end def times(times) @request_execution_verifier.expected_times_executed = times.to_i self end def matches?(webmock) @request_execution_verifier.matches? end def does_not_match?(webmock) @request_execution_verifier.does_not_match? end def failure_message @request_execution_verifier.failure_message end def failure_message_when_negated @request_execution_verifier.failure_message_when_negated end def description @request_execution_verifier.description end # RSpec 2 compatibility: alias_method :negative_failure_message, :failure_message_when_negated end end webmock-3.18.1/lib/webmock/callback_registry.rb0000644000004100000410000000145714333126774021512 0ustar www-datawww-datamodule WebMock class CallbackRegistry @@callbacks = [] def self.add_callback(options, block) @@callbacks << {options: options, block: block} end def self.callbacks @@callbacks end def self.invoke_callbacks(options, request_signature, response) return if @@callbacks.empty? CallbackRegistry.callbacks.each do |callback| except = callback[:options][:except] real_only = callback[:options][:real_requests_only] unless except && except.include?(options[:lib]) if !real_only || options[:real_request] callback[:block].call(request_signature, response) end end end end def self.reset @@callbacks = [] end def self.any_callbacks? !@@callbacks.empty? end end end webmock-3.18.1/lib/webmock/request_body_diff.rb0000644000004100000410000000276514333126774021526 0ustar www-datawww-datarequire "hashdiff" require "json" module WebMock class RequestBodyDiff def initialize(request_signature, request_stub) @request_signature = request_signature @request_stub = request_stub end def body_diff return {} unless request_signature_diffable? && request_stub_diffable? Hashdiff.diff(request_signature_body_hash, request_stub_body_hash) end attr_reader :request_signature, :request_stub private :request_signature, :request_stub private def request_signature_diffable? request_signature.json_headers? && request_signature_parseable_json? end def request_stub_diffable? request_stub_body.is_a?(Hash) || request_stub_parseable_json? end def request_signature_body_hash JSON.parse(request_signature.body) end def request_stub_body_hash return request_stub_body if request_stub_body.is_a?(Hash) JSON.parse(request_stub_body) end def request_stub_body request_stub.request_pattern && request_stub.request_pattern.body_pattern && request_stub.request_pattern.body_pattern.pattern end def request_signature_parseable_json? parseable_json?(request_signature.body) end def request_stub_parseable_json? parseable_json?(request_stub_body) end def parseable_json?(body_pattern) return false unless body_pattern.is_a?(String) JSON.parse(body_pattern) true rescue JSON::ParserError false end end end webmock-3.18.1/lib/webmock/webmock.rb0000644000004100000410000001154214333126774017451 0ustar www-datawww-datamodule WebMock def self.included(clazz) WebMock::Deprecation.warning("include WebMock is deprecated. Please include WebMock::API instead") if clazz.instance_methods.map(&:to_s).include?('request') warn "WebMock#request was not included in #{clazz} to avoid name collision" else clazz.class_eval do def request(method, uri) WebMock::Deprecation.warning("WebMock#request is deprecated. Please use WebMock::API#a_request method instead") WebMock.a_request(method, uri) end end end end include WebMock::API extend WebMock::API class << self alias :request :a_request end def self.version VERSION end def self.disable!(options = {}) except = [options[:except]].flatten.compact HttpLibAdapterRegistry.instance.each_adapter do |name, adapter| adapter.enable! adapter.disable! unless except.include?(name) end end def self.enable!(options = {}) except = [options[:except]].flatten.compact HttpLibAdapterRegistry.instance.each_adapter do |name, adapter| adapter.disable! adapter.enable! unless except.include?(name) end end def self.allow_net_connect!(options = {}) Config.instance.allow_net_connect = true Config.instance.net_http_connect_on_start = options[:net_http_connect_on_start] end def self.disable_net_connect!(options = {}) Config.instance.allow_net_connect = false Config.instance.allow_localhost = options[:allow_localhost] Config.instance.allow = options[:allow] Config.instance.net_http_connect_on_start = options[:net_http_connect_on_start] end class << self alias :enable_net_connect! :allow_net_connect! alias :disallow_net_connect! :disable_net_connect! end def self.net_connect_allowed?(uri = nil) return !!Config.instance.allow_net_connect if uri.nil? if uri.is_a?(String) uri = WebMock::Util::URI.normalize_uri(uri) end !!Config.instance.allow_net_connect || ( Config.instance.allow_localhost && WebMock::Util::URI.is_uri_localhost?(uri) || Config.instance.allow && net_connect_explicit_allowed?(Config.instance.allow, uri) ) end def self.net_http_connect_on_start?(uri) allowed = Config.instance.net_http_connect_on_start || false if [true, false].include?(allowed) allowed else net_connect_explicit_allowed?(allowed, uri) end end def self.net_connect_explicit_allowed?(allowed, uri=nil) case allowed when Array allowed.any? { |allowed_item| net_connect_explicit_allowed?(allowed_item, uri) } when Regexp (uri.to_s =~ allowed) != nil || (uri.omit(:port).to_s =~ allowed) != nil && uri.port == uri.default_port when String allowed == uri.to_s || allowed == uri.host || allowed == "#{uri.host}:#{uri.port}" || allowed == "#{uri.scheme}://#{uri.host}:#{uri.port}" || allowed == "#{uri.scheme}://#{uri.host}" && uri.port == uri.default_port else if allowed.respond_to?(:call) allowed.call(uri) end end end def self.show_body_diff! Config.instance.show_body_diff = true end def self.hide_body_diff! Config.instance.show_body_diff = false end def self.show_body_diff? Config.instance.show_body_diff end def self.hide_stubbing_instructions! Config.instance.show_stubbing_instructions = false end def self.show_stubbing_instructions! Config.instance.show_stubbing_instructions = true end def self.show_stubbing_instructions? Config.instance.show_stubbing_instructions end def self.reset! WebMock::RequestRegistry.instance.reset! WebMock::StubRegistry.instance.reset! end def self.reset_webmock WebMock::Deprecation.warning("WebMock.reset_webmock is deprecated. Please use WebMock.reset! method instead") reset! end def self.reset_callbacks WebMock::CallbackRegistry.reset end def self.after_request(options={}, &block) WebMock::CallbackRegistry.add_callback(options, block) end def self.registered_request?(request_signature) WebMock::StubRegistry.instance.registered_request?(request_signature) end def self.print_executed_requests puts WebMock::RequestExecutionVerifier.executed_requests_message end def self.globally_stub_request(order = :before_local_stubs, &block) WebMock::StubRegistry.instance.register_global_stub(order, &block) end %w( allow_net_connect! disable_net_connect! net_connect_allowed? reset_webmock reset_callbacks after_request registered_request? ).each do |method| self.class_eval(%Q( def #{method}(*args, &block) WebMock::Deprecation.warning("WebMock##{method} instance method is deprecated. Please use WebMock.#{method} class method instead") WebMock.#{method}(*args, &block) end )) end end webmock-3.18.1/lib/webmock/response.rb0000644000004100000410000001024714333126774017661 0ustar www-datawww-datarequire "pathname" module WebMock class ResponseFactory def self.response_for(options) if options.respond_to?(:call) WebMock::DynamicResponse.new(options) else WebMock::Response.new(options) end end end class Response def initialize(options = {}) case options when IO, StringIO self.options = read_raw_response(options) when String self.options = read_raw_response(StringIO.new(options)) else self.options = options end end def headers @headers end def headers=(headers) @headers = headers if @headers && !@headers.is_a?(Proc) @headers = Util::Headers.normalize_headers(@headers) end end def body @body || '' end def body=(body) @body = body assert_valid_body! stringify_body! end def status @status || [200, ""] end def status=(status) @status = status.is_a?(Integer) ? [status, ""] : status end def exception @exception end def exception=(exception) @exception = case exception when String then StandardError.new(exception) when Class then exception.new('Exception from WebMock') when Exception then exception end end def raise_error_if_any raise @exception if @exception end def should_timeout @should_timeout == true end def options=(options) options = WebMock::Util::HashKeysStringifier.stringify_keys!(options) HashValidator.new(options).validate_keys('headers', 'status', 'body', 'exception', 'should_timeout') self.headers = options['headers'] self.status = options['status'] self.body = options['body'] self.exception = options['exception'] @should_timeout = options['should_timeout'] end def evaluate(request_signature) self.body = @body.call(request_signature) if @body.is_a?(Proc) self.headers = @headers.call(request_signature) if @headers.is_a?(Proc) self.status = @status.call(request_signature) if @status.is_a?(Proc) @should_timeout = @should_timeout.call(request_signature) if @should_timeout.is_a?(Proc) @exception = @exception.call(request_signature) if @exception.is_a?(Proc) self end def ==(other) self.body == other.body && self.headers === other.headers && self.status == other.status && self.exception == other.exception && self.should_timeout == other.should_timeout end private def stringify_body! if @body.is_a?(IO) || @body.is_a?(Pathname) io = @body @body = io.read io.close if io.respond_to?(:close) end end def assert_valid_body! valid_types = [Proc, IO, Pathname, String, Array] return if @body.nil? return if valid_types.any? { |c| @body.is_a?(c) } if @body.class.is_a?(Hash) raise InvalidBody, "must be one of: #{valid_types}, but you've used a #{@body.class}' instead." \ "\n What shall we encode it to? try calling .to_json .to_xml instead on the hash instead, or otherwise convert it to a string." else raise InvalidBody, "must be one of: #{valid_types}. '#{@body.class}' given" end end def read_raw_response(io) socket = ::Net::BufferedIO.new(io) response = ::Net::HTTPResponse.read_new(socket) transfer_encoding = response.delete('transfer-encoding') #chunks were already read by curl response.reading_body(socket, true) {} options = {} options[:headers] = {} response.each_header {|name, value| options[:headers][name] = value} options[:headers]['transfer-encoding'] = transfer_encoding if transfer_encoding options[:body] = response.read_body options[:status] = [response.code.to_i, response.message] options ensure socket.close end InvalidBody = Class.new(StandardError) end class DynamicResponse < Response attr_accessor :responder def initialize(responder) @responder = responder end def evaluate(request_signature) options = @responder.call(request_signature) Response.new(options) end end end webmock-3.18.1/lib/webmock/request_pattern.rb0000644000004100000410000003075514333126774021256 0ustar www-datawww-datamodule WebMock module RSpecMatcherDetector def rSpecHashIncludingMatcher?(matcher) matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashIncludingMatcher/ end def rSpecHashExcludingMatcher?(matcher) matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashExcludingMatcher/ end end class RequestPattern attr_reader :method_pattern, :uri_pattern, :body_pattern, :headers_pattern def initialize(method, uri, options = {}) @method_pattern = MethodPattern.new(method) @uri_pattern = create_uri_pattern(uri) @body_pattern = nil @headers_pattern = nil @with_block = nil assign_options(options) end def with(options = {}, &block) raise ArgumentError.new('#with method invoked with no arguments. Either options hash or block must be specified. Created a block with do..end? Try creating it with curly braces {} instead.') if options.empty? && !block_given? assign_options(options) @with_block = block self end def matches?(request_signature) content_type = request_signature.headers['Content-Type'] if request_signature.headers content_type = content_type.split(';').first if content_type @method_pattern.matches?(request_signature.method) && @uri_pattern.matches?(request_signature.uri) && (@body_pattern.nil? || @body_pattern.matches?(request_signature.body, content_type || "")) && (@headers_pattern.nil? || @headers_pattern.matches?(request_signature.headers)) && (@with_block.nil? || @with_block.call(request_signature)) end def to_s string = "#{@method_pattern.to_s.upcase}".dup string << " #{@uri_pattern.to_s}" string << " with body #{@body_pattern.to_s}" if @body_pattern string << " with headers #{@headers_pattern.to_s}" if @headers_pattern string << " with given block" if @with_block string end private def assign_options(options) options = WebMock::Util::HashKeysStringifier.stringify_keys!(options, deep: true) HashValidator.new(options).validate_keys('body', 'headers', 'query', 'basic_auth') set_basic_auth_as_headers!(options) @body_pattern = BodyPattern.new(options['body']) if options.has_key?('body') @headers_pattern = HeadersPattern.new(options['headers']) if options.has_key?('headers') @uri_pattern.add_query_params(options['query']) if options.has_key?('query') end def set_basic_auth_as_headers!(options) if basic_auth = options.delete('basic_auth') validate_basic_auth!(basic_auth) options['headers'] ||= {} options['headers']['Authorization'] = WebMock::Util::Headers.basic_auth_header(basic_auth[0],basic_auth[1]) end end def validate_basic_auth!(basic_auth) if !basic_auth.is_a?(Array) || basic_auth.map{|e| e.is_a?(String)}.uniq != [true] raise "The basic_auth option value should be an array which contains 2 strings: username and password" end end def create_uri_pattern(uri) if uri.is_a?(Regexp) URIRegexpPattern.new(uri) elsif uri.is_a?(Addressable::Template) URIAddressablePattern.new(uri) elsif uri.respond_to?(:call) URICallablePattern.new(uri) else URIStringPattern.new(uri) end end end class MethodPattern def initialize(pattern) @pattern = pattern end def matches?(method) @pattern == method || @pattern == :any end def to_s @pattern.to_s end end class URIPattern include RSpecMatcherDetector def initialize(pattern) @pattern = if pattern.is_a?(Addressable::URI) \ || pattern.is_a?(Addressable::Template) pattern elsif pattern.respond_to?(:call) pattern else WebMock::Util::URI.normalize_uri(pattern) end @query_params = nil end def add_query_params(query_params) @query_params = if query_params.is_a?(Hash) query_params elsif query_params.is_a?(WebMock::Matchers::HashIncludingMatcher) \ || query_params.is_a?(WebMock::Matchers::HashExcludingMatcher) query_params elsif rSpecHashIncludingMatcher?(query_params) WebMock::Matchers::HashIncludingMatcher.from_rspec_matcher(query_params) elsif rSpecHashExcludingMatcher?(query_params) WebMock::Matchers::HashExcludingMatcher.from_rspec_matcher(query_params) else WebMock::Util::QueryMapper.query_to_values(query_params, notation: Config.instance.query_values_notation) end end def matches?(uri) pattern_matches?(uri) && query_params_matches?(uri) end def to_s str = pattern_inspect str += " with query params #{@query_params.inspect}" if @query_params str end private def pattern_inspect @pattern.inspect end def query_params_matches?(uri) @query_params.nil? || @query_params == WebMock::Util::QueryMapper.query_to_values(uri.query, notation: Config.instance.query_values_notation) end end class URICallablePattern < URIPattern private def pattern_matches?(uri) @pattern.call(uri) end end class URIRegexpPattern < URIPattern private def pattern_matches?(uri) WebMock::Util::URI.variations_of_uri_as_strings(uri).any? { |u| u.match(@pattern) } end end class URIAddressablePattern < URIPattern def add_query_params(query_params) @@add_query_params_warned ||= false if not @@add_query_params_warned @@add_query_params_warned = true warn "WebMock warning: ignoring query params in RFC 6570 template and checking them with WebMock" end super(query_params) end private def pattern_matches?(uri) if @query_params.nil? # Let Addressable check the whole URI matches_with_variations?(uri) else # WebMock checks the query, Addressable checks everything else matches_with_variations?(uri.omit(:query)) end end def pattern_inspect @pattern.pattern.inspect end def matches_with_variations?(uri) template = begin Addressable::Template.new(WebMock::Util::URI.heuristic_parse(@pattern.pattern)) rescue Addressable::URI::InvalidURIError Addressable::Template.new(@pattern.pattern) end WebMock::Util::URI.variations_of_uri_as_strings(uri).any? { |u| template_matches_uri?(template, u) } end def template_matches_uri?(template, uri) template.match(uri) rescue Addressable::URI::InvalidURIError false end end class URIStringPattern < URIPattern def add_query_params(query_params) super if @query_params.is_a?(Hash) || @query_params.is_a?(String) query_hash = (WebMock::Util::QueryMapper.query_to_values(@pattern.query, notation: Config.instance.query_values_notation) || {}).merge(@query_params) @pattern.query = WebMock::Util::QueryMapper.values_to_query(query_hash, notation: WebMock::Config.instance.query_values_notation) @query_params = nil end end private def pattern_matches?(uri) if @pattern.is_a?(Addressable::URI) if @query_params uri.omit(:query) === @pattern else uri === @pattern end else false end end def pattern_inspect WebMock::Util::URI.strip_default_port_from_uri_string(@pattern.to_s) end end class BodyPattern include RSpecMatcherDetector BODY_FORMATS = { 'text/xml' => :xml, 'application/xml' => :xml, 'application/json' => :json, 'text/json' => :json, 'application/javascript' => :json, 'text/javascript' => :json, 'text/html' => :html, 'application/x-yaml' => :yaml, 'text/yaml' => :yaml, 'text/plain' => :plain } attr_reader :pattern def initialize(pattern) @pattern = if pattern.is_a?(Hash) normalize_hash(pattern) elsif rSpecHashIncludingMatcher?(pattern) WebMock::Matchers::HashIncludingMatcher.from_rspec_matcher(pattern) else pattern end end def matches?(body, content_type = "") assert_non_multipart_body(content_type) if (@pattern).is_a?(Hash) return true if @pattern.empty? matching_body_hashes?(body_as_hash(body, content_type), @pattern, content_type) elsif (@pattern).is_a?(Array) matching_body_array?(body_as_hash(body, content_type), @pattern, content_type) elsif (@pattern).is_a?(WebMock::Matchers::HashIncludingMatcher) @pattern == body_as_hash(body, content_type) else empty_string?(@pattern) && empty_string?(body) || @pattern == body || @pattern === body end end def to_s @pattern.inspect end private def body_as_hash(body, content_type) case body_format(content_type) when :json then WebMock::Util::JSON.parse(body) when :xml then Crack::XML.parse(body) else WebMock::Util::QueryMapper.query_to_values(body, notation: Config.instance.query_values_notation) end end def body_format(content_type) normalized_content_type = content_type.sub(/\A(application\/)[a-zA-Z0-9.-]+\+(json|xml)\Z/,'\1\2') BODY_FORMATS[normalized_content_type] end def assert_non_multipart_body(content_type) if content_type =~ %r{^multipart/form-data} raise ArgumentError.new("WebMock does not support matching body for multipart/form-data requests yet :(") end end # Compare two hashes for equality # # For two hashes to match they must have the same length and all # values must match when compared using `#===`. # # The following hashes are examples of matches: # # {a: /\d+/} and {a: '123'} # # {a: '123'} and {a: '123'} # # {a: {b: /\d+/}} and {a: {b: '123'}} # # {a: {b: 'wow'}} and {a: {b: 'wow'}} # # @param [Hash] query_parameters typically the result of parsing # JSON, XML or URL encoded parameters. # # @param [Hash] pattern which contains keys with a string, hash or # regular expression value to use for comparison. # # @return [Boolean] true if the paramaters match the comparison # hash, false if not. def matching_body_hashes?(query_parameters, pattern, content_type) return false unless query_parameters.is_a?(Hash) return false unless query_parameters.keys.sort == pattern.keys.sort query_parameters.all? do |key, actual| expected = pattern[key] matching_values(actual, expected, content_type) end end def matching_body_array?(query_parameters, pattern, content_type) return false unless query_parameters.is_a?(Array) return false unless query_parameters.length == pattern.length query_parameters.each_with_index do |actual, index| expected = pattern[index] return false unless matching_values(actual, expected, content_type) end true end def matching_values(actual, expected, content_type) return matching_body_hashes?(actual, expected, content_type) if actual.is_a?(Hash) && expected.is_a?(Hash) return matching_body_array?(actual, expected, content_type) if actual.is_a?(Array) && expected.is_a?(Array) expected = WebMock::Util::ValuesStringifier.stringify_values(expected) if url_encoded_body?(content_type) expected === actual end def empty_string?(string) string.nil? || string == "" end def normalize_hash(hash) Hash[WebMock::Util::HashKeysStringifier.stringify_keys!(hash, deep: true).sort] end def url_encoded_body?(content_type) content_type =~ %r{^application/x-www-form-urlencoded} end end class HeadersPattern def initialize(pattern) @pattern = WebMock::Util::Headers.normalize_headers(pattern) || {} end def matches?(headers) if empty_headers?(@pattern) empty_headers?(headers) else return false if empty_headers?(headers) @pattern.each do |key, value| return false unless headers.has_key?(key) && value === headers[key] end true end end def to_s WebMock::Util::Headers.sorted_headers_string(@pattern) end def pp_to_s WebMock::Util::Headers.pp_headers_string(@pattern) end private def empty_headers?(headers) headers.nil? || headers == {} end end end webmock-3.18.1/lib/webmock/cucumber.rb0000644000004100000410000000021314333126774017620 0ustar www-datawww-datarequire 'webmock' require 'webmock/rspec/matchers' WebMock.enable! World(WebMock::API, WebMock::Matchers) After do WebMock.reset! end webmock-3.18.1/lib/webmock/http_lib_adapters/0000755000004100000410000000000014333126774021162 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/http_lib_adapters/net_http.rb0000644000004100000410000002125714333126774023343 0ustar www-datawww-datarequire 'net/http' require 'net/https' require 'stringio' require File.join(File.dirname(__FILE__), 'net_http_response') module WebMock module HttpLibAdapters class NetHttpAdapter < HttpLibAdapter adapter_for :net_http OriginalNetHTTP = Net::HTTP unless const_defined?(:OriginalNetHTTP) def self.enable! Net.send(:remove_const, :HTTP) Net.send(:remove_const, :HTTPSession) Net.send(:const_set, :HTTP, @webMockNetHTTP) Net.send(:const_set, :HTTPSession, @webMockNetHTTP) end def self.disable! Net.send(:remove_const, :HTTP) Net.send(:remove_const, :HTTPSession) Net.send(:const_set, :HTTP, OriginalNetHTTP) Net.send(:const_set, :HTTPSession, OriginalNetHTTP) #copy all constants from @webMockNetHTTP to original Net::HTTP #in case any constants were added to @webMockNetHTTP instead of Net::HTTP #after WebMock was enabled. #i.e Net::HTTP::DigestAuth @webMockNetHTTP.constants.each do |constant| if !OriginalNetHTTP.constants.map(&:to_s).include?(constant.to_s) OriginalNetHTTP.send(:const_set, constant, @webMockNetHTTP.const_get(constant)) end end end @webMockNetHTTP = Class.new(Net::HTTP) do class << self def socket_type StubSocket end if Module.method(:const_defined?).arity == 1 def const_defined?(name) super || self.superclass.const_defined?(name) end else def const_defined?(name, inherit=true) super || self.superclass.const_defined?(name, inherit) end end if Module.method(:const_get).arity != 1 def const_get(name, inherit=true) super rescue NameError self.superclass.const_get(name, inherit) end end if Module.method(:constants).arity != 0 def constants(inherit=true) (super + self.superclass.constants(inherit)).uniq end end end def request(request, body = nil, &block) request_signature = WebMock::NetHTTPUtility.request_signature_from_request(self, request, body) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) @socket = Net::HTTP.socket_type.new WebMock::CallbackRegistry.invoke_callbacks( {lib: :net_http}, request_signature, webmock_response) build_net_http_response(webmock_response, &block) elsif WebMock.net_connect_allowed?(request_signature.uri) check_right_http_connection after_request = lambda do |response| if WebMock::CallbackRegistry.any_callbacks? webmock_response = build_webmock_response(response) WebMock::CallbackRegistry.invoke_callbacks( {lib: :net_http, real_request: true}, request_signature, webmock_response) end response.extend Net::WebMockHTTPResponse block.call response if block response end super_with_after_request = lambda { response = super(request, nil, &nil) after_request.call(response) } if started? ensure_actual_connection super_with_after_request.call else start_with_connect { super_with_after_request.call } end else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def start_without_connect raise IOError, 'HTTP session already opened' if @started if block_given? begin @socket = Net::HTTP.socket_type.new @started = true return yield(self) ensure do_finish end end @socket = Net::HTTP.socket_type.new @started = true self end def ensure_actual_connection if @socket.is_a?(StubSocket) @socket&.close @socket = nil do_start end end alias_method :start_with_connect, :start def start(&block) uri = Addressable::URI.parse(WebMock::NetHTTPUtility.get_uri(self)) if WebMock.net_http_connect_on_start?(uri) super(&block) else start_without_connect(&block) end end def build_net_http_response(webmock_response, &block) response = Net::HTTPResponse.send(:response_class, webmock_response.status[0].to_s).new("1.0", webmock_response.status[0].to_s, webmock_response.status[1]) body = webmock_response.body body = nil if webmock_response.status[0].to_s == '204' response.instance_variable_set(:@body, body) webmock_response.headers.to_a.each do |name, values| values = [values] unless values.is_a?(Array) values.each do |value| response.add_field(name, value) end end response.instance_variable_set(:@read, true) response.extend Net::WebMockHTTPResponse if webmock_response.should_timeout raise Net::OpenTimeout, "execution expired" end webmock_response.raise_error_if_any yield response if block_given? response end def build_webmock_response(net_http_response) webmock_response = WebMock::Response.new webmock_response.status = [ net_http_response.code.to_i, net_http_response.message] webmock_response.headers = net_http_response.to_hash webmock_response.body = net_http_response.body webmock_response end def check_right_http_connection unless @@alredy_checked_for_right_http_connection ||= false WebMock::NetHTTPUtility.puts_warning_for_right_http_if_needed @@alredy_checked_for_right_http_connection = true end end end @webMockNetHTTP.version_1_2 [ [:Get, Net::HTTP::Get], [:Post, Net::HTTP::Post], [:Put, Net::HTTP::Put], [:Delete, Net::HTTP::Delete], [:Head, Net::HTTP::Head], [:Options, Net::HTTP::Options] ].each do |c| @webMockNetHTTP.const_set(c[0], c[1]) end end end end class StubSocket #:nodoc: attr_accessor :read_timeout, :continue_timeout, :write_timeout def initialize(*args) @closed = false end def closed? @closed end def close @closed = true nil end def readuntil(*args) end def io @io ||= StubIO.new end class StubIO def setsockopt(*args); end def peer_cert; end def peeraddr; ["AF_INET", 443, "127.0.0.1", "127.0.0.1"] end def ssl_version; "TLSv1.3" end def cipher; ["TLS_AES_128_GCM_SHA256", "TLSv1.3", 128, 128] end end end module WebMock module NetHTTPUtility def self.request_signature_from_request(net_http, request, body = nil) path = request.path if path.respond_to?(:request_uri) #https://github.com/bblimke/webmock/issues/288 path = path.request_uri end path = WebMock::Util::URI.heuristic_parse(path).request_uri if path =~ /^http/ uri = get_uri(net_http, path) method = request.method.downcase.to_sym headers = Hash[*request.to_hash.map {|k,v| [k, v]}.inject([]) {|r,x| r + x}] if request.body_stream body = request.body_stream.read request.body_stream = nil end if body != nil && body.respond_to?(:read) request.set_body_internal body.read else request.set_body_internal body end WebMock::RequestSignature.new(method, uri, body: request.body, headers: headers) end def self.get_uri(net_http, path = nil) protocol = net_http.use_ssl? ? "https" : "http" hostname = net_http.address hostname = "[#{hostname}]" if /\A\[.*\]\z/ !~ hostname && /:/ =~ hostname "#{protocol}://#{hostname}:#{net_http.port}#{path}" end def self.check_right_http_connection @was_right_http_connection_loaded = defined?(RightHttpConnection) end def self.puts_warning_for_right_http_if_needed if !@was_right_http_connection_loaded && defined?(RightHttpConnection) $stderr.puts "\nWarning: RightHttpConnection has to be required before WebMock is required !!!\n" end end end end WebMock::NetHTTPUtility.check_right_http_connection webmock-3.18.1/lib/webmock/http_lib_adapters/excon_adapter.rb0000644000004100000410000001220314333126774024321 0ustar www-datawww-databegin require 'excon' rescue LoadError # excon not found end if defined?(Excon) WebMock::VersionChecker.new('Excon', Excon::VERSION, '0.27.5').check_version! module WebMock module HttpLibAdapters class ExconAdapter < HttpLibAdapter PARAMS_TO_DELETE = [:expects, :idempotent, :instrumentor_name, :instrumentor, :response_block, :__construction_args, :stack, :connection, :response] adapter_for :excon instance_exec do @original_excon_mock_default = nil @stub = nil end def self.enable! self.add_excon_stub end def self.disable! self.remove_excon_stub end def self.add_excon_stub if not @stub @original_excon_mock_default = ::Excon.defaults[:mock] ::Excon.defaults[:mock] = true @stub = ::Excon.stub({}) do |params| self.handle_request(params) end end end def self.remove_excon_stub ::Excon.defaults[:mock] = @original_excon_mock_default @original_excon_mock_default = nil Excon.stubs.delete(@stub) @stub = nil end def self.handle_request(params) mock_request = self.build_request params.dup WebMock::RequestRegistry.instance.requested_signatures.put(mock_request) if mock_response = WebMock::StubRegistry.instance.response_for_request(mock_request) self.perform_callbacks(mock_request, mock_response, real_request: false) response = self.real_response(mock_response) response elsif WebMock.net_connect_allowed?(mock_request.uri) conn = new_excon_connection(params) real_response = conn.request(request_params_from(params.merge(mock: false))) ExconAdapter.perform_callbacks(mock_request, ExconAdapter.mock_response(real_response), real_request: true) real_response.data else raise WebMock::NetConnectNotAllowedError.new(mock_request) end end def self.new_excon_connection(params) # Ensure the connection is constructed with the exact same args # that the orginal connection was constructed with. args = params.fetch(:__construction_args) ::Excon::Connection.new(connection_params_from args.merge(mock: false)) end def self.connection_params_from(hash) hash = hash.dup PARAMS_TO_DELETE.each { |key| hash.delete(key) } hash end def self.request_params_from(hash) hash = hash.dup if defined?(Excon::VALID_REQUEST_KEYS) hash.reject! {|key,_| !Excon::VALID_REQUEST_KEYS.include?(key) } end PARAMS_TO_DELETE.each { |key| hash.delete(key) } hash end def self.to_query(hash) string = "".dup for key, values in hash if values.nil? string << key.to_s << '&' else for value in [*values] string << key.to_s << '=' << CGI.escape(value.to_s) << '&' end end end string.chop! # remove trailing '&' end def self.build_request(params) params = params.dup params.delete(:user) params.delete(:password) method = (params.delete(:method) || :get).to_s.downcase.to_sym params[:query] = to_query(params[:query]) if params[:query].is_a?(Hash) uri = Addressable::URI.new(params).to_s WebMock::RequestSignature.new method, uri, body: body_from(params), headers: params[:headers] end def self.body_from(params) body = params[:body] return body unless body.respond_to?(:read) contents = body.read body.rewind if body.respond_to?(:rewind) contents end def self.real_response(mock) raise Excon::Errors::Timeout if mock.should_timeout mock.raise_error_if_any { body: mock.body, status: mock.status[0].to_i, reason_phrase: mock.status[1], headers: mock.headers || {} } end def self.mock_response(real) mock = WebMock::Response.new mock.status = [real.status, real.reason_phrase] mock.headers = real.headers mock.body = real.body.dup mock end def self.perform_callbacks(request, response, options = {}) return unless WebMock::CallbackRegistry.any_callbacks? WebMock::CallbackRegistry.invoke_callbacks(options.merge(lib: :excon), request, response) end end end end Excon::Connection.class_eval do def self.new(args = {}) args.delete(:__construction_args) super(args).tap do |instance| instance.data[:__construction_args] = args end end end # Suppresses Excon connection argument validation warning Excon::VALID_CONNECTION_KEYS << :__construction_args end webmock-3.18.1/lib/webmock/http_lib_adapters/async_http_client_adapter.rb0000644000004100000410000001507214333126774026726 0ustar www-datawww-databegin require 'async' require 'async/http' rescue LoadError # async-http not found end if defined?(Async::HTTP) module WebMock module HttpLibAdapters class AsyncHttpClientAdapter < HttpLibAdapter adapter_for :async_http_client OriginalAsyncHttpClient = Async::HTTP::Client unless const_defined?(:OriginalAsyncHttpClient) class << self def enable! Async::HTTP.send(:remove_const, :Client) Async::HTTP.send(:const_set, :Client, Async::HTTP::WebMockClientWrapper) end def disable! Async::HTTP.send(:remove_const, :Client) Async::HTTP.send(:const_set, :Client, OriginalAsyncHttpClient) end end end end end module Async module HTTP class WebMockClientWrapper < Client def initialize( endpoint, protocol = endpoint.protocol, scheme = endpoint.scheme, authority = endpoint.authority, **options ) webmock_endpoint = WebMockEndpoint.new(scheme, authority, protocol) @network_client = WebMockClient.new(endpoint, **options) @webmock_client = WebMockClient.new(webmock_endpoint, **options) @scheme = scheme @authority = authority end def call(request) request.scheme ||= self.scheme request.authority ||= self.authority request_signature = build_request_signature(request) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) net_connect_allowed = WebMock.net_connect_allowed?(request_signature.uri) real_request = false if webmock_response webmock_response.raise_error_if_any raise Async::TimeoutError, 'WebMock timeout error' if webmock_response.should_timeout WebMockApplication.add_webmock_response(request, webmock_response) response = @webmock_client.call(request) elsif net_connect_allowed response = @network_client.call(request) real_request = true else raise WebMock::NetConnectNotAllowedError.new(request_signature) unless webmock_response end if WebMock::CallbackRegistry.any_callbacks? webmock_response ||= build_webmock_response(response) WebMock::CallbackRegistry.invoke_callbacks( { lib: :async_http_client, real_request: real_request }, request_signature, webmock_response ) end response end def close @network_client.close @webmock_client.close end private def build_request_signature(request) body = request.read request.body = ::Protocol::HTTP::Body::Buffered.wrap(body) WebMock::RequestSignature.new( request.method.downcase.to_sym, "#{request.scheme}://#{request.authority}#{request.path}", headers: request.headers.to_h, body: body ) end def build_webmock_response(response) body = response.read response.body = ::Protocol::HTTP::Body::Buffered.wrap(body) webmock_response = WebMock::Response.new webmock_response.status = [ response.status, ::Protocol::HTTP1::Reason::DESCRIPTIONS[response.status] ] webmock_response.headers = build_webmock_response_headers(response) webmock_response.body = body webmock_response end def build_webmock_response_headers(response) response.headers.each.each_with_object({}) do |(k, v), o| o[k] ||= [] o[k] << v end end end class WebMockClient < Client end class WebMockEndpoint def initialize(scheme, authority, protocol) @scheme = scheme @authority = authority @protocol = protocol end attr :scheme, :authority, :protocol def connect server_socket, client_socket = create_connected_sockets Async(transient: true) do accept_socket(server_socket) end client_socket end def inspect "\#<#{self.class}> #{scheme}://#{authority} protocol=#{protocol}" end private def create_connected_sockets pair = begin Async::IO::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM) rescue Errno::EAFNOSUPPORT Async::IO::Socket.pair(Socket::AF_INET, Socket::SOCK_STREAM) end pair.tap do |sockets| sockets.each do |socket| socket.instance_variable_set :@alpn_protocol, nil socket.instance_eval do def alpn_protocol nil # means HTTP11 will be used for HTTPS end end end end end def accept_socket(socket) server = Async::HTTP::Server.new(WebMockApplication, self) server.accept(socket, socket.remote_address) end end module WebMockApplication WEBMOCK_REQUEST_ID_HEADER = 'x-webmock-request-id'.freeze class << self def call(request) request.read webmock_response = get_webmock_response(request) build_response(webmock_response) end def add_webmock_response(request, webmock_response) webmock_request_id = request.object_id.to_s request.headers.add(WEBMOCK_REQUEST_ID_HEADER, webmock_request_id) webmock_responses[webmock_request_id] = webmock_response end def get_webmock_response(request) webmock_request_id = request.headers[WEBMOCK_REQUEST_ID_HEADER][0] webmock_responses.fetch(webmock_request_id) end private def webmock_responses @webmock_responses ||= {} end def build_response(webmock_response) headers = (webmock_response.headers || {}).each_with_object([]) do |(k, value), o| Array(value).each do |v| o.push [k, v] end end ::Protocol::HTTP::Response[ webmock_response.status[0], headers, webmock_response.body ] end end end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/curb_adapter.rb0000644000004100000410000002351214333126774024145 0ustar www-datawww-databegin require 'curb' rescue LoadError # curb not found end if defined?(Curl) WebMock::VersionChecker.new('Curb', Curl::CURB_VERSION, '0.7.16', '1.0.1', ['0.8.7']).check_version! module WebMock module HttpLibAdapters class CurbAdapter < HttpLibAdapter adapter_for :curb OriginalCurlEasy = Curl::Easy unless const_defined?(:OriginalCurlEasy) def self.enable! Curl.send(:remove_const, :Easy) Curl.send(:const_set, :Easy, Curl::WebMockCurlEasy) end def self.disable! Curl.send(:remove_const, :Easy) Curl.send(:const_set, :Easy, OriginalCurlEasy) end # Borrowed from Patron: # http://github.com/toland/patron/blob/master/lib/patron/response.rb def self.parse_header_string(header_string) status, headers = nil, {} header_string.split(/\r\n/).each do |header| if header =~ %r|^HTTP/1.[01] \d\d\d (.*)| status = $1 else parts = header.split(':', 2) unless parts.empty? parts[1].strip! unless parts[1].nil? if headers.has_key?(parts[0]) headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array headers[parts[0]] << parts[1] else headers[parts[0]] = parts[1] end end end end return status, headers end end end end module Curl class WebMockCurlEasy < Curl::Easy def curb_or_webmock request_signature = build_request_signature WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) build_curb_response(webmock_response) WebMock::CallbackRegistry.invoke_callbacks( {lib: :curb}, request_signature, webmock_response) invoke_curb_callbacks true elsif WebMock.net_connect_allowed?(request_signature.uri) res = yield if WebMock::CallbackRegistry.any_callbacks? webmock_response = build_webmock_response WebMock::CallbackRegistry.invoke_callbacks( {lib: :curb, real_request: true}, request_signature, webmock_response) end res else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def build_request_signature method = @webmock_method.to_s.downcase.to_sym uri = WebMock::Util::URI.heuristic_parse(self.url) uri.path = uri.normalized_path.gsub("[^:]//","/") headers = headers_as_hash(self.headers).merge(basic_auth_headers) request_body = case method when :post, :patch self.post_body || @post_body when :put @put_data else nil end if defined?( @on_debug ) @on_debug.call("Trying 127.0.0.1...\r\n", 0) @on_debug.call('Connected to ' + uri.hostname + "\r\n", 0) @debug_method = method.upcase @debug_path = uri.path @debug_host = uri.hostname http_request = ["#{@debug_method} #{@debug_path} HTTP/1.1"] http_request << "Host: #{uri.hostname}" headers.each do |name, value| http_request << "#{name}: #{value}" end @on_debug.call(http_request.join("\r\n") + "\r\n\r\n", 2) if request_body @on_debug.call(request_body + "\r\n", 4) @on_debug.call( "upload completely sent off: #{request_body.bytesize}"\ " out of #{request_body.bytesize} bytes\r\n", 0 ) end end request_signature = WebMock::RequestSignature.new( method, uri.to_s, body: request_body, headers: headers ) request_signature end def headers_as_hash(headers) if headers.is_a?(Array) headers.inject({}) {|hash, header| name, value = header.split(":", 2).map(&:strip) hash[name] = value hash } else headers end end def basic_auth_headers if self.username {'Authorization' => WebMock::Util::Headers.basic_auth_header(self.username, self.password)} else {} end end def build_curb_response(webmock_response) raise Curl::Err::TimeoutError if webmock_response.should_timeout webmock_response.raise_error_if_any @body_str = webmock_response.body @response_code = webmock_response.status[0] @header_str = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}\r\n".dup @on_debug.call(@header_str, 1) if defined?( @on_debug ) if webmock_response.headers @header_str << webmock_response.headers.map do |k,v| header = "#{k}: #{v.is_a?(Array) ? v.join(", ") : v}" @on_debug.call(header + "\r\n", 1) if defined?( @on_debug ) header end.join("\r\n") @on_debug.call("\r\n", 1) if defined?( @on_debug ) location = webmock_response.headers['Location'] if self.follow_location? && location @last_effective_url = location webmock_follow_location(location) end @content_type = webmock_response.headers["Content-Type"] @transfer_encoding = webmock_response.headers["Transfer-Encoding"] end @last_effective_url ||= self.url end def webmock_follow_location(location) first_url = self.url self.url = location curb_or_webmock do send( :http, {'method' => @webmock_method} ) end self.url = first_url end def invoke_curb_callbacks @on_progress.call(0.0,1.0,0.0,1.0) if defined?( @on_progress ) self.header_str.lines.each { |header_line| @on_header.call header_line } if defined?( @on_header ) if defined?( @on_body ) if chunked_response? self.body_str.each do |chunk| @on_body.call(chunk) end else @on_body.call(self.body_str) end end @on_complete.call(self) if defined?( @on_complete ) case response_code when 200..299 @on_success.call(self) if defined?( @on_success ) when 400..499 @on_missing.call(self, self.response_code) if defined?( @on_missing ) when 500..599 @on_failure.call(self, self.response_code) if defined?( @on_failure ) end end def chunked_response? defined?( @transfer_encoding ) && @transfer_encoding == 'chunked' && self.body_str.respond_to?(:each) end def build_webmock_response status, headers = WebMock::HttpLibAdapters::CurbAdapter.parse_header_string(self.header_str) if defined?( @on_debug ) http_response = ["HTTP/1.0 #{@debug_method} #{@debug_path}"] headers.each do |name, value| http_response << "#{name}: #{value}" end http_response << self.body_str @on_debug.call(http_response.join("\r\n") + "\r\n", 3) @on_debug.call("Connection #0 to host #{@debug_host} left intact\r\n", 0) end webmock_response = WebMock::Response.new webmock_response.status = [self.response_code, status] webmock_response.body = self.body_str webmock_response.headers = headers webmock_response end ### ### Mocks of Curl::Easy methods below here. ### def http(method) @webmock_method = method super end %w[ get head delete ].each do |verb| define_method "http_#{verb}" do @webmock_method = verb super() end end def http_put data = nil @webmock_method = :put @put_data = data if data super end alias put http_put def http_post *data @webmock_method = :post @post_body = data.join('&') if data && !data.empty? super end alias post http_post def perform @webmock_method ||= :get curb_or_webmock { super } ensure reset_webmock_method end def put_data= data @webmock_method = :put @put_data = data super end def post_body= data @webmock_method = :post super end def delete= value @webmock_method = :delete if value super end def head= value @webmock_method = :head if value super end def verbose=(verbose) @verbose = verbose end def verbose? @verbose ||= false end def body_str @body_str ||= super end alias body body_str def response_code @response_code ||= super end def header_str @header_str ||= super end alias head header_str def last_effective_url @last_effective_url ||= super end def content_type @content_type ||= super end %w[ success failure missing header body complete progress debug ].each do |callback| class_eval <<-METHOD, __FILE__, __LINE__ def on_#{callback} &block @on_#{callback} = block super end METHOD end def reset_webmock_method @webmock_method = :get end def reset instance_variable_set(:@body_str, nil) instance_variable_set(:@content_type, nil) instance_variable_set(:@header_str, nil) instance_variable_set(:@last_effective_url, nil) instance_variable_set(:@response_code, nil) super end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb0000644000004100000410000000051114333126774026741 0ustar www-datawww-datamodule WebMock class HttpLibAdapterRegistry include Singleton attr_accessor :http_lib_adapters def initialize @http_lib_adapters = {} end def register(lib, adapter) @http_lib_adapters[lib] = adapter end def each_adapter(&block) @http_lib_adapters.each(&block) end end endwebmock-3.18.1/lib/webmock/http_lib_adapters/manticore_adapter.rb0000644000004100000410000001222714333126774025174 0ustar www-datawww-databegin require 'manticore' rescue LoadError # manticore not found end if defined?(Manticore) module WebMock module HttpLibAdapters class ManticoreAdapter < HttpLibAdapter adapter_for :manticore OriginalManticoreClient = Manticore::Client def self.enable! Manticore.send(:remove_const, :Client) Manticore.send(:const_set, :Client, WebMockManticoreClient) Manticore.instance_variable_set(:@manticore_facade, WebMockManticoreClient.new) end def self.disable! Manticore.send(:remove_const, :Client) Manticore.send(:const_set, :Client, OriginalManticoreClient) Manticore.instance_variable_set(:@manticore_facade, OriginalManticoreClient.new) end class StubbedTimeoutResponse < Manticore::StubbedResponse def call @handlers[:failure].call(Manticore::ConnectTimeout.new("Too slow (mocked timeout)")) end end class WebMockManticoreClient < Manticore::Client def request(klass, url, options={}, &block) super(klass, WebMock::Util::URI.normalize_uri(url).to_s, format_options(options)) end private def format_options(options) return options unless headers = options[:headers] options.merge(headers: join_array_values(headers)) end def join_array_values(headers) headers.reduce({}) do |h, (k,v)| v = v.join(', ') if v.is_a?(Array) h.merge(k => v) end end def response_object_for(request, context, &block) request_signature = generate_webmock_request_signature(request, context) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_response = registered_response_for(request_signature) webmock_response.raise_error_if_any manticore_response = generate_manticore_response(webmock_response) manticore_response.on_success do WebMock::CallbackRegistry.invoke_callbacks({lib: :manticore, real_request: false}, request_signature, webmock_response) end elsif real_request_allowed?(request_signature.uri) manticore_response = Manticore::Response.new(self, request, context, &block) manticore_response.on_complete do |completed_response| webmock_response = generate_webmock_response(completed_response) WebMock::CallbackRegistry.invoke_callbacks({lib: :manticore, real_request: true}, request_signature, webmock_response) end else raise WebMock::NetConnectNotAllowedError.new(request_signature) end manticore_response end def registered_response_for(request_signature) WebMock::StubRegistry.instance.response_for_request(request_signature) end def real_request_allowed?(uri) WebMock.net_connect_allowed?(uri) end def generate_webmock_request_signature(request, context) method = request.method.downcase uri = request.uri.to_s body = read_body(request) headers = split_array_values(request.headers) if context.get_credentials_provider && credentials = context.get_credentials_provider.get_credentials(AuthScope::ANY) headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(credentials.get_user_name,credentials.get_password) end WebMock::RequestSignature.new(method, uri, {body: body, headers: headers}) end def read_body(request) if request.respond_to?(:entity) && !request.entity.nil? Manticore::EntityConverter.new.read_entity(request.entity) end end def split_array_values(headers = []) headers.each_with_object({}) do |(k, v), h| h[k] = case v when /,/ then v.split(',').map(&:strip) else v end end end def generate_manticore_response(webmock_response) if webmock_response.should_timeout StubbedTimeoutResponse.new else Manticore::StubbedResponse.stub( code: webmock_response.status[0], body: webmock_response.body, headers: webmock_response.headers, cookies: {} ) end end def generate_webmock_response(manticore_response) webmock_response = WebMock::Response.new webmock_response.status = [manticore_response.code, manticore_response.message] webmock_response.headers = manticore_response.headers # The attempt to read the body could fail if manticore is used in a streaming mode webmock_response.body = begin manticore_response.body rescue ::Manticore::StreamClosedException nil end webmock_response end end end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb_adapter.rb0000644000004100000410000000150414333126774024651 0ustar www-datawww-databegin require "http" rescue LoadError # HTTP gem not found end if defined?(HTTP) && defined?(HTTP::VERSION) WebMock::VersionChecker.new("HTTP Gem", HTTP::VERSION, "0.6.0").check_version! module WebMock module HttpLibAdapters class HttpRbAdapter < HttpLibAdapter adapter_for :http_rb class << self def enable! @enabled = true end def disable! @enabled = false end def enabled? @enabled end end end end end require "webmock/http_lib_adapters/http_rb/client" require "webmock/http_lib_adapters/http_rb/request" require "webmock/http_lib_adapters/http_rb/response" require "webmock/http_lib_adapters/http_rb/streamer" require "webmock/http_lib_adapters/http_rb/webmock" end webmock-3.18.1/lib/webmock/http_lib_adapters/em_http_request_adapter.rb0000644000004100000410000001614714333126774026430 0ustar www-datawww-databegin require 'em-http-request' rescue LoadError # em-http-request not found end if defined?(EventMachine::HttpClient) module WebMock module HttpLibAdapters class EmHttpRequestAdapter < HttpLibAdapter adapter_for :em_http_request OriginalHttpClient = EventMachine::HttpClient unless const_defined?(:OriginalHttpClient) OriginalHttpConnection = EventMachine::HttpConnection unless const_defined?(:OriginalHttpConnection) def self.enable! EventMachine.send(:remove_const, :HttpConnection) EventMachine.send(:const_set, :HttpConnection, EventMachine::WebMockHttpConnection) EventMachine.send(:remove_const, :HttpClient) EventMachine.send(:const_set, :HttpClient, EventMachine::WebMockHttpClient) end def self.disable! EventMachine.send(:remove_const, :HttpConnection) EventMachine.send(:const_set, :HttpConnection, OriginalHttpConnection) EventMachine.send(:remove_const, :HttpClient) EventMachine.send(:const_set, :HttpClient, OriginalHttpClient) end end end end module EventMachine if defined?(Synchrony) && HTTPMethods.instance_methods.include?(:aget) # have to make the callbacks fire on the next tick in order # to avoid the dreaded "double resume" exception module HTTPMethods %w[get head post delete put].each do |type| class_eval %[ def #{type}(options = {}, &blk) f = Fiber.current conn = setup_request(:#{type}, options, &blk) conn.callback { EM.next_tick { f.resume(conn) } } conn.errback { EM.next_tick { f.resume(conn) } } Fiber.yield end ] end end end class WebMockHttpConnection < HttpConnection def activate_connection(client) request_signature = client.request_signature if client.stubbed_webmock_response conn = HttpStubConnection.new rand(10000) post_init @deferred = false @conn = conn conn.parent = self conn.pending_connect_timeout = @connopts.connect_timeout conn.comm_inactivity_timeout = @connopts.inactivity_timeout finalize_request(client) @conn.set_deferred_status :succeeded elsif WebMock.net_connect_allowed?(request_signature.uri) super else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def drop_client @clients.shift end end class WebMockHttpClient < EventMachine::HttpClient include HttpEncoding def uri @req.uri end def setup(response, uri, error = nil) @last_effective_url = @uri = uri if error on_error(error) @conn.drop_client fail(self) else @conn.receive_data(response) succeed(self) end end def connection_completed @state = :response_header send_request(request_signature.headers, request_signature.body) end def send_request(head, body) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if stubbed_webmock_response WebMock::CallbackRegistry.invoke_callbacks({lib: :em_http_request}, request_signature, stubbed_webmock_response) @uri ||= nil EM.next_tick { setup(make_raw_response(stubbed_webmock_response), @uri, stubbed_webmock_response.should_timeout ? Errno::ETIMEDOUT : nil) } self elsif WebMock.net_connect_allowed?(request_signature.uri) super else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def unbind(reason = nil) if !stubbed_webmock_response && WebMock::CallbackRegistry.any_callbacks? webmock_response = build_webmock_response WebMock::CallbackRegistry.invoke_callbacks( {lib: :em_http_request, real_request: true}, request_signature, webmock_response) end @request_signature = nil remove_instance_variable(:@stubbed_webmock_response) super end def request_signature @request_signature ||= build_request_signature end def stubbed_webmock_response unless defined?(@stubbed_webmock_response) @stubbed_webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) end @stubbed_webmock_response end def get_response_cookie(name) name = name.to_s raw_cookie = response_header.cookie raw_cookie = [raw_cookie] if raw_cookie.is_a? String cookie = raw_cookie.select { |c| c.start_with? name }.first cookie and cookie.split('=', 2)[1] end private def build_webmock_response webmock_response = WebMock::Response.new webmock_response.status = [response_header.status, response_header.http_reason] webmock_response.headers = response_header webmock_response.body = response webmock_response end def build_request_signature headers, body = build_request, @req.body @conn.middleware.select {|m| m.respond_to?(:request) }.each do |m| headers, body = m.request(self, headers, body) end method = @req.method uri = @req.uri.clone query = @req.query uri.query = encode_query(@req.uri, query).slice(/\?(.*)/, 1) body = form_encode_body(body) if body.is_a?(Hash) if headers['authorization'] && headers['authorization'].is_a?(Array) headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(headers.delete('authorization')) end WebMock::RequestSignature.new( method.downcase.to_sym, uri.to_s, body: body || (@req.file && File.read(@req.file)), headers: headers ) end def make_raw_response(response) response.raise_error_if_any status, headers, body = response.status, response.headers, response.body headers ||= {} response_string = [] response_string << "HTTP/1.1 #{status[0]} #{status[1]}" headers["Content-Length"] = body.bytesize unless headers["Content-Length"] headers.each do |header, value| if header =~ /set-cookie/i [value].flatten.each do |cookie| response_string << "#{header}: #{cookie}" end else value = value.join(", ") if value.is_a?(Array) # WebMock's internal processing will not handle the body # correctly if the header indicates that it is chunked, unless # we also create all the chunks. # It's far easier just to remove the header. next if header =~ /transfer-encoding/i && value =~/chunked/i response_string << "#{header}: #{value}" end end if headers response_string << "" << body response_string.join("\n") end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/0000755000004100000410000000000014333126774022624 5ustar www-datawww-datawebmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/streamer.rb0000644000004100000410000000123714333126774024776 0ustar www-datawww-datamodule HTTP class Response class Streamer def initialize(str, encoding: Encoding::BINARY) @io = StringIO.new str @encoding = encoding end def readpartial(size = nil, outbuf = nil) unless size if defined?(HTTP::Client::BUFFER_SIZE) size = HTTP::Client::BUFFER_SIZE elsif defined?(HTTP::Connection::BUFFER_SIZE) size = HTTP::Connection::BUFFER_SIZE end end chunk = @io.read size, outbuf chunk.force_encoding(@encoding) if chunk end def close @io.close end def sequence_id -1 end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/client.rb0000644000004100000410000000055114333126774024430 0ustar www-datawww-datamodule HTTP class Client alias_method :__perform__, :perform def perform(request, options) return __perform__(request, options) unless webmock_enabled? WebMockPerform.new(request, options) { __perform__(request, options) }.exec end def webmock_enabled? ::WebMock::HttpLibAdapters::HttpRbAdapter.enabled? end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/request.rb0000644000004100000410000000063014333126774024640 0ustar www-datawww-datamodule HTTP class Request def webmock_signature request_body = if defined?(HTTP::Request::Body) ''.tap { |string| body.each { |part| string << part } } else body end ::WebMock::RequestSignature.new(verb, uri.to_s, { headers: headers.to_h, body: request_body }) end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/webmock.rb0000644000004100000410000000356414333126774024610 0ustar www-datawww-datamodule HTTP class WebMockPerform def initialize(request, options, &perform) @request = request @options = options @perform = perform @request_signature = nil end def exec replay || perform || halt end def request_signature unless @request_signature @request_signature = @request.webmock_signature register_request(@request_signature) end @request_signature end protected def response_for_request(signature) ::WebMock::StubRegistry.instance.response_for_request(signature) end def register_request(signature) ::WebMock::RequestRegistry.instance.requested_signatures.put(signature) end def replay webmock_response = response_for_request request_signature return unless webmock_response raise_timeout_error if webmock_response.should_timeout webmock_response.raise_error_if_any invoke_callbacks(webmock_response, real_request: false) response = ::HTTP::Response.from_webmock @request, webmock_response, request_signature @options.features.each { |_name, feature| response = feature.wrap_response(response) } response end def raise_timeout_error raise Errno::ETIMEDOUT if HTTP::VERSION < "1.0.0" raise HTTP::TimeoutError, "connection error: #{Errno::ETIMEDOUT.new}" end def perform return unless ::WebMock.net_connect_allowed?(request_signature.uri) response = @perform.call invoke_callbacks(response.to_webmock, real_request: true) response end def halt raise ::WebMock::NetConnectNotAllowedError.new request_signature end def invoke_callbacks(webmock_response, options = {}) ::WebMock::CallbackRegistry.invoke_callbacks( options.merge({ lib: :http_rb }), request_signature, webmock_response ) end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_rb/response.rb0000644000004100000410000000360214333126774025010 0ustar www-datawww-datamodule HTTP class Response def to_webmock webmock_response = ::WebMock::Response.new webmock_response.status = [status.to_i, reason] webmock_response.body = body.to_s webmock_response.headers = headers.to_h webmock_response end class << self def from_webmock(request, webmock_response, request_signature = nil) status = Status.new(webmock_response.status.first) headers = webmock_response.headers || {} uri = normalize_uri(request_signature && request_signature.uri) # HTTP.rb 3.0+ uses a keyword argument to pass the encoding, but 1.x # and 2.x use a positional argument, and 0.x don't support supplying # the encoding. body = if HTTP::VERSION < "1.0.0" Body.new(Streamer.new(webmock_response.body)) elsif HTTP::VERSION < "3.0.0" Body.new(Streamer.new(webmock_response.body), webmock_response.body.encoding) else Body.new( Streamer.new(webmock_response.body, encoding: webmock_response.body.encoding), encoding: webmock_response.body.encoding ) end return new(status, "1.1", headers, body, uri) if HTTP::VERSION < "1.0.0" # 5.0.0 had a breaking change to require request instead of uri. if HTTP::VERSION < '5.0.0' return new({ status: status, version: "1.1", headers: headers, body: body, uri: uri }) end new({ status: status, version: "1.1", headers: headers, body: body, request: request, }) end private def normalize_uri(uri) return unless uri uri = Addressable::URI.parse uri uri.port = nil if uri.default_port && uri.port == uri.default_port uri end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/patron_adapter.rb0000644000004100000410000001120614333126774024512 0ustar www-datawww-databegin require 'patron' rescue LoadError # patron not found end if defined?(::Patron) module WebMock module HttpLibAdapters class PatronAdapter < ::WebMock::HttpLibAdapter adapter_for :patron OriginalPatronSession = ::Patron::Session unless const_defined?(:OriginalPatronSession) class WebMockPatronSession < ::Patron::Session def handle_request(req) request_signature = WebMock::HttpLibAdapters::PatronAdapter.build_request_signature(req) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature) WebMock::HttpLibAdapters::PatronAdapter. handle_file_name(req, webmock_response) res = WebMock::HttpLibAdapters::PatronAdapter. build_patron_response(webmock_response, default_response_charset) WebMock::CallbackRegistry.invoke_callbacks( {lib: :patron}, request_signature, webmock_response) res elsif WebMock.net_connect_allowed?(request_signature.uri) res = super if WebMock::CallbackRegistry.any_callbacks? webmock_response = WebMock::HttpLibAdapters::PatronAdapter. build_webmock_response(res) WebMock::CallbackRegistry.invoke_callbacks( {lib: :patron, real_request: true}, request_signature, webmock_response) end res else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end end def self.enable! Patron.send(:remove_const, :Session) Patron.send(:const_set, :Session, WebMockPatronSession) end def self.disable! Patron.send(:remove_const, :Session) Patron.send(:const_set, :Session, OriginalPatronSession) end def self.handle_file_name(req, webmock_response) if req.action == :get && req.file_name begin File.open(req.file_name, "w") do |f| f.write webmock_response.body end rescue Errno::EACCES raise ArgumentError.new("Unable to open specified file.") end end end def self.build_request_signature(req) uri = WebMock::Util::URI.heuristic_parse(req.url) uri.path = uri.normalized_path.gsub("[^:]//","/") if [:put, :post, :patch].include?(req.action) if req.file_name if !File.exist?(req.file_name) || !File.readable?(req.file_name) raise ArgumentError.new("Unable to open specified file.") end request_body = File.read(req.file_name) elsif req.upload_data request_body = req.upload_data else raise ArgumentError.new("Must provide either data or a filename when doing a PUT or POST") end end headers = req.headers if req.credentials headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(req.credentials) end request_signature = WebMock::RequestSignature.new( req.action, uri.to_s, body: request_body, headers: headers ) request_signature end def self.build_patron_response(webmock_response, default_response_charset) raise ::Patron::TimeoutError if webmock_response.should_timeout webmock_response.raise_error_if_any header_fields = (webmock_response.headers || []).map { |(k, vs)| Array(vs).map { |v| "#{k}: #{v}" } }.flatten status_line = "HTTP/1.1 #{webmock_response.status[0]} #{webmock_response.status[1]}" header_data = ([status_line] + header_fields).join("\r\n") ::Patron::Response.new( "".dup, webmock_response.status[0], 0, header_data, webmock_response.body.dup, default_response_charset ) end def self.build_webmock_response(patron_response) webmock_response = WebMock::Response.new reason = patron_response.status_line. scan(%r(\AHTTP/(\d+(?:\.\d+)?)\s+(\d\d\d)\s*([^\r\n]+)?))[0][2] webmock_response.status = [patron_response.status, reason] webmock_response.body = patron_response.body webmock_response.headers = patron_response.headers webmock_response end end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/net_http_response.rb0000644000004100000410000000236614333126774025261 0ustar www-datawww-data# This code is entierly copied from VCR (http://github.com/myronmarston/vcr) by courtesy of Myron Marston # A Net::HTTP response that has already been read raises an IOError when #read_body # is called with a destination string or block. # # This causes a problem when VCR records a response--it reads the body before yielding # the response, and if the code that is consuming the HTTP requests uses #read_body, it # can cause an error. # # This is a bit of a hack, but it allows a Net::HTTP response to be "re-read" # after it has aleady been read. This attemps to preserve the behavior of # #read_body, acting just as if it had never been read. module Net module WebMockHTTPResponse def read_body(dest = nil, &block) if !(defined?(@__read_body_previously_called).nil?) && @__read_body_previously_called return super end return @body if dest.nil? && block.nil? raise ArgumentError.new("both arg and block given for HTTP method") if dest && block return nil if @body.nil? dest ||= ::Net::ReadAdapter.new(block) dest << @body.dup @body = dest ensure # allow subsequent calls to #read_body to proceed as normal, without our hack... @__read_body_previously_called = true end end end webmock-3.18.1/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb0000644000004100000410000001322414333126774026260 0ustar www-datawww-databegin require 'typhoeus' rescue LoadError # typhoeus not found end if defined?(Typhoeus) WebMock::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.3.2').check_version! module WebMock module HttpLibAdapters class TyphoeusAdapter < HttpLibAdapter adapter_for :typhoeus def self.enable! @disabled = false add_before_callback add_after_request_callback ::Typhoeus::Config.block_connection = true end def self.disable! @disabled = true remove_after_request_callback remove_before_callback ::Typhoeus::Config.block_connection = false end def self.disabled? !!@disabled end def self.add_before_callback unless Typhoeus.before.include?(BEFORE_CALLBACK) Typhoeus.before << BEFORE_CALLBACK end end def self.remove_before_callback Typhoeus.before.delete_if {|v| v == BEFORE_CALLBACK } end def self.add_after_request_callback unless Typhoeus.on_complete.include?(AFTER_REQUEST_CALLBACK) Typhoeus.on_complete << AFTER_REQUEST_CALLBACK end end def self.remove_after_request_callback Typhoeus.on_complete.delete_if {|v| v == AFTER_REQUEST_CALLBACK } end def self.build_request_signature(req) uri = WebMock::Util::URI.heuristic_parse(req.url) uri.path = uri.normalized_path.gsub("[^:]//","/") headers = req.options[:headers] if req.options[:userpwd] headers['Authorization'] = WebMock::Util::Headers.basic_auth_header(req.options[:userpwd]) end body = req.options[:body] if body.is_a?(Hash) body = WebMock::Util::QueryMapper.values_to_query(body) end request_signature = WebMock::RequestSignature.new( req.options[:method] || :get, uri.to_s, body: body, headers: headers ) req.instance_variable_set(:@__webmock_request_signature, request_signature) request_signature end def self.build_webmock_response(typhoeus_response) webmock_response = WebMock::Response.new webmock_response.status = [typhoeus_response.code, typhoeus_response.status_message] webmock_response.body = typhoeus_response.body webmock_response.headers = typhoeus_response.headers webmock_response end def self.generate_typhoeus_response(request_signature, webmock_response) response = if webmock_response.should_timeout ::Typhoeus::Response.new( code: 0, status_message: "", body: "", headers: {}, return_code: :operation_timedout ) else ::Typhoeus::Response.new( code: webmock_response.status[0], status_message: webmock_response.status[1], body: webmock_response.body, headers: webmock_response.headers, effective_url: request_signature.uri ) end response.mock = :webmock response end def self.request_hash(request_signature) hash = {} hash[:body] = request_signature.body hash[:headers] = request_signature.headers hash end AFTER_REQUEST_CALLBACK = Proc.new do |response| request = response.request request_signature = request.instance_variable_get(:@__webmock_request_signature) webmock_response = ::WebMock::HttpLibAdapters::TyphoeusAdapter. build_webmock_response(response) if response.mock WebMock::CallbackRegistry.invoke_callbacks( {lib: :typhoeus}, request_signature, webmock_response ) else WebMock::CallbackRegistry.invoke_callbacks( {lib: :typhoeus, real_request: true}, request_signature, webmock_response ) end end BEFORE_CALLBACK = Proc.new do |request| Typhoeus::Expectation.all.delete_if {|e| e.from == :webmock } res = true unless WebMock::HttpLibAdapters::TyphoeusAdapter.disabled? request_signature = ::WebMock::HttpLibAdapters::TyphoeusAdapter.build_request_signature(request) request.block_connection = false; ::WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_response = ::WebMock::StubRegistry.instance.response_for_request(request_signature) # ::WebMock::HttpLibAdapters::TyphoeusAdapter.stub_typhoeus(request_signature, webmock_response, self) response = ::WebMock::HttpLibAdapters::TyphoeusAdapter.generate_typhoeus_response(request_signature, webmock_response) if request.respond_to?(:on_headers) request.execute_headers_callbacks(response) end if request.respond_to?(:streaming?) && request.streaming? response.options[:response_body] = "" request.on_body.each { |callback| callback.call(webmock_response.body, response) } end request.finish(response) webmock_response.raise_error_if_any res = false elsif !WebMock.net_connect_allowed?(request_signature.uri) raise WebMock::NetConnectNotAllowedError.new(request_signature) end end res end end end end end webmock-3.18.1/lib/webmock/http_lib_adapters/http_lib_adapter.rb0000644000004100000410000000023014333126774025007 0ustar www-datawww-datamodule WebMock class HttpLibAdapter def self.adapter_for(lib) WebMock::HttpLibAdapterRegistry.instance.register(lib, self) end end endwebmock-3.18.1/lib/webmock/http_lib_adapters/httpclient_adapter.rb0000644000004100000410000002013414333126774025365 0ustar www-datawww-databegin require 'httpclient' require 'jsonclient' # defined in 'httpclient' gem as well rescue LoadError # httpclient not found # or jsonclient not defined (in old versions of httclient gem) end if defined?(::HTTPClient) module WebMock module HttpLibAdapters class HTTPClientAdapter < HttpLibAdapter adapter_for :httpclient unless const_defined?(:OriginalHttpClient) OriginalHttpClient = ::HTTPClient end unless const_defined?(:OriginalJsonClient) OriginalJsonClient = ::JSONClient if defined?(::JSONClient) end def self.enable! Object.send(:remove_const, :HTTPClient) Object.send(:const_set, :HTTPClient, WebMockHTTPClient) if defined? ::JSONClient Object.send(:remove_const, :JSONClient) Object.send(:const_set, :JSONClient, WebMockJSONClient) end end def self.disable! Object.send(:remove_const, :HTTPClient) Object.send(:const_set, :HTTPClient, OriginalHttpClient) if defined? ::JSONClient Object.send(:remove_const, :JSONClient) Object.send(:const_set, :JSONClient, OriginalJsonClient) end end end end end module WebMockHTTPClients REQUEST_RESPONSE_LOCK = Mutex.new def do_get_block(req, proxy, conn, &block) do_get(req, proxy, conn, false, &block) end def do_get_stream(req, proxy, conn, &block) do_get(req, proxy, conn, true, &block) end def do_get(req, proxy, conn, stream = false, &block) request_signature = build_request_signature(req, :reuse_existing) WebMock::RequestRegistry.instance.requested_signatures.put(request_signature) if webmock_responses[request_signature] webmock_response = synchronize_request_response { webmock_responses.delete(request_signature) } response = build_httpclient_response(webmock_response, stream, req.header, &block) @request_filter.each do |filter| filter.filter_response(req, response) end res = conn.push(response) WebMock::CallbackRegistry.invoke_callbacks( {lib: :httpclient}, request_signature, webmock_response) res elsif WebMock.net_connect_allowed?(request_signature.uri) # in case there is a nil entry in the hash... synchronize_request_response { webmock_responses.delete(request_signature) } res = if stream do_get_stream_without_webmock(req, proxy, conn, &block) elsif block body = '' do_get_block_without_webmock(req, proxy, conn) do |http_res, chunk| if chunk && chunk.bytesize > 0 body += chunk block.call(http_res, chunk) end end else do_get_block_without_webmock(req, proxy, conn) end res = conn.pop conn.push(res) if WebMock::CallbackRegistry.any_callbacks? webmock_response = build_webmock_response(res, body) WebMock::CallbackRegistry.invoke_callbacks( {lib: :httpclient, real_request: true}, request_signature, webmock_response) end res else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def do_request_async(method, uri, query, body, extheader) req = create_request(method, uri, query, body, extheader) request_signature = build_request_signature(req) synchronize_request_response { webmock_request_signatures << request_signature } if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri) super else raise WebMock::NetConnectNotAllowedError.new(request_signature) end end def build_httpclient_response(webmock_response, stream = false, req_header = nil, &block) body = stream ? StringIO.new(webmock_response.body) : webmock_response.body response = HTTP::Message.new_response(body, req_header) response.header.init_response(webmock_response.status[0]) response.reason=webmock_response.status[1] webmock_response.headers.to_a.each { |name, value| response.header.set(name, value) } raise HTTPClient::TimeoutError if webmock_response.should_timeout webmock_response.raise_error_if_any block.call(response, body) if block && body && body.bytesize > 0 response end def build_webmock_response(httpclient_response, body = nil) webmock_response = WebMock::Response.new webmock_response.status = [httpclient_response.status, httpclient_response.reason] webmock_response.headers = {}.tap do |hash| httpclient_response.header.all.each do |(key, value)| if hash.has_key?(key) hash[key] = Array(hash[key]) + [value] else hash[key] = value end end end if body webmock_response.body = body elsif httpclient_response.content.respond_to?(:read) webmock_response.body = httpclient_response.content.read body = HTTP::Message::Body.new body.init_response(StringIO.new(webmock_response.body)) httpclient_response.body = body else webmock_response.body = httpclient_response.content end webmock_response end def build_request_signature(req, reuse_existing = false) uri = WebMock::Util::URI.heuristic_parse(req.header.request_uri.to_s) uri.query = WebMock::Util::QueryMapper.values_to_query(req.header.request_query, notation: WebMock::Config.instance.query_values_notation) if req.header.request_query uri.port = req.header.request_uri.port @request_filter.each do |filter| filter.filter_request(req) end headers = req.header.all.inject({}) do |hdrs, header| hdrs[header[0]] ||= [] hdrs[header[0]] << header[1] hdrs end headers = headers_from_session(uri).merge(headers) signature = WebMock::RequestSignature.new( req.header.request_method.downcase.to_sym, uri.to_s, body: req.http_body.dump, headers: headers ) # reuse a previous identical signature object if we stored one for later use if reuse_existing && previous_signature = previous_signature_for(signature) return previous_signature end signature end def webmock_responses @webmock_responses ||= Hash.new do |hash, request_signature| synchronize_request_response do hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature) end end end def webmock_request_signatures @webmock_request_signatures ||= [] end def previous_signature_for(signature) synchronize_request_response do return nil unless index = webmock_request_signatures.index(signature) webmock_request_signatures.delete_at(index) end end private # some of the headers sent by HTTPClient are derived from # the client session def headers_from_session(uri) session_headers = HTTP::Message::Headers.new @session_manager.send(:open, uri).send(:set_header, MessageMock.new(session_headers)) session_headers.all.inject({}) do |hdrs, header| hdrs[header[0]] = header[1] hdrs end end def synchronize_request_response if REQUEST_RESPONSE_LOCK.owned? yield else REQUEST_RESPONSE_LOCK.synchronize do yield end end end end class WebMockHTTPClient < HTTPClient alias_method :do_get_block_without_webmock, :do_get_block alias_method :do_get_stream_without_webmock, :do_get_stream include WebMockHTTPClients end if defined? ::JSONClient class WebMockJSONClient < JSONClient alias_method :do_get_block_without_webmock, :do_get_block alias_method :do_get_stream_without_webmock, :do_get_stream include WebMockHTTPClients end end # Mocks a HTTPClient HTTP::Message class MessageMock attr_reader :header def initialize(headers) @header = headers end def http_version=(value);end end end webmock-3.18.1/lib/webmock/request_signature.rb0000644000004100000410000000250714333126774021574 0ustar www-datawww-datamodule WebMock class RequestSignature attr_accessor :method, :uri, :body attr_reader :headers def initialize(method, uri, options = {}) self.method = method.to_sym self.uri = uri.is_a?(Addressable::URI) ? uri : WebMock::Util::URI.normalize_uri(uri) assign_options(options) end def to_s string = "#{self.method.to_s.upcase}".dup string << " #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}" string << " with body '#{body.to_s}'" if body && body.to_s != '' if headers && !headers.empty? string << " with headers #{WebMock::Util::Headers.sorted_headers_string(headers)}" end string end def headers=(headers) @headers = WebMock::Util::Headers.normalize_headers(headers) end def hash self.to_s.hash end def eql?(other) self.to_s == other.to_s end alias == eql? def url_encoded? !!(headers&.fetch('Content-Type', nil)&.start_with?('application/x-www-form-urlencoded')) end def json_headers? !!(headers&.fetch('Content-Type', nil)&.start_with?('application/json')) end private def assign_options(options) self.body = options[:body] if options.has_key?(:body) self.headers = options[:headers] if options.has_key?(:headers) end end end webmock-3.18.1/lib/webmock/rack_response.rb0000644000004100000410000000337014333126774020660 0ustar www-datawww-datamodule WebMock class RackResponse < Response def initialize(app) @app = app end def evaluate(request) env = build_rack_env(request) status, headers, response = @app.call(env) Response.new( body: body_from_rack_response(response), headers: headers, status: [status, Rack::Utils::HTTP_STATUS_CODES[status]] ) end def body_from_rack_response(response) body = "".dup response.each { |line| body << line } response.close if response.respond_to?(:close) return body end def build_rack_env(request) uri = request.uri headers = (request.headers || {}).dup body = request.body || '' env = { # CGI variables specified by Rack 'REQUEST_METHOD' => request.method.to_s.upcase, 'CONTENT_TYPE' => headers.delete('Content-Type'), 'CONTENT_LENGTH' => body.bytesize, 'PATH_INFO' => uri.path, 'QUERY_STRING' => uri.query || '', 'SERVER_NAME' => uri.host, 'SERVER_PORT' => uri.port, 'SCRIPT_NAME' => "" } env['HTTP_AUTHORIZATION'] = 'Basic ' + [uri.userinfo].pack('m').delete("\r\n") if uri.userinfo # Rack-specific variables env['rack.input'] = StringIO.new(body) env['rack.errors'] = $stderr env['rack.version'] = Rack::VERSION env['rack.url_scheme'] = uri.scheme env['rack.run_once'] = true env['rack.session'] = session env['rack.session.options'] = session_options headers.each do |k, v| env["HTTP_#{k.tr('-','_').upcase}"] = v end env end def session @session ||= {} end def session_options @session_options ||= {} end end end webmock-3.18.1/lib/webmock/config.rb0000644000004100000410000000065014333126774017265 0ustar www-datawww-datamodule WebMock class Config include Singleton def initialize @show_stubbing_instructions = true @show_body_diff = true end attr_accessor :allow_net_connect attr_accessor :allow_localhost attr_accessor :allow attr_accessor :net_http_connect_on_start attr_accessor :show_stubbing_instructions attr_accessor :query_values_notation attr_accessor :show_body_diff end end webmock-3.18.1/lib/webmock/request_stub.rb0000644000004100000410000000623314333126774020550 0ustar www-datawww-datamodule WebMock class RequestStub attr_accessor :request_pattern def initialize(method, uri) @request_pattern = RequestPattern.new(method, uri) @responses_sequences = [] self end def with(params = {}, &block) @request_pattern.with(params, &block) self end def to_return(*response_hashes, &block) if block @responses_sequences << ResponsesSequence.new([ResponseFactory.response_for(block)]) else @responses_sequences << ResponsesSequence.new([*response_hashes].flatten.map {|r| ResponseFactory.response_for(r)}) end self end alias_method :and_return, :to_return def to_return_json(*response_hashes) raise ArgumentError, '#to_return_json does not support passing a block' if block_given? json_response_hashes = [*response_hashes].flatten.map do |resp_h| headers, body = resp_h.values_at(:headers, :body) resp_h.merge( headers: {content_type: 'application/json'}.merge(headers.to_h), body: body.is_a?(Hash) ? body.to_json : body ) end to_return(json_response_hashes) end alias_method :and_return_json, :to_return_json def to_rack(app, options={}) @responses_sequences << ResponsesSequence.new([RackResponse.new(app)]) end def to_raise(*exceptions) @responses_sequences << ResponsesSequence.new([*exceptions].flatten.map {|e| ResponseFactory.response_for(exception: e) }) self end alias_method :and_raise, :to_raise def to_timeout @responses_sequences << ResponsesSequence.new([ResponseFactory.response_for(should_timeout: true)]) self end alias_method :and_timeout, :to_timeout def response if @responses_sequences.empty? WebMock::Response.new elsif @responses_sequences.length > 1 @responses_sequences.shift if @responses_sequences.first.end? @responses_sequences.first.next_response else @responses_sequences[0].next_response end end def has_responses? !@responses_sequences.empty? end def then self end def times(number) raise "times(N) accepts integers >= 1 only" if !number.is_a?(Integer) || number < 1 if @responses_sequences.empty? raise "Invalid WebMock stub declaration." + " times(N) can be declared only after response declaration." end @responses_sequences.last.times_to_repeat += number-1 self end def matches?(request_signature) self.request_pattern.matches?(request_signature) end def to_s self.request_pattern.to_s end def self.from_request_signature(signature) stub = self.new(signature.method.to_sym, signature.uri.to_s) if signature.body.to_s != '' body = if signature.url_encoded? WebMock::Util::QueryMapper.query_to_values(signature.body, notation: Config.instance.query_values_notation) else signature.body end stub.with(body: body) end if (signature.headers && !signature.headers.empty?) stub.with(headers: signature.headers) end stub end end end webmock-3.18.1/lib/webmock/rspec.rb0000644000004100000410000000162214333126774017134 0ustar www-datawww-datarequire 'webmock' # RSpec 1.x and 2.x compatibility if defined?(RSpec::Expectations::ExpectationNotMetError) RSPEC_NAMESPACE = RSPEC_CONFIGURER = RSpec elsif defined?(Spec) && defined?(Spec.configure) RSPEC_NAMESPACE = Spec RSPEC_CONFIGURER = Spec::Runner else begin require 'rspec/core' require 'rspec/expectations' RSPEC_NAMESPACE = RSPEC_CONFIGURER = RSpec rescue LoadError require 'spec' RSPEC_NAMESPACE = Spec RSPEC_CONFIGURER = Spec::Runner end end require 'webmock/rspec/matchers' RSPEC_CONFIGURER.configure { |config| config.include WebMock::API config.include WebMock::Matchers config.before(:suite) do WebMock.enable! end config.after(:suite) do WebMock.disable! end config.around(:each) do |example| example.run WebMock.reset! end } WebMock::AssertionFailure.error_class = RSPEC_NAMESPACE::Expectations::ExpectationNotMetError webmock-3.18.1/lib/webmock/test_unit.rb0000644000004100000410000000045614333126774020042 0ustar www-datawww-datarequire 'test/unit' require 'webmock' WebMock.enable! module Test module Unit class TestCase include WebMock::API teardown def teardown_with_webmock WebMock.reset! end end end end WebMock::AssertionFailure.error_class = Test::Unit::AssertionFailedError webmock-3.18.1/lib/webmock.rb0000644000004100000410000000443414333126774016024 0ustar www-datawww-datarequire 'singleton' require 'addressable/uri' require 'addressable/template' require 'crack/xml' require_relative 'webmock/deprecation' require_relative 'webmock/version' require_relative 'webmock/errors' require_relative 'webmock/util/query_mapper' require_relative 'webmock/util/uri' require_relative 'webmock/util/headers' require_relative 'webmock/util/hash_counter' require_relative 'webmock/util/hash_keys_stringifier' require_relative 'webmock/util/values_stringifier' require_relative 'webmock/util/json' require_relative 'webmock/util/version_checker' require_relative 'webmock/util/hash_validator' require_relative 'webmock/matchers/hash_argument_matcher' require_relative 'webmock/matchers/hash_excluding_matcher' require_relative 'webmock/matchers/hash_including_matcher' require_relative 'webmock/matchers/any_arg_matcher' require_relative 'webmock/request_pattern' require_relative 'webmock/request_signature' require_relative 'webmock/responses_sequence' require_relative 'webmock/request_stub' require_relative 'webmock/response' require_relative 'webmock/rack_response' require_relative 'webmock/stub_request_snippet' require_relative 'webmock/request_signature_snippet' require_relative 'webmock/request_body_diff' require_relative 'webmock/assertion_failure' require_relative 'webmock/request_execution_verifier' require_relative 'webmock/config' require_relative 'webmock/callback_registry' require_relative 'webmock/request_registry' require_relative 'webmock/stub_registry' require_relative 'webmock/api' require_relative 'webmock/http_lib_adapters/http_lib_adapter_registry' require_relative 'webmock/http_lib_adapters/http_lib_adapter' require_relative 'webmock/http_lib_adapters/net_http' require_relative 'webmock/http_lib_adapters/http_rb_adapter' require_relative 'webmock/http_lib_adapters/httpclient_adapter' require_relative 'webmock/http_lib_adapters/patron_adapter' require_relative 'webmock/http_lib_adapters/curb_adapter' require_relative 'webmock/http_lib_adapters/em_http_request_adapter' require_relative 'webmock/http_lib_adapters/typhoeus_hydra_adapter' require_relative 'webmock/http_lib_adapters/excon_adapter' require_relative 'webmock/http_lib_adapters/manticore_adapter' require_relative 'webmock/http_lib_adapters/async_http_client_adapter' require_relative 'webmock/webmock' webmock-3.18.1/Gemfile0000644000004100000410000000014314333126774014566 0ustar www-datawww-datasource 'https://rubygems.org/' gemspec gem 'rake' platforms :jruby do gem 'jruby-openssl' end webmock-3.18.1/.github/0000755000004100000410000000000014333126774014635 5ustar www-datawww-datawebmock-3.18.1/.github/workflows/0000755000004100000410000000000014333126774016672 5ustar www-datawww-datawebmock-3.18.1/.github/workflows/CI.yml0000644000004100000410000000137714333126774017720 0ustar www-datawww-dataname: CI on: push: branches: - master pull_request: jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: ruby: - head - '3.1' - '3.0' - '2.7' - '2.6' - '2.5' - jruby continue-on-error: ${{ matrix.ruby == 'head' }} name: Ruby ${{ matrix.ruby }} env: JRUBY_OPTS: "--debug" steps: - uses: actions/checkout@v2 - name: Install Apt Packages run: | sudo apt-get install libcurl4-openssl-dev -y - uses: ruby/setup-ruby@v1 continue-on-error: true with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: | bundle exec rake webmock-3.18.1/.rspec-tm0000644000004100000410000000003714333126774015030 0ustar www-datawww-data--rspec-version 2.0.0 --bundler