sean-rets 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,86 @@
1
+ require_relative "helper"
2
+
3
+ class TestParserCompact < MiniTest::Test
4
+ def test_parse_document_raises_on_invalid_delimiter
5
+ assert_raises Rets::Parser::Compact::InvalidDelimiter do
6
+ Rets::Parser::Compact.parse_document(INVALID_DELIMETER)
7
+ end
8
+ end
9
+
10
+ def test_parse_document_uses_default_delimiter_when_none_provided
11
+ # we assert that the delimeter character getting to parse is a tab
12
+ # even though COMPACT defines no delimiter tag
13
+ Rets::Parser::Compact.expects(:parse).with("A\tB", "1\t2", /\t/)
14
+ Rets::Parser::Compact.expects(:parse).with("A\tB", "4\t5", /\t/)
15
+ Rets::Parser::Compact.parse_document(COMPACT)
16
+ end
17
+
18
+ def test_parse_document_delegates_to_parse
19
+ result = Rets::Parser::Compact.parse_document(COMPACT)
20
+
21
+ assert_equal([{"A" => "1", "B" => "2"}, {"A" => "4", "B" => "5"}], result)
22
+ end
23
+
24
+ def test_parser_rejects_empty_key_value_pairs
25
+ result = Rets::Parser::Compact.parse_document(METADATA_OBJECT)
26
+
27
+ result.each do |row|
28
+ assert !row.any? { |k,v| k.to_s.size == 0 }, "Should not contain empty keys"
29
+ end
30
+ end
31
+
32
+ def test_parse_returns_key_value_pairs
33
+ result = Rets::Parser::Compact.parse("A\tB", "1\t2")
34
+
35
+ assert_equal({"A" => "1", "B" => "2"}, result)
36
+ end
37
+
38
+ # RMLS does this. :|
39
+ def test_remaining_columns_produce_empty_string_values
40
+ columns = "A B C D"
41
+ data = "1 2"
42
+
43
+ assert_equal({"A" => "1", "B" => "2", "C" => "", "D" => ""}, Rets::Parser::Compact.parse(columns, data, / /))
44
+ end
45
+
46
+ def test_leading_empty_columns_are_preserved_with_delimiter
47
+ columns = "A\tB\tC\tD"
48
+ data = "\t\t3\t4" # first two columns are empty data.
49
+
50
+ assert_equal({"A" => "", "B" => "", "C" => "3", "D" => "4"}, Rets::Parser::Compact.parse(columns, data, /\t/))
51
+ end
52
+
53
+ def test_parse_only_accepts_regexp
54
+ assert_raises ArgumentError do
55
+ Rets::Parser::Compact.parse("a", "b", " ")
56
+ end
57
+ end
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
+
69
+ def test_get_count_with_no_matching_records
70
+ count = Rets::Parser::Compact.get_count(RETS_STATUS_NO_MATCHING_RECORDS)
71
+ assert_equal 0, count
72
+ end
73
+
74
+ def test_parse_example
75
+ rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT))
76
+
77
+ assert_equal "7", rows.first["MetadataEntryID"]
78
+ end
79
+
80
+ def test_parse_example_2
81
+ rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT_2))
82
+
83
+ assert_equal "", rows.first["ModTimeStamp"]
84
+ end
85
+
86
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "helper"
2
+
3
+ class TestParserMultipart < MiniTest::Test
4
+ def test_parse_returns_multiple_parts
5
+ headers = {"content-type"=>"image/jpeg", "content-id"=>"90020062739", "content-length"=>"10"}
6
+
7
+ parts = Rets::Parser::Multipart.parse(MULITPART_RESPONSE, "simple boundary")
8
+
9
+ assert_equal 2, parts.size
10
+
11
+ part = parts[0]
12
+
13
+ assert_equal headers.merge("object-id" => "1"), part.headers
14
+ assert_equal "xxxxxxxx", part.body.strip
15
+
16
+ part = parts[1]
17
+
18
+ assert_equal headers.merge("object-id" => "2"), part.headers
19
+ assert_equal "yyyyyyyy", part.body.strip
20
+ end
21
+
22
+ def test_parse_real_mls_data
23
+ parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
24
+ assert_equal 5, parts.size
25
+ end
26
+
27
+ def test_parse_values_with_colon_data
28
+ parts = Rets::Parser::Multipart.parse(MULTIPART_RESPONSE_URLS, "rets.object.content.boundary.1330546052739")
29
+ assert_equal 'http://foobarmls.com/RETS//MediaDisplay/98/hr2890998-1.jpg', parts[0].headers['location']
30
+ end
31
+
32
+ def test_parse_with_error
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
+ boundary = "89467f8e0c6b48158c8f1883910212ec"
35
+ assert_raises Rets::InvalidRequest do
36
+ Rets::Parser::Multipart.parse(raw, boundary)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,262 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://rets.example.com/GetObject.asmx/GetObject
6
+ body:
7
+ encoding: US-ASCII
8
+ string: Resource=Property&Type=Photo&ID=2661580%3A1&Location=0
9
+ headers:
10
+ User-Agent:
11
+ - Estately/1.0
12
+ Host:
13
+ - rets.example.com:80
14
+ Rets-Version:
15
+ - RETS/1.7.2
16
+ Authorization:
17
+ - Digest username="login", realm="fake_realm", qop="auth",
18
+ uri="/Login.asmx/Login", nonce="a8f4bc805062602c8ba7a87b2109f808", nc=00000001,
19
+ cnonce="6e2dd038eea6cbacf0b956fd11f914b6", response="fake_digest",
20
+ opaque="96eda461-41d0-4624-b7fe-b59e966035f3"
21
+ Cookie:
22
+ - ASP.NET_SessionId=mapij045k3bphj3gqqgpmmrx
23
+ Accept:
24
+ - image/jpeg, image/png;q=0.5, image/gif;q=0.1
25
+ Content-Type:
26
+ - application/x-www-form-urlencoded
27
+ Content-Length:
28
+ - '54'
29
+ response:
30
+ status:
31
+ code: 401
32
+ message: Unauthorized
33
+ headers:
34
+ Connection:
35
+ - close
36
+ Date:
37
+ - Thu, 26 Jul 2012 00:11:02 GMT
38
+ Server:
39
+ - Microsoft-IIS/6.0
40
+ Cache-Control:
41
+ - private
42
+ - private
43
+ X-Aspnet-Version:
44
+ - 2.0.50727
45
+ Www-Authenticate:
46
+ - Digest realm="fake_realm",nonce="dfd74deac03147e1a4fff598679f1a80",opaque="8e5029c6-bb9c-4562-b440-e7c2b8960743",qop="auth"
47
+ Content-Type:
48
+ - text/plain
49
+ body:
50
+ encoding: US-ASCII
51
+ string: ! "Unauthorized Request. Digest Session Invalid Reauthenticate\r\nReference:
52
+ e0ff89c0-2d64-4287-a6b7-6be27c7d3ade"
53
+ http_version:
54
+ recorded_at: Thu, 26 Jul 2012 00:11:13 GMT
55
+ - request:
56
+ method: post
57
+ uri: http://rets.example.com/Login.asmx/Login
58
+ body:
59
+ encoding: US-ASCII
60
+ string: ''
61
+ headers:
62
+ User-Agent:
63
+ - Estately/1.0
64
+ Host:
65
+ - rets.example.com:80
66
+ Rets-Version:
67
+ - RETS/1.7.2
68
+ Accept:
69
+ - ! '*/*'
70
+ response:
71
+ status:
72
+ code: 401
73
+ message: Unauthorized
74
+ headers:
75
+ Connection:
76
+ - close
77
+ Date:
78
+ - Thu, 26 Jul 2012 00:11:03 GMT
79
+ Server:
80
+ - Microsoft-IIS/6.0
81
+ Cache-Control:
82
+ - private
83
+ - private
84
+ X-Aspnet-Version:
85
+ - 2.0.50727
86
+ Www-Authenticate:
87
+ - Digest realm="fake_realm",nonce="17fdfe2c6125296bd93bb81bd88dc4be",opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd",qop="auth"
88
+ Content-Type:
89
+ - text/plain
90
+ body:
91
+ encoding: US-ASCII
92
+ string: ! "Unauthorized Request. Authentication needed\r\nReference: c2c5ab9f-8c12-42bb-94ce-5b6ebf156da4"
93
+ http_version:
94
+ recorded_at: Thu, 26 Jul 2012 00:11:13 GMT
95
+ - request:
96
+ method: post
97
+ uri: http://rets.example.com/Login.asmx/Login
98
+ body:
99
+ encoding: US-ASCII
100
+ string: ''
101
+ headers:
102
+ User-Agent:
103
+ - Estately/1.0
104
+ Host:
105
+ - rets.example.com:80
106
+ Rets-Version:
107
+ - RETS/1.7.2
108
+ Authorization:
109
+ - Digest username="login", realm="fake_realm", qop="auth",
110
+ uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
111
+ cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
112
+ opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
113
+ Accept:
114
+ - ! '*/*'
115
+ response:
116
+ status:
117
+ code: 200
118
+ message: OK
119
+ headers:
120
+ Date:
121
+ - Thu, 26 Jul 2012 00:11:03 GMT
122
+ Server:
123
+ - Microsoft-IIS/6.0
124
+ Cache-Control:
125
+ - private
126
+ - private, max-age=0
127
+ X-Aspnet-Version:
128
+ - 2.0.50727
129
+ Rets-Version:
130
+ - RETS/1.7.2
131
+ Rets-Server:
132
+ - Interealty-RETS/1.5.247.0
133
+ Transfer-Encoding:
134
+ - chunked
135
+ Set-Cookie:
136
+ - ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; path=/; HttpOnly
137
+ - RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
138
+ Content-Type:
139
+ - text/xml
140
+ body:
141
+ encoding: US-ASCII
142
+ string: ! "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RETS ReplyCode=\"0\"
143
+ ReplyText=\"Success. Reference ID: a3073726-a011-4391-b22e-900adae5184b\">\r\n
144
+ \ <RETS-RESPONSE>\r\nMemberName=John Wolff\r\nUser=23756,60,RH,login\r\nBroker=BRDA,BRDA01\r\nMetadataVersion=31.76.69587\r\nMetadataTimeStamp=2012-07-24T17:33:07Z\r\nMinMetadataTimeStamp=2012-07-24T17:33:07Z\r\nTimeoutSeconds=7200\r\nChangePassword=/ChangePassword.asmx/ChangePassword\r\nGetObject=/GetObject.asmx/GetObject\r\nLogin=/Login.asmx/Login\r\nLogout=/Logout.asmx/Logout\r\nSearch=/Search.asmx/Search\r\nGetMetadata=/GetMetadata.asmx/GetMetadata\r\n</RETS-RESPONSE>\r\n</RETS>"
145
+ http_version:
146
+ recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
147
+ - request:
148
+ method: post
149
+ uri: http://rets.example.com/Login.asmx/Login
150
+ body:
151
+ encoding: US-ASCII
152
+ string: ''
153
+ headers:
154
+ User-Agent:
155
+ - Estately/1.0
156
+ Host:
157
+ - rets.example.com:80
158
+ Rets-Version:
159
+ - RETS/1.7.2
160
+ Authorization:
161
+ - Digest username="login", realm="fake_realm", qop="auth",
162
+ uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
163
+ cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
164
+ opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
165
+ Cookie:
166
+ - ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; RETS-Session-ID=vuesmq55l0cpjy45zyn0e555
167
+ Accept:
168
+ - ! '*/*'
169
+ response:
170
+ status:
171
+ code: 200
172
+ message: OK
173
+ headers:
174
+ Date:
175
+ - Thu, 26 Jul 2012 00:11:03 GMT
176
+ Server:
177
+ - Microsoft-IIS/6.0
178
+ Cache-Control:
179
+ - private
180
+ - private, max-age=0
181
+ X-Aspnet-Version:
182
+ - 2.0.50727
183
+ Rets-Version:
184
+ - RETS/1.7.2
185
+ Rets-Server:
186
+ - Interealty-RETS/1.5.247.0
187
+ Transfer-Encoding:
188
+ - chunked
189
+ Set-Cookie:
190
+ - RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
191
+ Content-Type:
192
+ - text/xml
193
+ body:
194
+ encoding: US-ASCII
195
+ string: ! "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<RETS ReplyCode=\"0\"
196
+ ReplyText=\"Success. Reference ID: a48b4f59-cb22-41be-8e7b-1cee28fb8644\">\r\n
197
+ \ <RETS-RESPONSE>\r\nMemberName=John Wolff\r\nUser=23756,60,RH,login\r\nBroker=BRDA,BRDA01\r\nMetadataVersion=31.76.69587\r\nMetadataTimeStamp=2012-07-24T17:33:07Z\r\nMinMetadataTimeStamp=2012-07-24T17:33:07Z\r\nTimeoutSeconds=7200\r\nChangePassword=/ChangePassword.asmx/ChangePassword\r\nGetObject=/GetObject.asmx/GetObject\r\nLogin=/Login.asmx/Login\r\nLogout=/Logout.asmx/Logout\r\nSearch=/Search.asmx/Search\r\nGetMetadata=/GetMetadata.asmx/GetMetadata\r\n</RETS-RESPONSE>\r\n</RETS>"
198
+ http_version:
199
+ recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
200
+ - request:
201
+ method: post
202
+ uri: http://rets.example.com/GetObject.asmx/GetObject
203
+ body:
204
+ encoding: US-ASCII
205
+ string: Resource=Property&Type=Photo&ID=2661580%3A1&Location=0
206
+ headers:
207
+ User-Agent:
208
+ - Estately/1.0
209
+ Host:
210
+ - rets.example.com:80
211
+ Rets-Version:
212
+ - RETS/1.7.2
213
+ Authorization:
214
+ - Digest username="login", realm="fake_realm", qop="auth",
215
+ uri="/Login.asmx/Login", nonce="17fdfe2c6125296bd93bb81bd88dc4be", nc=00000001,
216
+ cnonce="ad805b9e2d6f08ad82175085e5febd8d", response="7402076f53663602f052e1aa343d3dab",
217
+ opaque="aee1e7da-60eb-41b3-b704-8eb3969645fd"
218
+ Cookie:
219
+ - ASP.NET_SessionId=vuesmq55l0cpjy45zyn0e555; RETS-Session-ID=vuesmq55l0cpjy45zyn0e555
220
+ Accept:
221
+ - image/jpeg, image/png;q=0.5, image/gif;q=0.1
222
+ Content-Type:
223
+ - application/x-www-form-urlencoded
224
+ Content-Length:
225
+ - '54'
226
+ response:
227
+ status:
228
+ code: 200
229
+ message: OK
230
+ headers:
231
+ Date:
232
+ - Thu, 26 Jul 2012 00:11:04 GMT
233
+ Server:
234
+ - Microsoft-IIS/6.0
235
+ Cache-Control:
236
+ - private
237
+ - private, max-age=0
238
+ X-Aspnet-Version:
239
+ - 2.0.50727
240
+ Mime-Version:
241
+ - '1.0'
242
+ Rets-Version:
243
+ - RETS/1.7.2
244
+ Rets-Server:
245
+ - Interealty-RETS/1.5.247.0
246
+ Content-Id:
247
+ - '2661580'
248
+ Object-Id:
249
+ - '1'
250
+ Transfer-Encoding:
251
+ - chunked
252
+ Set-Cookie:
253
+ - RETS-Session-ID=vuesmq55l0cpjy45zyn0e555; path=/
254
+ Content-Type:
255
+ - image/jpeg
256
+ body:
257
+ encoding: ASCII-8BIT
258
+ string: !binary |-
259
+ /9j/4AAQSkZJRgABAQEAYABgAAD///2Q==
260
+ http_version:
261
+ recorded_at: Thu, 26 Jul 2012 00:11:14 GMT
262
+ recorded_with: VCR 2.2.2
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sean-rets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Estately, Inc. Open Source
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpclient
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.11.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.11.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: vcr
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 2.2.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 2.2.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.8.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: hoe
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.6'
111
+ description: |-
112
+ [![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
113
+ A pure-ruby library for fetching data from [RETS] servers.
114
+
115
+ [RETS]: http://www.rets.org
116
+ email:
117
+ - opensource@estately.com
118
+ executables:
119
+ - rets
120
+ extensions: []
121
+ extra_rdoc_files:
122
+ - CHANGELOG.md
123
+ - Manifest.txt
124
+ - README.md
125
+ files:
126
+ - ".gemtest"
127
+ - CHANGELOG.md
128
+ - Manifest.txt
129
+ - README.md
130
+ - Rakefile
131
+ - bin/rets
132
+ - lib/rets.rb
133
+ - lib/rets/client.rb
134
+ - lib/rets/client_progress_reporter.rb
135
+ - lib/rets/http_client.rb
136
+ - lib/rets/locking_http_client.rb
137
+ - lib/rets/measuring_http_client.rb
138
+ - lib/rets/metadata.rb
139
+ - lib/rets/metadata/containers.rb
140
+ - lib/rets/metadata/lookup_type.rb
141
+ - lib/rets/metadata/resource.rb
142
+ - lib/rets/metadata/rets_class.rb
143
+ - lib/rets/metadata/root.rb
144
+ - lib/rets/metadata/table.rb
145
+ - lib/rets/parser/compact.rb
146
+ - lib/rets/parser/multipart.rb
147
+ - test/fixtures.rb
148
+ - test/helper.rb
149
+ - test/test_client.rb
150
+ - test/test_locking_http_client.rb
151
+ - test/test_metadata.rb
152
+ - test/test_parser_compact.rb
153
+ - test/test_parser_multipart.rb
154
+ - test/vcr_cassettes/unauthorized_response.yml
155
+ homepage: http://github.com/estately/rets
156
+ licenses: []
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options:
160
+ - "--main"
161
+ - README.md
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project: rets
176
+ rubygems_version: 2.2.2
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: "[![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
180
+ A pure-ruby library for fetching data from [RETS] servers"
181
+ test_files:
182
+ - test/test_client.rb
183
+ - test/test_locking_http_client.rb
184
+ - test/test_metadata.rb
185
+ - test/test_parser_compact.rb
186
+ - test/test_parser_multipart.rb