webmock 3.14.0 → 3.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +207 -3
  3. data/README.md +65 -20
  4. data/lib/webmock/api.rb +2 -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 +16 -4
  12. data/lib/webmock/http_lib_adapters/curb_adapter.rb +4 -2
  13. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +17 -7
  14. data/lib/webmock/http_lib_adapters/excon_adapter.rb +2 -0
  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 +3 -3
  18. data/lib/webmock/http_lib_adapters/http_rb/request.rb +17 -5
  19. data/lib/webmock/http_lib_adapters/http_rb/response.rb +32 -9
  20. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +10 -2
  21. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +8 -2
  22. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +7 -5
  23. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +26 -25
  24. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +2 -0
  25. data/lib/webmock/http_lib_adapters/net_http.rb +28 -117
  26. data/lib/webmock/http_lib_adapters/net_http_response.rb +2 -0
  27. data/lib/webmock/http_lib_adapters/patron_adapter.rb +3 -1
  28. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +18 -2
  29. data/lib/webmock/matchers/any_arg_matcher.rb +2 -0
  30. data/lib/webmock/matchers/hash_argument_matcher.rb +2 -0
  31. data/lib/webmock/matchers/hash_excluding_matcher.rb +2 -0
  32. data/lib/webmock/matchers/hash_including_matcher.rb +2 -0
  33. data/lib/webmock/minitest.rb +2 -0
  34. data/lib/webmock/rack_response.rb +5 -1
  35. data/lib/webmock/request_body_diff.rb +2 -0
  36. data/lib/webmock/request_execution_verifier.rb +2 -0
  37. data/lib/webmock/request_pattern.rb +35 -12
  38. data/lib/webmock/request_registry.rb +2 -0
  39. data/lib/webmock/request_signature.rb +4 -2
  40. data/lib/webmock/request_signature_snippet.rb +2 -0
  41. data/lib/webmock/request_stub.rb +34 -0
  42. data/lib/webmock/response.rb +15 -13
  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 +2 -0
  48. data/lib/webmock/stub_registry.rb +2 -0
  49. data/lib/webmock/stub_request_snippet.rb +2 -0
  50. data/lib/webmock/test_unit.rb +2 -0
  51. data/lib/webmock/util/hash_counter.rb +12 -6
  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 +23 -10
  55. data/lib/webmock/util/parsers/json.rb +72 -0
  56. data/lib/webmock/util/parsers/parse_error.rb +7 -0
  57. data/lib/webmock/util/parsers/xml.rb +16 -0
  58. data/lib/webmock/util/query_mapper.rb +2 -0
  59. data/lib/webmock/util/uri.rb +3 -1
  60. data/lib/webmock/util/values_stringifier.rb +2 -0
  61. data/lib/webmock/util/version_checker.rb +7 -5
  62. data/lib/webmock/version.rb +3 -1
  63. data/lib/webmock/webmock.rb +12 -0
  64. data/lib/webmock.rb +4 -2
  65. metadata +66 -182
  66. data/.gemtest +0 -0
  67. data/.github/workflows/CI.yml +0 -37
  68. data/.gitignore +0 -34
  69. data/.rspec-tm +0 -2
  70. data/Gemfile +0 -9
  71. data/Rakefile +0 -38
  72. data/lib/webmock/util/json.rb +0 -67
  73. data/minitest/test_helper.rb +0 -34
  74. data/minitest/test_webmock.rb +0 -9
  75. data/minitest/webmock_spec.rb +0 -60
  76. data/spec/acceptance/async_http_client/async_http_client_spec.rb +0 -375
  77. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +0 -73
  78. data/spec/acceptance/curb/curb_spec.rb +0 -499
  79. data/spec/acceptance/curb/curb_spec_helper.rb +0 -147
  80. data/spec/acceptance/em_http_request/em_http_request_spec.rb +0 -462
  81. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +0 -77
  82. data/spec/acceptance/excon/excon_spec.rb +0 -77
  83. data/spec/acceptance/excon/excon_spec_helper.rb +0 -52
  84. data/spec/acceptance/http_rb/http_rb_spec.rb +0 -93
  85. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +0 -54
  86. data/spec/acceptance/httpclient/httpclient_spec.rb +0 -217
  87. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +0 -57
  88. data/spec/acceptance/manticore/manticore_spec.rb +0 -107
  89. data/spec/acceptance/manticore/manticore_spec_helper.rb +0 -35
  90. data/spec/acceptance/net_http/net_http_shared.rb +0 -153
  91. data/spec/acceptance/net_http/net_http_spec.rb +0 -369
  92. data/spec/acceptance/net_http/net_http_spec_helper.rb +0 -64
  93. data/spec/acceptance/net_http/real_net_http_spec.rb +0 -20
  94. data/spec/acceptance/patron/patron_spec.rb +0 -125
  95. data/spec/acceptance/patron/patron_spec_helper.rb +0 -54
  96. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +0 -313
  97. data/spec/acceptance/shared/callbacks.rb +0 -148
  98. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +0 -36
  99. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +0 -95
  100. data/spec/acceptance/shared/precedence_of_stubs.rb +0 -15
  101. data/spec/acceptance/shared/request_expectations.rb +0 -930
  102. data/spec/acceptance/shared/returning_declared_responses.rb +0 -409
  103. data/spec/acceptance/shared/stubbing_requests.rb +0 -678
  104. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +0 -135
  105. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +0 -60
  106. data/spec/acceptance/webmock_shared.rb +0 -41
  107. data/spec/fixtures/test.txt +0 -1
  108. data/spec/quality_spec.rb +0 -84
  109. data/spec/spec_helper.rb +0 -48
  110. data/spec/support/example_curl_output.txt +0 -22
  111. data/spec/support/failures.rb +0 -9
  112. data/spec/support/my_rack_app.rb +0 -53
  113. data/spec/support/network_connection.rb +0 -19
  114. data/spec/support/webmock_server.rb +0 -70
  115. data/spec/unit/api_spec.rb +0 -175
  116. data/spec/unit/errors_spec.rb +0 -129
  117. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +0 -17
  118. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +0 -12
  119. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +0 -61
  120. data/spec/unit/matchers/hash_including_matcher_spec.rb +0 -87
  121. data/spec/unit/rack_response_spec.rb +0 -112
  122. data/spec/unit/request_body_diff_spec.rb +0 -90
  123. data/spec/unit/request_execution_verifier_spec.rb +0 -208
  124. data/spec/unit/request_pattern_spec.rb +0 -736
  125. data/spec/unit/request_registry_spec.rb +0 -95
  126. data/spec/unit/request_signature_snippet_spec.rb +0 -89
  127. data/spec/unit/request_signature_spec.rb +0 -155
  128. data/spec/unit/request_stub_spec.rb +0 -199
  129. data/spec/unit/response_spec.rb +0 -286
  130. data/spec/unit/stub_registry_spec.rb +0 -103
  131. data/spec/unit/stub_request_snippet_spec.rb +0 -115
  132. data/spec/unit/util/hash_counter_spec.rb +0 -39
  133. data/spec/unit/util/hash_keys_stringifier_spec.rb +0 -27
  134. data/spec/unit/util/headers_spec.rb +0 -28
  135. data/spec/unit/util/json_spec.rb +0 -33
  136. data/spec/unit/util/query_mapper_spec.rb +0 -157
  137. data/spec/unit/util/uri_spec.rb +0 -371
  138. data/spec/unit/util/version_checker_spec.rb +0 -65
  139. data/spec/unit/webmock_spec.rb +0 -60
  140. data/test/http_request.rb +0 -24
  141. data/test/shared_test.rb +0 -108
  142. data/test/test_helper.rb +0 -23
  143. data/test/test_webmock.rb +0 -12
  144. data/webmock.gemspec +0 -54
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  module RSpecMatcherDetector
@@ -82,11 +84,14 @@ module WebMock
82
84
  URIAddressablePattern.new(uri)
