pax_global_header 0000666 0000000 0000000 00000000064 14624075502 0014517 g ustar 00root root 0000000 0000000 52 comment=1b23927c10971bbdfdc01d7e433c26f527debd0f
webmock-3.23.1/ 0000775 0000000 0000000 00000000000 14624075502 0013234 5 ustar 00root root 0000000 0000000 webmock-3.23.1/.gemtest 0000664 0000000 0000000 00000000000 14624075502 0014673 0 ustar 00root root 0000000 0000000 webmock-3.23.1/.github/ 0000775 0000000 0000000 00000000000 14624075502 0014574 5 ustar 00root root 0000000 0000000 webmock-3.23.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14624075502 0016631 5 ustar 00root root 0000000 0000000 webmock-3.23.1/.github/workflows/CI.yml 0000664 0000000 0000000 00000001513 14624075502 0017647 0 ustar 00root root 0000000 0000000 name: CI
on:
push:
branches:
- master
pull_request:
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby:
- head
- '3.3'
- '3.2'
- '3.1'
- '3.0'
- '2.7'
- '2.6'
- jruby
continue-on-error: ${{ matrix.ruby == 'head' }}
name: Ruby ${{ matrix.ruby }}
env:
JRUBY_OPTS: "--debug"
steps:
- uses: actions/checkout@v4
- name: Install Apt Packages
run: |
sudo apt-get install libcurl4-openssl-dev -y
- uses: ruby/setup-ruby@v1
continue-on-error: false
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
rubygems: 'latest'
bundler: 'latest'
- run: |
bundle exec rake
webmock-3.23.1/.gitignore 0000664 0000000 0000000 00000000434 14624075502 0015225 0 ustar 00root root 0000000 0000000 ## 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.23.1/.rspec-tm 0000664 0000000 0000000 00000000037 14624075502 0014767 0 ustar 00root root 0000000 0000000 --rspec-version 2.0.0
--bundler webmock-3.23.1/CHANGELOG.md 0000664 0000000 0000000 00000213731 14624075502 0015054 0 ustar 00root root 0000000 0000000 # Changelog
# 3.23.1
* Added support for async-http version >= 0.65.0 [PR](https://github.com/bblimke/webmock/pull/1056)
Thanks to [Jacob Frautschi](https://github.com/jakeonfire)
# 3.23.0
* Fixed HTTP.rb adapter to support streaming real responses when WebMock is enabled.
Thanks to [Viacheslav Nepomniashchikh](https://github.com/aka-nez) for reporting and investigating this [issue](https://github.com/bblimke/webmock/issues/1017).
# 3.22.0
* Addressed an issue in the HTTPClient adapter where memoized stubbed responses and memoized request_signatures were incorrectly persisted between subsequent requests ([#1019](https://github.com/bblimke/webmock/issues/1019)). The implementation of a more robust thread-safety solution by [Tom Beauvais](https://github.com/tbeauvais) in [PR #300](https://github.com/bblimke/webmock/pull/300) not only resolved the memoization problem but also enhanced the overall thread safety of the adapter. This update ensures that stubbed responses and request signatures are correctly isolated to individual requests, improving both consistency and thread safety.
# 3.21.2
* Corrected type checking in `WebMock::Response#assert_valid_body!` to accurately recognize `Hash` objects. Additionally, improved the clarity of the error message for unsupported body types, guiding users towards proper usage.
Thanks to [Jake Robb](https://github.com/jakerobb) for reporting.
# 3.21.1
* The stubbed Net::HTTPResponse#uri now returns request.uri, aligning it with the behavior of an actual Net::HTTPResponse.
Thanks to [Abe Voelker](https://github.com/abevoelker) for reporting and to [Victor Maslov](https://github.com/Nakilon) and [Gio Lodi](https://github.com/mokagio) for the suggested solution.
# 3.21.0
* Don't use deprecated Rack::VERSION for Rack >= 3
Thanks to [Étienne Barrié](https://github.com/etiennebarrie)
* Updated HTTPClient adapter, to build request signature using the URI after filters have been applied.
Thanks to [Matt Brown](https://github.com/mattbnz)
# 3.20.0
* Optimised EmHttpRequestAdapter performance.
Thanks to [Ricardo Trindade](https://github.com/RicardoTrindade)
* Removed runtime dependency on base64.
Thanks to [Earlopain](https://github.com/Earlopain)
* Typhoeus::Response objects constructed from stubbed responses now have all timing attributes set to 0.0.
Thanks to [James Brown](https://github.com/Roguelazer)
* Optimised WebMock::Util::Headers by removing redundant freeze invocations.
Thanks to [Kazuhiro NISHIYAMA](https://github.com/znz)
* The default stubbed response body, which is an empty String, is unfrozen.
* When building signatures of requests made by http.rb, the request body encoding is now preserved.
# 3.19.1
* When passing a Proc or lambda as response body to `to_return_json`, the body is evaluated at the time of request and not at the time of `to_return_json` method invocation.
Thanks to [Jason Karns](https://github.com/jasonkarns) for reporting.
# 3.19.0
* Do not alter real (non-stubbed) request headers when handling em-http-request requests.
Thanks to [Yoann Lecuyer](https://github.com/ylecuyer)
* Fix matching stubs with HashExcludingMatcher
Thanks to [Lucas Arnaud](https://github.com/lucasarnaud)
* Remove development and test files from the gem package
Thanks to [Orien Madgwick](https://github.com/orien)
* Fix supported http client gem version checks.
Thanks to [Marc Rohloff](https://github.com/marcrohloff) and [Roman Stražanec](https://github.com/romanstrazanec)
* Non-string body passed to #to_return_json is now converted to JSON string.
Thanks to [inkstak](https://github.com/inkstak)
* `[::1]` is recognised as localhost e.g when passing `allow_localhost` option to `disable_net_connect!`
Thanks to [Yuki Inoue](https://github.com/Yuki-Inoue)
* Optimized `normalize_headers` for performance
Thanks to [Brandon Weaver](https://github.com/baweaver)
* Added Frozen string literal to files to optimise memory usage
Thanks to [Josh Nichols](https://github.com/technicalpickles)
# 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 [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.23.1/Gemfile 0000664 0000000 0000000 00000000143 14624075502 0014525 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org/'
gemspec
gem 'rake'
platforms :jruby do
gem 'jruby-openssl'
end
webmock-3.23.1/LICENSE 0000664 0000000 0000000 00000002047 14624075502 0014244 0 ustar 00root root 0000000 0000000 Copyright (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.23.1/README.md 0000664 0000000 0000000 00000076743 14624075502 0014534 0 ustar 00root root 0000000 0000000 WebMock
=======
[](http://badge.fury.io/rb/webmock)
[](https://github.com/bblimke/webmock/actions)
[](https://codeclimate.com/github/bblimke/webmock)
[](https://github.com/markets/awesome-ruby)
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.6
* MRI 2.7
* MRI 3.0
* MRI 3.1
* MRI 3.2
* MRI 3.3
* JRuby
## 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
```bash
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 JSON body
```ruby
stub_request(:any, "www.example.com").
to_return_json(body: {foo: "bar"})
Net::HTTP.get('www.example.com', '/') # ===> "{\"foo\": \"bar\"}"
```
### 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`. At the time of connection being made there is no information about the request or URL yet, therefore WebMock is not able to decide whether to stub a request or not and all connections are allowed. To enable connections only to a specific domain (e.g. your test server) use:
```ruby
WebMock.allow_net_connect!(net_http_connect_on_start: "www.example.com")
```
## 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 [](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
* Henrik Nyh
* Yoann Lecuyer
* Lucas Arnaud
* Marc Rohloff
* inkstak
* Yuki Inoue
* Brandon Weaver
* Josh Nichols
* Ricardo Trindade
* Earlopain
* James Brown
* Kazuhiro NISHIYAMA
* Étienne Barrié
* Matt Brown
* Victor Maslov
* Gio Lodi
* Ryan Brooks
* Jacob Frautschi
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.23.1/Rakefile 0000664 0000000 0000000 00000001754 14624075502 0014710 0 ustar 00root root 0000000 0000000 require '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.23.1/lib/ 0000775 0000000 0000000 00000000000 14624075502 0014002 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock.rb 0000664 0000000 0000000 00000004473 14624075502 0015766 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require '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.23.1/lib/webmock/ 0000775 0000000 0000000 00000000000 14624075502 0015431 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/api.rb 0000664 0000000 0000000 00000007345 14624075502 0016540 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/assertion_failure.rb 0000664 0000000 0000000 00000000371 14624075502 0021475 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/callback_registry.rb 0000664 0000000 0000000 00000001516 14624075502 0021445 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/config.rb 0000664 0000000 0000000 00000000707 14624075502 0017227 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/cucumber.rb 0000664 0000000 0000000 00000000252 14624075502 0017562 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'webmock'
require 'webmock/rspec/matchers'
WebMock.enable!
World(WebMock::API, WebMock::Matchers)
After do
WebMock.reset!
end
webmock-3.23.1/lib/webmock/deprecation.rb 0000664 0000000 0000000 00000000302 14624075502 0020246 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module WebMock
class Deprecation
class << self
def warning(message)
warn "WebMock deprecation warning: #{message}"
end
end
end
end
webmock-3.23.1/lib/webmock/errors.rb 0000664 0000000 0000000 00000000771 14624075502 0017277 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/http_lib_adapters/ 0000775 0000000 0000000 00000000000 14624075502 0021121 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/http_lib_adapters/async_http_client_adapter.rb 0000664 0000000 0000000 00000015270 14624075502 0026665 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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 socket_class
defined?(Async::IO::Socket) ? Async::IO::Socket : Socket
end
def create_connected_sockets
pair = begin
socket_class.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
rescue Errno::EAFNOSUPPORT
socket_class.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.23.1/lib/webmock/http_lib_adapters/curb_adapter.rb 0000664 0000000 0000000 00000023551 14624075502 0024107 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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.23.1/lib/webmock/http_lib_adapters/em_http_request_adapter.rb 0000664 0000000 0000000 00000016511 14624075502 0026362 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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(*headers_and_body_processed_by_middleware)
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.detect { |c| c.start_with? name }
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 headers_and_body_processed_by_middleware
@headers_and_body_processed_by_middleware ||= begin
head, body = build_request, @req.body
@conn.middleware.each do |m|
head, body = m.request(self, head, body) if m.respond_to?(:request)
end
[head, body]
end
end
def build_request_signature
headers, body = headers_and_body_processed_by_middleware
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.23.1/lib/webmock/http_lib_adapters/excon_adapter.rb 0000664 0000000 0000000 00000012242 14624075502 0024263 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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.23.1/lib/webmock/http_lib_adapters/http_lib_adapter.rb 0000664 0000000 0000000 00000000267 14624075502 0024760 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module WebMock
class HttpLibAdapter
def self.adapter_for(lib)
WebMock::HttpLibAdapterRegistry.instance.register(lib, self)
end
end
end webmock-3.23.1/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb 0000664 0000000 0000000 00000000550 14624075502 0026703 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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
end webmock-3.23.1/lib/webmock/http_lib_adapters/http_rb/ 0000775 0000000 0000000 00000000000 14624075502 0022563 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/http_lib_adapters/http_rb/client.rb 0000664 0000000 0000000 00000000610 14624075502 0024363 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/http_lib_adapters/http_rb/request.rb 0000664 0000000 0000000 00000001172 14624075502 0024601 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module HTTP
class Request
def webmock_signature
request_body = nil
if defined?(HTTP::Request::Body)
request_body = String.new
first_chunk_encoding = nil
body.each do |part|
request_body << part
first_chunk_encoding ||= part.encoding
end
request_body.force_encoding(first_chunk_encoding) if first_chunk_encoding
request_body
else
request_body = body
end
::WebMock::RequestSignature.new(verb, uri.to_s, {
headers: headers.to_h,
body: request_body
})
end
end
end
webmock-3.23.1/lib/webmock/http_lib_adapters/http_rb/response.rb 0000664 0000000 0000000 00000006024 14624075502 0024750 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module HTTP
class Response
def to_webmock
webmock_response = ::WebMock::Response.new
webmock_response.status = [status.to_i, reason]
webmock_response.body = body.to_s
# This call is used to reset the body of the response to enable it to be streamed if necessary.
# The `body.to_s` call above reads the body, which allows WebMock to trigger any registered callbacks.
# However, once the body is read to_s, it cannot be streamed again and attempting to do so
# will raise a "HTTP::StateError: body has already been consumed" error.
# To avoid this error, we replace the original body with a new one.
# The new body has its @stream attribute set to new Streamer, instead of the original Connection.
# Unfortunately, it's not possible to reset the original body to its initial streaming state.
# Therefore, this replacement is the best workaround currently available.
reset_body_to_allow_it_to_be_streamed!(webmock_response)
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 = build_http_rb_response_body_from_webmock_response(webmock_response)
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
def build_http_rb_response_body_from_webmock_response(webmock_response)
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
end
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
private
def reset_body_to_allow_it_to_be_streamed!(webmock_response)
@body = self.class.build_http_rb_response_body_from_webmock_response(webmock_response)
end
end
end
webmock-3.23.1/lib/webmock/http_lib_adapters/http_rb/streamer.rb 0000664 0000000 0000000 00000001276 14624075502 0024740 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/http_lib_adapters/http_rb/webmock.rb 0000664 0000000 0000000 00000003623 14624075502 0024543 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/http_lib_adapters/http_rb_adapter.rb 0000664 0000000 0000000 00000001416 14624075502 0024612 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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_relative "http_rb/client"
require_relative "http_rb/request"
require_relative "http_rb/response"
require_relative "http_rb/streamer"
require_relative "http_rb/webmock"
end
webmock-3.23.1/lib/webmock/http_lib_adapters/httpclient_adapter.rb 0000664 0000000 0000000 00000020641 14624075502 0025327 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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
WEBMOCK_HTTPCLIENT_RESPONSES = :webmock_httpclient_responses
WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES = :webmock_httpclient_request_signatures
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)
clear_thread_variables unless conn.async_thread
request_signature = build_request_signature(req, :reuse_existing)
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
if webmock_responses[request_signature]
webmock_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...
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)
clear_thread_variables
req = create_request(method, uri, query, body, extheader)
request_signature = build_request_signature(req)
webmock_request_signatures << request_signature
if webmock_responses[request_signature] || WebMock.net_connect_allowed?(request_signature.uri)
conn = super
conn.async_thread[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] = Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES]
conn.async_thread[WEBMOCK_HTTPCLIENT_RESPONSES] = Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES]
conn
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)
@request_filter.each do |filter|
filter.filter_request(req)
end
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
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
Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES] ||= Hash.new do |hash, request_signature|
hash[request_signature] = WebMock::StubRegistry.instance.response_for_request(request_signature)
end
end
def webmock_request_signatures
Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] ||= []
end
def previous_signature_for(signature)
return nil unless index = webmock_request_signatures.index(signature)
webmock_request_signatures.delete_at(index)
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 clear_thread_variables
Thread.current[WEBMOCK_HTTPCLIENT_REQUEST_SIGNATURES] = nil
Thread.current[WEBMOCK_HTTPCLIENT_RESPONSES] = nil
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.23.1/lib/webmock/http_lib_adapters/manticore_adapter.rb 0000664 0000000 0000000 00000012266 14624075502 0025136 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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.23.1/lib/webmock/http_lib_adapters/net_http.rb 0000664 0000000 0000000 00000021416 14624075502 0023277 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require '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, request.uri, &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, request_uri, &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.uri = request_uri
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.23.1/lib/webmock/http_lib_adapters/net_http_response.rb 0000664 0000000 0000000 00000002425 14624075502 0025214 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
# 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.23.1/lib/webmock/http_lib_adapters/patron_adapter.rb 0000664 0000000 0000000 00000011245 14624075502 0024454 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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.23.1/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb 0000664 0000000 0000000 00000014237 14624075502 0026224 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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,
total_time: 0.0,
starttransfer_time: 0.0,
appconnect_time: 0.0,
pretransfer_time: 0.0,
connect_time: 0.0,
namelookup_time: 0.0,
redirect_time: 0.0
)
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,
total_time: 0.0,
starttransfer_time: 0.0,
appconnect_time: 0.0,
pretransfer_time: 0.0,
connect_time: 0.0,
namelookup_time: 0.0,
redirect_time: 0.0
)
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.23.1/lib/webmock/matchers/ 0000775 0000000 0000000 00000000000 14624075502 0017237 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/matchers/any_arg_matcher.rb 0000664 0000000 0000000 00000000404 14624075502 0022705 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/matchers/hash_argument_matcher.rb 0000664 0000000 0000000 00000001136 14624075502 0024115 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/matchers/hash_excluding_matcher.rb 0000664 0000000 0000000 00000000745 14624075502 0024262 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/matchers/hash_including_matcher.rb 0000664 0000000 0000000 00000001016 14624075502 0024244 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/minitest.rb 0000664 0000000 0000000 00000002033 14624075502 0017610 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
begin
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.23.1/lib/webmock/rack_response.rb 0000664 0000000 0000000 00000003542 14624075502 0020620 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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
if !Rack.const_defined?(:RELEASE) || Rack::RELEASE < "3"
env['rack.version'] = Rack::VERSION
end
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.23.1/lib/webmock/request_body_diff.rb 0000664 0000000 0000000 00000003024 14624075502 0021452 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "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.23.1/lib/webmock/request_execution_verifier.rb 0000664 0000000 0000000 00000004440 14624075502 0023426 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/request_pattern.rb 0000664 0000000 0000000 00000031013 14624075502 0021201 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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::HashArgumentMatcher)
@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.23.1/lib/webmock/request_registry.rb 0000664 0000000 0000000 00000001525 14624075502 0021401 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/request_signature.rb 0000664 0000000 0000000 00000002546 14624075502 0021536 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/request_signature_snippet.rb 0000664 0000000 0000000 00000003157 14624075502 0023277 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "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.23.1/lib/webmock/request_stub.rb 0000664 0000000 0000000 00000007077 14624075502 0020516 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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)
json_body = if body.respond_to?(:call)
->(request_signature) {
b = if body.respond_to?(:arity) && body.arity == 1
body.call(request_signature)
else
body.call
end
b = b.to_json unless b.is_a?(String)
b
}
elsif !body.is_a?(String)
body.to_json
else
body
end
resp_h.merge(
headers: {content_type: 'application/json'}.merge(headers.to_h),
body: 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.23.1/lib/webmock/response.rb 0000664 0000000 0000000 00000010233 14624075502 0017613 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "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 || String.new("")
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.is_a?(Hash)
raise InvalidBody, "must be one of: #{valid_types}, but you've used a #{@body.class}. " \
"Please convert it by calling .to_json .to_xml, 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.23.1/lib/webmock/responses_sequence.rb 0000664 0000000 0000000 00000001302 14624075502 0021663 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/rspec.rb 0000664 0000000 0000000 00000001661 14624075502 0017076 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require '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.23.1/lib/webmock/rspec/ 0000775 0000000 0000000 00000000000 14624075502 0016545 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/rspec/matchers.rb 0000664 0000000 0000000 00000001170 14624075502 0020677 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require '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.23.1/lib/webmock/rspec/matchers/ 0000775 0000000 0000000 00000000000 14624075502 0020353 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/rspec/matchers/request_pattern_matcher.rb 0000664 0000000 0000000 00000003445 14624075502 0025636 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/rspec/matchers/webmock_matcher.rb 0000664 0000000 0000000 00000003035 14624075502 0024033 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/stub_registry.rb 0000664 0000000 0000000 00000004446 14624075502 0020673 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/stub_request_snippet.rb 0000664 0000000 0000000 00000002220 14624075502 0022241 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/test_unit.rb 0000664 0000000 0000000 00000000515 14624075502 0017775 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require '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.23.1/lib/webmock/util/ 0000775 0000000 0000000 00000000000 14624075502 0016406 5 ustar 00root root 0000000 0000000 webmock-3.23.1/lib/webmock/util/hash_counter.rb 0000664 0000000 0000000 00000001413 14624075502 0021414 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'thread'
module WebMock
module Util
class HashCounter
attr_accessor :hash
def initialize
self.hash = Hash.new(0)
@order = {}
@max = 0
@lock = ::Mutex.new
end
def put(key, num=1)
@lock.synchronize do
hash[key] += num
@order[key] = @max += 1
end
end
def get(key)
@lock.synchronize do
hash[key]
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.23.1/lib/webmock/util/hash_keys_stringifier.rb 0000664 0000000 0000000 00000001143 14624075502 0023315 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/util/hash_validator.rb 0000664 0000000 0000000 00000001025 14624075502 0021721 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/util/headers.rb 0000664 0000000 0000000 00000004033 14624075502 0020346 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module WebMock
module Util
class Headers
STANDARD_HEADER_DELIMITER = '-'
NONSTANDARD_HEADER_DELIMITER = '_'
JOIN = ', '
def self.normalize_headers(headers)
return nil unless headers
headers.each_with_object({}) do |(name, value), new_headers|
new_headers[normalize_name(name)] =
case value
when Regexp then value
when Array then (value.size == 1) ? value.first.to_s : value.map(&:to_s).sort
else value.to_s
end
end
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)
strict_base64_encoded = [credentials.join(':')].pack("m0")
"Basic #{strict_base64_encoded.chomp}"
end
def self.normalize_name(name)
name
.to_s
.tr(NONSTANDARD_HEADER_DELIMITER, STANDARD_HEADER_DELIMITER)
.split(STANDARD_HEADER_DELIMITER)
.map!(&:capitalize)
.join(STANDARD_HEADER_DELIMITER)
end
end
end
end
webmock-3.23.1/lib/webmock/util/json.rb 0000664 0000000 0000000 00000005460 14624075502 0017711 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
# 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.23.1/lib/webmock/util/query_mapper.rb 0000664 0000000 0000000 00000023733 14624075502 0021454 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/lib/webmock/util/uri.rb 0000664 0000000 0000000 00000007204 14624075502 0017535 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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 [::1]).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.23.1/lib/webmock/util/values_stringifier.rb 0000664 0000000 0000000 00000000631 14624075502 0022637 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class 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.23.1/lib/webmock/util/version_checker.rb 0000664 0000000 0000000 00000007730 14624075502 0022113 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
# 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 @major == @min_major && @minor < @min_minor then :too_low
when @major == @min_major && @minor == @min_minor && @patch < @min_patch then :too_low
when @max_major && @major > @max_major then :too_high
when @max_major && @major == @max_major && @max_minor && @minor > @max_minor then :too_high
else :ok
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.23.1/lib/webmock/version.rb 0000664 0000000 0000000 00000000153 14624075502 0017442 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module WebMock
VERSION = '3.23.1' unless defined?(::WebMock::VERSION)
end
webmock-3.23.1/lib/webmock/webmock.rb 0000664 0000000 0000000 00000011601 14624075502 0017404 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module 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.23.1/minitest/ 0000775 0000000 0000000 00000000000 14624075502 0015070 5 ustar 00root root 0000000 0000000 webmock-3.23.1/minitest/test_helper.rb 0000664 0000000 0000000 00000001437 14624075502 0017740 0 ustar 00root root 0000000 0000000 require '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.23.1/minitest/test_webmock.rb 0000664 0000000 0000000 00000000435 14624075502 0020105 0 ustar 00root root 0000000 0000000 require 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.23.1/minitest/webmock_spec.rb 0000664 0000000 0000000 00000004365 14624075502 0020066 0 ustar 00root root 0000000 0000000 require 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.23.1/spec/ 0000775 0000000 0000000 00000000000 14624075502 0014166 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/ 0000775 0000000 0000000 00000000000 14624075502 0016254 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/async_http_client/ 0000775 0000000 0000000 00000000000 14624075502 0021766 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/async_http_client/async_http_client_spec.rb 0000664 0000000 0000000 00000022555 14624075502 0027050 0 ustar 00root root 0000000 0000000 # encoding: utf-8
require 'spec_helper'
require 'acceptance/webmock_shared'
require_relative './async_http_client_spec_helper'
unless RUBY_PLATFORM =~ /java/
require 'protocol/http/body/file'
Async.logger.debug! if ENV['ASYNC_LOGGER_DEBUG']
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)
result = 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
result.is_a?(Exception) ? raise(result) : result
end
def response_to_hash(response)
{
status: response.status,
headers: response.headers.to_h,
body: response.read
}
end
end
end
webmock-3.23.1/spec/acceptance/async_http_client/async_http_client_spec_helper.rb 0000664 0000000 0000000 00000003252 14624075502 0030400 0 ustar 00root root 0000000 0000000 require 'ostruct'
module 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', WebMock::Util::Headers.basic_auth_header(options[:basic_auth])]
) if options[:basic_auth]
body = options[:body]
result = 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
result.is_a?(Exception) ? raise(result) : result
end
def client_timeout_exception_class
Async::TimeoutError
end
def connection_refused_exception_class
Errno::ECONNREFUSED
end
def connection_error_class
HTTP::ConnectionError
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.23.1/spec/acceptance/curb/ 0000775 0000000 0000000 00000000000 14624075502 0017207 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/curb/curb_spec.rb 0000664 0000000 0000000 00000040072 14624075502 0021504 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/acceptance/curb/curb_spec_helper.rb 0000664 0000000 0000000 00000006362 14624075502 0023047 0 ustar 00root root 0000000 0000000 require '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 = 5
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 connection_error_class
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.23.1/spec/acceptance/em_http_request/ 0000775 0000000 0000000 00000000000 14624075502 0021464 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/em_http_request/em_http_request_spec.rb 0000664 0000000 0000000 00000036774 14624075502 0026254 0 ustar 00root root 0000000 0000000 # 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 "doesn't modify headers" do
EM.run do
conn = EventMachine::HttpRequest.new(webmock_server_url)
http = conn.post(head: { 'content-length' => '4' }, body: 'test')
expect(conn).to receive(:send_data).with(/POST \/ HTTP\/1.1\r\nContent-Length: 4\r\nConnection: close\r\nHost: localhost:\d+\r\nUser-Agent: EventMachine HttpClient\r\nAccept-Encoding: gzip, compressed\r\n\r\n/).and_call_original
expect(conn).to receive(:send_data).with('test')
http.callback do
EM.stop
end
end
end
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.23.1/spec/acceptance/em_http_request/em_http_request_spec_helper.rb 0000664 0000000 0000000 00000003367 14624075502 0027603 0 ustar 00root root 0000000 0000000 module 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
RuntimeError # 'Errno::ETIMEDOUT'
end
def connection_refused_exception_class
RuntimeError
end
def connection_error_class
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.23.1/spec/acceptance/excon/ 0000775 0000000 0000000 00000000000 14624075502 0017370 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/excon/excon_spec.rb 0000664 0000000 0000000 00000005175 14624075502 0022053 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/acceptance/excon/excon_spec_helper.rb 0000664 0000000 0000000 00000002674 14624075502 0023413 0 ustar 00root root 0000000 0000000 require '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 connection_error_class
end
def http_library
:excon
end
end
webmock-3.23.1/spec/acceptance/http_rb/ 0000775 0000000 0000000 00000000000 14624075502 0017716 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/http_rb/http_rb_spec.rb 0000664 0000000 0000000 00000006506 14624075502 0022726 0 ustar 00root root 0000000 0000000 # 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
it "should preserve request body encoding when matching requests" do
stub_request(:post, "www.example.com").with(body: (lambda {|body|
body.encoding == Encoding::UTF_8
}))
http_request(:post, "http://www.example.com/", body: "abc")
end
describe "when making real requests", net_connect: true do
before do
WebMock.allow_net_connect!
end
it "should allow streaming the response body" do
response = HTTP.get("http://localhost:#{WebMockServer.instance.port}")
read_body = ""
response.body.each do |chunk|
read_body << chunk
end
expect(read_body).to eql("hello world")
end
end
end
webmock-3.23.1/spec/acceptance/http_rb/http_rb_spec_helper.rb 0000664 0000000 0000000 00000002607 14624075502 0024263 0 ustar 00root root 0000000 0000000 require "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 connection_error_class
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.23.1/spec/acceptance/httpclient/ 0000775 0000000 0000000 00000000000 14624075502 0020432 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/httpclient/httpclient_spec.rb 0000664 0000000 0000000 00000016112 14624075502 0024150 0 ustar 00root root 0000000 0000000 require '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"
request.header.request_uri.query = "webmock=here"
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(
query: {'webmock' => 'here'},
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.23.1/spec/acceptance/httpclient/httpclient_spec_helper.rb 0000664 0000000 0000000 00000003126 14624075502 0025510 0 ustar 00root root 0000000 0000000 module 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 connection_error_class
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.23.1/spec/acceptance/manticore/ 0000775 0000000 0000000 00000000000 14624075502 0020235 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/manticore/manticore_spec.rb 0000664 0000000 0000000 00000007107 14624075502 0023562 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/acceptance/manticore/manticore_spec_helper.rb 0000664 0000000 0000000 00000001532 14624075502 0025115 0 ustar 00root root 0000000 0000000 module 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 connection_error_class
end
def http_library
:manticore
end
end
webmock-3.23.1/spec/acceptance/net_http/ 0000775 0000000 0000000 00000000000 14624075502 0020101 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/net_http/net_http_shared.rb 0000664 0000000 0000000 00000014177 14624075502 0023613 0 ustar 00root root 0000000 0000000 require '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 return response that returns request uri" do
uri = URI.parse("http://localhost:#{port}/")
response = Net::HTTP.get_response(uri)
expect(response.uri).to eql(uri)
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.23.1/spec/acceptance/net_http/net_http_spec.rb 0000664 0000000 0000000 00000035634 14624075502 0023300 0 ustar 00root root 0000000 0000000 require '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
context "returning response that returns request uri" do
context "when making a real request" do
it "should return response that reports request uri" do
WebMock.allow_net_connect!
uri = URI.parse("http://localhost:#{port}/")
response = Net::HTTP.get_response(uri)
expect(response.uri).to eql(uri)
end
end
it "should return response that returns request uri" do
stub_request(:get, "www.example.com")
uri = URI.parse("http://www.example.com/")
response = Net::HTTP.get_response(uri)
expect(response.uri).to eql(URI.parse("http://www.example.com/"))
end
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.23.1/spec/acceptance/net_http/net_http_spec_helper.rb 0000664 0000000 0000000 00000003272 14624075502 0024630 0 ustar 00root root 0000000 0000000 module 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 connection_error_class
end
def http_library
:net_http
end
end
webmock-3.23.1/spec/acceptance/net_http/real_net_http_spec.rb 0000664 0000000 0000000 00000000731 14624075502 0024271 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/acceptance/patron/ 0000775 0000000 0000000 00000000000 14624075502 0017557 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/patron/patron_spec.rb 0000664 0000000 0000000 00000010024 14624075502 0022416 0 ustar 00root root 0000000 0000000 # 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.23.1/spec/acceptance/patron/patron_spec_helper.rb 0000664 0000000 0000000 00000002574 14624075502 0023770 0 ustar 00root root 0000000 0000000 require '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 connection_error_class
end
def http_library
:patron
end
end
webmock-3.23.1/spec/acceptance/shared/ 0000775 0000000 0000000 00000000000 14624075502 0017522 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/acceptance/shared/allowing_and_disabling_net_connect.rb 0000664 0000000 0000000 00000032164 14624075502 0027106 0 ustar 00root root 0000000 0000000 shared_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.23.1/spec/acceptance/shared/callbacks.rb 0000664 0000000 0000000 00000011674 14624075502 0021777 0 ustar 00root root 0000000 0000000 shared_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.23.1/spec/acceptance/shared/complex_cross_concern_behaviors.rb 0000664 0000000 0000000 00000002463 14624075502 0026505 0 ustar 00root root 0000000 0000000 shared_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.23.1/spec/acceptance/shared/enabling_and_disabling_webmock.rb 0000664 0000000 0000000 00000004705 14624075502 0026201 0 ustar 00root root 0000000 0000000 shared_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.23.1/spec/acceptance/shared/precedence_of_stubs.rb 0000664 0000000 0000000 00000001264 14624075502 0024053 0 ustar 00root root 0000000 0000000 shared_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.23.1/spec/acceptance/shared/request_expectations.rb 0000664 0000000 0000000 00000130600 14624075502 0024325 0 ustar 00root root 0000000 0000000 shared_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: "
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.23.1/spec/support/failures.rb 0000664 0000000 0000000 00000000310 14624075502 0020033 0 ustar 00root root 0000000 0000000 module Failures def fail() raise_error(RSpec::Expectations::ExpectationNotMetError) end def fail_with(message) raise_error(RSpec::Expectations::ExpectationNotMetError, message) end end webmock-3.23.1/spec/support/my_rack_app.rb 0000664 0000000 0000000 00000003111 14624075502 0020510 0 ustar 00root root 0000000 0000000 require '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, {}, ['']] when ['GET', '/env'] [200, {}, [JSON.dump(env)]] 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.23.1/spec/support/network_connection.rb 0000664 0000000 0000000 00000000501 14624075502 0022133 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/support/webmock_server.rb 0000664 0000000 0000000 00000002425 14624075502 0021247 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/ 0000775 0000000 0000000 00000000000 14624075502 0015145 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/unit/api_spec.rb 0000664 0000000 0000000 00000012645 14624075502 0017265 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/errors_spec.rb 0000664 0000000 0000000 00000014522 14624075502 0020024 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/http_lib_adapters/ 0000775 0000000 0000000 00000000000 14624075502 0020635 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb 0000664 0000000 0000000 00000001057 14624075502 0027434 0 ustar 00root root 0000000 0000000 require '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 end webmock-3.23.1/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb 0000664 0000000 0000000 00000000544 14624075502 0025504 0 ustar 00root root 0000000 0000000 require '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 end webmock-3.23.1/spec/unit/matchers/ 0000775 0000000 0000000 00000000000 14624075502 0016753 5 ustar 00root root 0000000 0000000 webmock-3.23.1/spec/unit/matchers/hash_excluding_matcher_spec.rb 0000664 0000000 0000000 00000003633 14624075502 0025007 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/matchers/hash_including_matcher_spec.rb 0000664 0000000 0000000 00000005622 14624075502 0025001 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/rack_response_spec.rb 0000664 0000000 0000000 00000010377 14624075502 0021352 0 ustar 00root root 0000000 0000000 # 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 it "should send or not a rack.version depending on the Rack version" do request = WebMock::RequestSignature.new(:get, 'www.example.com/env') response = @rack_response.evaluate(request) expect(response.status.first).to eq(200) body = JSON.parse(response.body) if Gem.loaded_specs["rack"].version > Gem::Version.new("3.0.0") expect(body).not_to include("rack.version") else expect(body).to include("rack.version") end 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.23.1/spec/unit/request_body_diff_spec.rb 0000664 0000000 0000000 00000004570 14624075502 0022207 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/request_execution_verifier_spec.rb 0000664 0000000 0000000 00000021012 14624075502 0024146 0 ustar 00root root 0000000 0000000 require '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.23.1/spec/unit/request_pattern_spec.rb 0000664 0000000 0000000 00000115621 14624075502 0021737 0 ustar 00root root 0000000 0000000 require '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: "