webmock 1.8.6 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
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