webmock 1.8.6 → 3.14.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 +7 -0
- data/.github/workflows/CI.yml +37 -0
- data/.gitignore +6 -0
- data/CHANGELOG.md +1198 -0
- data/Gemfile +3 -15
- data/README.md +761 -305
- data/Rakefile +13 -40
- data/lib/webmock/api.rb +63 -17
- data/lib/webmock/callback_registry.rb +1 -1
- data/lib/webmock/config.rb +8 -0
- data/lib/webmock/cucumber.rb +2 -0
- data/lib/webmock/errors.rb +8 -24
- data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
- data/lib/webmock/http_lib_adapters/curb_adapter.rb +148 -84
- data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +224 -4
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +104 -34
- data/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
- data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
- data/lib/webmock/http_lib_adapters/http_rb/response.rb +64 -0
- data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
- data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
- data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +152 -86
- data/lib/webmock/http_lib_adapters/manticore_adapter.rb +145 -0
- data/lib/webmock/http_lib_adapters/net_http.rb +155 -46
- data/lib/webmock/http_lib_adapters/net_http_response.rb +1 -1
- data/lib/webmock/http_lib_adapters/patron_adapter.rb +16 -15
- data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +76 -82
- data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
- data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
- data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
- data/lib/webmock/matchers/hash_including_matcher.rb +4 -12
- data/lib/webmock/minitest.rb +29 -3
- data/lib/webmock/rack_response.rb +14 -7
- data/lib/webmock/request_body_diff.rb +64 -0
- data/lib/webmock/request_execution_verifier.rb +38 -17
- data/lib/webmock/request_pattern.rb +158 -38
- data/lib/webmock/request_registry.rb +3 -3
- data/lib/webmock/request_signature.rb +7 -3
- data/lib/webmock/request_signature_snippet.rb +61 -0
- data/lib/webmock/request_stub.rb +9 -6
- data/lib/webmock/response.rb +30 -15
- data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +38 -2
- data/lib/webmock/rspec/matchers/webmock_matcher.rb +23 -2
- data/lib/webmock/rspec/matchers.rb +0 -1
- data/lib/webmock/rspec.rb +11 -2
- data/lib/webmock/stub_registry.rb +31 -10
- data/lib/webmock/stub_request_snippet.rb +14 -6
- data/lib/webmock/test_unit.rb +4 -4
- data/lib/webmock/util/hash_counter.rb +20 -6
- data/lib/webmock/util/hash_keys_stringifier.rb +5 -3
- data/lib/webmock/util/hash_validator.rb +17 -0
- data/lib/webmock/util/headers.rb +23 -2
- data/lib/webmock/util/json.rb +20 -7
- data/lib/webmock/util/query_mapper.rb +281 -0
- data/lib/webmock/util/uri.rb +29 -19
- data/lib/webmock/util/values_stringifier.rb +20 -0
- data/lib/webmock/util/version_checker.rb +40 -2
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +56 -17
- data/lib/webmock.rb +56 -46
- data/minitest/test_helper.rb +8 -3
- data/minitest/test_webmock.rb +4 -1
- data/minitest/webmock_spec.rb +16 -6
- data/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
- data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
- data/spec/acceptance/curb/curb_spec.rb +227 -68
- data/spec/acceptance/curb/curb_spec_helper.rb +11 -8
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +322 -28
- data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +15 -10
- data/spec/acceptance/excon/excon_spec.rb +66 -4
- data/spec/acceptance/excon/excon_spec_helper.rb +21 -7
- data/spec/acceptance/http_rb/http_rb_spec.rb +93 -0
- data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
- data/spec/acceptance/httpclient/httpclient_spec.rb +152 -11
- data/spec/acceptance/httpclient/httpclient_spec_helper.rb +25 -16
- data/spec/acceptance/manticore/manticore_spec.rb +107 -0
- data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
- data/spec/acceptance/net_http/net_http_shared.rb +52 -24
- data/spec/acceptance/net_http/net_http_spec.rb +164 -50
- data/spec/acceptance/net_http/net_http_spec_helper.rb +19 -10
- data/spec/acceptance/net_http/real_net_http_spec.rb +1 -1
- data/spec/acceptance/patron/patron_spec.rb +29 -40
- data/spec/acceptance/patron/patron_spec_helper.rb +15 -11
- data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +229 -58
- data/spec/acceptance/shared/callbacks.rb +32 -30
- data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +20 -5
- data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +14 -14
- data/spec/acceptance/shared/precedence_of_stubs.rb +6 -6
- data/spec/acceptance/shared/request_expectations.rb +560 -296
- data/spec/acceptance/shared/returning_declared_responses.rb +180 -138
- data/spec/acceptance/shared/stubbing_requests.rb +385 -154
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +78 -17
- data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +19 -15
- data/spec/acceptance/webmock_shared.rb +2 -2
- data/spec/fixtures/test.txt +1 -0
- data/spec/quality_spec.rb +27 -3
- data/spec/spec_helper.rb +11 -20
- data/spec/support/failures.rb +9 -0
- data/spec/support/my_rack_app.rb +8 -3
- data/spec/support/network_connection.rb +7 -13
- data/spec/support/webmock_server.rb +8 -3
- data/spec/unit/api_spec.rb +175 -0
- data/spec/unit/errors_spec.rb +116 -19
- data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +1 -1
- data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +2 -2
- data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
- data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
- data/spec/unit/rack_response_spec.rb +54 -16
- data/spec/unit/request_body_diff_spec.rb +90 -0
- data/spec/unit/request_execution_verifier_spec.rb +147 -39
- data/spec/unit/request_pattern_spec.rb +462 -198
- data/spec/unit/request_registry_spec.rb +29 -9
- data/spec/unit/request_signature_snippet_spec.rb +89 -0
- data/spec/unit/request_signature_spec.rb +91 -49
- data/spec/unit/request_stub_spec.rb +71 -70
- data/spec/unit/response_spec.rb +100 -81
- data/spec/unit/stub_registry_spec.rb +37 -20
- data/spec/unit/stub_request_snippet_spec.rb +51 -31
- data/spec/unit/util/hash_counter_spec.rb +6 -6
- data/spec/unit/util/hash_keys_stringifier_spec.rb +4 -4
- data/spec/unit/util/headers_spec.rb +4 -4
- data/spec/unit/util/json_spec.rb +29 -3
- data/spec/unit/util/query_mapper_spec.rb +157 -0
- data/spec/unit/util/uri_spec.rb +150 -36
- data/spec/unit/util/version_checker_spec.rb +15 -9
- data/spec/unit/webmock_spec.rb +57 -4
- data/test/http_request.rb +3 -3
- data/test/shared_test.rb +45 -13
- data/test/test_helper.rb +1 -1
- data/test/test_webmock.rb +6 -0
- data/webmock.gemspec +30 -11
- metadata +308 -199
- data/.rvmrc +0 -1
- data/.travis.yml +0 -11
- data/Guardfile +0 -24
- data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_0_x.rb +0 -151
- data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +0 -210
@@ -6,6 +6,11 @@ unless RUBY_PLATFORM =~ /java/
|
|
6
6
|
|
7
7
|
describe "Typhoeus::Hydra" do
|
8
8
|
include TyphoeusHydraSpecHelper
|
9
|
+
let(:hydra) { Typhoeus::Hydra.new }
|
10
|
+
|
11
|
+
before do
|
12
|
+
Typhoeus::Expectation.clear
|
13
|
+
end
|
9
14
|
|
10
15
|
include_context "with WebMock"
|
11
16
|
|
@@ -15,15 +20,37 @@ unless RUBY_PLATFORM =~ /java/
|
|
15
20
|
WebMock.reset!
|
16
21
|
end
|
17
22
|
|
23
|
+
describe "supposed response fields" do
|
24
|
+
it "present" do
|
25
|
+
stub_request(:get, "http://www.example.com").to_return(headers: {'X-Test' => '1'})
|
26
|
+
response = Typhoeus.get("http://www.example.com")
|
27
|
+
expect(response.code).not_to be_nil
|
28
|
+
expect(response.status_message).not_to be_nil
|
29
|
+
expect(response.body).not_to be_nil
|
30
|
+
expect(response.headers).not_to be_nil
|
31
|
+
expect(response.effective_url).not_to be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
18
35
|
describe "when params are used" do
|
19
36
|
it "should take into account params for POST request" do
|
20
|
-
stub_request(:post, "www.example.com").with(:
|
21
|
-
Typhoeus::Request.
|
37
|
+
stub_request(:post, "www.example.com/?hello=world").with(query: {hello: 'world'})
|
38
|
+
request = Typhoeus::Request.new("http://www.example.com", method: :post, params: {hello: 'world'})
|
39
|
+
hydra.queue(request)
|
40
|
+
hydra.run
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should take into account body for POST request" do
|
44
|
+
stub_request(:post, "www.example.com").with(body: {hello: 'world'})
|
45
|
+
response = Typhoeus.post("http://www.example.com", method: :post, body: {hello: 'world'})
|
46
|
+
expect(response.code).to eq(200)
|
22
47
|
end
|
23
48
|
|
24
49
|
it "should take into account params for GET request" do
|
25
|
-
stub_request(:get, "http://www.example.com/?hello=world")
|
26
|
-
Typhoeus::Request.
|
50
|
+
stub_request(:get, "http://www.example.com/?hello=world").to_return({})
|
51
|
+
request = Typhoeus::Request.new("http://www.example.com/?hello=world", method: :get)
|
52
|
+
hydra.queue(request)
|
53
|
+
hydra.run
|
27
54
|
end
|
28
55
|
end
|
29
56
|
|
@@ -31,42 +58,76 @@ unless RUBY_PLATFORM =~ /java/
|
|
31
58
|
it "should support native typhoeus timeouts" do
|
32
59
|
stub_request(:any, "example.com").to_timeout
|
33
60
|
|
34
|
-
|
61
|
+
request = Typhoeus::Request.new("http://example.com", method: :get)
|
62
|
+
hydra.queue(request)
|
63
|
+
hydra.run
|
35
64
|
|
36
|
-
response.
|
65
|
+
expect(request.response).to be_timed_out
|
37
66
|
end
|
38
67
|
end
|
39
68
|
|
40
69
|
describe "callbacks" do
|
41
70
|
before(:each) do
|
42
|
-
@hydra = Typhoeus::Hydra.new
|
43
71
|
@request = Typhoeus::Request.new("http://example.com")
|
44
72
|
end
|
45
73
|
|
46
74
|
it "should call on_complete with 2xx response" do
|
47
75
|
body = "on_success fired"
|
48
|
-
stub_request(:any, "example.com").to_return(:
|
76
|
+
stub_request(:any, "example.com").to_return(body: body)
|
49
77
|
|
50
78
|
test = nil
|
51
|
-
|
79
|
+
Typhoeus.on_complete do |c|
|
52
80
|
test = c.body
|
53
81
|
end
|
54
|
-
|
55
|
-
|
56
|
-
test.
|
82
|
+
hydra.queue @request
|
83
|
+
hydra.run
|
84
|
+
expect(test).to eq(body)
|
57
85
|
end
|
58
86
|
|
59
87
|
it "should call on_complete with 5xx response" do
|
60
88
|
response_code = 599
|
61
|
-
stub_request(:any, "example.com").to_return(:
|
89
|
+
stub_request(:any, "example.com").to_return(status: [response_code, "Server On Fire"])
|
62
90
|
|
63
91
|
test = nil
|
64
|
-
|
92
|
+
Typhoeus.on_complete do |c|
|
65
93
|
test = c.code
|
66
94
|
end
|
67
|
-
|
68
|
-
|
69
|
-
test.
|
95
|
+
hydra.queue @request
|
96
|
+
hydra.run
|
97
|
+
expect(test).to eq(response_code)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should call on_body with 2xx response" do
|
101
|
+
body = "on_body fired"
|
102
|
+
stub_request(:any, "example.com").to_return(body: body)
|
103
|
+
|
104
|
+
test_body = nil
|
105
|
+
test_complete = nil
|
106
|
+
skip("This test requires a newer version of Typhoeus") unless @request.respond_to?(:on_body)
|
107
|
+
@request.on_body do |body_chunk, response|
|
108
|
+
test_body = body_chunk
|
109
|
+
end
|
110
|
+
@request.on_complete do |response|
|
111
|
+
test_complete = response.body
|
112
|
+
end
|
113
|
+
hydra.queue @request
|
114
|
+
hydra.run
|
115
|
+
expect(test_body).to eq(body)
|
116
|
+
expect(test_complete).to eq("")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should call on_headers with 2xx response" do
|
120
|
+
body = "on_headers fired"
|
121
|
+
stub_request(:any, "example.com").to_return(body: body, headers: {'X-Test' => '1'})
|
122
|
+
|
123
|
+
test_headers = nil
|
124
|
+
skip("This test requires a newer version of Typhoeus") unless @request.respond_to?(:on_headers)
|
125
|
+
@request.on_headers do |response|
|
126
|
+
test_headers = response.headers
|
127
|
+
end
|
128
|
+
hydra.queue @request
|
129
|
+
hydra.run
|
130
|
+
expect(test_headers.to_h).to include('X-Test' => '1')
|
70
131
|
end
|
71
132
|
end
|
72
133
|
end
|
@@ -6,26 +6,30 @@ module TyphoeusHydraSpecHelper
|
|
6
6
|
|
7
7
|
|
8
8
|
def http_request(method, uri, options = {}, &block)
|
9
|
-
uri.gsub
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
uri = uri.gsub(" ", "%20") #typhoeus doesn't like spaces in the uri
|
10
|
+
request_options = {
|
11
|
+
method: method,
|
12
|
+
body: options[:body],
|
13
|
+
headers: options[:headers],
|
14
|
+
timeout: 25000
|
15
|
+
}
|
16
|
+
if options[:basic_auth]
|
17
|
+
request_options[:userpwd] = options[:basic_auth].join(':')
|
18
|
+
end
|
19
|
+
request = Typhoeus::Request.new(uri, request_options)
|
20
|
+
|
21
|
+
hydra = Typhoeus::Hydra.new
|
19
22
|
hydra.queue(request)
|
20
23
|
hydra.run
|
24
|
+
|
21
25
|
response = request.response
|
26
|
+
raise FakeTyphoeusHydraConnectError.new if response.return_code == :couldnt_connect
|
22
27
|
raise FakeTyphoeusHydraTimeoutError.new if response.timed_out?
|
23
|
-
raise FakeTyphoeusHydraConnectError.new if response.code == 0
|
24
28
|
OpenStruct.new({
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
+
body: response.body,
|
30
|
+
headers: WebMock::Util::Headers.normalize_headers(join_array_values(response.headers)),
|
31
|
+
status: response.code.to_s,
|
32
|
+
message: response.status_message
|
29
33
|
})
|
30
34
|
end
|
31
35
|
|
@@ -10,8 +10,8 @@ require 'acceptance/shared/complex_cross_concern_behaviors'
|
|
10
10
|
|
11
11
|
unless defined? SAMPLE_HEADERS
|
12
12
|
SAMPLE_HEADERS = { "Content-Length" => "8888", "Accept" => "application/json" }
|
13
|
-
ESCAPED_PARAMS = "x=ab%20c&z=%27Stop%21%27%20said%20Fred"
|
14
|
-
NOT_ESCAPED_PARAMS = "z='Stop!' said Fred&x=ab c"
|
13
|
+
ESCAPED_PARAMS = "x=ab%20c&z=%27Stop%21%27%20said%20Fred%20m"
|
14
|
+
NOT_ESCAPED_PARAMS = "z='Stop!' said Fred m&x=ab c"
|
15
15
|
end
|
16
16
|
|
17
17
|
shared_examples "with WebMock" do |*adapter_info|
|
@@ -0,0 +1 @@
|
|
1
|
+
test
|
data/spec/quality_spec.rb
CHANGED
@@ -2,6 +2,30 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
# Borrowed from Bundler
|
4
4
|
# https://github.com/carlhuda/bundler/blob/1-0-stable/spec/quality_spec.rb
|
5
|
+
# Portions copyright (c) 2010 Andre Arko
|
6
|
+
# Portions copyright (c) 2009 Engine Yard
|
7
|
+
|
8
|
+
# MIT License
|
9
|
+
|
10
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
11
|
+
# a copy of this software and associated documentation files (the
|
12
|
+
# "Software"), to deal in the Software without restriction, including
|
13
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
14
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
15
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
16
|
+
# the following conditions:
|
17
|
+
|
18
|
+
# The above copyright notice and this permission notice shall be
|
19
|
+
# included in all copies or substantial portions of the Software.
|
20
|
+
|
21
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
22
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
23
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
24
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
25
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
26
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
27
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
28
|
+
|
5
29
|
describe "The library itself" do
|
6
30
|
def check_for_tab_characters(filename)
|
7
31
|
failing_lines = []
|
@@ -27,7 +51,7 @@ describe "The library itself" do
|
|
27
51
|
end
|
28
52
|
|
29
53
|
RSpec::Matchers.define :be_well_formed do
|
30
|
-
|
54
|
+
failure_message do |actual|
|
31
55
|
actual.join("\n")
|
32
56
|
end
|
33
57
|
|
@@ -45,13 +69,13 @@ describe "The library itself" do
|
|
45
69
|
error_messages << check_for_extra_spaces(filename)
|
46
70
|
end
|
47
71
|
end
|
48
|
-
error_messages.compact.
|
72
|
+
expect(error_messages.compact).to be_well_formed
|
49
73
|
end
|
50
74
|
|
51
75
|
it "can still be built" do
|
52
76
|
Dir.chdir(File.expand_path('../../', __FILE__)) do
|
53
77
|
`gem build webmock.gemspec`
|
54
|
-
|
78
|
+
expect($?).to eq(0)
|
55
79
|
|
56
80
|
# clean up the .gem generated
|
57
81
|
system("rm webmock-#{WebMock.version}.gem")
|
data/spec/spec_helper.rb
CHANGED
@@ -6,6 +6,9 @@ unless RUBY_PLATFORM =~ /java/
|
|
6
6
|
require 'em-http'
|
7
7
|
require 'typhoeus'
|
8
8
|
end
|
9
|
+
if RUBY_PLATFORM =~ /java/
|
10
|
+
require 'manticore'
|
11
|
+
end
|
9
12
|
|
10
13
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
11
14
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
@@ -16,19 +19,18 @@ require 'webmock/rspec'
|
|
16
19
|
require 'support/network_connection'
|
17
20
|
require 'support/webmock_server'
|
18
21
|
require 'support/my_rack_app'
|
22
|
+
require 'support/failures'
|
19
23
|
|
20
|
-
CURL_EXAMPLE_OUTPUT_PATH = File.expand_path(
|
24
|
+
CURL_EXAMPLE_OUTPUT_PATH = File.expand_path('../support/example_curl_output.txt', __FILE__)
|
21
25
|
|
22
26
|
RSpec.configure do |config|
|
23
|
-
|
27
|
+
no_network_connection = ENV["NO_CONNECTION"] || ! NetworkConnection.is_network_available?
|
28
|
+
if no_network_connection
|
24
29
|
warn("No network connectivity. Only examples which do not make real network connections will run.")
|
25
|
-
|
26
|
-
end
|
27
|
-
if ENV["NO_CONNECTION"] || no_network_connection
|
28
|
-
config.filter_run_excluding :net_connect => true
|
30
|
+
config.filter_run_excluding net_connect: true
|
29
31
|
end
|
30
32
|
|
31
|
-
config.filter_run_excluding :
|
33
|
+
config.filter_run_excluding without_webmock: true
|
32
34
|
|
33
35
|
config.before(:suite) do
|
34
36
|
WebMockServer.instance.start unless WebMockServer.instance.started
|
@@ -38,20 +40,9 @@ RSpec.configure do |config|
|
|
38
40
|
WebMockServer.instance.stop
|
39
41
|
end
|
40
42
|
|
41
|
-
config.filter_run :
|
43
|
+
config.filter_run focus: true
|
42
44
|
config.run_all_when_everything_filtered = true
|
43
|
-
end
|
44
45
|
|
45
|
-
|
46
|
-
raise_error(RSpec::Expectations::ExpectationNotMetError)
|
46
|
+
config.include Failures
|
47
47
|
end
|
48
48
|
|
49
|
-
def fail_with(message)
|
50
|
-
raise_error(RSpec::Expectations::ExpectationNotMetError, message)
|
51
|
-
end
|
52
|
-
|
53
|
-
class Proc
|
54
|
-
def should_pass
|
55
|
-
lambda { self.call }.should_not raise_error
|
56
|
-
end
|
57
|
-
end
|
data/spec/support/my_rack_app.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rack'
|
|
2
2
|
|
3
3
|
class MyRackApp
|
4
4
|
class NonArrayResponse
|
5
|
-
# The rack response body need not implement #join,
|
5
|
+
# The rack response body need not implement #join,
|
6
6
|
# but it must implement #each. It need not be an Array.
|
7
7
|
# ActionDispatch::Response, for example, exercises that fact.
|
8
8
|
# See: http://rack.rubyforge.org/doc/SPEC.html
|
@@ -24,14 +24,19 @@ class MyRackApp
|
|
24
24
|
when ['GET', '/locked']
|
25
25
|
[200, {}, ["Single threaded response."]]
|
26
26
|
when ['POST', '/greet']
|
27
|
-
name = env["rack.input"].read
|
27
|
+
name = env["rack.input"].read(env["CONTENT_LENGTH"])
|
28
|
+
name = name.force_encoding("UTF-8") if name.respond_to? :force_encoding
|
29
|
+
name = name[/name=([^&]*)/, 1] || "World"
|
28
30
|
[200, {}, ["Good to meet you, #{name}!"]]
|
29
31
|
when ['GET', '/compute']
|
30
|
-
if env['SERVER_PORT'] == 80
|
32
|
+
if env['SERVER_PORT'] == 80 && env["SCRIPT_NAME"] == ""
|
31
33
|
[200, {}, [""]]
|
32
34
|
else
|
33
35
|
[401, {}, [""]]
|
34
36
|
end
|
37
|
+
when ['GET', '/error']
|
38
|
+
env['rack.errors'].puts('Error!')
|
39
|
+
[500, {}, ['']]
|
35
40
|
else
|
36
41
|
[404, {}, ['']]
|
37
42
|
end
|
@@ -1,22 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
addr = Socket.getaddrinfo(host, nil)
|
4
|
-
sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
|
1
|
+
require 'timeout'
|
2
|
+
require 'socket'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
|
11
|
-
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
4
|
+
module NetworkConnection
|
5
|
+
def self.connect_to(host, port, timeout=10)
|
6
|
+
Timeout.timeout(timeout) do
|
7
|
+
TCPSocket.new(host, port)
|
12
8
|
end
|
13
|
-
sock.connect(Socket.pack_sockaddr_in(port, addr[0][3]))
|
14
|
-
sock
|
15
9
|
end
|
16
10
|
|
17
11
|
def self.is_network_available?
|
18
12
|
begin
|
19
|
-
self.connect_to("
|
13
|
+
self.connect_to("8.8.8.8", 53, 5)
|
20
14
|
true
|
21
15
|
rescue
|
22
16
|
false
|
@@ -23,15 +23,20 @@ class WebMockServer
|
|
23
23
|
|
24
24
|
def start
|
25
25
|
@started = true
|
26
|
-
server = WEBrick::GenericServer.new(:
|
26
|
+
server = WEBrick::GenericServer.new(Port: 0, Logger: Logger.new("/dev/null"))
|
27
27
|
server.logger.level = 0
|
28
28
|
@port = server.config[:Port]
|
29
29
|
|
30
30
|
concurrent do
|
31
31
|
['TERM', 'INT'].each do |signal|
|
32
|
-
trap(signal)
|
32
|
+
trap(signal) do
|
33
|
+
Thread.new do
|
34
|
+
server.shutdown
|
35
|
+
end
|
36
|
+
end
|
33
37
|
end
|
34
38
|
server.start do |socket|
|
39
|
+
socket.read(1)
|
35
40
|
socket.puts <<-EOT.gsub(/^\s+\|/, '')
|
36
41
|
|HTTP/1.1 200 OK\r
|
37
42
|
|Date: Fri, 31 Dec 1999 23:59:59 GMT\r
|
@@ -48,7 +53,7 @@ class WebMockServer
|
|
48
53
|
|
49
54
|
loop do
|
50
55
|
begin
|
51
|
-
|
56
|
+
TCPSocket.new("localhost", port)
|
52
57
|
sleep 0.1
|
53
58
|
break
|
54
59
|
rescue Errno::ECONNREFUSED
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WebMock::API do
|
4
|
+
describe '#hash_including' do
|
5
|
+
subject { klass.new.hash_including(args) }
|
6
|
+
let(:args) { { data: :one } }
|
7
|
+
|
8
|
+
context 'when mixed into a class that does not define `hash_including`' do
|
9
|
+
let(:klass) do
|
10
|
+
Class.new do
|
11
|
+
include WebMock::API
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'uses WebMock::Matchers::HashIncludingMatcher' do
|
16
|
+
expect(subject).to be_a(WebMock::Matchers::HashIncludingMatcher)
|
17
|
+
end
|
18
|
+
|
19
|
+
# by testing equality for HashIncludingMatcher (which stringifies the passed hash) we are
|
20
|
+
# testing HashIncludingMatcher.initialize behavior as well
|
21
|
+
context "when args correspond to an hash" do
|
22
|
+
it "creates 'HashIncludingMatcher'" do
|
23
|
+
expect(subject).to eq("data" => :one)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when args are one or many keys" do
|
28
|
+
subject {klass.new.hash_including(:foo, :bar)}
|
29
|
+
let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
|
30
|
+
|
31
|
+
it "creates 'HashIncludingMatcher' with keys anythingized" do
|
32
|
+
expect(subject).to eq("foo" => anything, "bar" => anything )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when args are both keys and key/value pairs" do
|
37
|
+
subject {klass.new.hash_including(:foo, :bar, data: :one)}
|
38
|
+
let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
|
39
|
+
|
40
|
+
it "creates 'HashIncludingMatcher' with keys anythingized" do
|
41
|
+
expect(subject).to eq("foo" => anything, "bar" => anything, "data" => :one)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when args are an empty hash" do
|
46
|
+
subject {klass.new.hash_including({})}
|
47
|
+
|
48
|
+
it "creates 'HashIncludingMatcher' with an empty hash" do
|
49
|
+
expect(subject).to eq({})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
context 'when mixed into a class with a parent that defines `hash_including`' do
|
56
|
+
subject { klass.new.hash_including(*args) }
|
57
|
+
let(:args) { %w(:foo, :bar, {:data => :one}) }
|
58
|
+
let(:klass) do
|
59
|
+
Class.new(
|
60
|
+
Class.new do
|
61
|
+
def hash_including(*args)
|
62
|
+
args
|
63
|
+
end
|
64
|
+
end
|
65
|
+
) { include WebMock::API }
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'uses super and passes the args untampered' do
|
69
|
+
expect(subject).to eq(args)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#hash_excluding' do
|
75
|
+
subject { klass.new.hash_excluding(args) }
|
76
|
+
let(:args) { { data: :one } }
|
77
|
+
|
78
|
+
context 'when mixed into a class that does not define `hash_including`' do
|
79
|
+
let(:klass) do
|
80
|
+
Class.new do
|
81
|
+
include WebMock::API
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'uses WebMock::Matchers::HashIncludingMatcher' do
|
86
|
+
expect(subject).to be_a(WebMock::Matchers::HashExcludingMatcher)
|
87
|
+
end
|
88
|
+
|
89
|
+
# by testing equality for HashIncludingMatcher (which stringifies the passed hash) we are
|
90
|
+
# testing HashIncludingMatcher.initialize behavior as well
|
91
|
+
context 'when args correspond to an hash' do
|
92
|
+
context 'creates "HashExcludingMatcher"' do
|
93
|
+
it 'equals hash with similar key but different value' do
|
94
|
+
expect(subject).to eq('data' => :two)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'equals hash with similar value but different key' do
|
98
|
+
expect(subject).to eq('data2' => :one)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'equals hash with defferent value and key' do
|
102
|
+
expect(subject).to eq('data2' => :two)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'not equals with similar value and key' do
|
106
|
+
expect(subject).not_to eq('data' => :one)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when args are one or many keys' do
|
112
|
+
subject { klass.new.hash_excluding(:foo, :bar) }
|
113
|
+
let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
|
114
|
+
|
115
|
+
it "creates 'HashExcludingMatcher' with keys anythingized" do
|
116
|
+
expect(subject).not_to eq('foo' => anything, 'bar' => anything )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'when args are both keys and key/value pairs' do
|
121
|
+
subject { klass.new.hash_excluding(:foo, :bar, data: :one) }
|
122
|
+
let(:anything) { WebMock::Matchers::AnyArgMatcher.new(nil) }
|
123
|
+
|
124
|
+
it 'creates "HashExcludingMatcher" with keys anythingized' do
|
125
|
+
expect(subject).not_to eq('foo' => anything, 'bar' => anything, 'data' => :one)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when args are an empty hash' do
|
130
|
+
subject { klass.new.hash_excluding({}) }
|
131
|
+
|
132
|
+
it 'creates "HashExcludingMatcher" with an empty hash' do
|
133
|
+
expect(subject).to eq({})
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when mixed into a class with a parent that defines `hash_excluding`' do
|
139
|
+
subject { klass.new.hash_excluding(*args) }
|
140
|
+
let(:args) { %w(:foo, :bar, {:data => :one}) }
|
141
|
+
let(:klass) do
|
142
|
+
Class.new(
|
143
|
+
Class.new do
|
144
|
+
def hash_excluding(*args)
|
145
|
+
args
|
146
|
+
end
|
147
|
+
end
|
148
|
+
) { include WebMock::API }
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'uses super and passes the args untampered' do
|
152
|
+
expect(subject).to eq(args)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#reset_executed_requests!' do
|
158
|
+
subject { WebMock::API.reset_executed_requests! }
|
159
|
+
|
160
|
+
let(:request_signature) { WebMock::RequestSignature.new(:get, "www.example.com") }
|
161
|
+
let(:request_pattern) { WebMock::RequestPattern.new(:get, "www.example.com") }
|
162
|
+
|
163
|
+
before do
|
164
|
+
WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'resets request registry counter' do
|
168
|
+
expect{
|
169
|
+
subject
|
170
|
+
}.to change{
|
171
|
+
WebMock::RequestRegistry.instance.times_executed(request_pattern)
|
172
|
+
}.from(1).to(0)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|