83
85
  elsif uri.respond_to?(:call)
84
86
  URICallablePattern.new(uri)
85
- else
87
+ elsif uri.is_a?(::URI::Generic)
88
+ URIStringPattern.new(uri.to_s)
89
+ elsif uri.is_a?(String)
86
90
  URIStringPattern.new(uri)
91
+ else
92
+ raise ArgumentError.new("URI should be a String, Regexp, Addressable::Template or a callable object. Got: #{uri.class}")
87
93
  end
88
94
  end
89
-
90
95
  end
91
96
 
92
97
 
@@ -281,7 +286,9 @@ module WebMock
281
286
  if (@pattern).is_a?(Hash)
282
287
  return true if @pattern.empty?
283
288
  matching_body_hashes?(body_as_hash(body, content_type), @pattern, content_type)
284
- elsif (@pattern).is_a?(WebMock::Matchers::HashIncludingMatcher)
289
+ elsif (@pattern).is_a?(Array)
290
+ matching_body_array?(body_as_hash(body, content_type), @pattern, content_type)
291
+ elsif (@pattern).is_a?(WebMock::Matchers::HashArgumentMatcher)
285
292
  @pattern == body_as_hash(body, content_type)
286
293
  else
287
294
  empty_string?(@pattern) && empty_string?(body) ||
