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
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class TestLockingHttpClient < MiniTest::Test
|
4
|
+
def setup
|
5
|
+
@fake_client = stub('fake_client')
|
6
|
+
@locker = stub('locker')
|
7
|
+
@locking_client = Rets::LockingHttpClient.new(@fake_client, @locker, 'lock_name')
|
8
|
+
@url = "fake rets url"
|
9
|
+
@params = {'fake_param' => 'fake_param_value'}
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_locking_client_calls_the_real_client_if_lock_succeeds
|
13
|
+
@locker.stubs(:lock).with('lock_name', {}).yields(nil)
|
14
|
+
@fake_client.expects(:http_post).with(@url, @params, {})
|
15
|
+
@locking_client.http_post(@url, @params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_locking_client_does_nothing_if_lock_fails_to_yield
|
19
|
+
@fake_client.expects(:http_post).never
|
20
|
+
@locker.stubs(:lock).with('lock_name', {})
|
21
|
+
@locking_client.http_post(@url, @params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_locking_client_returns_result_from_client
|
25
|
+
@fake_client.stubs(:http_post).returns('result')
|
26
|
+
@locker.stubs(:lock).with('lock_name', {}).yields(nil)
|
27
|
+
assert_equal 'result', @locking_client.http_post(@url, @params)
|
28
|
+
end
|
29
|
+
end
|
data/test/test_metadata.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestMetadata < Test
|
3
|
+
class TestMetadata < MiniTest::Test
|
4
4
|
def setup
|
5
5
|
@root = Rets::Metadata::Root.new
|
6
|
+
$VERBOSE = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
$VERBOSE = false
|
6
11
|
end
|
7
12
|
|
8
13
|
def test_metadata_root_fetch_sources_returns_hash_of_metadata_types
|
data/test/test_parser_compact.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestParserCompact < Test
|
3
|
+
class TestParserCompact < MiniTest::Test
|
4
4
|
def test_parse_document_raises_on_invalid_delimiter
|
5
|
-
|
5
|
+
assert_raises Rets::Parser::Compact::InvalidDelimiter do
|
6
6
|
Rets::Parser::Compact.parse_document(INVALID_DELIMETER)
|
7
7
|
end
|
8
8
|
end
|
@@ -56,6 +56,16 @@ class TestParserCompact < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def test_parse_empty_document
|
60
|
+
rows = Rets::Parser::Compact.parse_document(EMPTY_COMPACT)
|
61
|
+
assert_equal [], rows
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_get_count
|
65
|
+
count = Rets::Parser::Compact.get_count(COUNT_ONLY)
|
66
|
+
assert_equal 1234, count
|
67
|
+
end
|
68
|
+
|
59
69
|
def test_parse_example
|
60
70
|
rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT))
|
61
71
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
|
-
class TestParserMultipart < Test
|
3
|
+
class TestParserMultipart < MiniTest::Test
|
4
4
|
def test_parse_returns_multiple_parts
|
5
5
|
headers = {"content-type"=>"image/jpeg", "content-id"=>"90020062739", "content-length"=>"10"}
|
6
6
|
|
@@ -18,12 +18,12 @@ class TestParserMultipart < Test::Unit::TestCase
|
|
18
18
|
assert_equal headers.merge("object-id" => "2"), part.headers
|
19
19
|
assert_equal "yyyyyyyy", part.body.strip
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def test_parse_real_mls_data
|
23
23
|
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
24
24
|
assert_equal 5, parts.size
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def test_parse_values_with_colon_data
|
28
28
|
parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
|
29
29
|
assert_equal 'http://foobarmls.com/RETS//MediaDisplay/98/hr2890998-1.jpg', parts[0].headers['location']
|
@@ -32,7 +32,7 @@ class TestParserMultipart < Test::Unit::TestCase
|
|
32
32
|
def test_parse_with_error
|
33
33
|
raw = "\r\n--89467f8e0c6b48158c8f1883910212ec\r\nContent-Type: text/xml\r\nContent-ID: foo\r\nObject-ID: *\r\n\r\n<RETS ReplyCode=\"20403\" ReplyText=\"No Object Found\" />\r\n\r\n--89467f8e0c6b48158c8f1883910212ec--\r\n"
|
34
34
|
boundary = "89467f8e0c6b48158c8f1883910212ec"
|
35
|
-
|
35
|
+
assert_raises Rets::InvalidRequest do
|
36
36
|
Rets::Parser::Multipart.parse(raw, boundary)
|
37
37
|
end
|
38
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,16 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-09-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: httpclient
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 2.3.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 2.3.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: nokogiri
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '4.0'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '4.0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: mocha
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
117
|
+
version: '3.6'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '3.
|
125
|
+
version: '3.6'
|
126
126
|
description: ! '[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
127
127
|
|
128
128
|
A pure-ruby library for fetching data from [RETS] servers.
|
@@ -135,7 +135,9 @@ executables:
|
|
135
135
|
- rets
|
136
136
|
extensions: []
|
137
137
|
extra_rdoc_files:
|
138
|
+
- CHANGELOG.md
|
138
139
|
- Manifest.txt
|
140
|
+
- README.md
|
139
141
|
files:
|
140
142
|
- CHANGELOG.md
|
141
143
|
- Manifest.txt
|
@@ -143,7 +145,6 @@ files:
|
|
143
145
|
- Rakefile
|
144
146
|
- bin/rets
|
145
147
|
- lib/rets.rb
|
146
|
-
- lib/rets/authentication.rb
|
147
148
|
- lib/rets/client.rb
|
148
149
|
- lib/rets/metadata.rb
|
149
150
|
- lib/rets/metadata/containers.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- test/test_metadata.rb
|
161
162
|
- test/test_parser_compact.rb
|
162
163
|
- test/test_parser_multipart.rb
|
164
|
+
- test/test_locking_http_client.rb
|
163
165
|
- .gemtest
|
164
166
|
homepage: http://github.com/estately/rets
|
165
167
|
licenses: []
|
@@ -175,6 +177,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
177
|
- - ! '>='
|
176
178
|
- !ruby/object:Gem::Version
|
177
179
|
version: '0'
|
180
|
+
segments:
|
181
|
+
- 0
|
182
|
+
hash: -2023944965655718483
|
178
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
184
|
none: false
|
180
185
|
requirements:
|
@@ -183,13 +188,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
188
|
version: '0'
|
184
189
|
requirements: []
|
185
190
|
rubyforge_project: rets
|
186
|
-
rubygems_version: 1.8.
|
191
|
+
rubygems_version: 1.8.23
|
187
192
|
signing_key:
|
188
193
|
specification_version: 3
|
189
194
|
summary: ! '[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
|
190
195
|
A pure-ruby library for fetching data from [RETS] servers'
|
191
196
|
test_files:
|
192
197
|
- test/test_client.rb
|
198
|
+
- test/test_locking_http_client.rb
|
193
199
|
- test/test_metadata.rb
|
194
200
|
- test/test_parser_compact.rb
|
195
201
|
- test/test_parser_multipart.rb
|
data/lib/rets/authentication.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Rets
|
2
|
-
# Adapted from dbrain's Net::HTTP::DigestAuth gem, and RETS4R auth
|
3
|
-
# in order to support RETS' usage of digest authentication.
|
4
|
-
module Authentication
|
5
|
-
def build_auth(digest_authenticate, uri, nc = 0, method = "POST")
|
6
|
-
user = CGI.unescape uri.user
|
7
|
-
password = CGI.unescape uri.password
|
8
|
-
|
9
|
-
digest_authenticate =~ /^(\w+) (.*)/
|
10
|
-
|
11
|
-
params = {}
|
12
|
-
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
13
|
-
|
14
|
-
cnonce = Digest::MD5.hexdigest "%x" % (Time.now.to_i + rand(65535))
|
15
|
-
|
16
|
-
digest = calculate_digest(
|
17
|
-
user, password, params['realm'], params['nonce'], method, uri.request_uri, params['qop'], cnonce, nc
|
18
|
-
)
|
19
|
-
|
20
|
-
header = [
|
21
|
-
%Q(Digest username="#{user}"),
|
22
|
-
%Q(realm="#{params['realm']}"),
|
23
|
-
%Q(qop="#{params['qop']}"),
|
24
|
-
%Q(uri="#{uri.request_uri}"),
|
25
|
-
%Q(nonce="#{params['nonce']}"),
|
26
|
-
%Q(nc=#{('%08x' % nc)}),
|
27
|
-
%Q(cnonce="#{cnonce}"),
|
28
|
-
%Q(response="#{digest}"),
|
29
|
-
%Q(opaque="#{params['opaque']}"),
|
30
|
-
]
|
31
|
-
|
32
|
-
header.join(", ")
|
33
|
-
end
|
34
|
-
|
35
|
-
def calculate_digest(user, password, realm, nonce, method, uri, qop, cnonce, nc)
|
36
|
-
a1 = Digest::MD5.hexdigest "#{user}:#{realm}:#{password}"
|
37
|
-
a2 = Digest::MD5.hexdigest "#{method}:#{uri}"
|
38
|
-
|
39
|
-
if qop
|
40
|
-
Digest::MD5.hexdigest("#{a1}:#{nonce}:#{'%08x' % nc}:#{cnonce}:#{qop}:#{a2}")
|
41
|
-
else
|
42
|
-
Digest::MD5.hexdigest("#{a1}:#{nonce}:#{a2}")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def calculate_user_agent_digest(product, user_agent_password, rets_request_id, session_id, version)
|
47
|
-
a1 = Digest::MD5.hexdigest "#{product}:#{user_agent_password}"
|
48
|
-
|
49
|
-
Digest::MD5.hexdigest "#{a1}:#{rets_request_id}:#{session_id}:#{version}"
|
50
|
-
end
|
51
|
-
|
52
|
-
def build_user_agent_auth(*args)
|
53
|
-
%Q(Digest #{calculate_user_agent_digest(*args)})
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|