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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/CI.yml +37 -0
  3. data/.gitignore +6 -0
  4. data/CHANGELOG.md +1198 -0
  5. data/Gemfile +3 -15
  6. data/README.md +761 -305
  7. data/Rakefile +13 -40
  8. data/lib/webmock/api.rb +63 -17
  9. data/lib/webmock/callback_registry.rb +1 -1
  10. data/lib/webmock/config.rb +8 -0
  11. data/lib/webmock/cucumber.rb +2 -0
  12. data/lib/webmock/errors.rb +8 -24
  13. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +216 -0
  14. data/lib/webmock/http_lib_adapters/curb_adapter.rb +148 -84
  15. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +224 -4
  16. data/lib/webmock/http_lib_adapters/excon_adapter.rb +104 -34
  17. data/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
  18. data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  19. data/lib/webmock/http_lib_adapters/http_rb/response.rb +64 -0
  20. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  21. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  22. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  23. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +152 -86
  24. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +145 -0
  25. data/lib/webmock/http_lib_adapters/net_http.rb +155 -46
  26. data/lib/webmock/http_lib_adapters/net_http_response.rb +1 -1
  27. data/lib/webmock/http_lib_adapters/patron_adapter.rb +16 -15
  28. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +76 -82
  29. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  30. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  31. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  32. data/lib/webmock/matchers/hash_including_matcher.rb +4 -12
  33. data/lib/webmock/minitest.rb +29 -3
  34. data/lib/webmock/rack_response.rb +14 -7
  35. data/lib/webmock/request_body_diff.rb +64 -0
  36. data/lib/webmock/request_execution_verifier.rb +38 -17
  37. data/lib/webmock/request_pattern.rb +158 -38
  38. data/lib/webmock/request_registry.rb +3 -3
  39. data/lib/webmock/request_signature.rb +7 -3
  40. data/lib/webmock/request_signature_snippet.rb +61 -0
  41. data/lib/webmock/request_stub.rb +9 -6
  42. data/lib/webmock/response.rb +30 -15
  43. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +38 -2
  44. data/lib/webmock/rspec/matchers/webmock_matcher.rb +23 -2
  45. data/lib/webmock/rspec/matchers.rb +0 -1
  46. data/lib/webmock/rspec.rb +11 -2
  47. data/lib/webmock/stub_registry.rb +31 -10
  48. data/lib/webmock/stub_request_snippet.rb +14 -6
  49. data/lib/webmock/test_unit.rb +4 -4
  50. data/lib/webmock/util/hash_counter.rb +20 -6
  51. data/lib/webmock/util/hash_keys_stringifier.rb +5 -3
  52. data/lib/webmock/util/hash_validator.rb +17 -0
  53. data/lib/webmock/util/headers.rb +23 -2
  54. data/lib/webmock/util/json.rb +20 -7
  55. data/lib/webmock/util/query_mapper.rb +281 -0
  56. data/lib/webmock/util/uri.rb +29 -19
  57. data/lib/webmock/util/values_stringifier.rb +20 -0
  58. data/lib/webmock/util/version_checker.rb +40 -2
  59. data/lib/webmock/version.rb +1 -1
  60. data/lib/webmock/webmock.rb +56 -17
  61. data/lib/webmock.rb +56 -46
  62. data/minitest/test_helper.rb +8 -3
  63. data/minitest/test_webmock.rb +4 -1
  64. data/minitest/webmock_spec.rb +16 -6
  65. data/spec/acceptance/async_http_client/async_http_client_spec.rb +375 -0
  66. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  67. data/spec/acceptance/curb/curb_spec.rb +227 -68
  68. data/spec/acceptance/curb/curb_spec_helper.rb +11 -8
  69. data/spec/acceptance/em_http_request/em_http_request_spec.rb +322 -28
  70. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +15 -10
  71. data/spec/acceptance/excon/excon_spec.rb +66 -4
  72. data/spec/acceptance/excon/excon_spec_helper.rb +21 -7
  73. data/spec/acceptance/http_rb/http_rb_spec.rb +93 -0
  74. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  75. data/spec/acceptance/httpclient/httpclient_spec.rb +152 -11
  76. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +25 -16
  77. data/spec/acceptance/manticore/manticore_spec.rb +107 -0
  78. data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  79. data/spec/acceptance/net_http/net_http_shared.rb +52 -24
  80. data/spec/acceptance/net_http/net_http_spec.rb +164 -50
  81. data/spec/acceptance/net_http/net_http_spec_helper.rb +19 -10
  82. data/spec/acceptance/net_http/real_net_http_spec.rb +1 -1
  83. data/spec/acceptance/patron/patron_spec.rb +29 -40
  84. data/spec/acceptance/patron/patron_spec_helper.rb +15 -11
  85. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +229 -58
  86. data/spec/acceptance/shared/callbacks.rb +32 -30
  87. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +20 -5
  88. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +14 -14
  89. data/spec/acceptance/shared/precedence_of_stubs.rb +6 -6
  90. data/spec/acceptance/shared/request_expectations.rb +560 -296
  91. data/spec/acceptance/shared/returning_declared_responses.rb +180 -138
  92. data/spec/acceptance/shared/stubbing_requests.rb +385 -154
  93. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +78 -17
  94. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +19 -15
  95. data/spec/acceptance/webmock_shared.rb +2 -2
  96. data/spec/fixtures/test.txt +1 -0
  97. data/spec/quality_spec.rb +27 -3
  98. data/spec/spec_helper.rb +11 -20
  99. data/spec/support/failures.rb +9 -0
  100. data/spec/support/my_rack_app.rb +8 -3
  101. data/spec/support/network_connection.rb +7 -13
  102. data/spec/support/webmock_server.rb +8 -3
  103. data/spec/unit/api_spec.rb +175 -0
  104. data/spec/unit/errors_spec.rb +116 -19
  105. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +1 -1
  106. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +2 -2
  107. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  108. data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  109. data/spec/unit/rack_response_spec.rb +54 -16
  110. data/spec/unit/request_body_diff_spec.rb +90 -0
  111. data/spec/unit/request_execution_verifier_spec.rb +147 -39
  112. data/spec/unit/request_pattern_spec.rb +462 -198
  113. data/spec/unit/request_registry_spec.rb +29 -9
  114. data/spec/unit/request_signature_snippet_spec.rb +89 -0
  115. data/spec/unit/request_signature_spec.rb +91 -49
  116. data/spec/unit/request_stub_spec.rb +71 -70
  117. data/spec/unit/response_spec.rb +100 -81
  118. data/spec/unit/stub_registry_spec.rb +37 -20
  119. data/spec/unit/stub_request_snippet_spec.rb +51 -31
  120. data/spec/unit/util/hash_counter_spec.rb +6 -6
  121. data/spec/unit/util/hash_keys_stringifier_spec.rb +4 -4
  122. data/spec/unit/util/headers_spec.rb +4 -4
  123. data/spec/unit/util/json_spec.rb +29 -3
  124. data/spec/unit/util/query_mapper_spec.rb +157 -0
  125. data/spec/unit/util/uri_spec.rb +150 -36
  126. data/spec/unit/util/version_checker_spec.rb +15 -9
  127. data/spec/unit/webmock_spec.rb +57 -4
  128. data/test/http_request.rb +3 -3
  129. data/test/shared_test.rb +45 -13
  130. data/test/test_helper.rb +1 -1
  131. data/test/test_webmock.rb +6 -0
  132. data/webmock.gemspec +30 -11
  133. metadata +308 -199
  134. data/.rvmrc +0 -1
  135. data/.travis.yml +0 -11
  136. data/Guardfile +0 -24
  137. data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_0_x.rb +0 -151
  138. 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(:body => {:hello => 'world'})