@@ -299,12 +306,14 @@ module WebMock
299
306
  def body_as_hash(body, content_type)
300
307
  case body_format(content_type)
301
308
  when :json then
302
- WebMock::Util::JSON.parse(body)
309
+ WebMock::Util::Parsers::JSON.parse(body)
303
310
  when :xml then
304
- Crack::XML.parse(body)
311
+ WebMock::Util::Parsers::XML.parse(body)
305
312
  else
306
313
  WebMock::Util::QueryMapper.query_to_values(body, notation: Config.instance.query_values_notation)
307
314
  end
315
+ rescue WebMock::Util::Parsers::ParseError
316
+ nil
308
317
  end
309
318
 
310
319
  def body_format(content_type)
@@ -344,19 +353,33 @@ module WebMock
344
353
  def matching_body_hashes?(query_parameters, pattern, content_type)
345
354
  return false unless query_parameters.is_a?(Hash)
346
355
  return false unless query_parameters.keys.sort == pattern.keys.sort
347
- query_parameters.each do |key, actual|
356
+
357
+ query_parameters.all? do |key, actual|
348
358
  expected = pattern[key]
359
+ matching_values(actual, expected, content_type)
360
+ end
361
+ end
349
362
 
350
- if actual.is_a?(Hash) && expected.is_a?(Hash)
351
- return false unless matching_body_hashes?(actual, expected, content_type)
352
- else
353
- expected = WebMock::Util::ValuesStringifier.stringify_values(expected) if url_encoded_body?(content_type)
354
- return false unless expected === actual
355
- end
363
+ def matching_body_array?(query_parameters, pattern, content_type)
364
+ return false unless query_parameters.is_a?(Array)
365
+ return false unless query_parameters.length == pattern.length
366
+
367
+ query_parameters.each_with_index do |actual, index|
368
+ expected = pattern[index]
369
+ return false unless matching_values(actual, expected, content_type)
356
370
  end
371
+
357
372
  true
358
373
  end
359
374
 
375
+ def matching_values(actual, expected, content_type)
376
+ return matching_body_hashes?(actual, expected, content_type) if actual.is_a?(Hash) && expected.is_a?(Hash)
377
+ return matching_body_array?(actual, expected, content_type) if actual.is_a?(Array) && expected.is_a?(Array)
378
+
379
+ expected = WebMock::Util::ValuesStringifier.stringify_values(expected) if url_encoded_body?(content_type)
380
+ expected === actual
381
+ end
382
+
360
383
  def empty_string?(string)
361
384
  string.nil? || string == ""
362
385
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class RequestRegistry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class RequestSignature
@@ -35,11 +37,11 @@ module WebMock
35
37
  alias == eql?
36
38
 
37
39
  def url_encoded?
38
- !!(headers && headers['Content-Type'] == 'application/x-www-form-urlencoded')
40
+ !!(headers&.fetch('Content-Type', nil)&.start_with?('application/x-www-form-urlencoded'))
39
41
  end
40
42
 
41
43
  def json_headers?
42
- !!(headers && headers['Content-Type'] == 'application/json')
44
+ !!(headers&.fetch('Content-Type', nil)&.start_with?('application/json'))
43
45
  end
44
46
 
45
47
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pp"
2
4
 
3
5
  module WebMock
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class RequestStub
3
5
 
@@ -24,6 +26,38 @@ module WebMock
24
26
  end
25
27
  alias_method :and_return, :to_return
26
28
 
