webmock 3.0.1 → 3.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +558 -2
- data/README.md +200 -42
- data/lib/webmock/api.rb +14 -0
- data/lib/webmock/assertion_failure.rb +2 -0
- data/lib/webmock/callback_registry.rb +2 -0
- data/lib/webmock/config.rb +2 -0
- data/lib/webmock/cucumber.rb +2 -0
- data/lib/webmock/deprecation.rb +2 -0
- data/lib/webmock/errors.rb +2 -0
- data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +223 -0
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +21 -5
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +20 -9
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +7 -2
- data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +2 -0
- data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +2 -0
- data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +19 -1
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +29 -3
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +11 -3
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +9 -3
- data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +2 -0
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +30 -9
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +35 -15
- data/lib/webmock/http_lib_adapters/net_http.rb +38 -89
- data/lib/webmock/http_lib_adapters/net_http_response.rb +3 -1
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +6 -4
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
- data/lib/webmock/matchers/any_arg_matcher.rb +15 -0
- data/lib/webmock/matchers/hash_argument_matcher.rb +23 -0
- data/lib/webmock/matchers/hash_excluding_matcher.rb +17 -0
- data/lib/webmock/matchers/hash_including_matcher.rb +6 -23
- data/lib/webmock/minitest.rb +2 -0
- data/lib/webmock/rack_response.rb +3 -1
- data/lib/webmock/request_body_diff.rb +3 -1
- data/lib/webmock/request_execution_verifier.rb +4 -3
- data/lib/webmock/request_pattern.rb +132 -52
- data/lib/webmock/request_registry.rb +3 -1
- data/lib/webmock/request_signature.rb +5 -3
- data/lib/webmock/request_signature_snippet.rb +6 -4
- data/lib/webmock/request_stub.rb +34 -0
- data/lib/webmock/response.rb +22 -14
- data/lib/webmock/responses_sequence.rb +2 -0
- data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +2 -0
- data/lib/webmock/rspec/matchers.rb +2 -0
- data/lib/webmock/rspec.rb +12 -3
- data/lib/webmock/stub_registry.rb +28 -11
- data/lib/webmock/stub_request_snippet.rb +12 -6
- data/lib/webmock/test_unit.rb +3 -3
- data/lib/webmock/util/hash_counter.rb +15 -9
- data/lib/webmock/util/hash_keys_stringifier.rb +2 -0
- data/lib/webmock/util/hash_validator.rb +2 -0
- data/lib/webmock/util/headers.rb +39 -11
- data/lib/webmock/util/json.rb +3 -2
- data/lib/webmock/util/query_mapper.rb +11 -7
- data/lib/webmock/util/uri.rb +13 -11
- data/lib/webmock/util/values_stringifier.rb +22 -0
- data/lib/webmock/util/version_checker.rb +7 -5
- data/lib/webmock/version.rb +3 -1
- data/lib/webmock/webmock.rb +22 -3
- data/lib/webmock.rb +55 -48
- metadata +106 -175
- data/.gemtest +0 -0
- data/.gitignore +0 -34
- data/.rspec-tm +0 -2
- data/.travis.yml +0 -20
- data/Gemfile +0 -9
- data/Rakefile +0 -30
- data/minitest/test_helper.rb +0 -34
- data/minitest/test_webmock.rb +0 -9
- data/minitest/webmock_spec.rb +0 -60
- data/spec/acceptance/curb/curb_spec.rb +0 -466
- data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -406
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
- data/spec/acceptance/excon/excon_spec.rb +0 -75
- data/spec/acceptance/excon/excon_spec_helper.rb +0 -50
- data/spec/acceptance/http_rb/http_rb_spec.rb +0 -73
- data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -51
- data/spec/acceptance/httpclient/httpclient_spec.rb +0 -210
- data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
- data/spec/acceptance/manticore/manticore_spec.rb +0 -56
- data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
- data/spec/acceptance/net_http/net_http_shared.rb +0 -153
- data/spec/acceptance/net_http/net_http_spec.rb +0 -317
- data/spec/acceptance/net_http/net_http_spec_helper.rb +0 -64
- data/spec/acceptance/net_http/real_net_http_spec.rb +0 -20
- data/spec/acceptance/patron/patron_spec.rb +0 -118
- data/spec/acceptance/patron/patron_spec_helper.rb +0 -54
- data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +0 -313
- data/spec/acceptance/shared/callbacks.rb +0 -147
- data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
- data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
- data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
- data/spec/acceptance/shared/request_expectations.rb +0 -916
- data/spec/acceptance/shared/returning_declared_responses.rb +0 -388
- data/spec/acceptance/shared/stubbing_requests.rb +0 -583
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
- data/spec/acceptance/webmock_shared.rb +0 -41
- data/spec/fixtures/test.txt +0 -1
- data/spec/quality_spec.rb +0 -84
- data/spec/spec_helper.rb +0 -48
- data/spec/support/example_curl_output.txt +0 -22
- data/spec/support/failures.rb +0 -9
- data/spec/support/my_rack_app.rb +0 -53
- data/spec/support/network_connection.rb +0 -19
- data/spec/support/webmock_server.rb +0 -69
- data/spec/unit/api_spec.rb +0 -75
- data/spec/unit/errors_spec.rb +0 -129
- data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +0 -17
- data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +0 -12
- data/spec/unit/matchers/hash_including_matcher_spec.rb +0 -87
- data/spec/unit/rack_response_spec.rb +0 -112
- data/spec/unit/request_body_diff_spec.rb +0 -90
- data/spec/unit/request_execution_verifier_spec.rb +0 -208
- data/spec/unit/request_pattern_spec.rb +0 -590
- data/spec/unit/request_registry_spec.rb +0 -95
- data/spec/unit/request_signature_snippet_spec.rb +0 -89
- data/spec/unit/request_signature_spec.rb +0 -155
- data/spec/unit/request_stub_spec.rb +0 -199
- data/spec/unit/response_spec.rb +0 -282
- data/spec/unit/stub_registry_spec.rb +0 -103
- data/spec/unit/stub_request_snippet_spec.rb +0 -95
- data/spec/unit/util/hash_counter_spec.rb +0 -39
- data/spec/unit/util/hash_keys_stringifier_spec.rb +0 -27
- data/spec/unit/util/headers_spec.rb +0 -28
- data/spec/unit/util/json_spec.rb +0 -33
- data/spec/unit/util/query_mapper_spec.rb +0 -144
- data/spec/unit/util/uri_spec.rb +0 -299
- data/spec/unit/util/version_checker_spec.rb +0 -65
- data/spec/unit/webmock_spec.rb +0 -11
- data/test/http_request.rb +0 -24
- data/test/shared_test.rb +0 -95
- data/test/test_helper.rb +0 -23
- data/test/test_webmock.rb +0 -6
- data/webmock.gemspec +0 -46
data/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
WebMock
|
|
2
2
|
=======
|
|
3
|
-
[](http://badge.fury.io/rb/webmock)
|
|
3
|
+
[](http://badge.fury.io/rb/webmock)
|
|
4
|
+
[](https://github.com/bblimke/webmock/actions)
|
|
5
|
+
[](https://codeclimate.com/github/bblimke/webmock)
|
|
6
|
+
[](https://github.com/markets/awesome-ruby)
|
|
4
7
|
|
|
5
8
|
Library for stubbing and setting expectations on HTTP requests in Ruby.
|
|
6
9
|
|
|
@@ -19,71 +22,85 @@ Features
|
|
|
19
22
|
Supported HTTP libraries
|
|
20
23
|
------------------------
|
|
21
24
|
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* [Async::HTTP::Client](https://github.com/socketry/async-http)
|
|
26
|
+
* [Curb](https://github.com/taf2/curb) (currently only Curb::Easy)
|
|
27
|
+
* [EM-HTTP-Request](https://github.com/igrigorik/em-http-request)
|
|
28
|
+
* [Excon](https://github.com/excon/excon)
|
|
29
|
+
* [HTTPClient](https://github.com/nahi/httpclient)
|
|
30
|
+
* [HTTP Gem (also known as http.rb)](https://github.com/httprb/http)
|
|
31
|
+
* [httpx](https://honeyryderchuck.gitlab.io/httpx/wiki/Webmock-Adapter)
|
|
32
|
+
* [Manticore](https://github.com/cheald/manticore)
|
|
33
|
+
* [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.:
|
|
34
|
+
* [HTTParty](https://github.com/jnunemaker/httparty)
|
|
35
|
+
* [REST Client](https://github.com/rest-client/rest-client)
|
|
36
|
+
* [Patron](https://github.com/toland/patron)
|
|
37
|
+
* [Typhoeus](https://github.com/typhoeus/typhoeus) (currently only Typhoeus::Hydra)
|
|
31
38
|
|
|
32
39
|
Supported Ruby Interpreters
|
|
33
40
|
---------------------------
|
|
34
|
-
|
|
35
|
-
* MRI 2.
|
|
36
|
-
* MRI
|
|
37
|
-
* MRI
|
|
38
|
-
* MRI 2
|
|
39
|
-
* MRI 2.4
|
|
41
|
+
* MRI 2.6
|
|
42
|
+
* MRI 2.7
|
|
43
|
+
* MRI 3.0
|
|
44
|
+
* MRI 3.1
|
|
45
|
+
* MRI 3.2
|
|
40
46
|
* JRuby
|
|
41
|
-
* Rubinius
|
|
42
47
|
|
|
43
48
|
## Installation
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
```bash
|
|
51
|
+
gem install webmock
|
|
52
|
+
```
|
|
53
|
+
or alternatively:
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
# add to your Gemfile
|
|
57
|
+
group :test do
|
|
58
|
+
gem "webmock"
|
|
59
|
+
end
|
|
60
|
+
```
|
|
46
61
|
|
|
47
62
|
### or to install the latest development version from github master
|
|
48
63
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
64
|
+
```bash
|
|
65
|
+
git clone http://github.com/bblimke/webmock.git
|
|
66
|
+
cd webmock
|
|
67
|
+
rake install
|
|
68
|
+
```
|
|
52
69
|
|
|
53
70
|
## Upgrading from v1.x to v2.x
|
|
54
71
|
|
|
55
72
|
WebMock 2.x has changed somewhat since version 1.x. Changes are listed in [CHANGELOG.md](CHANGELOG.md)
|
|
56
73
|
|
|
57
|
-
###
|
|
74
|
+
### Cucumber
|
|
58
75
|
|
|
59
|
-
|
|
76
|
+
Create a file `features/support/webmock.rb` with the following contents:
|
|
60
77
|
|
|
61
78
|
```ruby
|
|
62
|
-
require 'webmock/
|
|
79
|
+
require 'webmock/cucumber'
|
|
63
80
|
```
|
|
64
81
|
|
|
65
|
-
###
|
|
82
|
+
### MiniTest
|
|
66
83
|
|
|
67
|
-
Add the following code to `
|
|
84
|
+
Add the following code to `test/test_helper`:
|
|
68
85
|
|
|
69
86
|
```ruby
|
|
70
|
-
require 'webmock/
|
|
87
|
+
require 'webmock/minitest'
|
|
71
88
|
```
|
|
72
89
|
|
|
73
|
-
###
|
|
90
|
+
### RSpec
|
|
74
91
|
|
|
75
|
-
Add the following code to `
|
|
92
|
+
Add the following code to `spec/spec_helper`:
|
|
76
93
|
|
|
77
94
|
```ruby
|
|
78
|
-
require 'webmock/
|
|
95
|
+
require 'webmock/rspec'
|
|
79
96
|
```
|
|
80
97
|
|
|
81
|
-
###
|
|
98
|
+
### Test::Unit
|
|
82
99
|
|
|
83
|
-
|
|
100
|
+
Add the following code to `test/test_helper.rb`
|
|
84
101
|
|
|
85
102
|
```ruby
|
|
86
|
-
require 'webmock/
|
|
103
|
+
require 'webmock/test_unit'
|
|
87
104
|
```
|
|
88
105
|
|
|
89
106
|
### Outside a test framework
|
|
@@ -97,13 +114,10 @@ include WebMock::API
|
|
|
97
114
|
WebMock.enable!
|
|
98
115
|
```
|
|
99
116
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
# Examples
|
|
103
118
|
|
|
104
119
|
## Stubbing
|
|
105
120
|
|
|
106
|
-
|
|
107
121
|
### Stubbed request based on uri only and with the default response
|
|
108
122
|
|
|
109
123
|
```ruby
|
|
@@ -236,6 +250,12 @@ stub_request(:any, /example/)
|
|
|
236
250
|
Net::HTTP.get('www.example.com', '/') # ===> Success
|
|
237
251
|
```
|
|
238
252
|
|
|
253
|
+
### Matching uris using lambda
|
|
254
|
+
|
|
255
|
+
```ruby
|
|
256
|
+
stub_request(:any, ->(uri) { true })
|
|
257
|
+
```
|
|
258
|
+
|
|
239
259
|
### Matching uris using RFC 6570 - Basic Example
|
|
240
260
|
|
|
241
261
|
```ruby
|
|
@@ -273,6 +293,16 @@ stub_request(:get, "www.example.com").
|
|
|
273
293
|
RestClient.get("http://www.example.com/?a[]=b&a[]=c&x=1") # ===> Success
|
|
274
294
|
```
|
|
275
295
|
|
|
296
|
+
### Matching partial query params using hash_excluding
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
stub_request(:get, "www.example.com").
|
|
300
|
+
with(query: hash_excluding({"a" => "b"}))
|
|
301
|
+
|
|
302
|
+
RestClient.get("http://www.example.com/?a=b") # ===> Failure
|
|
303
|
+
RestClient.get("http://www.example.com/?a=c") # ===> Success
|
|
304
|
+
```
|
|
305
|
+
|
|
276
306
|
### Stubbing with custom response
|
|
277
307
|
|
|
278
308
|
```ruby
|
|
@@ -283,6 +313,12 @@ stub_request(:any, "www.example.com").
|
|
|
283
313
|
Net::HTTP.get("www.example.com", '/') # ===> "abc"
|
|
284
314
|
```
|
|
285
315
|
|
|
316
|
+
Set appropriate Content-Type for HTTParty's `parsed_response`.
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
stub_request(:any, "www.example.com").to_return body: '{}', headers: {content_type: 'application/json'}
|
|
320
|
+
```
|
|
321
|
+
|
|
286
322
|
### Response with body specified as IO object
|
|
287
323
|
|
|
288
324
|
```ruby
|
|
@@ -294,6 +330,16 @@ stub_request(:any, "www.example.com").
|
|
|
294
330
|
Net::HTTP.get('www.example.com', '/') # ===> "abc\n"
|
|
295
331
|
```
|
|
296
332
|
|
|
333
|
+
### Response with JSON body
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
|
|
337
|
+
stub_request(:any, "www.example.com").
|
|
338
|
+
to_return_json(body: {foo: "bar"})
|
|
339
|
+
|
|
340
|
+
Net::HTTP.get('www.example.com', '/') # ===> "{\"foo\": \"bar\"}"
|
|
341
|
+
```
|
|
342
|
+
|
|
297
343
|
### Response with custom status message
|
|
298
344
|
|
|
299
345
|
```ruby
|
|
@@ -347,7 +393,8 @@ RestClient.post('www.example.net', 'abc') # ===> "abc\n"
|
|
|
347
393
|
|
|
348
394
|
### Dynamically evaluated raw responses recorded with `curl -is`
|
|
349
395
|
|
|
350
|
-
|
|
396
|
+
`curl -is www.example.com > /tmp/www.example.com.txt`
|
|
397
|
+
|
|
351
398
|
```ruby
|
|
352
399
|
stub_request(:get, "www.example.com").
|
|
353
400
|
to_return(lambda { |request| File.new("/tmp/#{request.uri.host.to_s}.txt") })
|
|
@@ -504,7 +551,7 @@ RestClient.get('www.example.org:8080', '/') # ===> Allowed
|
|
|
504
551
|
With a `Regexp` matching the URI:
|
|
505
552
|
|
|
506
553
|
```ruby
|
|
507
|
-
WebMock.disable_net_connect!(allow: %r{ample
|
|
554
|
+
WebMock.disable_net_connect!(allow: %r{ample\.org/foo})
|
|
508
555
|
|
|
509
556
|
RestClient.get('www.example.org', '/foo/bar') # ===> Allowed
|
|
510
557
|
RestClient.get('sample.org', '/foo') # ===> Allowed
|
|
@@ -514,9 +561,9 @@ RestClient.get('sample.org', '/bar') # ===> Failure
|
|
|
514
561
|
With an object that responds to `#call`, receiving a `URI` object and returning a boolean:
|
|
515
562
|
|
|
516
563
|
```ruby
|
|
517
|
-
|
|
564
|
+
denylist = ['google.com', 'facebook.com', 'apple.com']
|
|
518
565
|
allowed_sites = lambda{|uri|
|
|
519
|
-
|
|
566
|
+
denylist.none?{|site| uri.host.include?(site) }
|
|
520
567
|
}
|
|
521
568
|
WebMock.disable_net_connect!(allow: allowed_sites)
|
|
522
569
|
|
|
@@ -696,6 +743,28 @@ Net::HTTP.get('www.example.com', '/') # ===> Failure
|
|
|
696
743
|
assert_not_requested :get, "www.example.com" # ===> Success
|
|
697
744
|
```
|
|
698
745
|
|
|
746
|
+
## Clearing request counters
|
|
747
|
+
|
|
748
|
+
If you want to reset **only** the counters of the executed requests use `WebMock.reset_executed_requests!`
|
|
749
|
+
|
|
750
|
+
```ruby
|
|
751
|
+
stub = stub_request(:get, "www.example.com")
|
|
752
|
+
stub2 = stub_request(:get, "www.example2.com")
|
|
753
|
+
|
|
754
|
+
Net::HTTP.get('www.example.com', '/')
|
|
755
|
+
Net::HTTP.get('www.example.com', '/')
|
|
756
|
+
|
|
757
|
+
Net::HTTP.get('www.example2.com', '/')
|
|
758
|
+
|
|
759
|
+
expect(stub).to have_been_requested.times(2)
|
|
760
|
+
expect(stub2).to have_been_requested.times(1)
|
|
761
|
+
|
|
762
|
+
WebMock.reset_executed_requests!
|
|
763
|
+
|
|
764
|
+
expect(stub).not_to have_been_requested
|
|
765
|
+
expect(stub2).not_to have_been_requested
|
|
766
|
+
```
|
|
767
|
+
|
|
699
768
|
## Disabling and enabling WebMock or only some http client adapters
|
|
700
769
|
|
|
701
770
|
```ruby
|
|
@@ -841,6 +910,10 @@ end
|
|
|
841
910
|
|
|
842
911
|
Please submit them here [http://github.com/bblimke/webmock/issues](http://github.com/bblimke/webmock/issues)
|
|
843
912
|
|
|
913
|
+
## Issue triage [](https://www.codetriage.com/bblimke/webmock)
|
|
914
|
+
|
|
915
|
+
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).
|
|
916
|
+
|
|
844
917
|
## Suggestions
|
|
845
918
|
|
|
846
919
|
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)
|
|
@@ -1035,13 +1108,98 @@ People who submitted patches and new features or suggested improvements. Many th
|
|
|
1035
1108
|
* George Ulmer
|
|
1036
1109
|
* Christof Koenig
|
|
1037
1110
|
* Chung-Yi Chi
|
|
1111
|
+
* Olexandr Hoshylyk
|
|
1112
|
+
* Janko Marohnić
|
|
1113
|
+
* Pat Allan
|
|
1114
|
+
* Rick Song
|
|
1115
|
+
* NARUSE, Yui
|
|
1116
|
+
* Piotr Boniecki
|
|
1117
|
+
* Olia Kremmyda
|
|
1118
|
+
* Michał Matyas
|
|
1119
|
+
* Matt Brictson
|
|
1120
|
+
* Kenny Ortmann
|
|
1121
|
+
* redbar0n
|
|
1122
|
+
* Lukas Pokorny
|
|
1123
|
+
* Arkadiy Tetelman
|
|
1124
|
+
* Kazato Sugimoto
|
|
1125
|
+
* Olle Jonsson
|
|
1126
|
+
* Pavel Rosický
|
|
1127
|
+
* Geremia Taglialatela
|
|
1128
|
+
* Koichi Sasada
|
|
1129
|
+
* Yusuke Endoh
|
|
1130
|
+
* Grey Baker
|
|
1131
|
+
* SoonKhen OwYong
|
|
1132
|
+
* Pavel Valena
|
|
1133
|
+
* Adam Sokolnicki
|
|
1134
|
+
* Jeff Felchner
|
|
1135
|
+
* Eike Send
|
|
1136
|
+
* Claudio Poli
|
|
1137
|
+
* Csaba Apagyi
|
|
1138
|
+
* Frederick Cheung
|
|
1139
|
+
* Fábio D. Batista
|
|
1140
|
+
* Andriy Yanko
|
|
1141
|
+
* y-yagi
|
|
1142
|
+
* Rafael França
|
|
1143
|
+
* George Claghorn
|
|
1144
|
+
* Alex Junger
|
|
1145
|
+
* Orien Madgwick
|
|
1146
|
+
* Andrei Sidorov
|
|
1147
|
+
* Marco Costa
|
|
1148
|
+
* Ryan Davis
|
|
1149
|
+
* Brandur
|
|
1150
|
+
* Samuel Williams
|
|
1151
|
+
* Patrik Ragnarsson
|
|
1152
|
+
* Alex Coomans
|
|
1153
|
+
* Vesa Laakso
|
|
1154
|
+
* John Hawthorn
|
|
1155
|
+
* guppy0356
|
|
1156
|
+
* Thilo Rusche
|
|
1157
|
+
* Andrew Stuntz
|
|
1158
|
+
* Lucas Uyezu
|
|
1159
|
+
* Bruno Sutic
|
|
1160
|
+
* Ryan Kerr
|
|
1161
|
+
* Adam Harwood
|
|
1162
|
+
* Ben Koshy
|
|
1163
|
+
* Jesse Bowes
|
|
1164
|
+
* Marek Kasztelnik
|
|
1165
|
+
* ce07c3
|
|
1166
|
+
* Jun Jiang
|
|
1167
|
+
* Oleksiy Kovyrin
|
|
1168
|
+
* Matt Larraz
|
|
1169
|
+
* Tony Schneider
|
|
1170
|
+
* Niklas Hösl
|
|
1171
|
+
* Johanna Hartmann
|
|
1172
|
+
* Alex Vondrak
|
|
1173
|
+
* Will Storey
|
|
1174
|
+
* Eduardo Hernandez
|
|
1175
|
+
* ojab
|
|
1176
|
+
* Giorgio Gambino
|
|
1177
|
+
* Timmitry
|
|
1178
|
+
* Michael Fairley
|
|
1179
|
+
* Ray Zane
|
|
1180
|
+
* Go Sueyoshi
|
|
1181
|
+
* Cedric Sohrauer
|
|
1182
|
+
* Akira Matsuda
|
|
1183
|
+
* Mark Spangler
|
|
1184
|
+
* Henrik Nyh
|
|
1185
|
+
* Yoann Lecuyer
|
|
1186
|
+
* Lucas Arnaud
|
|
1187
|
+
* Marc Rohloff
|
|
1188
|
+
* inkstak
|
|
1189
|
+
* Yuki Inoue
|
|
1190
|
+
* Brandon Weaver
|
|
1191
|
+
* Josh Nichols
|
|
1192
|
+
* Ricardo Trindade
|
|
1193
|
+
* Earlopain
|
|
1194
|
+
* James Brown
|
|
1195
|
+
* Kazuhiro NISHIYAMA
|
|
1038
1196
|
|
|
1039
1197
|
For a full list of contributors you can visit the
|
|
1040
1198
|
[contributors](https://github.com/bblimke/webmock/contributors) page.
|
|
1041
1199
|
|
|
1042
1200
|
## Background
|
|
1043
1201
|
|
|
1044
|
-
Thank you Fakeweb! This library was inspired by [FakeWeb](
|
|
1202
|
+
Thank you Fakeweb! This library was inspired by [FakeWeb](https://github.com/chrisk/fakeweb).
|
|
1045
1203
|
I imported some solutions from that project to WebMock. I also copied some code i.e Net:HTTP adapter.
|
|
1046
1204
|
Fakeweb architecture unfortunately didn't allow me to extend it easily with the features I needed.
|
|
1047
1205
|
I also preferred some things to work differently i.e request stub precedence.
|
data/lib/webmock/api.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module WebMock
|
|
2
4
|
module API
|
|
3
5
|
extend self
|
|
@@ -54,10 +56,22 @@ module WebMock
|
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
58
|
|
|
59
|
+
def hash_excluding(*args)
|
|
60
|
+
if defined?(super)
|
|
61
|
+
super
|
|
62
|
+
else
|
|
63
|
+
WebMock::Matchers::HashExcludingMatcher.new(anythingize_lonely_keys(*args))
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
57
67
|
def remove_request_stub(stub)
|
|
58
68
|
WebMock::StubRegistry.instance.remove_request_stub(stub)
|
|
59
69
|
end
|
|
60
70
|
|
|
71
|
+
def reset_executed_requests!
|
|
72
|
+
WebMock::RequestRegistry.instance.reset!
|
|
73
|
+
end
|
|
74
|
+
|
|
61
75
|
private
|
|
62
76
|
|
|
63
77
|
def convert_uri_method_and_options_to_request_and_options(method, uri, options, &block)
|
data/lib/webmock/config.rb
CHANGED
data/lib/webmock/cucumber.rb
CHANGED
data/lib/webmock/deprecation.rb
CHANGED
data/lib/webmock/errors.rb
CHANGED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'async'
|
|
5
|
+
require 'async/http'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
# async-http not found
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
if defined?(Async::HTTP)
|
|
11
|
+
module WebMock
|
|
12
|
+
module HttpLibAdapters
|
|
13
|
+
class AsyncHttpClientAdapter < HttpLibAdapter
|
|
14
|
+
adapter_for :async_http_client
|
|
15
|
+
|
|
16
|
+
OriginalAsyncHttpClient = Async::HTTP::Client unless const_defined?(:OriginalAsyncHttpClient)
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
def enable!
|
|
20
|
+
Async::HTTP.send(:remove_const, :Client)
|
|
21
|
+
Async::HTTP.send(:const_set, :Client, Async::HTTP::WebMockClientWrapper)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def disable!
|
|
25
|
+
Async::HTTP.send(:remove_const, :Client)
|
|
26
|
+
Async::HTTP.send(:const_set, :Client, OriginalAsyncHttpClient)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module Async
|
|
34
|
+
module HTTP
|
|
35
|
+
class WebMockClientWrapper < Client
|
|
36
|
+
def initialize(
|
|
37
|
+
endpoint,
|
|
38
|
+
protocol = endpoint.protocol,
|
|
39
|
+
scheme = endpoint.scheme,
|
|
40
|
+
authority = endpoint.authority,
|
|
41
|
+
**options
|
|
42
|
+
)
|
|
43
|
+
webmock_endpoint = WebMockEndpoint.new(scheme, authority, protocol)
|
|
44
|
+
|
|
45
|
+
@network_client = WebMockClient.new(endpoint, **options)
|
|
46
|
+
@webmock_client = WebMockClient.new(webmock_endpoint, **options)
|
|
47
|
+
|
|
48
|
+
@scheme = scheme
|
|
49
|
+
@authority = authority
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def call(request)
|
|
53
|
+
request.scheme ||= self.scheme
|
|
54
|
+
request.authority ||= self.authority
|
|
55
|
+
|
|
56
|
+
request_signature = build_request_signature(request)
|
|
57
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
|
58
|
+
webmock_response = WebMock::StubRegistry.instance.response_for_request(request_signature)
|
|
59
|
+
net_connect_allowed = WebMock.net_connect_allowed?(request_signature.uri)
|
|
60
|
+
real_request = false
|
|
61
|
+
|
|
62
|
+
if webmock_response
|
|
63
|
+
webmock_response.raise_error_if_any
|
|
64
|
+
raise Async::TimeoutError, 'WebMock timeout error' if webmock_response.should_timeout
|
|
65
|
+
WebMockApplication.add_webmock_response(request, webmock_response)
|
|
66
|
+
response = @webmock_client.call(request)
|
|
67
|
+
elsif net_connect_allowed
|
|
68
|
+
response = @network_client.call(request)
|
|
69
|
+
real_request = true
|
|
70
|
+
else
|
|
71
|
+
raise WebMock::NetConnectNotAllowedError.new(request_signature) unless webmock_response
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if WebMock::CallbackRegistry.any_callbacks?
|
|
75
|
+
webmock_response ||= build_webmock_response(response)
|
|
76
|
+
WebMock::CallbackRegistry.invoke_callbacks(
|
|
77
|
+
{
|
|
78
|
+
lib: :async_http_client,
|
|
79
|
+
real_request: real_request
|
|
80
|
+
},
|
|
81
|
+
request_signature,
|
|
82
|
+
webmock_response
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
response
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def close
|
|
90
|
+
@network_client.close
|
|
91
|
+
@webmock_client.close
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def build_request_signature(request)
|
|
97
|
+
body = request.read
|
|
98
|
+
request.body = ::Protocol::HTTP::Body::Buffered.wrap(body)
|
|
99
|
+
WebMock::RequestSignature.new(
|
|
100
|
+
request.method.downcase.to_sym,
|
|
101
|
+
"#{request.scheme}://#{request.authority}#{request.path}",
|
|
102
|
+
headers: request.headers.to_h,
|
|
103
|
+
body: body
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def build_webmock_response(response)
|
|
108
|
+
body = response.read
|
|
109
|
+
response.body = ::Protocol::HTTP::Body::Buffered.wrap(body)
|
|
110
|
+
|
|
111
|
+
webmock_response = WebMock::Response.new
|
|
112
|
+
webmock_response.status = [
|
|
113
|
+
response.status,
|
|
114
|
+
::Protocol::HTTP1::Reason::DESCRIPTIONS[response.status]
|
|
115
|
+
]
|
|
116
|
+
webmock_response.headers = build_webmock_response_headers(response)
|
|
117
|
+
webmock_response.body = body
|
|
118
|
+
webmock_response
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def build_webmock_response_headers(response)
|
|
122
|
+
response.headers.each.each_with_object({}) do |(k, v), o|
|
|
123
|
+
o[k] ||= []
|
|
124
|
+
o[k] << v
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class WebMockClient < Client
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class WebMockEndpoint
|
|
133
|
+
def initialize(scheme, authority, protocol)
|
|
134
|
+
@scheme = scheme
|
|
135
|
+
@authority = authority
|
|
136
|
+
@protocol = protocol
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
attr :scheme, :authority, :protocol
|
|
140
|
+
|
|
141
|
+
def connect
|
|
142
|
+
server_socket, client_socket = create_connected_sockets
|
|
143
|
+
Async(transient: true) do
|
|
144
|
+
accept_socket(server_socket)
|
|
145
|
+
end
|
|
146
|
+
client_socket
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def inspect
|
|
150
|
+
"\#<#{self.class}> #{scheme}://#{authority} protocol=#{protocol}"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
def create_connected_sockets
|
|
156
|
+
pair = begin
|
|
157
|
+
Async::IO::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
|
|
158
|
+
rescue Errno::EAFNOSUPPORT
|
|
159
|
+
Async::IO::Socket.pair(Socket::AF_INET, Socket::SOCK_STREAM)
|
|
160
|
+
end
|
|
161
|
+
pair.tap do |sockets|
|
|
162
|
+
sockets.each do |socket|
|
|
163
|
+
socket.instance_variable_set :@alpn_protocol, nil
|
|
164
|
+
socket.instance_eval do
|
|
165
|
+
def alpn_protocol
|
|
166
|
+
nil # means HTTP11 will be used for HTTPS
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def accept_socket(socket)
|
|
174
|
+
server = Async::HTTP::Server.new(WebMockApplication, self)
|
|
175
|
+
server.accept(socket, socket.remote_address)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
module WebMockApplication
|
|
180
|
+
WEBMOCK_REQUEST_ID_HEADER = 'x-webmock-request-id'.freeze
|
|
181
|
+
|
|
182
|
+
class << self
|
|
183
|
+
def call(request)
|
|
184
|
+
request.read
|
|
185
|
+
webmock_response = get_webmock_response(request)
|
|
186
|
+
build_response(webmock_response)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def add_webmock_response(request, webmock_response)
|
|
190
|
+
webmock_request_id = request.object_id.to_s
|
|
191
|
+
request.headers.add(WEBMOCK_REQUEST_ID_HEADER, webmock_request_id)
|
|
192
|
+
webmock_responses[webmock_request_id] = webmock_response
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def get_webmock_response(request)
|
|
196
|
+
webmock_request_id = request.headers[WEBMOCK_REQUEST_ID_HEADER][0]
|
|
197
|
+
webmock_responses.fetch(webmock_request_id)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
private
|
|
201
|
+
|
|
202
|
+
def webmock_responses
|
|
203
|
+
@webmock_responses ||= {}
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def build_response(webmock_response)
|
|
207
|
+
headers = (webmock_response.headers || {}).each_with_object([]) do |(k, value), o|
|
|
208
|
+
Array(value).each do |v|
|
|
209
|
+
o.push [k, v]
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
::Protocol::HTTP::Response[
|
|
214
|
+
webmock_response.status[0],
|
|
215
|
+
headers,
|
|
216
|
+
webmock_response.body
|
|
217
|
+
]
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|