rets 0.4.0 → 0.5.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.
- 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
|