29
+ def to_return_json(*response_hashes)
30
+ raise ArgumentError, '#to_return_json does not support passing a block' if block_given?
31
+
32
+ json_response_hashes = [*response_hashes].flatten.map do |resp_h|
33
+ headers, body = resp_h.values_at(:headers, :body)
34
+
35
+ json_body = if body.respond_to?(:call)
36
+ ->(request_signature) {
37
+ b = if body.respond_to?(:arity) && body.arity == 1
38
+ body.call(request_signature)
39
+ else
40
+ body.call
41
+ end
42
+ b = b.to_json unless b.is_a?(String)
43
+ b
44
+ }
45
+ elsif !body.is_a?(String)
46
+ body.to_json
47
+ else
48
+ body
49
+ end
50
+
51
+ resp_h.merge(
52
+ headers: {content_type: 'application/json'}.merge(headers.to_h),
53
+ body: json_body
54
+ )
55
+ end
56
+
57
+ to_return(json_response_hashes)
58
+ end
59
+ alias_method :and_return_json, :to_return_json
60
+
27
61
  def to_rack(app, options={})
28
62
  @responses_sequences << ResponsesSequence.new([RackResponse.new(app)])
29
63
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "pathname"
2
4
 
3
5
  module WebMock
@@ -14,8 +16,11 @@ module WebMock
14
16
 
15
17
  class Response
16
18
  def initialize(options = {})
17
- if options.is_a?(IO) || options.is_a?(String)
19
+ case options
20
+ when IO, StringIO
18
21
  self.options = read_raw_response(options)
22
+ when String
23
+ self.options = read_raw_response(StringIO.new(options))
19
24
  else
20
25
  self.options = options
21
26
  end
@@ -33,7 +38,7 @@ module WebMock
33
38
  end
34
39
 
35
40
  def body
36
- @body || ''
41
+ @body || String.new("")
37
42
  end
38
43
 
39
44
  def body=(body)
@@ -112,21 +117,16 @@ module WebMock
112
117
  return if @body.nil?
113
118
  return if valid_types.any? { |c| @body.is_a?(c) }
114
119
 
115
- if @body.class.is_a?(Hash)
116
- raise InvalidBody, "must be one of: #{valid_types}, but you've used a #{@body.class}' instead." \
117
- "\n What shall we encode it to? try calling .to_json .to_xml instead on the hash instead, or otherwise convert it to a string."
120
+ if @body.is_a?(Hash)
121
+ raise InvalidBody, "must be one of: #{valid_types}, but you've used a #{@body.class}. " \
122
+ "Please convert it by calling .to_json .to_xml, or otherwise convert it to a string."
118
123
  else
119
- raise InvalidBody, "must be one of: #{valid_types}. '#{@body.class}' given"
124
+ raise InvalidBody, "must be one of: #{valid_types}. '#{@body.class}' given."
120
125
  end
121
126
  end
122
127
 
123
- def read_raw_response(raw_response)
124
- if raw_response.is_a?(IO)
125
- string = raw_response.read
126
- raw_response.close
127
- raw_response = string
128
- end
129
- socket = ::Net::BufferedIO.new(raw_response)
128
+ def read_raw_response(io)
129
+ socket = ::Net::BufferedIO.new(io)
130
130
  response = ::Net::HTTPResponse.read_new(socket)
131
131
  transfer_encoding = response.delete('transfer-encoding') #chunks were already read by curl
132
132
  response.reading_body(socket, true) {}
@@ -138,6 +138,8 @@ module WebMock
138
138
  options[:body] = response.read_body
139
139
  options[:status] = [response.code.to_i, response.message]
140
140
  options
141
+ ensure
142
+ socket.close
141
143
  end
142
144
 
143
145
  InvalidBody = Class.new(StandardError)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class ResponsesSequence
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class RequestPatternMatcher
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class WebMockMatcher
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webmock'
2
4
  require 'webmock/rspec/matchers/request_pattern_matcher'
3
5
  require 'webmock/rspec/matchers/webmock_matcher'
data/lib/webmock/rspec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'webmock'
2
4
 
3
5
  # RSpec 1.x and 2.x compatibility
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  class StubRegistry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class StubRequestSnippet
3
5
  def initialize(request_stub)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test/unit'
2
4
  require 'webmock'
3
5
 
@@ -1,29 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
 
3
5
  module WebMock
4
6
  module Util
5
7
  class HashCounter
6
8
  attr_accessor :hash
9
+
7
10
  def initialize
8
- self.hash = {}
11
+ self.hash = Hash.new(0)
9
12
  @order = {}
10
13
  @max = 0
11
14
  @lock = ::Mutex.new
12
15
  end
13
- def put key, num=1
16
+
17
+ def put(key, num=1)
14
18
  @lock.synchronize do