21
- Typhoeus::Request.post("www.example.com", :params => {:hello => 'world'})
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.get("www.example.com", :params => {:hello => 'world'})
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
- response = Typhoeus::Request.get("http://example.com")
61
+ request = Typhoeus::Request.new("http://example.com", method: :get)
62
+ hydra.queue(request)
63
+ hydra.run
35
64
 
36
- response.should be_timed_out
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(:body => body)
76
+ stub_request(:any, "example.com").to_return(body: body)
49
77
 
50
78
  test = nil
51
- @hydra.on_complete do |c|
79
+ Typhoeus.on_complete do |c|
52
80
  test = c.body
53
81
  end
54
- @hydra.queue @request
55
- @hydra.run
56
- test.should == body
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(:status => [response_code, "Server On Fire"])
89
+ stub_request(:any, "example.com").to_return(status: [response_code, "Server On Fire"])
62
90
 
63
91
  test = nil
64
- @hydra.on_complete do |c|
92
+ Typhoeus.on_complete do |c|
65
93
  test = c.code
66
94
  end
67
- @hydra.queue @request
68
- @hydra.run
69
- test.should == response_code
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!(" ", "%20") #typhoeus doesn't like spaces in the uri
10
- request = Typhoeus::Request.new(uri,
11
- {
12
- :method => method,
13
- :body => options[:body],
14
- :headers => options[:headers],
15
- :timeout => 25000
16
- }
17
- )
18
- hydra = Typhoeus::Hydra.new(:initial_pool_size => 0)
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
- :body => response.body,
26
- :headers => WebMock::Util::Headers.normalize_headers(join_array_values(response.headers_hash)),
27
- :status => response.code.to_s,
28
- :message => response.status_message
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
- failure_message_for_should do |actual|
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.should be_well_formed
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
- $?.should == 0
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(File.dirname(__FILE__)) + "/support/example_curl_output.txt" unless defined? CURL_EXAMPLE_OUTPUT_PATH
24
+ CURL_EXAMPLE_OUTPUT_PATH = File.expand_path('../support/example_curl_output.txt', __FILE__)
21
25
 
22
26
  RSpec.configure do |config|
23
- unless NetworkConnection.is_network_available?
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
- no_network_connection = true
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 :without_webmock => true
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 :focus => true
43
+ config.filter_run focus: true
42
44
  config.run_all_when_everything_filtered = true
43
- end
44
45
 
45
- def fail()
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
@@ -0,0 +1,9 @@
1
+ module Failures
2
+ def fail()
3
+ raise_error(RSpec::Expectations::ExpectationNotMetError)
4
+ end
5
+
6
+ def fail_with(message)
7
+ raise_error(RSpec::Expectations::ExpectationNotMetError, message)
8
+ end
9
+ end
@@ -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[/name=([^&]*)/, 1] || "World"
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
- module NetworkConnection
2
- def self.connect_to(host, port, timeout=nil)
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
- if timeout
7
- secs = Integer(timeout)
8
- usecs = Integer((timeout - secs) * 1_000_000)
9
- optval = [secs, usecs].pack("l_2")
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("192.0.32.10", 80, 5)
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(:Port => 0, :Logger => Logger.new("/dev/null"))
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){ server.shutdown }
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
- s = TCPSocket.new("localhost", port)
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