webmock 3.7.1

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 (142) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +34 -0
  4. data/.rspec-tm +2 -0
  5. data/.travis.yml +19 -0
  6. data/CHANGELOG.md +1698 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +20 -0
  9. data/README.md +1125 -0
  10. data/Rakefile +28 -0
  11. data/lib/webmock.rb +59 -0
  12. data/lib/webmock/api.rb +109 -0
  13. data/lib/webmock/assertion_failure.rb +11 -0
  14. data/lib/webmock/callback_registry.rb +35 -0
  15. data/lib/webmock/config.rb +18 -0
  16. data/lib/webmock/cucumber.rb +10 -0
  17. data/lib/webmock/deprecation.rb +9 -0
  18. data/lib/webmock/errors.rb +17 -0
  19. data/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +214 -0
  20. data/lib/webmock/http_lib_adapters/curb_adapter.rb +347 -0
  21. data/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +228 -0
  22. data/lib/webmock/http_lib_adapters/excon_adapter.rb +162 -0
  23. data/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
  24. data/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
  25. data/lib/webmock/http_lib_adapters/http_rb/client.rb +14 -0
  26. data/lib/webmock/http_lib_adapters/http_rb/request.rb +16 -0
  27. data/lib/webmock/http_lib_adapters/http_rb/response.rb +43 -0
  28. data/lib/webmock/http_lib_adapters/http_rb/streamer.rb +29 -0
  29. data/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  30. data/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  31. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +242 -0
  32. data/lib/webmock/http_lib_adapters/manticore_adapter.rb +130 -0
  33. data/lib/webmock/http_lib_adapters/net_http.rb +361 -0
  34. data/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
  35. data/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
  36. data/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
  37. data/lib/webmock/matchers/any_arg_matcher.rb +13 -0
  38. data/lib/webmock/matchers/hash_argument_matcher.rb +21 -0
  39. data/lib/webmock/matchers/hash_excluding_matcher.rb +15 -0
  40. data/lib/webmock/matchers/hash_including_matcher.rb +17 -0
  41. data/lib/webmock/minitest.rb +41 -0
  42. data/lib/webmock/rack_response.rb +69 -0
  43. data/lib/webmock/request_body_diff.rb +64 -0
  44. data/lib/webmock/request_execution_verifier.rb +77 -0
  45. data/lib/webmock/request_pattern.rb +370 -0
  46. data/lib/webmock/request_registry.rb +35 -0
  47. data/lib/webmock/request_signature.rb +54 -0
  48. data/lib/webmock/request_signature_snippet.rb +61 -0
  49. data/lib/webmock/request_stub.rb +100 -0
  50. data/lib/webmock/response.rb +153 -0
  51. data/lib/webmock/responses_sequence.rb +40 -0
  52. data/lib/webmock/rspec.rb +41 -0
  53. data/lib/webmock/rspec/matchers.rb +27 -0
  54. data/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
  55. data/lib/webmock/rspec/matchers/webmock_matcher.rb +67 -0
  56. data/lib/webmock/stub_registry.rb +67 -0
  57. data/lib/webmock/stub_request_snippet.rb +38 -0
  58. data/lib/webmock/test_unit.rb +22 -0
  59. data/lib/webmock/util/hash_counter.rb +39 -0
  60. data/lib/webmock/util/hash_keys_stringifier.rb +25 -0
  61. data/lib/webmock/util/hash_validator.rb +17 -0
  62. data/lib/webmock/util/headers.rb +64 -0
  63. data/lib/webmock/util/json.rb +67 -0
  64. data/lib/webmock/util/query_mapper.rb +281 -0
  65. data/lib/webmock/util/uri.rb +110 -0
  66. data/lib/webmock/util/values_stringifier.rb +20 -0
  67. data/lib/webmock/util/version_checker.rb +111 -0
  68. data/lib/webmock/version.rb +3 -0
  69. data/lib/webmock/webmock.rb +161 -0
  70. data/minitest/test_helper.rb +34 -0
  71. data/minitest/test_webmock.rb +9 -0
  72. data/minitest/webmock_spec.rb +60 -0
  73. data/spec/acceptance/async_http_client/async_http_client_spec.rb +349 -0
  74. data/spec/acceptance/async_http_client/async_http_client_spec_helper.rb +73 -0
  75. data/spec/acceptance/curb/curb_spec.rb +492 -0
  76. data/spec/acceptance/curb/curb_spec_helper.rb +147 -0
  77. data/spec/acceptance/em_http_request/em_http_request_spec.rb +406 -0
  78. data/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
  79. data/spec/acceptance/excon/excon_spec.rb +77 -0
  80. data/spec/acceptance/excon/excon_spec_helper.rb +50 -0
  81. data/spec/acceptance/http_rb/http_rb_spec.rb +82 -0
  82. data/spec/acceptance/http_rb/http_rb_spec_helper.rb +54 -0
  83. data/spec/acceptance/httpclient/httpclient_spec.rb +217 -0
  84. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
  85. data/spec/acceptance/manticore/manticore_spec.rb +56 -0
  86. data/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  87. data/spec/acceptance/net_http/net_http_shared.rb +153 -0
  88. data/spec/acceptance/net_http/net_http_spec.rb +331 -0
  89. data/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
  90. data/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
  91. data/spec/acceptance/patron/patron_spec.rb +125 -0
  92. data/spec/acceptance/patron/patron_spec_helper.rb +54 -0
  93. data/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
  94. data/spec/acceptance/shared/callbacks.rb +148 -0
  95. data/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
  96. data/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
  97. data/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
  98. data/spec/acceptance/shared/request_expectations.rb +930 -0
  99. data/spec/acceptance/shared/returning_declared_responses.rb +409 -0
  100. data/spec/acceptance/shared/stubbing_requests.rb +643 -0
  101. data/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
  102. data/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
  103. data/spec/acceptance/webmock_shared.rb +41 -0
  104. data/spec/fixtures/test.txt +1 -0
  105. data/spec/quality_spec.rb +84 -0
  106. data/spec/spec_helper.rb +48 -0
  107. data/spec/support/example_curl_output.txt +22 -0
  108. data/spec/support/failures.rb +9 -0
  109. data/spec/support/my_rack_app.rb +53 -0
  110. data/spec/support/network_connection.rb +19 -0
  111. data/spec/support/webmock_server.rb +70 -0
  112. data/spec/unit/api_spec.rb +175 -0
  113. data/spec/unit/errors_spec.rb +129 -0
  114. data/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
  115. data/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
  116. data/spec/unit/matchers/hash_excluding_matcher_spec.rb +61 -0
  117. data/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  118. data/spec/unit/rack_response_spec.rb +112 -0
  119. data/spec/unit/request_body_diff_spec.rb +90 -0
  120. data/spec/unit/request_execution_verifier_spec.rb +208 -0
  121. data/spec/unit/request_pattern_spec.rb +601 -0
  122. data/spec/unit/request_registry_spec.rb +95 -0
  123. data/spec/unit/request_signature_snippet_spec.rb +89 -0
  124. data/spec/unit/request_signature_spec.rb +155 -0
  125. data/spec/unit/request_stub_spec.rb +199 -0
  126. data/spec/unit/response_spec.rb +282 -0
  127. data/spec/unit/stub_registry_spec.rb +103 -0
  128. data/spec/unit/stub_request_snippet_spec.rb +115 -0
  129. data/spec/unit/util/hash_counter_spec.rb +39 -0
  130. data/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
  131. data/spec/unit/util/headers_spec.rb +28 -0
  132. data/spec/unit/util/json_spec.rb +33 -0
  133. data/spec/unit/util/query_mapper_spec.rb +157 -0
  134. data/spec/unit/util/uri_spec.rb +361 -0
  135. data/spec/unit/util/version_checker_spec.rb +65 -0
  136. data/spec/unit/webmock_spec.rb +19 -0
  137. data/test/http_request.rb +24 -0
  138. data/test/shared_test.rb +108 -0
  139. data/test/test_helper.rb +23 -0
  140. data/test/test_webmock.rb +6 -0
  141. data/webmock.gemspec +45 -0
  142. metadata +496 -0