15
- hash[key] = (hash[key] || 0) + num
16
- @order[key] = @max = @max + 1
19
+ hash[key] += num
20
+ @order[key] = @max += 1
17
21
  end
18
22
  end
19
- def get key
23
+
24
+ def get(key)
20
25
  @lock.synchronize do
21
- hash[key] || 0
26
+ hash[key]
22
27
  end
23
28
  end
24
29
 
25
30
  def select(&block)
26
31
  return unless block_given?
32
+
27
33
  @lock.synchronize do
28
34
  hash.select(&block)
29
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  module Util
3
5
  class HashKeysStringifier
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
  class HashValidator
3
5
  def initialize(hash)
@@ -1,4 +1,4 @@
1
- require 'base64'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module WebMock
4
4
 
@@ -6,18 +6,21 @@ module WebMock
6
6
 
7
7
  class Headers
8
8
 
9
+ STANDARD_HEADER_DELIMITER = '-'
10
+ NONSTANDARD_HEADER_DELIMITER = '_'
11
+ JOIN = ', '
12
+
9
13
  def self.normalize_headers(headers)
10
14
  return nil unless headers
11
- array = headers.map { |name, value|
12
- [name.to_s.split(/_|-/).map { |segment| segment.capitalize }.join("-"),
13
- case value
15
+
16
+ headers.each_with_object({}) do |(name, value), new_headers|
17
+ new_headers[normalize_name(name)] =
18
+ case value
14
19
  when Regexp then value
15
- when Array then (value.size == 1) ? value.first.to_s : value.map {|v| v.to_s}.sort
20
+ when Array then (value.size == 1) ? value.first.to_s : value.map(&:to_s).sort
16
21
  else value.to_s
17
- end
18
- ]
19
- }
20
- Hash[*array.inject([]) {|r,x| r + x}]
22
+ end
23
+ end
21
24
  end
22
25
 
23
26
  def self.sorted_headers_string(headers)
@@ -54,7 +57,17 @@ module WebMock
54
57
  end
55
58
 
56
59
  def self.basic_auth_header(*credentials)
57
- "Basic #{Base64.strict_encode64(credentials.join(':')).chomp}"
60
+ strict_base64_encoded = [credentials.join(':')].pack("m0")
61
+ "Basic #{strict_base64_encoded.chomp}"
62
+ end
63
+
64
+ def self.normalize_name(name)
65
+ name
66
+ .to_s
67
+ .tr(NONSTANDARD_HEADER_DELIMITER, STANDARD_HEADER_DELIMITER)
68
+ .split(STANDARD_HEADER_DELIMITER)
69
+ .map!(&:capitalize)
70
+ .join(STANDARD_HEADER_DELIMITER)
58
71
  end
59
72
 
