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.
Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +558 -2
  3. data/README.md +200 -42
  4. data/lib/webmock/api.rb +14 -0
  5. data/lib/webmock/assertion_failure.rb +2 -0
  6. data/lib/webmock/callback_registry.rb +2 -0
  7. data/lib/webmock/config.rb +2 -0
  8. data/lib/webmock/cucumber.rb +2 -0
  9. data/lib/webmock/deprecation.rb +2 -0
  10. data/lib/webmock/errors.rb +2 -0
  11. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +223 -0
  12. data/lib/webmock/http_lib_adapters/curb_adapter.rb +21 -5
  13. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +20 -9
  14. data/lib/webmock/http_lib_adapters/excon_adapter.rb +7 -2
  15. data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +2 -0
  16. data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +2 -0
  17. data/lib/webmock/http_lib_adapters/http_rb/client.rb +4 -1
  18. data/lib/webmock/http_lib_adapters/http_rb/request.rb +19 -1
  19. data/lib/webmock/http_lib_adapters/http_rb/response.rb +29 -3
  20. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +11 -3
  21. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +9 -3
  22. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +2 -0
  23. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +30 -9
  24. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +35 -15
  25. data/lib/webmock/http_lib_adapters/net_http.rb +38 -89
  26. data/lib/webmock/http_lib_adapters/net_http_response.rb +3 -1
  27. data/lib/webmock/http_lib_adapters/patron_adapter.rb +6 -4
  28. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
  29. data/lib/webmock/matchers/any_arg_matcher.rb +15 -0
  30. data/lib/webmock/matchers/hash_argument_matcher.rb +23 -0
  31. data/lib/webmock/matchers/hash_excluding_matcher.rb +17 -0
  32. data/lib/webmock/matchers/hash_including_matcher.rb +6 -23
  33. data/lib/webmock/minitest.rb +2 -0
  34. data/lib/webmock/rack_response.rb +3 -1
  35. data/lib/webmock/request_body_diff.rb +3 -1
  36. data/lib/webmock/request_execution_verifier.rb +4 -3
  37. data/lib/webmock/request_pattern.rb +132 -52
  38. data/lib/webmock/request_registry.rb +3 -1
  39. data/lib/webmock/request_signature.rb +5 -3
  40. data/lib/webmock/request_signature_snippet.rb +6 -4
  41. data/lib/webmock/request_stub.rb +34 -0
  42. data/lib/webmock/response.rb +22 -14
  43. data/lib/webmock/responses_sequence.rb +2 -0
  44. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +2 -0
  45. data/lib/webmock/rspec/matchers/webmock_matcher.rb +2 -0
  46. data/lib/webmock/rspec/matchers.rb +2 -0
  47. data/lib/webmock/rspec.rb +12 -3
  48. data/lib/webmock/stub_registry.rb +28 -11
  49. data/lib/webmock/stub_request_snippet.rb +12 -6
  50. data/lib/webmock/test_unit.rb +3 -3
  51. data/lib/webmock/util/hash_counter.rb +15 -9
  52. data/lib/webmock/util/hash_keys_stringifier.rb +2 -0
  53. data/lib/webmock/util/hash_validator.rb +2 -0
  54. data/lib/webmock/util/headers.rb +39 -11
  55. data/lib/webmock/util/json.rb +3 -2
  56. data/lib/webmock/util/query_mapper.rb +11 -7
  57. data/lib/webmock/util/uri.rb +13 -11
  58. data/lib/webmock/util/values_stringifier.rb +22 -0
  59. data/lib/webmock/util/version_checker.rb +7 -5
  60. data/lib/webmock/version.rb +3 -1
  61. data/lib/webmock/webmock.rb +22 -3
  62. data/lib/webmock.rb +55 -48
  63. metadata +106 -175
  64. data/.gemtest +0 -0
  65. data/.gitignore +0 -34
  66. data/.rspec-tm +0 -2
  67. data/.travis.yml +0 -20
  68. data/Gemfile +0 -9
  69. data/Rakefile +0 -30
  70. data/minitest/test_helper.rb +0 -34
  71. data/minitest/test_webmock.rb +0 -9
  72. data/minitest/webmock_spec.rb +0 -60
  73. data/spec/acceptance/curb/curb_spec.rb +0 -466
  74. data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
  75. data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -406
  76. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
  77. data/spec/acceptance/excon/excon_spec.rb +0 -75
  78. data/spec/acceptance/excon/excon_spec_helper.rb +0 -50
  79. data/spec/acceptance/http_rb/http_rb_spec.rb +0 -73
  80. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -51
  81. data/spec/acceptance/httpclient/httpclient_spec.rb +0 -210
  82. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
  83. data/spec/acceptance/manticore/manticore_spec.rb +0 -56
  84. data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
  85. data/spec/acceptance/net_http/net_http_shared.rb +0 -153
  86. data/spec/acceptance/net_http/net_http_spec.rb +0 -317
  87. data/spec/acceptance/net_http/net_http_spec_helper.rb +0 -64
  88. data/spec/acceptance/net_http/real_net_http_spec.rb +0 -20
  89. data/spec/acceptance/patron/patron_spec.rb +0 -118
  90. data/spec/acceptance/patron/patron_spec_helper.rb +0 -54
  91. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +0 -313
  92. data/spec/acceptance/shared/callbacks.rb +0 -147
  93. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
  94. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
  95. data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
  96. data/spec/acceptance/shared/request_expectations.rb +0 -916
  97. data/spec/acceptance/shared/returning_declared_responses.rb +0 -388
  98. data/spec/acceptance/shared/stubbing_requests.rb +0 -583
  99. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
  100. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
  101. data/spec/acceptance/webmock_shared.rb +0 -41
  102. data/spec/fixtures/test.txt +0 -1
  103. data/spec/quality_spec.rb +0 -84
  104. data/spec/spec_helper.rb +0 -48
  105. data/spec/support/example_curl_output.txt +0 -22
  106. data/spec/support/failures.rb +0 -9
  107. data/spec/support/my_rack_app.rb +0 -53
  108. data/spec/support/network_connection.rb +0 -19
  109. data/spec/support/webmock_server.rb +0 -69
  110. data/spec/unit/api_spec.rb +0 -75
  111. data/spec/unit/errors_spec.rb +0 -129
  112. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +0 -17
  113. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +0 -12
  114. data/spec/unit/matchers/hash_including_matcher_spec.rb +0 -87
  115. data/spec/unit/rack_response_spec.rb +0 -112
  116. data/spec/unit/request_body_diff_spec.rb +0 -90
  117. data/spec/unit/request_execution_verifier_spec.rb +0 -208
  118. data/spec/unit/request_pattern_spec.rb +0 -590
  119. data/spec/unit/request_registry_spec.rb +0 -95
  120. data/spec/unit/request_signature_snippet_spec.rb +0 -89
  121. data/spec/unit/request_signature_spec.rb +0 -155
  122. data/spec/unit/request_stub_spec.rb +0 -199
  123. data/spec/unit/response_spec.rb +0 -282
  124. data/spec/unit/stub_registry_spec.rb +0 -103
  125. data/spec/unit/stub_request_snippet_spec.rb +0 -95
  126. data/spec/unit/util/hash_counter_spec.rb +0 -39
  127. data/spec/unit/util/hash_keys_stringifier_spec.rb +0 -27
  128. data/spec/unit/util/headers_spec.rb +0 -28
  129. data/spec/unit/util/json_spec.rb +0 -33
  130. data/spec/unit/util/query_mapper_spec.rb +0 -144
  131. data/spec/unit/util/uri_spec.rb +0 -299
  132. data/spec/unit/util/version_checker_spec.rb +0 -65
  133. data/spec/unit/webmock_spec.rb +0 -11
  134. data/test/http_request.rb +0 -24
  135. data/test/shared_test.rb +0 -95
  136. data/test/test_helper.rb +0 -23
  137. data/test/test_webmock.rb +0 -6
  138. data/webmock.gemspec +0 -46
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  WebMock
2
2
  =======