@@ -0,0 +1,20 @@
1
+ class WebMock::Util::ValuesStringifier
2
+ def self.stringify_values(value)
3
+ case value
4
+ when String, Numeric, TrueClass, FalseClass
5
+ value.to_s
6
+ when Hash
7
+ Hash[
8
+ value.map do |k, v|
9
+ [k, stringify_values(v)]
10
+ end
11
+ ]
12
+ when Array
13
+ value.map do |v|
14
+ stringify_values(v)
15
+ end
16
+ else
17
+ value
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,111 @@
1
+ # This code was created based on https://github.com/myronmarston/vcr/blob/master/lib/vcr/util/version_checker.rb
2
+ # Thanks to @myronmarston
3
+
4
+ # Copyright (c) 2010-2012 Myron Marston
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ module WebMock
26
+ class VersionChecker
27
+ def initialize(library_name, library_version, min_patch_level, max_minor_version = nil, unsupported_versions = [])
28
+ @library_name, @library_version = library_name, library_version
29
+ @min_patch_level, @max_minor_version = min_patch_level, max_minor_version
30
+ @unsupported_versions = unsupported_versions || []
31
+
32
+ @major, @minor, @patch = parse_version(library_version)
33
+ @min_major, @min_minor, @min_patch = parse_version(min_patch_level)
34
+ if max_minor_version
35
+ @max_major, @max_minor = parse_version(max_minor_version)
36
+ else
37
+ @max_major, @max_minor = nil, nil
38
+ end
39
+
40
+ @comparison_result = compare_version
41
+ end
42
+
43
+ def check_version!
44
+ warn_about_too_low if too_low?
45
+ warn_about_too_high if too_high?
46
+ warn_about_unsupported_version if unsupported_version?
47
+ end
48
+
49
+ private
50
+
51
+ def too_low?
52
+ @comparison_result == :too_low
53
+ end
54
+
55
+ def too_high?
56
+ @comparison_result == :too_high
57
+ end
58
+
59
+ def unsupported_version?
60
+ @unsupported_versions.include?(@library_version)
61
+ end
62
+
63
+ def warn_about_too_low
64
+ warn_in_red "You are using #{@library_name} #{@library_version}. " +
65
+ "WebMock supports version #{version_requirement}."
66
+ end
67
+
68
+ def warn_about_too_high
69
+ warn_in_red "You are using #{@library_name} #{@library_version}. " +
70
+ "WebMock is known to work with #{@library_name} #{version_requirement}. " +
71
+ "It may not work with this version."
72
+ end
73
+
74
+ def warn_about_unsupported_version
75
+ warn_in_red "You are using #{@library_name} #{@library_version}. " +
76
+ "WebMock does not support this version. " +
77
+ "WebMock supports versions #{version_requirement}."
78
+ end
79
+
80
+ def warn_in_red(text)
81
+ Kernel.warn colorize(text, "\e[31m")
82
+ end
83
+
84
+ def compare_version
85
+ case
86
+ when @major < @min_major then :too_low
87
+ 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
93
+ end
94
+ end
95
+
96
+ def version_requirement
97
+ req = ">= #{@min_patch_level}"
98
+ req += ", < #{@max_major}.#{@max_minor + 1}" if @max_minor
99
+ req += ", except versions #{@unsupported_versions.join(',')}" unless @unsupported_versions.empty?
100
+ req
101
+ end
102
+
103
+ def parse_version(version)
104
+ version.split('.').map { |v| v.to_i }
105
+ end
106
+
107
+ def colorize(text, color_code)
108
+ "#{color_code}#{text}\e[0m"
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,3 @@
1
+ module WebMock
2
+ VERSION = '3.7.1' unless defined?(::WebMock::VERSION)
3
+ end
@@ -0,0 +1,161 @@
1
+ module WebMock
2
+
3
+ def self.included(clazz)
4
+ WebMock::Deprecation.warning("include WebMock is deprecated. Please include WebMock::API instead")
5
+ if clazz.instance_methods.map(&:to_s).include?('request')
6
+ warn "WebMock#request was not included in #{clazz} to avoid name collision"
7
+ else
8
+ clazz.class_eval do
9
+ def request(method, uri)
10
+ WebMock::Deprecation.warning("WebMock#request is deprecated. Please use WebMock::API#a_request method instead")
11
+ WebMock.a_request(method, uri)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ include WebMock::API
18
+ extend WebMock::API
19
+
20
+ class << self
21
+ alias :request :a_request
22
+ end
23
+
24
+ def self.version
25
+ VERSION
26
+ end
27
+
28
+ def self.disable!(options = {})
29
+ except = [options[:except]].flatten.compact
30
+ HttpLibAdapterRegistry.instance.each_adapter do |name, adapter|
31
+ adapter.enable!
32
+ adapter.disable! unless except.include?(name)
33
+ end
34
+ end
35
+
36
+ def self.enable!(options = {})
37
+ except = [options[:except]].flatten.compact
38
+ HttpLibAdapterRegistry.instance.each_adapter do |name, adapter|
39
+ adapter.disable!
40
+ adapter.enable! unless except.include?(name)
41
+ end
42
+ end
43
+
44
+ def self.allow_net_connect!(options = {})
45
+ Config.instance.allow_net_connect = true
46
+ Config.instance.net_http_connect_on_start = options[:net_http_connect_on_start]
47
+ end
48
+
49
+ def self.disable_net_connect!(options = {})
50
+ Config.instance.allow_net_connect = false
51
+ Config.instance.allow_localhost = options[:allow_localhost]
52
+ Config.instance.allow = options[:allow]
53
+ Config.instance.net_http_connect_on_start = options[:net_http_connect_on_start]
54
+ end
55
+
56
+ class << self
57
+ alias :enable_net_connect! :allow_net_connect!
58
+ alias :disallow_net_connect! :disable_net_connect!
59
+ end
60
+
61
+ def self.net_connect_allowed?(uri = nil)
62
+ if uri.is_a?(String)
63
+ uri = WebMock::Util::URI.normalize_uri(uri)
64
+ end
65
+
66
+ Config.instance.allow_net_connect ||
67
+ ( Config.instance.allow_localhost && WebMock::Util::URI.is_uri_localhost?(uri) ||
68
+ Config.instance.allow && net_connect_explicit_allowed?(Config.instance.allow, uri) )
69
+ end
70
+
71
+ def self.net_connect_explicit_allowed?(allowed, uri=nil)
72
+ case allowed
73
+ when Array
74
+ allowed.any? { |allowed_item| net_connect_explicit_allowed?(allowed_item, uri) }
75
+ when Regexp
76
+ (uri.to_s =~ allowed) != nil ||
77
+ (uri.omit(:port).to_s =~ allowed) != nil && uri.port == uri.default_port
78
+ when String
79
+ allowed == uri.to_s ||
80
+ allowed == uri.host ||
81
+ allowed == "#{uri.host}:#{uri.port}" ||
82
+ allowed == "#{uri.scheme}://#{uri.host}:#{uri.port}" ||
83
+ allowed == "#{uri.scheme}://#{uri.host}" && uri.port == uri.default_port
84
+ else
85
+ if allowed.respond_to?(:call)
86
+ allowed.call(uri)
87
+ end
88
+ end
89
+ end
90
+
91
+ def self.show_body_diff!
92
+ Config.instance.show_body_diff = true
93
+ end
94
+
95
+ def self.hide_body_diff!
96
+ Config.instance.show_body_diff = false
97
+ end
98
+
99
+ def self.show_body_diff?
100
+ Config.instance.show_body_diff
101
+ end
102
+
103
+ def self.hide_stubbing_instructions!
104
+ Config.instance.show_stubbing_instructions = false
105
+ end
106
+
107
+ def self.show_stubbing_instructions!
108
+ Config.instance.show_stubbing_instructions = true
109
+ end
110
+
111
+ def self.show_stubbing_instructions?
112
+ Config.instance.show_stubbing_instructions
113
+ end
114
+
115
+ def self.reset!
116
+ WebMock::RequestRegistry.instance.reset!
117
+ WebMock::StubRegistry.instance.reset!
118
+ end
119
+
120
+ def self.reset_webmock
121
+ WebMock::Deprecation.warning("WebMock.reset_webmock is deprecated. Please use WebMock.reset! method instead")
122
+ reset!
123
+ end
124
+
125
+ def self.reset_callbacks
126
+ WebMock::CallbackRegistry.reset
127
+ end
128
+
129
+ def self.after_request(options={}, &block)
130
+ WebMock::CallbackRegistry.add_callback(options, block)
131
+ end
132
+
133
+ def self.registered_request?(request_signature)
134
+ WebMock::StubRegistry.instance.registered_request?(request_signature)
135
+ end
136
+
137
+ def self.print_executed_requests
138
+ puts WebMock::RequestExecutionVerifier.executed_requests_message
139
+ end
140
+
141
+ def self.globally_stub_request(&block)
142
+ WebMock::StubRegistry.instance.register_global_stub(&block)
143
+ end
144
+
145
+ %w(
146
+ allow_net_connect!
147
+ disable_net_connect!
148
+ net_connect_allowed?
149
+ reset_webmock
150
+ reset_callbacks
151
+ after_request
152
+ registered_request?
153
+ ).each do |method|
154
+ self.class_eval(%Q(
155
+ def #{method}(*args, &block)
156
+ WebMock::Deprecation.warning("WebMock##{method} instance method is deprecated. Please use WebMock.#{method} class method instead")
157
+ WebMock.#{method}(*args, &block)
158
+ end
159
+ ))
160
+ end
161
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + '/../test/http_request')
7
+
8
+ gem 'minitest'
9
+
10
+ require 'minitest/autorun'
11
+ require 'webmock/minitest'
12
+
13
+ test_class = defined?(MiniTest::Test) ? MiniTest::Test : MiniTest::Unit::TestCase
14
+
15
+ test_class.class_eval do
16
+
17
+ def assert_raise(*exp, &block)
18
+ assert_raises(*exp, &block)
19
+ end
20
+
21
+ def assert_raise_with_message(e, message, &block)
22
+ e = assert_raises(e, &block)
23
+ if message.is_a?(Regexp)
24
+ assert_match(message, e.message)
25
+ else
26
+ assert_equal(message, e.message)
27
+ end
28
+ end
29
+
30
+ def assert_fail(message, &block)
31
+ assert_raise_with_message(MiniTest::Assertion, message, &block)
32
+ end
33
+
34
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../test/shared_test')
3
+
4
+ test_class = defined?(MiniTest::Test) ? MiniTest::Test : MiniTest::Unit::TestCase
5
+
6
+
7
+ class MiniTestWebMock < test_class
8
+ include SharedTest
9
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ describe "Webmock" do
4
+ include HttpRequestTestHelper
5
+
6
+ before do
7
+ @stub_http = stub_http_request(:any, "http://www.example.com")
8
+ @stub_https = stub_http_request(:any, "https://www.example.com")
9
+ end
10
+
11
+ it "should update assertions count" do
12
+ assert_equal 0, assertions
13
+ http_request(:get, "http://www.example.com/")
14
+
15
+ assert_requested(@stub_http)
16
+ assert_equal 2, assertions
17
+
18
+ assert_not_requested(:post, "http://www.example.com")
19
+ assert_equal 4, assertions
20
+ end
21
+
22
+ it "should raise error on non stubbed request" do
23
+ lambda { http_request(:get, "http://www.example.net/") }.must_raise(WebMock::NetConnectNotAllowedError)
24
+ end
25
+
26
+ it "should verify that expected request occured" do
27
+ http_request(:get, "http://www.example.com/")
28
+ assert_requested(:get, "http://www.example.com", times: 1)
29
+ assert_requested(:get, "http://www.example.com")
30
+ end
31
+
32
+ it "should verify that expected http stub occured" do
33
+ http_request(:get, "http://www.example.com/")
34
+ assert_requested(@stub_http, times: 1)
35
+ assert_requested(@stub_http)
36
+ end
37
+
38
+ it "should verify that expected https stub occured" do
39
+ http_request(:get, "https://www.example.com/")
40
+ http_request(:get, "https://www.example.com/")
41
+ assert_requested(@stub_https, times: 2)
42
+ end
43
+
44
+ it "should verify that expect request didn't occur" do
45
+ expected_message = "The request GET http://www.example.com/ was expected to execute 1 time but it executed 0 times"
46
+ expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================"
47
+ assert_fail(expected_message) do
48
+ assert_requested(:get, "http://www.example.com")
49
+ end
50
+ end
51
+
52
+ it "should verify that expect stub didn't occur" do
53
+ expected_message = "The request ANY http://www.example.com/ was expected to execute 1 time but it executed 0 times"
54
+ expected_message += "\n\nThe following requests were made:\n\nNo requests were made.\n============================================================"
55
+ assert_fail(expected_message) do
56
+ assert_requested(@stub_http)
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,349 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'acceptance/webmock_shared'
4
+ require_relative './async_http_client_spec_helper'
5
+
6
+ require 'protocol/http/body/file'
7
+
8
+ Async.logger.debug! if ENV['ASYNC_LOGGER_DEBUG']
9
+
10
+ unless RUBY_PLATFORM =~ /java/
11
+ describe 'Async::HTTP::Client' do
12
+ include AsyncHttpClientSpecHelper
13
+
14
+ include_context "with WebMock",
15
+ :no_status_message,
16
+ :no_url_auth,
17
+ :no_content_length_header
18
+
19
+ it 'works' do
20
+ stub_request(:get, 'http://www.example.com')
21
+ expect(make_request(:get, 'http://www.example.com')).to eq(
22
+ status: 200,
23
+ headers: {},
24
+ body: nil
25
+ )
26
+ end
27
+
28
+ it 'works with request path' do
29
+ stub_request(:get, 'http://www.example.com/foo')
30
+ expect(make_request(:get, 'http://www.example.com/foo')).to eq(
31
+ status: 200,
32
+ headers: {},
33
+ body: nil
34
+ )
35
+ end
36
+
37
+ it 'works with request query' do
38
+ stub_request(:get, 'http://www.example.com/').with(
39
+ query: {
40
+ 'foo' => 'bar'
41
+ }
42
+ )
43
+ expect(make_request(:get, 'http://www.example.com/?foo=bar')).to eq(
44
+ status: 200,
45
+ headers: {},
46
+ body: nil
47
+ )
48
+ end
49
+
50
+ it 'works with request headers' do
51
+ stub_request(:get, 'http://www.example.com').with(
52
+ headers: {
53
+ 'X-Token' => 'Token'
54
+ }
55
+ )
56
+ expect(
57
+ make_request :get, 'http://www.example.com',
58
+ headers: {
59
+ 'X-Token' => 'Token'
60
+ }
61
+ ).to eq(
62
+ status: 200,
63
+ headers: {},
64
+ body: nil
65
+ )
66
+ end
67
+
68
+ it 'works with request body as text' do
69
+ stub_request(:post, 'http://www.example.com').with(
70
+ body: 'x'*10_000
71
+ )
72
+ expect(
73
+ make_request :post, 'http://www.example.com',
74
+ body: 'x'*10_000
75
+ ).to eq(
76
+ status: 200,
77
+ headers: {},
78
+ body: nil
79
+ )
80
+ end
81
+
82
+ it 'works with request body as file' do
83
+ stub_request(:post, "www.example.com").with(
84
+ body: File.read(__FILE__)
85
+ )
86
+ expect(
87
+ make_request :post, "http://www.example.com",
88
+ body: ::Protocol::HTTP::Body::File.open(__FILE__, block_size: 32)
89
+ ).to eq(
90
+ status: 200,
91
+ headers: {},
92
+ body: nil
93
+ )
94
+ end
95
+
96
+ it 'works with response status' do
97
+ stub_request(:get, 'http://www.example.com').to_return(
98
+ status: 400
99
+ )
100
+ expect(make_request(:get, 'http://www.example.com')).to eq(
101
+ status: 400,
102
+ headers: {},
103
+ body: nil
104
+ )
105
+ end
106
+
107
+ it 'works with response headers' do
108
+ stub_request(:get, 'http://www.example.com').to_return(
109
+ headers: {
110
+ 'X-Token' => 'TOKEN'
111
+ }
112
+ )
113
+ expect(make_request(:get, 'http://www.example.com')).to eq(
114
+ status: 200,
115
+ headers: {
116
+ 'x-token' => ['TOKEN']
117
+ },
118
+ body: nil
119
+ )
120
+ end
121
+
122
+ it 'works with response body' do
123
+ stub_request(:get, 'http://www.example.com').to_return(
124
+ body: 'abc'
125
+ )
126
+ expect(make_request(:get, 'http://www.example.com')).to eq(
127
+ status: 200,
128
+ headers: {},
129
+ body: 'abc'
130
+ )
131
+ end
132
+
133
+ it 'works with to_timeout' do
134
+ stub_request(:get, 'http://www.example.com').to_timeout
135
+ expect { make_request(:get, 'http://www.example.com') }.to raise_error Async::TimeoutError
136
+ end
137
+
138
+ context 'scheme and protocol' do
139
+ before do
140
+ stub_request(
141
+ :get, "#{scheme}://www.example.com"
142
+ ).and_return(
143
+ body: 'BODY'
144
+ )
145
+ end
146
+
147
+ subject do
148
+ make_request(:get, "#{scheme}://www.example.com", protocol: protocol)
149
+ end
150
+
151
+ shared_examples :common do
152
+ specify do
153
+ expect(subject).to eq(
154
+ status: 200,
155
+ headers: {},
156
+ body: 'BODY'
157
+ )
158
+ end
159
+ end
160
+
161
+ context 'http scheme' do
162
+ let(:scheme) { 'http' }
163
+
164
+ context 'default protocol' do
165
+ let(:protocol) { nil }
166
+
167
+ include_examples :common
168
+ end
169
+
170
+ context 'HTTP10 protocol' do
171
+ let(:protocol) { Async::HTTP::Protocol::HTTP10 }
172
+
173
+ include_examples :common
174
+ end
175
+
176
+ context 'HTTP11 protocol' do
177
+ let(:protocol) { Async::HTTP::Protocol::HTTP11 }
178
+
179
+ include_examples :common
180
+ end
181
+
182
+ context 'HTTP2 protocol' do
183
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
184
+
185
+ include_examples :common
186
+ end
187
+ end
188
+
189
+ context 'https scheme' do
190
+ let(:scheme) { 'https' }
191
+
192
+ context 'default protocol' do
193
+ let(:protocol) { nil }
194
+
195
+ include_examples :common
196
+ end
197
+
198
+ context 'HTTP10 protocol' do
199
+ let(:protocol) { Async::HTTP::Protocol::HTTP10 }
200
+
201
+ include_examples :common
202
+ end
203
+
204
+ context 'HTTP11 protocol' do
205
+ let(:protocol) { Async::HTTP::Protocol::HTTP11 }
206
+
207
+ include_examples :common
208
+ end
209
+
210
+ context 'HTTP2 protocol' do
211
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
212
+
213
+ include_examples :common
214
+ end
215
+
216
+ context 'HTTPS protocol' do
217
+ let(:protocol) { Async::HTTP::Protocol::HTTPS }
218
+
219
+ include_examples :common
220
+ end
221
+ end
222
+ end
223
+
224
+ context 'multiple requests' do
225
+ let(:endpoint) { Async::HTTP::Endpoint.parse('http://www.example.com') }
226
+ let(:requests_count) { 3 }
227
+
228
+ shared_examples :common do
229
+ before do
230
+ requests_count.times do |index|
231
+ stub_request(
232
+ :get, "http://www.example.com/foo#{index}"
233
+ ).to_return(
234
+ status: 200 + index,
235
+ headers: {'X-Token' => "foo#{index}"},
236
+ body: "FOO#{index}"
237
+ )
238
+ end
239
+ end
240
+
241
+ specify do
242
+ expect(subject).to eq(
243
+ 0 => {
244
+ status: 200,
245
+ headers: {'x-token' => ['foo0']},
246
+ body: 'FOO0'
247
+ },
248
+ 1 => {
249
+ status: 201,
250
+ headers: {'x-token' => ['foo1']},
251
+ body: 'FOO1'
252
+ },
253
+ 2 => {
254
+ status: 202,
255
+ headers: {'x-token' => ['foo2']},
256
+ body: 'FOO2'
257
+ }
258
+ )
259
+ end
260
+ end
261
+
262
+ context 'sequential' do
263
+ subject do
264
+ responses = {}
265
+ Async do |task|
266
+ Async::HTTP::Client.open(endpoint, protocol) do |client|
267
+ requests_count.times do |index|
268
+ response = client.get "/foo#{index}"
269
+ responses[index] = response_to_hash(response)
270
+ end
271
+ end
272
+ end
273
+ responses
274
+ end
275
+
276
+ context 'HTTP1 protocol' do
277
+ let(:protocol) { Async::HTTP::Protocol::HTTP1 }
278
+
279
+ include_examples :common
280
+ end
281
+
282
+ context 'HTTP2 protocol' do
283
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
284
+
285
+ include_examples :common
286
+ end
287
+ end
288
+
289
+ context 'asynchronous' do
290
+ subject do
291
+ responses = {}
292
+ Async do |task|
293
+ Async::HTTP::Client.open(endpoint, protocol) do |client|
294
+ tasks = requests_count.times.map do |index|
295
+ task.async do
296
+ response = client.get "/foo#{index}"
297
+ responses[index] = response_to_hash(response)
298
+ end
299
+ end
300
+
301
+ tasks.map(&:wait)
302
+ end
303
+ end
304
+ responses
305
+ end
306
+
307
+ context 'HTTP1 protocol' do
308
+ let(:protocol) { Async::HTTP::Protocol::HTTP1 }
309
+
310
+ include_examples :common
311
+ end
312
+
313
+ context 'HTTP2 protocol' do
314
+ let(:protocol) { Async::HTTP::Protocol::HTTP2 }
315
+
316
+ include_examples :common
317
+ end
318
+ end
319
+ end
320
+
321
+ def make_request(method, url, protocol: nil, headers: {}, body: nil)
322
+ Async do
323
+ endpoint = Async::HTTP::Endpoint.parse(url)
324
+
325
+ begin
326
+ Async::HTTP::Client.open(endpoint, protocol || endpoint.protocol) do |client|
327
+ response = client.send(
328
+ method,
329
+ endpoint.path,
330
+ headers,
331
+ body
332
+ )
333
+ response_to_hash(response)
334
+ end
335
+ rescue Async::TimeoutError => e
336
+ e
337
+ end
338
+ end.wait
339
+ end
340
+
341
+ def response_to_hash(response)
342
+ {
343
+ status: response.status,
344
+ headers: response.headers.to_h,
345
+ body: response.read
346
+ }
347
+ end
348
+ end
349
+ end