60
73
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is a copy of https://github.com/jnunemaker/crack/blob/master/lib/crack/json.rb
4
+ # with date parsing removed
5
+ # Copyright (c) 2004-2008 David Heinemeier Hansson
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+
10
+ require_relative "parse_error"
11
+
12
+ module WebMock
13
+ module Util
14
+ module Parsers
15
+ class JSON
16
+ def self.parse(json)
17
+ yaml = unescape(convert_json_to_yaml(json))
18
+ YAML.load(yaml)
19
+ rescue ArgumentError, Psych::SyntaxError => e
20
+ raise ParseError, "Invalid JSON string: #{yaml}, Error: #{e.inspect}"
21
+ end
22
+
23
+ protected
24
+
25
+ def self.unescape(str)
26
+ str.gsub(/\\u([0-9a-f]{4})/) { [$1.hex].pack("U") }
27
+ end
28
+
29
+ # Ensure that ":" and "," are always followed by a space
30
+ def self.convert_json_to_yaml(json) #:nodoc:
31
+ scanner, quoting, marks, times = StringScanner.new(json), false, [], []
32
+ while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
33
+ case char = scanner[1]
34
+ when '"', "'"
35
+ if !quoting
36
+ quoting = char
37
+ elsif quoting == char
38
+ quoting = false
39
+ end
40
+ when ":",","
41
+ marks << scanner.pos - 1 unless quoting
42
+ when "\\"
43
+ scanner.skip(/\\/)
44
+ end
45
+ end
46
+
47
+ if marks.empty?
48
+ json.gsub(/\\\//, '/')
49
+ else
50
+ left_pos = [-1].push(*marks)
51
+ right_pos = marks << json.bytesize
52
+ output = []
53
+
54
+ left_pos.each_with_index do |left, i|
55
+ if json.respond_to?(:byteslice)
56
+ output << json.byteslice(left.succ..right_pos[i])
57
+ else
58
+ output << json[left.succ..right_pos[i]]
59
+ end
60
+ end
61
+
62
+ output = output * " "
63
+
64
+ times.each { |i| output[i-1] = ' ' }
65
+ output.gsub!(/\\\//, '/')
66
+ output
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,7 @@
1
+ module WebMock
2
+ module Util
3
+ module Parsers
4
+ class ParseError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ require_relative "parse_error"
2
+ require "crack/xml"
3
+
4
+ module WebMock
5
+ module Util
6
+ module Parsers
7
+ class XML
8
+ def self.parse(xml)
9
+ ::Crack::XML.parse(xml)
10
+ rescue ::REXML::ParseException => e
11
+ raise ParseError, "Invalid XML string: #{xml}, Error: #{e.inspect}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock::Util
2
4
  class QueryMapper
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  module Util
@@ -68,7 +70,7 @@ module WebMock
68
70
 
69
71
  def self.is_uri_localhost?(uri)
70
72
  uri.is_a?(Addressable::URI) &&
71
- %w(localhost 127.0.0.1 0.0.0.0).include?(uri.host)
73
+ %w(localhost 127.0.0.1 0.0.0.0 [::1]).include?(uri.host)
72
74
  end
73
75
 
74
76
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class WebMock::Util::ValuesStringifier
2
4
  def self.stringify_values(value)
3
5
  case value
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This code was created based on https://github.com/myronmarston/vcr/blob/master/lib/vcr/util/version_checker.rb
2
4
  # Thanks to @myronmarston
3
5
 
@@ -84,12 +86,12 @@ module WebMock
84
86
  def compare_version
85
87
  case
86
88
  when @major < @min_major then :too_low
89
+ when @major == @min_major && @minor < @min_minor then :too_low
90
+ when @major == @min_major && @minor == @min_minor && @patch < @min_patch then :too_low
87
91
  when @max_major && @major > @max_major then :too_high
88
- when @major > @min_major then :ok
89
- when @minor < @min_minor then :too_low
90
- when @max_minor && @minor > @max_minor then :too_high
91
- when @minor > @min_minor then :ok
92
- when @patch < @min_patch then :too_low
92
+ when @max_major && @major == @max_major && @max_minor && @minor > @max_minor then :too_high
93
+
94
+ else :ok
93
95
  end
94
96
  end
95
97
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
- VERSION = '3.14.0' unless defined?(::WebMock::VERSION)
4
+ VERSION = '3.24.0' unless defined?(::WebMock::VERSION)
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WebMock
2
4
 
3
5
  def self.included(clazz)
@@ -70,6 +72,16 @@ module WebMock
70
72
  Config.instance.allow && net_connect_explicit_allowed?(Config.instance.allow, uri) )
71
73
  end
72
74
 
75
+ def self.net_http_connect_on_start?(uri)
76
+ allowed = Config.instance.net_http_connect_on_start || false
77
+
78
+ if [true, false].include?(allowed)
79
+ allowed
80
+ else
81
+ net_connect_explicit_allowed?(allowed, uri)
82
+ end
83
+ end
84
+
73
85
  def self.net_connect_explicit_allowed?(allowed, uri=nil)
74
86
  case allowed
75
87
  when Array
data/lib/webmock.rb CHANGED
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
 
3
5
  require 'addressable/uri'
4
6
  require 'addressable/template'
5
- require 'crack/xml'
6
7
 
7
8
  require_relative 'webmock/deprecation'
8
9
  require_relative 'webmock/version'
@@ -15,7 +16,8 @@ require_relative 'webmock/util/headers'
15
16
  require_relative 'webmock/util/hash_counter'
16
17
  require_relative 'webmock/util/hash_keys_stringifier'
17
18
  require_relative 'webmock/util/values_stringifier'
18
- require_relative 'webmock/util/json'
19
+ require_relative 'webmock/util/parsers/json'
20
+ require_relative 'webmock/util/parsers/xml'
19
21
  require_relative 'webmock/util/version_checker'
20
22
  require_relative 'webmock/util/hash_validator'
21
23