http 5.3.1 → 6.0.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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +241 -41
  3. data/LICENSE.txt +1 -1
  4. data/README.md +110 -13
  5. data/UPGRADING.md +491 -0
  6. data/http.gemspec +32 -29
  7. data/lib/http/base64.rb +11 -1
  8. data/lib/http/chainable/helpers.rb +62 -0
  9. data/lib/http/chainable/verbs.rb +136 -0
  10. data/lib/http/chainable.rb +232 -136
  11. data/lib/http/client.rb +158 -127
  12. data/lib/http/connection/internals.rb +141 -0
  13. data/lib/http/connection.rb +126 -97
  14. data/lib/http/content_type.rb +61 -6
  15. data/lib/http/errors.rb +25 -1
  16. data/lib/http/feature.rb +65 -5
  17. data/lib/http/features/auto_deflate.rb +124 -17
  18. data/lib/http/features/auto_inflate.rb +38 -15
  19. data/lib/http/features/caching/entry.rb +178 -0
  20. data/lib/http/features/caching/in_memory_store.rb +63 -0
  21. data/lib/http/features/caching.rb +216 -0
  22. data/lib/http/features/digest_auth.rb +234 -0
  23. data/lib/http/features/instrumentation.rb +97 -17
  24. data/lib/http/features/logging.rb +183 -5
  25. data/lib/http/features/normalize_uri.rb +17 -0
  26. data/lib/http/features/raise_error.rb +18 -3
  27. data/lib/http/form_data/composite_io.rb +106 -0
  28. data/lib/http/form_data/file.rb +95 -0
  29. data/lib/http/form_data/multipart/param.rb +62 -0
  30. data/lib/http/form_data/multipart.rb +106 -0
  31. data/lib/http/form_data/part.rb +52 -0
  32. data/lib/http/form_data/readable.rb +58 -0
  33. data/lib/http/form_data/urlencoded.rb +175 -0
  34. data/lib/http/form_data/version.rb +8 -0
  35. data/lib/http/form_data.rb +102 -0
  36. data/lib/http/headers/known.rb +3 -0
  37. data/lib/http/headers/normalizer.rb +17 -36
  38. data/lib/http/headers.rb +172 -65
  39. data/lib/http/mime_type/adapter.rb +24 -9
  40. data/lib/http/mime_type/json.rb +19 -4
  41. data/lib/http/mime_type.rb +21 -3
  42. data/lib/http/options/definitions.rb +189 -0
  43. data/lib/http/options.rb +172 -125
  44. data/lib/http/redirector.rb +80 -75
  45. data/lib/http/request/body.rb +87 -6
  46. data/lib/http/request/builder.rb +184 -0
  47. data/lib/http/request/proxy.rb +83 -0
  48. data/lib/http/request/writer.rb +76 -16
  49. data/lib/http/request.rb +214 -98
  50. data/lib/http/response/body.rb +103 -18
  51. data/lib/http/response/inflater.rb +35 -7
  52. data/lib/http/response/parser.rb +98 -4
  53. data/lib/http/response/status/reasons.rb +2 -4
  54. data/lib/http/response/status.rb +141 -31
  55. data/lib/http/response.rb +219 -61
  56. data/lib/http/retriable/delay_calculator.rb +38 -11
  57. data/lib/http/retriable/errors.rb +21 -0
  58. data/lib/http/retriable/performer.rb +82 -38
  59. data/lib/http/session.rb +280 -0
  60. data/lib/http/timeout/global.rb +147 -34
  61. data/lib/http/timeout/null.rb +155 -9
  62. data/lib/http/timeout/per_operation.rb +139 -18
  63. data/lib/http/uri/normalizer.rb +82 -0
  64. data/lib/http/uri/parsing.rb +182 -0
  65. data/lib/http/uri.rb +289 -124
  66. data/lib/http/version.rb +2 -1
  67. data/lib/http.rb +11 -2
  68. data/sig/deps.rbs +122 -0
  69. data/sig/http.rbs +1619 -0
  70. data/test/http/base64_test.rb +28 -0
  71. data/test/http/client_test.rb +739 -0
  72. data/test/http/connection_test.rb +1533 -0
  73. data/test/http/content_type_test.rb +190 -0
  74. data/test/http/errors_test.rb +28 -0
  75. data/test/http/feature_test.rb +49 -0
  76. data/test/http/features/auto_deflate_test.rb +317 -0
  77. data/test/http/features/auto_inflate_test.rb +213 -0
  78. data/test/http/features/caching_test.rb +942 -0
  79. data/test/http/features/digest_auth_test.rb +996 -0
  80. data/test/http/features/instrumentation_test.rb +246 -0
  81. data/test/http/features/logging_test.rb +654 -0
  82. data/test/http/features/normalize_uri_test.rb +41 -0
  83. data/test/http/features/raise_error_test.rb +77 -0
  84. data/test/http/form_data/composite_io_test.rb +215 -0
  85. data/test/http/form_data/file_test.rb +255 -0
  86. data/test/http/form_data/fixtures/the-http-gem.info +1 -0
  87. data/test/http/form_data/multipart_test.rb +303 -0
  88. data/test/http/form_data/part_test.rb +90 -0
  89. data/test/http/form_data/urlencoded_test.rb +164 -0
  90. data/test/http/form_data_test.rb +232 -0
  91. data/test/http/headers/normalizer_test.rb +93 -0
  92. data/test/http/headers_test.rb +888 -0
  93. data/test/http/mime_type/json_test.rb +39 -0
  94. data/test/http/mime_type_test.rb +150 -0
  95. data/test/http/options/base_uri_test.rb +148 -0
  96. data/test/http/options/body_test.rb +21 -0
  97. data/test/http/options/features_test.rb +38 -0
  98. data/test/http/options/form_test.rb +21 -0
  99. data/test/http/options/headers_test.rb +32 -0
  100. data/test/http/options/json_test.rb +21 -0
  101. data/test/http/options/merge_test.rb +78 -0
  102. data/test/http/options/new_test.rb +37 -0
  103. data/test/http/options/proxy_test.rb +32 -0
  104. data/test/http/options_test.rb +575 -0
  105. data/test/http/redirector_test.rb +639 -0
  106. data/test/http/request/body_test.rb +318 -0
  107. data/test/http/request/builder_test.rb +623 -0
  108. data/test/http/request/writer_test.rb +391 -0
  109. data/test/http/request_test.rb +1733 -0
  110. data/test/http/response/body_test.rb +292 -0
  111. data/test/http/response/parser_test.rb +105 -0
  112. data/test/http/response/status_test.rb +322 -0
  113. data/test/http/response_test.rb +502 -0
  114. data/test/http/retriable/delay_calculator_test.rb +194 -0
  115. data/test/http/retriable/errors_test.rb +71 -0
  116. data/test/http/retriable/performer_test.rb +551 -0
  117. data/test/http/session_test.rb +424 -0
  118. data/test/http/timeout/global_test.rb +239 -0
  119. data/test/http/timeout/null_test.rb +218 -0
  120. data/test/http/timeout/per_operation_test.rb +220 -0
  121. data/test/http/uri/normalizer_test.rb +89 -0
  122. data/test/http/uri_test.rb +1140 -0
  123. data/test/http/version_test.rb +15 -0
  124. data/test/http_test.rb +818 -0
  125. data/test/regression_tests.rb +27 -0
  126. data/test/support/dummy_server/encoding_routes.rb +47 -0
  127. data/test/support/dummy_server/routes.rb +201 -0
  128. data/test/support/dummy_server/servlet.rb +81 -0
  129. data/test/support/dummy_server.rb +200 -0
  130. data/{spec → test}/support/fakeio.rb +2 -2
  131. data/test/support/http_handling_shared/connection_reuse_tests.rb +97 -0
  132. data/test/support/http_handling_shared/timeout_tests.rb +134 -0
  133. data/test/support/http_handling_shared.rb +11 -0
  134. data/test/support/proxy_server.rb +207 -0
  135. data/test/support/servers/runner.rb +67 -0
  136. data/{spec → test}/support/simplecov.rb +11 -2
  137. data/test/support/ssl_helper.rb +108 -0
  138. data/test/test_helper.rb +38 -0
  139. metadata +108 -168
  140. data/.github/workflows/ci.yml +0 -67
  141. data/.gitignore +0 -15
  142. data/.rspec +0 -1
  143. data/.rubocop/layout.yml +0 -8
  144. data/.rubocop/metrics.yml +0 -4
  145. data/.rubocop/rspec.yml +0 -9
  146. data/.rubocop/style.yml +0 -32
  147. data/.rubocop.yml +0 -11
  148. data/.rubocop_todo.yml +0 -219
  149. data/.yardopts +0 -2
  150. data/CHANGES_OLD.md +0 -1002
  151. data/Gemfile +0 -51
  152. data/Guardfile +0 -18
  153. data/Rakefile +0 -64
  154. data/lib/http/headers/mixin.rb +0 -34
  155. data/lib/http/retriable/client.rb +0 -37
  156. data/logo.png +0 -0
  157. data/spec/lib/http/client_spec.rb +0 -556
  158. data/spec/lib/http/connection_spec.rb +0 -88
  159. data/spec/lib/http/content_type_spec.rb +0 -47
  160. data/spec/lib/http/features/auto_deflate_spec.rb +0 -77
  161. data/spec/lib/http/features/auto_inflate_spec.rb +0 -86
  162. data/spec/lib/http/features/instrumentation_spec.rb +0 -81
  163. data/spec/lib/http/features/logging_spec.rb +0 -65
  164. data/spec/lib/http/features/raise_error_spec.rb +0 -62
  165. data/spec/lib/http/headers/mixin_spec.rb +0 -36
  166. data/spec/lib/http/headers/normalizer_spec.rb +0 -52
  167. data/spec/lib/http/headers_spec.rb +0 -527
  168. data/spec/lib/http/options/body_spec.rb +0 -15
  169. data/spec/lib/http/options/features_spec.rb +0 -33
  170. data/spec/lib/http/options/form_spec.rb +0 -15
  171. data/spec/lib/http/options/headers_spec.rb +0 -24
  172. data/spec/lib/http/options/json_spec.rb +0 -15
  173. data/spec/lib/http/options/merge_spec.rb +0 -68
  174. data/spec/lib/http/options/new_spec.rb +0 -30
  175. data/spec/lib/http/options/proxy_spec.rb +0 -20
  176. data/spec/lib/http/options_spec.rb +0 -13
  177. data/spec/lib/http/redirector_spec.rb +0 -530
  178. data/spec/lib/http/request/body_spec.rb +0 -211
  179. data/spec/lib/http/request/writer_spec.rb +0 -121
  180. data/spec/lib/http/request_spec.rb +0 -234
  181. data/spec/lib/http/response/body_spec.rb +0 -85
  182. data/spec/lib/http/response/parser_spec.rb +0 -74
  183. data/spec/lib/http/response/status_spec.rb +0 -253
  184. data/spec/lib/http/response_spec.rb +0 -262
  185. data/spec/lib/http/retriable/delay_calculator_spec.rb +0 -69
  186. data/spec/lib/http/retriable/performer_spec.rb +0 -302
  187. data/spec/lib/http/uri/normalizer_spec.rb +0 -95
  188. data/spec/lib/http/uri_spec.rb +0 -71
  189. data/spec/lib/http_spec.rb +0 -535
  190. data/spec/regression_specs.rb +0 -24
  191. data/spec/spec_helper.rb +0 -89
  192. data/spec/support/black_hole.rb +0 -13
  193. data/spec/support/dummy_server/servlet.rb +0 -203
  194. data/spec/support/dummy_server.rb +0 -44
  195. data/spec/support/fuubar.rb +0 -21
  196. data/spec/support/http_handling_shared.rb +0 -190
  197. data/spec/support/proxy_server.rb +0 -39
  198. data/spec/support/servers/config.rb +0 -11
  199. data/spec/support/servers/runner.rb +0 -19
  200. data/spec/support/ssl_helper.rb +0 -104
  201. /data/{spec → test}/support/capture_warning.rb +0 -0
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class FormDataTest < Minitest::Test
6
+ cover "HTTP::FormData*"
7
+
8
+ def fixture_path
9
+ @fixture_path ||= Pathname.new(__dir__).join("form_data/fixtures/the-http-gem.info").realpath
10
+ end
11
+
12
+ # --- create ---
13
+
14
+ def test_create_returns_urlencoded_when_no_files
15
+ assert_instance_of HTTP::FormData::Urlencoded, HTTP::FormData.create({ foo: :bar })
16
+ end
17
+
18
+ def test_create_returns_multipart_when_file_param
19
+ file = HTTP::FormData::File.new(fixture_path.to_s)
20
+
21
+ assert_instance_of HTTP::FormData::Multipart, HTTP::FormData.create({ foo: :bar, baz: file })
22
+ end
23
+
24
+ def test_create_returns_multipart_when_file_in_array_param
25
+ file = HTTP::FormData::File.new(fixture_path.to_s)
26
+
27
+ assert_instance_of HTTP::FormData::Multipart, HTTP::FormData.create({ foo: :bar, baz: [file] })
28
+ end
29
+
30
+ def test_create_returns_empty_urlencoded_for_nil_data
31
+ result = HTTP::FormData.create(nil)
32
+
33
+ assert_instance_of HTTP::FormData::Urlencoded, result
34
+ assert_equal "", result.to_s
35
+ end
36
+
37
+ def test_create_includes_file_content_in_multipart
38
+ file = HTTP::FormData::File.new(StringIO.new("file content"))
39
+ result = HTTP::FormData.create({ name: file })
40
+
41
+ assert_instance_of HTTP::FormData::Multipart, result
42
+ assert_includes result.to_s, "file content"
43
+ end
44
+
45
+ def test_create_encodes_urlencoded_content
46
+ result = HTTP::FormData.create({ foo: "bar" })
47
+
48
+ assert_instance_of HTTP::FormData::Urlencoded, result
49
+ assert_equal "foo=bar", result.to_s
50
+ end
51
+
52
+ def test_create_passes_encoder_to_urlencoded
53
+ custom_encoder = proc { |data| data.map { |k, v| "#{k}:#{v}" }.join(",") }
54
+ result = HTTP::FormData.create({ foo: "bar" }, encoder: custom_encoder)
55
+
56
+ assert_instance_of HTTP::FormData::Urlencoded, result
57
+ assert_equal "foo:bar", result.to_s
58
+ end
59
+
60
+ def test_create_accepts_to_h_objects
61
+ obj = Object.new
62
+ def obj.to_h = { foo: "bar" }
63
+
64
+ result = HTTP::FormData.create(obj)
65
+
66
+ assert_instance_of HTTP::FormData::Urlencoded, result
67
+ assert_equal "foo=bar", result.to_s
68
+ end
69
+
70
+ # --- multipart? detection ---
71
+
72
+ def test_string_values_are_not_multipart
73
+ assert_instance_of HTTP::FormData::Urlencoded, HTTP::FormData.create({ foo: "bar", baz: "qux" })
74
+ end
75
+
76
+ def test_array_of_strings_is_not_multipart
77
+ assert_instance_of HTTP::FormData::Urlencoded, HTTP::FormData.create({ foo: %w[bar baz] })
78
+ end
79
+
80
+ def test_empty_array_is_not_multipart
81
+ assert_instance_of HTTP::FormData::Urlencoded, HTTP::FormData.create({ foo: [] })
82
+ end
83
+
84
+ def test_part_value_is_multipart
85
+ part = HTTP::FormData::Part.new("hello", content_type: "text/plain")
86
+
87
+ assert_instance_of HTTP::FormData::Multipart, HTTP::FormData.create({ foo: part })
88
+ end
89
+
90
+ def test_array_containing_part_is_multipart
91
+ part = HTTP::FormData::Part.new("hello", content_type: "text/plain")
92
+
93
+ assert_instance_of HTTP::FormData::Multipart, HTTP::FormData.create({ foo: [part] })
94
+ end
95
+
96
+ def test_to_ary_containing_part_is_multipart
97
+ part = HTTP::FormData::Part.new("hello")
98
+ obj = Object.new
99
+ obj.define_singleton_method(:to_ary) { [part] }
100
+
101
+ assert_instance_of HTTP::FormData::Multipart, HTTP::FormData.create({ foo: obj })
102
+ end
103
+
104
+ def test_create_multipart_preserves_all_params
105
+ file = HTTP::FormData::File.new(StringIO.new("content"))
106
+ body = HTTP::FormData.create({ user: "ixti", file: file }).to_s
107
+
108
+ assert_includes body, "ixti"
109
+ assert_includes body, "content"
110
+ assert_includes body, "user"
111
+ assert_includes body, "file"
112
+ end
113
+
114
+ # --- ensure_data ---
115
+
116
+ def test_ensure_data_with_hash
117
+ assert_equal({ foo: :bar }, HTTP::FormData.ensure_data({ foo: :bar }))
118
+ end
119
+
120
+ def test_ensure_data_with_array
121
+ data = [%i[foo bar], %i[foo baz]]
122
+
123
+ assert_equal data, HTTP::FormData.ensure_data(data)
124
+ end
125
+
126
+ def test_ensure_data_with_enumerator
127
+ assert_instance_of Enumerator, HTTP::FormData.ensure_data(Enumerator.new { |y| y << %i[foo bar] })
128
+ end
129
+
130
+ def test_ensure_data_with_to_h
131
+ obj = Object.new
132
+ def obj.to_h = { foo: :bar }
133
+
134
+ assert_equal({ foo: :bar }, HTTP::FormData.ensure_data(obj))
135
+ end
136
+
137
+ def test_ensure_data_with_nil
138
+ result = HTTP::FormData.ensure_data(nil)
139
+
140
+ assert_instance_of Array, result
141
+ assert_empty result
142
+ end
143
+
144
+ def test_ensure_data_with_invalid_input
145
+ error = assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_data(42) }
146
+
147
+ assert_includes error.message, "42"
148
+ assert_includes error.message, "is neither Enumerable nor responds to :to_h"
149
+ end
150
+
151
+ def test_ensure_data_with_false_raises
152
+ assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_data(false) }
153
+ end
154
+
155
+ def test_ensure_data_returns_same_array_object
156
+ input = [%i[foo bar]]
157
+
158
+ assert_same input, HTTP::FormData.ensure_data(input)
159
+ end
160
+
161
+ def test_ensure_data_returns_same_hash_object
162
+ input = { foo: :bar }
163
+
164
+ assert_same input, HTTP::FormData.ensure_data(input)
165
+ end
166
+
167
+ def test_ensure_data_error_message_uses_inspect
168
+ obj = Object.new
169
+ def obj.inspect = "CUSTOM_INSPECT"
170
+ def obj.to_s = "CUSTOM_TO_S"
171
+
172
+ error = assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_data(obj) }
173
+
174
+ assert_includes error.message, "CUSTOM_INSPECT"
175
+ refute_includes error.message, "CUSTOM_TO_S"
176
+ end
177
+
178
+ # --- ensure_hash ---
179
+
180
+ def test_ensure_hash_with_hash
181
+ assert_equal({ foo: :bar }, HTTP::FormData.ensure_hash({ foo: :bar }))
182
+ end
183
+
184
+ def test_ensure_hash_with_to_h
185
+ obj = Object.new
186
+ def obj.to_h = { foo: :bar }
187
+
188
+ assert_equal({ foo: :bar }, HTTP::FormData.ensure_hash(obj))
189
+ end
190
+
191
+ def test_ensure_hash_with_nil
192
+ result = HTTP::FormData.ensure_hash(nil)
193
+
194
+ assert_instance_of Hash, result
195
+ assert_empty result
196
+ end
197
+
198
+ def test_ensure_hash_with_invalid_input
199
+ error = assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_hash(42) }
200
+
201
+ assert_includes error.message, "42"
202
+ assert_includes error.message, "is neither Hash nor responds to :to_h"
203
+ end
204
+
205
+ def test_ensure_hash_with_hash_subclass
206
+ subclass = Class.new(Hash)
207
+ obj = subclass.new
208
+ obj[:foo] = :bar
209
+
210
+ assert_same obj, HTTP::FormData.ensure_hash(obj)
211
+ end
212
+
213
+ def test_ensure_hash_returns_same_hash_object
214
+ input = { foo: :bar }
215
+
216
+ assert_same input, HTTP::FormData.ensure_hash(input)
217
+ end
218
+
219
+ def test_ensure_hash_with_false_raises
220
+ assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_hash(false) }
221
+ end
222
+
223
+ def test_ensure_hash_error_message_uses_inspect
224
+ obj = Object.new
225
+ def obj.inspect = "HASH_INSPECT"
226
+ def obj.to_s = "HASH_TO_S"
227
+
228
+ error = assert_raises(HTTP::FormData::Error) { HTTP::FormData.ensure_hash(obj) }
229
+
230
+ assert_includes error.message, "HASH_INSPECT"
231
+ end
232
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class HTTPHeadersNormalizerTest < Minitest::Test
6
+ cover "HTTP::Headers::Normalizer*"
7
+
8
+ def normalizer
9
+ @normalizer ||= HTTP::Headers::Normalizer.new
10
+ end
11
+
12
+ def setup
13
+ super
14
+ Thread.current[HTTP::Headers::Normalizer::CACHE_KEY] = nil
15
+ end
16
+
17
+ def test_call_normalizes_the_header
18
+ assert_equal "Content-Type", normalizer.call("content_type")
19
+ end
20
+
21
+ def test_call_returns_a_non_frozen_string
22
+ refute_predicate normalizer.call("content_type"), :frozen?
23
+ end
24
+
25
+ def test_call_returns_mutable_strings
26
+ normalized_headers = Array.new(3) { normalizer.call("content_type") }
27
+
28
+ # All values should be equal
29
+ assert_equal 1, normalized_headers.uniq.size
30
+ # Each should be a distinct object
31
+ assert_equal normalized_headers.size, normalized_headers.map(&:object_id).uniq.size
32
+ # None should be frozen
33
+ assert normalized_headers.none?(&:frozen?)
34
+ end
35
+
36
+ if RUBY_ENGINE == "ruby"
37
+ def test_call_allocates_minimal_memory_for_normalization_of_the_same_header
38
+ normalizer.call("accept") # Ensure normalizer is pre-allocated
39
+
40
+ # On first call it is expected to allocate during normalization
41
+ assert_allocations(Array: 1, MatchData: 1, String: 6) do
42
+ normalizer.call("content_type")
43
+ end
44
+
45
+ # On subsequent call it is expected to only allocate copy of a cached string
46
+ assert_allocations(Array: 0, MatchData: 0, String: 1) do
47
+ normalizer.call("content_type")
48
+ end
49
+ end
50
+ end
51
+
52
+ def test_call_calls_to_s_on_the_name_argument
53
+ name = fake(to_s: "content_type")
54
+
55
+ assert_equal "Content-Type", normalizer.call(name)
56
+ end
57
+
58
+ def test_call_caches_the_normalized_value_and_reuses_it
59
+ first = normalizer.call("content_type")
60
+ second = normalizer.call("content_type")
61
+
62
+ assert_equal first, second
63
+ end
64
+
65
+ def test_call_passes_through_names_already_in_canonical_form
66
+ assert_equal "Content-Type", normalizer.call("Content-Type")
67
+ end
68
+
69
+ def test_call_normalizes_underscore_separated_names
70
+ assert_equal "Content-Type", normalizer.call("content_type")
71
+ end
72
+
73
+ def test_call_normalizes_dash_separated_names
74
+ assert_equal "Content-Type", normalizer.call("content-type")
75
+ end
76
+
77
+ def test_call_raises_header_error_for_invalid_header_names
78
+ err = assert_raises(HTTP::HeaderError) { normalizer.call("invalid header") }
79
+ assert_includes err.message, "invalid header"
80
+ end
81
+
82
+ def test_call_includes_inspect_formatted_name_in_invalid_header_error
83
+ err = assert_raises(HTTP::HeaderError) { normalizer.call("invalid header") }
84
+ assert_includes err.message, '"invalid header"'
85
+ end
86
+
87
+ def test_call_freezes_cached_value_internally_but_returns_a_dup
88
+ result = normalizer.call("accept")
89
+
90
+ refute_predicate result, :frozen?
91
+ assert_equal "Accept", result
92
+ end
93
+ end