rets 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/Manifest.txt +0 -1
- data/Rakefile +7 -1
- data/bin/rets +13 -5
- data/lib/rets.rb +32 -11
- data/lib/rets/client.rb +110 -299
- data/lib/rets/metadata/resource.rb +1 -1
- data/lib/rets/metadata/table.rb +1 -0
- data/lib/rets/parser/compact.rb +11 -1
- data/lib/rets/parser/multipart.rb +11 -12
- data/test/fixtures.rb +12 -0
- data/test/helper.rb +4 -4
- data/test/test_client.rb +29 -431
- data/test/test_locking_http_client.rb +29 -0
- data/test/test_metadata.rb +7 -2
- data/test/test_parser_compact.rb +13 -3
- data/test/test_parser_multipart.rb +5 -5
- metadata +17 -11
- data/lib/rets/authentication.rb +0 -57
data/lib/rets/metadata/table.rb
CHANGED
data/lib/rets/parser/compact.rb
CHANGED
@@ -17,7 +17,12 @@ module Rets
|
|
17
17
|
raise InvalidDelimiter, "Empty or invalid delimiter found, unable to parse."
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
column_node = doc.at("//COLUMNS")
|
21
|
+
if column_node.nil?
|
22
|
+
columns = ''
|
23
|
+
else
|
24
|
+
columns = column_node.text
|
25
|
+
end
|
21
26
|
rows = doc.xpath("//DATA")
|
22
27
|
|
23
28
|
rows.map do |data|
|
@@ -41,6 +46,11 @@ module Rets
|
|
41
46
|
hash = Hash[*zipped_key_values.flatten]
|
42
47
|
hash.reject { |key, value| key.empty? && value.to_s.empty? }
|
43
48
|
end
|
49
|
+
|
50
|
+
def self.get_count(xml)
|
51
|
+
doc = Nokogiri.parse(xml.to_s)
|
52
|
+
doc.at("//COUNT").attr('Records').to_i
|
53
|
+
end
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
@@ -5,29 +5,28 @@ module Rets
|
|
5
5
|
class Multipart
|
6
6
|
CRLF = "\r\n"
|
7
7
|
WSP = "\s"
|
8
|
-
|
9
8
|
HEADER_LINE = /^([!-9;-~]+:\s*.+)$/
|
10
9
|
|
11
10
|
Part = Struct.new(:headers, :body)
|
12
11
|
|
13
12
|
def self.parse(raw, boundary)
|
14
13
|
parts = []
|
15
|
-
|
16
14
|
boundary_regexp = /--#{Regexp.quote(boundary)}(--)?#{CRLF}/
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
header_part, body_part = chunk.split(/#{CRLF}#{WSP}*#{CRLF}/m, 2)
|
16
|
+
# WTF some RETS servers declare response body including jpeg binary is encoded in utf8
|
17
|
+
raw.force_encoding 'ascii-8bit' if raw.respond_to?(:force_encoding)
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
headers = Hash[*headers.flatten]
|
19
|
+
raw.split(boundary_regexp).each do |chunk|
|
20
|
+
header_part, body_part = chunk.split(/#{CRLF}#{WSP}*#{CRLF}/m, 2)
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
if header_part =~ HEADER_LINE
|
23
|
+
headers = header_part.split(/\r\n/).map { |kv| p = kv.split(/:\s?/); [p[0].downcase, p[1..-1].join(':')] }
|
24
|
+
headers = Hash[*headers.flatten]
|
25
|
+
parts << Part.new(headers, body_part)
|
26
|
+
else
|
27
|
+
next # not a valid chunk.
|
30
28
|
end
|
29
|
+
end
|
31
30
|
check_for_invalids_parts!(parts)
|
32
31
|
parts
|
33
32
|
end
|
data/test/fixtures.rb
CHANGED
@@ -21,6 +21,12 @@ CAPABILITIES = <<-XML
|
|
21
21
|
</RETS>
|
22
22
|
XML
|
23
23
|
|
24
|
+
COUNT_ONLY = <<XML
|
25
|
+
<RETS ReplyCode="0" ReplyText="Success">
|
26
|
+
<COUNT Records="1234" />
|
27
|
+
</RETS>
|
28
|
+
XML
|
29
|
+
|
24
30
|
CAPABILITIES_WITH_WHITESPACE = <<XML
|
25
31
|
<RETS ReplyCode="0" ReplyText="Operation Successful">
|
26
32
|
<RETS-RESPONSE>
|
@@ -49,6 +55,12 @@ COMPACT = <<-XML
|
|
49
55
|
</METADATA>
|
50
56
|
XML
|
51
57
|
|
58
|
+
|
59
|
+
EMPTY_COMPACT = <<-XML
|
60
|
+
<METADATA-TABLE Resource="OpenHouse" Class="OpenHouse" Version="01.01.00000" Date="2011-07-29T12:09:16">
|
61
|
+
</METADATA-TABLE>
|
62
|
+
XML
|
63
|
+
|
52
64
|
METADATA_UNKNOWN = <<-XML
|
53
65
|
<?xml version="1.0"?>
|
54
66
|
<RETS ReplyCode="0" ReplyText="Operation successful.">
|
data/test/helper.rb
CHANGED
data/test/test_client.rb
CHANGED
@@ -1,141 +1,11 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestClient < Test
|
3
|
+
class TestClient < MiniTest::Test
|
4
4
|
|
5
5
|
def setup
|
6
6
|
@client = Rets::Client.new(:login_url => "http://example.com/login")
|
7
7
|
end
|
8
8
|
|
9
|
-
def test_initialize_adds_escaped_username_to_uri
|
10
|
-
client = Rets::Client.new(
|
11
|
-
:login_url => "http://example.com",
|
12
|
-
:username => "bob@example.com")
|
13
|
-
|
14
|
-
assert_equal CGI.escape("bob@example.com"), client.login_uri.user
|
15
|
-
assert_nil client.login_uri.password
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_initialize_adds_escaped_password_to_uri
|
19
|
-
client = Rets::Client.new(
|
20
|
-
:login_url => "http://example.com",
|
21
|
-
:username => "bob",
|
22
|
-
:password => "secret@2!")
|
23
|
-
|
24
|
-
assert_equal CGI.escape("secret@2!"), client.login_uri.password
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_initialize_merges_default_options
|
28
|
-
client = Rets::Client.new(:login_url => "http://example.com", :foo => true)
|
29
|
-
|
30
|
-
assert client.options.include?(:foo)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_initialize_allows_default_options_to_be_overridden
|
34
|
-
assert Rets::Client::DEFAULT_OPTIONS.include?(:persistent)
|
35
|
-
|
36
|
-
client = Rets::Client.new(:login_url => "http://example.com")
|
37
|
-
assert_equal true, client.options[:persistent]
|
38
|
-
|
39
|
-
client = Rets::Client.new(:login_url => "http://example.com", :persistent => false)
|
40
|
-
assert_equal false, client.options[:persistent]
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def test_connection_uses_persistent
|
45
|
-
assert_kind_of Net::HTTP::Persistent, @client.connection
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_connection_uses_net_http
|
49
|
-
client = Rets::Client.new(:login_url => "http://example.com", :persistent => false)
|
50
|
-
|
51
|
-
assert_kind_of Net::HTTP, client.connection
|
52
|
-
assert_equal "example.com", client.connection.address
|
53
|
-
assert_equal 80, client.connection.port
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def test_request
|
58
|
-
post = mock()
|
59
|
-
post.expects(:body=).with("fake body")
|
60
|
-
|
61
|
-
headers = @client.build_headers('path')
|
62
|
-
|
63
|
-
Net::HTTP::Post.expects(:new).with("/foo", headers).returns(post)
|
64
|
-
|
65
|
-
@client.connection.expects(:request).with(@client.login_uri, post).returns(stub_everything)
|
66
|
-
|
67
|
-
@client.expects(:handle_cookies)
|
68
|
-
@client.expects(:handle_response)
|
69
|
-
|
70
|
-
@client.stubs(:format_headers)
|
71
|
-
|
72
|
-
@client.request("/foo", "fake body")
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_request_with_block
|
76
|
-
# TODO
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_request_passes_correct_arguments_to_persistent_connection
|
80
|
-
@client.connection.expects(:request).with(@client.login_uri, instance_of(Net::HTTP::Post)).returns(stub_everything)
|
81
|
-
|
82
|
-
@client.stubs(:handle_cookies)
|
83
|
-
@client.stubs(:handle_response)
|
84
|
-
@client.stubs(:format_headers)
|
85
|
-
|
86
|
-
@client.request("/foo")
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_request_passes_correct_arguments_to_net_http_connection
|
90
|
-
client = Rets::Client.new(:login_url => "http://example.com", :persistent => false)
|
91
|
-
|
92
|
-
client.connection.expects(:request).with(instance_of(Net::HTTP::Post)).returns(stub_everything)
|
93
|
-
|
94
|
-
client.stubs(:handle_cookies)
|
95
|
-
client.stubs(:handle_response)
|
96
|
-
client.stubs(:format_headers)
|
97
|
-
|
98
|
-
client.request("/foo")
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_handle_response_handles_rets_errors
|
102
|
-
response = Net::HTTPSuccess.new("", "", "")
|
103
|
-
response.stubs(:body => RETS_ERROR)
|
104
|
-
|
105
|
-
assert_raise Rets::InvalidRequest do
|
106
|
-
@client.handle_response(response)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_handle_response_handles_rets_valid_response
|
111
|
-
response = Net::HTTPSuccess.new("", "", "")
|
112
|
-
response.stubs(:body => RETS_REPLY)
|
113
|
-
|
114
|
-
assert_equal response, @client.handle_response(response)
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_handle_response_handles_empty_responses
|
118
|
-
response = Net::HTTPSuccess.new("", "", "")
|
119
|
-
response.stubs(:body => "")
|
120
|
-
|
121
|
-
assert_equal response, @client.handle_response(response)
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_handle_response_handles_non_xml_responses
|
125
|
-
response = Net::HTTPSuccess.new("", "", "")
|
126
|
-
response.stubs(:body => "<notxml")
|
127
|
-
|
128
|
-
assert_equal response, @client.handle_response(response)
|
129
|
-
end
|
130
|
-
|
131
|
-
def test_handle_response_raises_on_unknown_response_code
|
132
|
-
response = Net::HTTPServerError.new("", "", "")
|
133
|
-
|
134
|
-
assert_raise Rets::UnknownResponse do
|
135
|
-
assert_equal response, @client.handle_response(response)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
9
|
def test_extract_capabilities
|
140
10
|
assert_equal(
|
141
11
|
{"abc" => "123", "def" => "ghi=jk"},
|
@@ -151,17 +21,9 @@ class TestClient < Test::Unit::TestCase
|
|
151
21
|
end
|
152
22
|
|
153
23
|
def test_capability_url_returns_parsed_url
|
154
|
-
@client.capabilities = { "foo" => "
|
155
|
-
|
156
|
-
assert_equal URI.parse("http://example.com"), @client.capability_url("foo")
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_capability_url_raises_on_malformed_url
|
160
|
-
@client.capabilities = { "foo" => "http://e$^&#$&xample.com" }
|
24
|
+
@client.capabilities = { "foo" => "/foo" }
|
161
25
|
|
162
|
-
|
163
|
-
@client.capability_url("foo")
|
164
|
-
end
|
26
|
+
assert_equal "http://example.com/foo", @client.capability_url("foo")
|
165
27
|
end
|
166
28
|
|
167
29
|
def test_capabilities_calls_login_when_nil
|
@@ -169,157 +31,11 @@ class TestClient < Test::Unit::TestCase
|
|
169
31
|
@client.capabilities
|
170
32
|
end
|
171
33
|
|
172
|
-
def test_login_fails_if_cannot_read_capabilities
|
173
|
-
response = Net::HTTPSuccess.new("", "", "")
|
174
|
-
response.stubs(:body => RETS_REPLY)
|
175
|
-
@client.stubs(:request).returns(response)
|
176
|
-
@client.stubs(:extract_capabilities)
|
177
|
-
assert_raise Rets::UnknownResponse do
|
178
|
-
@client.login
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def test_cookies?
|
183
|
-
assert @client.cookies?({"set-cookie" => "FavoriteFruit=Plum;"})
|
184
|
-
assert !@client.cookies?({})
|
185
|
-
end
|
186
|
-
|
187
|
-
def test_cookies=
|
188
|
-
@client.cookies = ["abc=123; path=/; HttpOnly", "def=456;", "ghi=789"]
|
189
|
-
|
190
|
-
assert_equal(
|
191
|
-
{"abc" => "123", "def" => "456", "ghi" => "789"},
|
192
|
-
@client.instance_variable_get("@cookies")
|
193
|
-
)
|
194
|
-
|
195
|
-
@client.cookies = ["abc=111; blah", "zzz=123"]
|
196
|
-
|
197
|
-
assert_equal(
|
198
|
-
{"abc" => "111", "def" => "456", "ghi" => "789", "zzz" => "123"},
|
199
|
-
@client.instance_variable_get("@cookies")
|
200
|
-
)
|
201
|
-
end
|
202
|
-
|
203
|
-
def test_cookies
|
204
|
-
# Set an array instead of hash for predictable iteration and string construction
|
205
|
-
@client.instance_variable_set("@cookies", [%w(abc 123), %w(def 456)])
|
206
|
-
|
207
|
-
assert_equal "abc=123; def=456", @client.cookies
|
208
|
-
end
|
209
|
-
|
210
|
-
|
211
|
-
def test_build_headers_provides_basic_headers
|
212
|
-
assert_equal({
|
213
|
-
"User-Agent" => "Client/1.0",
|
214
|
-
"Host" => "example.com:80",
|
215
|
-
"RETS-Version" => "RETS/1.7.2"},
|
216
|
-
@client.build_headers('path'))
|
217
|
-
end
|
218
|
-
|
219
|
-
def test_build_headers_provides_authorization
|
220
|
-
@client.expects(:authorization).returns("Just trust me")
|
221
|
-
|
222
|
-
assert_equal({
|
223
|
-
"Authorization" => "Just trust me",
|
224
|
-
"User-Agent" => "Client/1.0",
|
225
|
-
"Host" => "example.com:80",
|
226
|
-
"RETS-Version" => "RETS/1.7.2"},
|
227
|
-
@client.build_headers('path'))
|
228
|
-
end
|
229
|
-
|
230
|
-
def test_build_headers_provides_cookies
|
231
|
-
@client.cookies = ["Allowed=totally"]
|
232
|
-
|
233
|
-
assert_equal({
|
234
|
-
"Cookie" => "Allowed=totally",
|
235
|
-
"User-Agent" => "Client/1.0",
|
236
|
-
"Host" => "example.com:80",
|
237
|
-
"RETS-Version" => "RETS/1.7.2"},
|
238
|
-
@client.build_headers('path'))
|
239
|
-
end
|
240
|
-
|
241
|
-
|
242
34
|
def test_tries_increments_with_each_call
|
243
35
|
assert_equal 1, @client.tries
|
244
36
|
assert_equal 2, @client.tries
|
245
37
|
end
|
246
38
|
|
247
|
-
def test_build_auth
|
248
|
-
www_authenticate =
|
249
|
-
%q(Digest realm="EXAMPLE", nonce="aec306b318feef4c360bc986e06d0a71", opaque="4211001cd29d5a65b3ed99f766a896b0", qop="auth")
|
250
|
-
|
251
|
-
uri = URI.parse("http://bob:secret@example.com/login")
|
252
|
-
|
253
|
-
Digest::MD5.stubs(:hexdigest => "heeheehee")
|
254
|
-
|
255
|
-
expected = <<-DIGEST.gsub(/\n/, "")
|
256
|
-
Digest username="bob", realm="EXAMPLE", qop="auth", uri="/login", nonce="aec306b318feef4c360bc986e06d0a71",
|
257
|
-
nc=00000000, cnonce="heeheehee", response="heeheehee", opaque="4211001cd29d5a65b3ed99f766a896b0"
|
258
|
-
DIGEST
|
259
|
-
|
260
|
-
assert_equal expected, @client.build_auth(www_authenticate, uri)
|
261
|
-
end
|
262
|
-
|
263
|
-
def test_calculate_digest_with_qop
|
264
|
-
Digest::MD5.expects(:hexdigest).with("bob:example:secret").returns("a1")
|
265
|
-
Digest::MD5.expects(:hexdigest).with("POST:/login").returns("a2")
|
266
|
-
|
267
|
-
Digest::MD5.expects(:hexdigest).with("a1:nonce:00000001:cnonce:qop:a2")
|
268
|
-
|
269
|
-
@client.calculate_digest("bob", "secret", "example", "nonce", "POST", URI.parse("/login"), "qop", "cnonce", 1)
|
270
|
-
end
|
271
|
-
|
272
|
-
def test_calculate_digest_without_qop
|
273
|
-
Digest::MD5.expects(:hexdigest).with("bob:example:secret").returns("a1")
|
274
|
-
Digest::MD5.expects(:hexdigest).with("POST:/login").returns("a2")
|
275
|
-
|
276
|
-
Digest::MD5.expects(:hexdigest).with("a1:nonce:a2").returns("hash")
|
277
|
-
|
278
|
-
assert_equal "hash",
|
279
|
-
@client.calculate_digest("bob", "secret", "example", "nonce", "POST", URI.parse("/login"), nil, "cnonce", 1)
|
280
|
-
end
|
281
|
-
|
282
|
-
def test_calculate_user_agent_digest
|
283
|
-
Digest::MD5.expects(:hexdigest).with("agent:secret").returns("a1")
|
284
|
-
Digest::MD5.expects(:hexdigest).with("a1::session:version").returns("hash")
|
285
|
-
|
286
|
-
assert_equal "hash",
|
287
|
-
@client.calculate_user_agent_digest("agent", "secret", '', "session", "version")
|
288
|
-
end
|
289
|
-
|
290
|
-
|
291
|
-
def test_session_restores_state
|
292
|
-
session = Rets::Session.new({:digest => 'true'}, {"Foo" => "/foo"}, "sessionid=123")
|
293
|
-
|
294
|
-
@client.session = session
|
295
|
-
|
296
|
-
assert_equal({:digest => 'true'}, @client.auth_digest)
|
297
|
-
assert_equal({"Foo" => "/foo"}, @client.capabilities)
|
298
|
-
assert_equal("sessionid=123", @client.cookies)
|
299
|
-
end
|
300
|
-
|
301
|
-
def test_session_dumps_state
|
302
|
-
@client.auth_digest = {:digest => 'true'}
|
303
|
-
@client.capabilities = {"Foo" => "/foo"}
|
304
|
-
@client.cookies = "session-id=123"
|
305
|
-
|
306
|
-
session = @client.session
|
307
|
-
|
308
|
-
assert_equal({:digest => 'true'}, session.auth_digest)
|
309
|
-
assert_equal({"Foo" => "/foo"}, session.capabilities)
|
310
|
-
assert_equal("session-id=123", session.cookies)
|
311
|
-
end
|
312
|
-
|
313
|
-
def test_initialize_with_session_restores_state
|
314
|
-
session = Rets::Session.new({:digest => true}, {"Foo" => "/foo"}, "sessionid=123")
|
315
|
-
|
316
|
-
client = Rets::Client.new(:login_url => "http://example.com", :session => session)
|
317
|
-
|
318
|
-
assert_equal({:digest => true}, client.auth_digest)
|
319
|
-
assert_equal({"Foo" => "/foo"}, client.capabilities)
|
320
|
-
assert_equal("sessionid=123", client.cookies)
|
321
|
-
end
|
322
|
-
|
323
39
|
def test_metadata_when_not_initialized_with_metadata
|
324
40
|
client = Rets::Client.new(:login_url => "http://example.com")
|
325
41
|
Rets::Metadata::Root.expects(:new)
|
@@ -356,99 +72,49 @@ DIGEST
|
|
356
72
|
|
357
73
|
def test_default_logger_returns_api_compatible_silent_logger
|
358
74
|
logger = @client.logger
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
logger.info "foo"
|
365
|
-
logger.debug "foo"
|
366
|
-
end
|
75
|
+
logger.fatal "foo"
|
76
|
+
logger.error "foo"
|
77
|
+
logger.warn "foo"
|
78
|
+
logger.info "foo"
|
79
|
+
logger.debug "foo"
|
367
80
|
end
|
368
81
|
|
369
82
|
|
370
83
|
def test_find_first_calls_find_every_with_limit_one
|
371
|
-
@client.expects(:find_every).with(:limit => 1, :foo => :bar).returns([1,2,3])
|
84
|
+
@client.expects(:find_every).with({:limit => 1, :foo => :bar}, nil).returns([1,2,3])
|
372
85
|
|
373
86
|
assert_equal 1, @client.find(:first, :foo => :bar, :limit => 5), "User-specified limit should be ignored"
|
374
87
|
end
|
375
88
|
|
376
89
|
def test_find_all_calls_find_every
|
377
|
-
@client.expects(:find_every).with(:limit => 5, :foo => :bar).returns([1,2,3])
|
90
|
+
@client.expects(:find_every).with({:limit => 5, :foo => :bar}, nil).returns([1,2,3])
|
378
91
|
|
379
92
|
assert_equal [1,2,3], @client.find(:all, :limit => 5, :foo => :bar)
|
380
93
|
end
|
381
94
|
|
382
95
|
def test_find_raises_on_unknown_quantity
|
383
|
-
|
96
|
+
assert_raises ArgumentError do
|
384
97
|
@client.find(:incorrect, :foo => :bar)
|
385
98
|
end
|
386
99
|
end
|
387
100
|
|
388
101
|
def test_find_retries_on_errors
|
389
|
-
@client.stubs(:find_every).raises(Rets::AuthorizationFailure).then.raises(Rets::InvalidRequest).then.returns([])
|
102
|
+
@client.stubs(:find_every).raises(Rets::AuthorizationFailure.new(401, 'Not Authorized')).then.raises(Rets::InvalidRequest.new(20134, 'Not Found')).then.returns([])
|
390
103
|
@client.find(:all, :foo => :bar)
|
391
104
|
end
|
392
105
|
|
106
|
+
def test_find_retries_on_errors_preserves_resolve
|
107
|
+
@client.stubs(:find_every).raises(Rets::AuthorizationFailure.new(401, 'Not Authorized')).then.raises(Rets::InvalidRequest.new(20134, 'Not Found')).then.with({:foo => :bar}, true).returns([])
|
108
|
+
@client.find(:all, {:foo => :bar, :resolve => true})
|
109
|
+
end
|
110
|
+
|
393
111
|
def test_find_eventually_reraises_errors
|
394
|
-
@client.stubs(:find_every).raises(Rets::AuthorizationFailure)
|
395
|
-
|
112
|
+
@client.stubs(:find_every).raises(Rets::AuthorizationFailure.new(401, 'Not Authorized'))
|
113
|
+
assert_raises Rets::AuthorizationFailure do
|
396
114
|
@client.find(:all, :foo => :bar)
|
397
115
|
end
|
398
116
|
end
|
399
117
|
|
400
|
-
def test_find_provides_default_values
|
401
|
-
@client.expects(:build_key_values).
|
402
|
-
with("QueryType" => "DMQL2", "Format" => "COMPACT", "Query" => "x", "Foo" => "bar").
|
403
|
-
returns("xxx")
|
404
|
-
|
405
|
-
@client.stubs(:capability_url => URI.parse("/example"))
|
406
|
-
@client.stubs(:request_with_compact_response)
|
407
|
-
|
408
|
-
@client.find(:all, :query => "x", :foo => "bar")
|
409
|
-
end
|
410
|
-
|
411
|
-
def test_find_allows_defaults_to_be_overridden
|
412
|
-
@client.expects(:build_key_values).
|
413
|
-
with("QueryType" => "DMQL3000", "Format" => "COMPACT", "Query" => "x", "Foo" => "bar").
|
414
|
-
returns("xxx")
|
415
|
-
|
416
|
-
@client.stubs(:capability_url => URI.parse("/example"))
|
417
|
-
@client.stubs(:request_with_compact_response)
|
418
|
-
|
419
|
-
@client.find(:all, :query => "x", :foo => "bar", :query_type => "DMQL3000")
|
420
|
-
end
|
421
|
-
|
422
|
-
def test_find_returns_undecorated_results
|
423
|
-
@client.stubs(:capability_url => URI.parse("/example"))
|
424
|
-
|
425
|
-
@client.expects(:request_with_compact_response).
|
426
|
-
with("/example", instance_of(String), instance_of(Hash)).
|
427
|
-
returns([["foo", "bar"]])
|
428
|
-
|
429
|
-
results = @client.find(:all, :search_type => "Property", :class => "Res", :query => "x", :foo => "bar")
|
430
|
-
|
431
|
-
assert_equal [["foo", "bar"]], results
|
432
|
-
end
|
433
|
-
|
434
|
-
def test_find_returns_decorated_results
|
435
|
-
@client.stubs(:capability_url => URI.parse("/example"))
|
436
|
-
|
437
|
-
@client.expects(:request_with_compact_response).
|
438
|
-
with("/example", instance_of(String), instance_of(Hash)).
|
439
|
-
returns([["foo", "bar"]])
|
440
|
-
|
441
|
-
fake_rets_class = stub(:rets_class)
|
442
|
-
fake_result = stub(:result)
|
443
|
-
|
444
|
-
@client.expects(:find_rets_class).with("Property", "Res").returns(fake_rets_class)
|
445
|
-
@client.expects(:decorate_results).with([["foo", "bar"]], fake_rets_class).returns(fake_result)
|
446
|
-
|
447
|
-
results = @client.find(:all, :search_type => "Property", :class => "Res", :query => "x", :foo => "bar", :resolve => true)
|
448
|
-
|
449
|
-
assert_equal fake_result, results
|
450
|
-
end
|
451
|
-
|
452
118
|
def test_fixup_keys
|
453
119
|
assert_equal({ "Foo" => "bar" }, @client.fixup_keys(:foo => "bar"))
|
454
120
|
assert_equal({ "FooFoo" => "bar" }, @client.fixup_keys(:foo_foo => "bar"))
|
@@ -474,49 +140,15 @@ DIGEST
|
|
474
140
|
@client.objects([1,2], :foo => :bar)
|
475
141
|
end
|
476
142
|
|
477
|
-
def test_unauthorized_session
|
478
|
-
session = Rets::Session.new(
|
479
|
-
"Digest username=\"login\", realm=\"fake_realm\", qop=\"auth\", uri=\"/Login.asmx/Login\", nonce=\"a8f4bc805062602c8ba7a87b2109f808\", nc=00000001, cnonce=\"6e2dd038eea6cbacf0b956fd11f914b6\", response=\"fake_digest\", opaque=\"96eda461-41d0-4624-b7fe-b59e966035f3\"",
|
480
|
-
{
|
481
|
-
"GetObject"=>"/GetObject.asmx/GetObject",
|
482
|
-
"GetMetadata"=>"/GetMetadata.asmx/GetMetadata",
|
483
|
-
"Login"=>"/Login.asmx/Login",
|
484
|
-
"metadatatimestamp"=>"2012-07-17T16:34:22Z",
|
485
|
-
"user"=>"23756,60,RH,login",
|
486
|
-
"Search"=>"/Search.asmx/Search",
|
487
|
-
"timeoutseconds"=>"7200"
|
488
|
-
},
|
489
|
-
"ASP.NET_SessionId=mapij045k3bphj3gqqgpmmrx; RETS-Session-ID=mapij045k3bphj3gqqgpmmrx"
|
490
|
-
)
|
491
|
-
opts = {
|
492
|
-
:username => 'login',
|
493
|
-
:password => 'Bn1X@y4L',
|
494
|
-
:login_url => 'http://rets.example.com/Login.asmx/Login',
|
495
|
-
:agent => 'Estately/1.0',
|
496
|
-
:persistent => false,
|
497
|
-
:session => session
|
498
|
-
}
|
499
|
-
client = Rets::Client.new(opts)
|
500
|
-
response = nil
|
501
|
-
VCR.use_cassette('unauthorized_response') do
|
502
|
-
response = client.objects("1",
|
503
|
-
:resource => 'Property',
|
504
|
-
:object_type => 'Photo',
|
505
|
-
:resource_id => '2661580'
|
506
|
-
)
|
507
|
-
end
|
508
|
-
assert_equal 'image/jpeg', response.first.headers['content-type']
|
509
|
-
end
|
510
|
-
|
511
|
-
|
512
143
|
def test_objects_raises_on_other_arguments
|
513
|
-
|
144
|
+
assert_raises ArgumentError do
|
514
145
|
@client.objects(Object.new, :foo => :bar)
|
515
146
|
end
|
516
147
|
end
|
517
148
|
|
518
149
|
def test_create_parts_from_response_returns_multiple_parts_when_multipart_response
|
519
|
-
response = {
|
150
|
+
response = {}
|
151
|
+
response.stubs(:header => { "content-type" => ['multipart; boundary="simple boundary"']})
|
520
152
|
response.stubs(:body => MULITPART_RESPONSE)
|
521
153
|
|
522
154
|
Rets::Parser::Multipart.expects(:parse).
|
@@ -527,7 +159,8 @@ DIGEST
|
|
527
159
|
end
|
528
160
|
|
529
161
|
def test_parse_boundary_wo_quotes
|
530
|
-
response = {
|
162
|
+
response = {}
|
163
|
+
response.stubs(:header => { "content-type" => ['multipart; boundary=simple boundary; foo;']})
|
531
164
|
response.stubs(:body => MULITPART_RESPONSE)
|
532
165
|
|
533
166
|
Rets::Parser::Multipart.expects(:parse).
|
@@ -538,7 +171,9 @@ DIGEST
|
|
538
171
|
end
|
539
172
|
|
540
173
|
def test_create_parts_from_response_returns_a_single_part_when_not_multipart_response
|
541
|
-
response = {
|
174
|
+
response = {}
|
175
|
+
response.stubs(:header => { "content-type" => ['text/plain']})
|
176
|
+
response.stubs(:headers => { "content-type" => ['text/plain']})
|
542
177
|
response.stubs(:body => "fakebody")
|
543
178
|
|
544
179
|
parts = @client.create_parts_from_response(response)
|
@@ -547,7 +182,7 @@ DIGEST
|
|
547
182
|
|
548
183
|
part = parts.first
|
549
184
|
|
550
|
-
assert_equal
|
185
|
+
assert_equal "text/plain", part.headers["content-type"]
|
551
186
|
assert_equal "fakebody", part.body
|
552
187
|
end
|
553
188
|
|
@@ -559,26 +194,6 @@ DIGEST
|
|
559
194
|
assert_equal "foo", @client.object("1", :foo => :bar)
|
560
195
|
end
|
561
196
|
|
562
|
-
def test_fetch_object
|
563
|
-
@client.expects(:capability_url).with("GetObject").returns(URI.parse("/obj"))
|
564
|
-
|
565
|
-
@client.expects(:build_key_values => "fakebody").with(
|
566
|
-
"Resource" => "Property",
|
567
|
-
"Type" => "Image",
|
568
|
-
"ID" => "123:*",
|
569
|
-
"Location" => 0
|
570
|
-
)
|
571
|
-
|
572
|
-
@client.expects(:request).with("/obj", "fakebody",
|
573
|
-
has_entries(
|
574
|
-
"Accept" => "image/jpeg, image/png;q=0.5, image/gif;q=0.1",
|
575
|
-
"Content-Type" => "application/x-www-form-urlencoded",
|
576
|
-
"Content-Length" => "8")
|
577
|
-
)
|
578
|
-
|
579
|
-
@client.fetch_object("*", :resource => "Property", :object_type => "Image", :resource_id => "123")
|
580
|
-
end
|
581
|
-
|
582
197
|
def test_metadata_caches
|
583
198
|
metadata = stub(:current? => true)
|
584
199
|
@client.metadata = metadata
|
@@ -587,23 +202,6 @@ DIGEST
|
|
587
202
|
assert_same metadata, @client.metadata, "Should be memoized"
|
588
203
|
end
|
589
204
|
|
590
|
-
def test_retrieve_metadata_type
|
591
|
-
@client.expects(:capability_url).with("GetMetadata").returns(URI.parse("/meta"))
|
592
|
-
|
593
|
-
@client.expects(:build_key_values => "fakebody").with(
|
594
|
-
"Format" => "COMPACT",
|
595
|
-
"Type" => "METADATA-FOO",
|
596
|
-
"ID" => "0"
|
597
|
-
)
|
598
|
-
|
599
|
-
@client.expects(:request => stub(:body => "response")).with("/meta", "fakebody", has_entries(
|
600
|
-
"Content-Type" => "application/x-www-form-urlencoded",
|
601
|
-
"Content-Length" => "8"
|
602
|
-
))
|
603
|
-
|
604
|
-
assert_equal "response", @client.retrieve_metadata_type("FOO")
|
605
|
-
end
|
606
|
-
|
607
205
|
def test_decorate_result_handles_bad_metadata
|
608
206
|
result = {'foo' => 'bar'}
|
609
207
|
rets_class = stub
|