3
- [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock) [![Build Status](https://secure.travis-ci.org/bblimke/webmock.svg?branch=master)](http://travis-ci.org/bblimke/webmock) [![Dependency Status](https://gemnasium.com/bblimke/webmock.svg)](http://gemnasium.com/bblimke/webmock) [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock) [![Inline docs](http://inch-ci.org/github/bblimke/webmock.svg?branch=master)](http://inch-ci.org/github/bblimke/webmock)
3
+ [![Gem Version](https://badge.fury.io/rb/webmock.svg)](http://badge.fury.io/rb/webmock)
4
+ [![Build Status](https://github.com/bblimke/webmock/workflows/CI/badge.svg?branch=master)](https://github.com/bblimke/webmock/actions)
5
+ [![Code Climate](https://codeclimate.com/github/bblimke/webmock/badges/gpa.svg)](https://codeclimate.com/github/bblimke/webmock)
6
+ [![Mentioned in Awesome Ruby](https://awesome.re/mentioned-badge.svg)](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
- * Net::HTTP and libraries based on Net::HTTP (i.e RightHttpConnection, REST Client, HTTParty)
23
- * HTTPClient
24
- * Patron
25
- * EM-HTTP-Request
26
- * Curb (currently only Curb::Easy)
27
- * Typhoeus (currently only Typhoeus::Hydra)
28
- * Excon
29
- * HTTP Gem
30
- * Manticore
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.0
36
- * MRI 2.1
37
- * MRI 2.2
38
- * MRI 2.3
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
- gem install webmock
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
- git clone http://github.com/bblimke/webmock.git
50
- cd webmock
51
- rake install
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
- ### Test::Unit
74
+ ### Cucumber
58
75
 
59
- Add the following code to `test/test_helper.rb`
76
+ Create a file `features/support/webmock.rb` with the following contents:
60
77
 
61
78
  ```ruby
62
- require 'webmock/test_unit'
79
+ require 'webmock/cucumber'
63
80
  ```
64
81
 
65
- ### RSpec
82
+ ### MiniTest
66
83
 
67
- Add the following code to `spec/spec_helper`:
84
+ Add the following code to `test/test_helper`:
68
85
 
69
86
  ```ruby
70
- require 'webmock/rspec'
87
+ require 'webmock/minitest'
71
88
  ```
72
89
 
73
- ### MiniTest
90
+ ### RSpec
74
91
 
75
- Add the following code to `test/test_helper`:
92
+ Add the following code to `spec/spec_helper`:
76
93
 
77
94
  ```ruby
78
- require 'webmock/minitest'
95
+ require 'webmock/rspec'
79
96
  ```
80
97
 
81
- ### Cucumber
98
+ ### Test::Unit
82
99
 
83
- Create a file `features/support/webmock.rb` with the following contents:
100
+ Add the following code to `test/test_helper.rb`
84
101
 
85
102
  ```ruby
86
- require 'webmock/cucumber'
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
- ## Examples
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
- `curl -is www.example.com > /tmp/www.example.com.txt`
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.org/foo})
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
- blacklist = ['google.com', 'facebook.com', 'apple.com']
564
+ denylist = ['google.com', 'facebook.com', 'apple.com']
518
565
  allowed_sites = lambda{|uri|
519
- blacklist.none?{|site| uri.host.include?(site) }
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 [![Open Source Helpers](https://www.codetriage.com/bblimke/webmock/badges/users.svg)](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](http://fakeweb.rubyforge.org).
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)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class AssertionFailure
3
5
  @error_class = RuntimeError
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class CallbackRegistry
3
5
  @@callbacks = []
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class Config
3
5
  include Singleton
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webmock'
2
4
  require 'webmock/rspec/matchers'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class Deprecation
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class NetConnectNotAllowedError < Exception
@@ -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