httparty 0.17.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Changelog.md +7 -0
- data/Gemfile +1 -0
- data/httparty.gemspec +0 -1
- data/lib/httparty.rb +2 -18
- data/lib/httparty/connection_adapter.rb +10 -0
- data/lib/httparty/headers_processor.rb +30 -0
- data/lib/httparty/request.rb +4 -4
- data/lib/httparty/version.rb +1 -1
- metadata +4 -103
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -56
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -92
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/example.html +0 -10
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -29
- data/spec/fixtures/ssl/generated/ca.crt +0 -31
- data/spec/fixtures/ssl/generated/ca.key +0 -52
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -29
- data/spec/fixtures/ssl/generated/server.crt +0 -30
- data/spec/fixtures/ssl/generated/server.key +0 -52
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/tiny.gif +0 -0
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -628
- data/spec/httparty/cookie_hash_spec.rb +0 -100
- data/spec/httparty/exception_spec.rb +0 -45
- data/spec/httparty/hash_conversions_spec.rb +0 -58
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -40
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
- data/spec/httparty/logger/logger_spec.rb +0 -43
- data/spec/httparty/logger/logstash_formatter_spec.rb +0 -44
- data/spec/httparty/net_digest_auth_spec.rb +0 -270
- data/spec/httparty/parser_spec.rb +0 -190
- data/spec/httparty/request/body_spec.rb +0 -165
- data/spec/httparty/request_spec.rb +0 -1389
- data/spec/httparty/response_fragment_spec.rb +0 -17
- data/spec/httparty/response_spec.rb +0 -374
- data/spec/httparty/ssl_spec.rb +0 -82
- data/spec/httparty_spec.rb +0 -943
- data/spec/spec_helper.rb +0 -57
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -50
@@ -1,270 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Net::HTTPHeader::DigestAuthenticator do
|
4
|
-
def setup_digest(response)
|
5
|
-
digest = Net::HTTPHeader::DigestAuthenticator.new("Mufasa",
|
6
|
-
"Circle Of Life", "GET", "/dir/index.html", response)
|
7
|
-
allow(digest).to receive(:random).and_return("deadbeef")
|
8
|
-
allow(Digest::MD5).to receive(:hexdigest) { |str| "md5(#{str})" }
|
9
|
-
digest
|
10
|
-
end
|
11
|
-
|
12
|
-
def authorization_header
|
13
|
-
@digest.authorization_header.join(", ")
|
14
|
-
end
|
15
|
-
|
16
|
-
def cookie_header
|
17
|
-
@digest.cookie_header
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'Net::HTTPHeader#digest_auth' do
|
21
|
-
let(:headers) {
|
22
|
-
(Class.new do
|
23
|
-
include Net::HTTPHeader
|
24
|
-
def initialize
|
25
|
-
@header = {}
|
26
|
-
@path = '/'
|
27
|
-
@method = 'GET'
|
28
|
-
end
|
29
|
-
end).new
|
30
|
-
}
|
31
|
-
|
32
|
-
let(:response){
|
33
|
-
(Class.new do
|
34
|
-
include Net::HTTPHeader
|
35
|
-
def initialize
|
36
|
-
@header = {}
|
37
|
-
self['WWW-Authenticate'] =
|
38
|
-
'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"'
|
39
|
-
end
|
40
|
-
end).new
|
41
|
-
}
|
42
|
-
|
43
|
-
it 'should set the authorization header' do
|
44
|
-
expect(headers['authorization']).to be_nil
|
45
|
-
headers.digest_auth('user','pass', response)
|
46
|
-
expect(headers['authorization']).to_not be_empty
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "with a cookie value in the response header" do
|
51
|
-
before do
|
52
|
-
@digest = setup_digest({
|
53
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com"',
|
54
|
-
'Set-Cookie' => 'custom-cookie=1234567'
|
55
|
-
})
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should set cookie header" do
|
59
|
-
expect(cookie_header).to include('custom-cookie=1234567')
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "without a cookie value in the response header" do
|
64
|
-
before do
|
65
|
-
@digest = setup_digest({
|
66
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
|
67
|
-
})
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should set empty cookie header array" do
|
71
|
-
expect(cookie_header).to eql []
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context "with an opaque value in the response header" do
|
76
|
-
before do
|
77
|
-
@digest = setup_digest({
|
78
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", opaque="solid"'
|
79
|
-
})
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should set opaque" do
|
83
|
-
expect(authorization_header).to include('opaque="solid"')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context "without an opaque valid in the response header" do
|
88
|
-
before do
|
89
|
-
@digest = setup_digest({
|
90
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com"'
|
91
|
-
})
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should not set opaque" do
|
95
|
-
expect(authorization_header).not_to include("opaque=")
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
context "with specified quality of protection (qop)" do
|
100
|
-
before do
|
101
|
-
@digest = setup_digest({
|
102
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
|
103
|
-
})
|
104
|
-
end
|
105
|
-
|
106
|
-
it "should set prefix" do
|
107
|
-
expect(authorization_header).to match(/^Digest /)
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should set username" do
|
111
|
-
expect(authorization_header).to include('username="Mufasa"')
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should set digest-uri" do
|
115
|
-
expect(authorization_header).to include('uri="/dir/index.html"')
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should set qop" do
|
119
|
-
expect(authorization_header).to include('qop="auth"')
|
120
|
-
end
|
121
|
-
|
122
|
-
it "should set cnonce" do
|
123
|
-
expect(authorization_header).to include('cnonce="md5(deadbeef)"')
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should set nonce-count" do
|
127
|
-
expect(authorization_header).to include("nc=00000001")
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should set response" do
|
131
|
-
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
|
132
|
-
expect(authorization_header).to include(%(response="#{request_digest}"))
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "when quality of protection (qop) is unquoted" do
|
137
|
-
before do
|
138
|
-
@digest = setup_digest({
|
139
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop=auth'
|
140
|
-
})
|
141
|
-
end
|
142
|
-
|
143
|
-
it "should still set qop" do
|
144
|
-
expect(authorization_header).to include('qop="auth"')
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
context "with unspecified quality of protection (qop)" do
|
149
|
-
before do
|
150
|
-
@digest = setup_digest({
|
151
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE"'
|
152
|
-
})
|
153
|
-
end
|
154
|
-
|
155
|
-
it "should set prefix" do
|
156
|
-
expect(authorization_header).to match(/^Digest /)
|
157
|
-
end
|
158
|
-
|
159
|
-
it "should set username" do
|
160
|
-
expect(authorization_header).to include('username="Mufasa"')
|
161
|
-
end
|
162
|
-
|
163
|
-
it "should set digest-uri" do
|
164
|
-
expect(authorization_header).to include('uri="/dir/index.html"')
|
165
|
-
end
|
166
|
-
|
167
|
-
it "should not set qop" do
|
168
|
-
expect(authorization_header).not_to include("qop=")
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should not set cnonce" do
|
172
|
-
expect(authorization_header).not_to include("cnonce=")
|
173
|
-
end
|
174
|
-
|
175
|
-
it "should not set nonce-count" do
|
176
|
-
expect(authorization_header).not_to include("nc=")
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should set response" do
|
180
|
-
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(GET:/dir/index.html))"
|
181
|
-
expect(authorization_header).to include(%(response="#{request_digest}"))
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context "with http basic auth response when net digest auth expected" do
|
186
|
-
it "should not fail" do
|
187
|
-
@digest = setup_digest({
|
188
|
-
'www-authenticate' => 'WWW-Authenticate: Basic realm="testrealm.com""'
|
189
|
-
})
|
190
|
-
|
191
|
-
expect(authorization_header).to include("Digest")
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context "with multiple authenticate headers" do
|
196
|
-
before do
|
197
|
-
@digest = setup_digest({
|
198
|
-
'www-authenticate' => 'NTLM, Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth"'
|
199
|
-
})
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should set prefix" do
|
203
|
-
expect(authorization_header).to match(/^Digest /)
|
204
|
-
end
|
205
|
-
|
206
|
-
it "should set username" do
|
207
|
-
expect(authorization_header).to include('username="Mufasa"')
|
208
|
-
end
|
209
|
-
|
210
|
-
it "should set digest-uri" do
|
211
|
-
expect(authorization_header).to include('uri="/dir/index.html"')
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should set qop" do
|
215
|
-
expect(authorization_header).to include('qop="auth"')
|
216
|
-
end
|
217
|
-
|
218
|
-
it "should set cnonce" do
|
219
|
-
expect(authorization_header).to include('cnonce="md5(deadbeef)"')
|
220
|
-
end
|
221
|
-
|
222
|
-
it "should set nonce-count" do
|
223
|
-
expect(authorization_header).to include("nc=00000001")
|
224
|
-
end
|
225
|
-
|
226
|
-
it "should set response" do
|
227
|
-
request_digest = "md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
|
228
|
-
expect(authorization_header).to include(%(response="#{request_digest}"))
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
context "with algorithm specified" do
|
233
|
-
before do
|
234
|
-
@digest = setup_digest({
|
235
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5'
|
236
|
-
})
|
237
|
-
end
|
238
|
-
|
239
|
-
it "should recognise algorithm was specified" do
|
240
|
-
expect( @digest.send :algorithm_present? ).to be(true)
|
241
|
-
end
|
242
|
-
|
243
|
-
it "should set the algorithm header" do
|
244
|
-
expect(authorization_header).to include('algorithm="MD5"')
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
context "with md5-sess algorithm specified" do
|
249
|
-
before do
|
250
|
-
@digest = setup_digest({
|
251
|
-
'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5-sess'
|
252
|
-
})
|
253
|
-
end
|
254
|
-
|
255
|
-
it "should recognise algorithm was specified" do
|
256
|
-
expect( @digest.send :algorithm_present? ).to be(true)
|
257
|
-
end
|
258
|
-
|
259
|
-
it "should set the algorithm header" do
|
260
|
-
expect(authorization_header).to include('algorithm="MD5-sess"')
|
261
|
-
end
|
262
|
-
|
263
|
-
it "should set response using md5-sess algorithm" do
|
264
|
-
request_digest = "md5(md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(deadbeef)):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
|
265
|
-
expect(authorization_header).to include(%(response="#{request_digest}"))
|
266
|
-
end
|
267
|
-
|
268
|
-
end
|
269
|
-
|
270
|
-
end
|
@@ -1,190 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe HTTParty::Parser do
|
4
|
-
describe ".SupportedFormats" do
|
5
|
-
it "returns a hash" do
|
6
|
-
expect(HTTParty::Parser::SupportedFormats).to be_instance_of(Hash)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
describe ".call" do
|
11
|
-
it "generates an HTTParty::Parser instance with the given body and format" do
|
12
|
-
expect(HTTParty::Parser).to receive(:new).with('body', :plain).and_return(double(parse: nil))
|
13
|
-
HTTParty::Parser.call('body', :plain)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "calls #parse on the parser" do
|
17
|
-
parser = double('Parser')
|
18
|
-
expect(parser).to receive(:parse)
|
19
|
-
allow(HTTParty::Parser).to receive_messages(new: parser)
|
20
|
-
parser = HTTParty::Parser.call('body', :plain)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe ".formats" do
|
25
|
-
it "returns the SupportedFormats constant" do
|
26
|
-
expect(HTTParty::Parser.formats).to eq(HTTParty::Parser::SupportedFormats)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "returns the SupportedFormats constant for subclasses" do
|
30
|
-
klass = Class.new(HTTParty::Parser)
|
31
|
-
klass::SupportedFormats = { "application/atom+xml" => :atom }
|
32
|
-
|
33
|
-
expect(klass.formats).to eq({"application/atom+xml" => :atom})
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe ".format_from_mimetype" do
|
38
|
-
it "returns a symbol representing the format mimetype" do
|
39
|
-
expect(HTTParty::Parser.format_from_mimetype("text/plain")).to eq(:plain)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "returns nil when the mimetype is not supported" do
|
43
|
-
expect(HTTParty::Parser.format_from_mimetype("application/atom+xml")).to be_nil
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe ".supported_formats" do
|
48
|
-
it "returns a unique set of supported formats represented by symbols" do
|
49
|
-
expect(HTTParty::Parser.supported_formats).to eq(HTTParty::Parser::SupportedFormats.values.uniq)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe ".supports_format?" do
|
54
|
-
it "returns true for a supported format" do
|
55
|
-
allow(HTTParty::Parser).to receive_messages(supported_formats: [:json])
|
56
|
-
expect(HTTParty::Parser.supports_format?(:json)).to be_truthy
|
57
|
-
end
|
58
|
-
|
59
|
-
it "returns false for an unsupported format" do
|
60
|
-
allow(HTTParty::Parser).to receive_messages(supported_formats: [])
|
61
|
-
expect(HTTParty::Parser.supports_format?(:json)).to be_falsey
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "#parse" do
|
66
|
-
it "attempts to parse supported formats" do
|
67
|
-
parser = HTTParty::Parser.new('body', :json)
|
68
|
-
allow(parser).to receive_messages(supports_format?: true)
|
69
|
-
|
70
|
-
expect(parser).to receive(:parse_supported_format)
|
71
|
-
parser.parse
|
72
|
-
end
|
73
|
-
|
74
|
-
it "returns the unparsed body when the format is unsupported" do
|
75
|
-
parser = HTTParty::Parser.new('body', :json)
|
76
|
-
allow(parser).to receive_messages(supports_format?: false)
|
77
|
-
|
78
|
-
expect(parser.parse).to eq(parser.body)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "returns nil for an empty body" do
|
82
|
-
parser = HTTParty::Parser.new('', :json)
|
83
|
-
expect(parser.parse).to be_nil
|
84
|
-
end
|
85
|
-
|
86
|
-
it "returns nil for a nil body" do
|
87
|
-
parser = HTTParty::Parser.new(nil, :json)
|
88
|
-
expect(parser.parse).to be_nil
|
89
|
-
end
|
90
|
-
|
91
|
-
it "returns nil for a 'null' body" do
|
92
|
-
parser = HTTParty::Parser.new("null", :json)
|
93
|
-
expect(parser.parse).to be_nil
|
94
|
-
end
|
95
|
-
|
96
|
-
it "returns nil for a body with spaces only" do
|
97
|
-
parser = HTTParty::Parser.new(" ", :json)
|
98
|
-
expect(parser.parse).to be_nil
|
99
|
-
end
|
100
|
-
|
101
|
-
it "does not raise exceptions for bodies with invalid encodings" do
|
102
|
-
parser = HTTParty::Parser.new("\x80", :invalid_format)
|
103
|
-
expect(parser.parse).to_not be_nil
|
104
|
-
end
|
105
|
-
|
106
|
-
it "ignores utf-8 bom" do
|
107
|
-
parser = HTTParty::Parser.new("\xEF\xBB\xBF\{\"hi\":\"yo\"\}", :json)
|
108
|
-
expect(parser.parse).to eq({"hi"=>"yo"})
|
109
|
-
end
|
110
|
-
|
111
|
-
it "parses ascii 8bit encoding" do
|
112
|
-
parser = HTTParty::Parser.new(
|
113
|
-
"{\"currency\":\"\xE2\x82\xAC\"}".force_encoding('ASCII-8BIT'),
|
114
|
-
:json
|
115
|
-
)
|
116
|
-
expect(parser.parse).to eq({"currency" => "€"})
|
117
|
-
end
|
118
|
-
|
119
|
-
it "parses frozen strings" do
|
120
|
-
parser = HTTParty::Parser.new('{"a":1}'.freeze, :json)
|
121
|
-
expect(parser.parse).to eq("a" => 1)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe "#supports_format?" do
|
126
|
-
it "utilizes the class method to determine if the format is supported" do
|
127
|
-
expect(HTTParty::Parser).to receive(:supports_format?).with(:json)
|
128
|
-
parser = HTTParty::Parser.new('body', :json)
|
129
|
-
parser.send(:supports_format?)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
describe "#parse_supported_format" do
|
134
|
-
it "calls the parser for the given format" do
|
135
|
-
parser = HTTParty::Parser.new('body', :json)
|
136
|
-
expect(parser).to receive(:json)
|
137
|
-
parser.send(:parse_supported_format)
|
138
|
-
end
|
139
|
-
|
140
|
-
context "when a parsing method does not exist for the given format" do
|
141
|
-
it "raises an exception" do
|
142
|
-
parser = HTTParty::Parser.new('body', :atom)
|
143
|
-
expect do
|
144
|
-
parser.send(:parse_supported_format)
|
145
|
-
end.to raise_error(NotImplementedError, "HTTParty::Parser has not implemented a parsing method for the :atom format.")
|
146
|
-
end
|
147
|
-
|
148
|
-
it "raises a useful exception message for subclasses" do
|
149
|
-
atom_parser = Class.new(HTTParty::Parser) do
|
150
|
-
def self.name
|
151
|
-
'AtomParser'
|
152
|
-
end
|
153
|
-
end
|
154
|
-
parser = atom_parser.new 'body', :atom
|
155
|
-
expect do
|
156
|
-
parser.send(:parse_supported_format)
|
157
|
-
end.to raise_error(NotImplementedError, "AtomParser has not implemented a parsing method for the :atom format.")
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
context "parsers" do
|
163
|
-
subject do
|
164
|
-
HTTParty::Parser.new('body', nil)
|
165
|
-
end
|
166
|
-
|
167
|
-
it "parses xml with MultiXml" do
|
168
|
-
expect(MultiXml).to receive(:parse).with('body')
|
169
|
-
subject.send(:xml)
|
170
|
-
end
|
171
|
-
|
172
|
-
it "parses json with JSON" do
|
173
|
-
expect(JSON).to receive(:parse).with('body', :quirks_mode => true, :allow_nan => true)
|
174
|
-
subject.send(:json)
|
175
|
-
end
|
176
|
-
|
177
|
-
it "parses html by simply returning the body" do
|
178
|
-
expect(subject.send(:html)).to eq('body')
|
179
|
-
end
|
180
|
-
|
181
|
-
it "parses plain text by simply returning the body" do
|
182
|
-
expect(subject.send(:plain)).to eq('body')
|
183
|
-
end
|
184
|
-
|
185
|
-
it "parses csv with CSV" do
|
186
|
-
expect(CSV).to receive(:parse).with('body')
|
187
|
-
subject.send(:csv)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|