rets4r 0.8.2

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.
@@ -0,0 +1 @@
1
+ <RETS ReplyCode="20400" ReplyText="Invalid Invalidness." />
@@ -0,0 +1,4 @@
1
+ <RETS ReplyCode="0" ReplyText="SUCCESS">
2
+ <COUNT Records="4"/>
3
+ <DELIMITER value="09" />
4
+ <COLUMNS> First Second Third </COL
@@ -0,0 +1,16 @@
1
+ <RETS ReplyCode="0" ReplyText="Login Request">
2
+ <RETS-RESPONSE>
3
+ MemberName=Spiffy Realtor
4
+ User=srealtor,1,11,11111
5
+ Broker=1,2
6
+ MetadataVersion=1.1.1
7
+ MinMetadataVersion=1.0.0
8
+ TimeoutSeconds=1200
9
+ Action=/rets/ActionURL
10
+ GetMetadata=/rets/GetMetadata
11
+ GetObject=/rets/GetObject
12
+ Login=/rets/Login
13
+ Logout=/rets/Logout
14
+ Search=/rets/Search
15
+ </RETS-RESPONSE>
16
+ </RETS>
File without changes
@@ -0,0 +1,8 @@
1
+ <RETS ReplyCode="0" ReplyText="SUCCESS">
2
+ <COUNT Records="4"/>
3
+ <DELIMITER value="09" />
4
+ <COLUMNS> First Second Third </COLUMNS>
5
+ <DATA> Datum1 Datum2 Datum3</DATA>
6
+ <DATA> Datum4 Datum5 Datum6</DATA>
7
+ <MAXROWS/>
8
+ </RETS>
@@ -0,0 +1,8 @@
1
+ <RETS ReplyCode="0" ReplyText="SUCCESS">
2
+ <COUNT Records="4"/>
3
+ <DELIMITER value="09" />
4
+ <COLUMNS> First Second Third </COLUMNS>
5
+ <DATA> Datum1 <Datum&2 Datum3</DATA>
6
+ <DATA> Datum4 D>atum5 Datum6</DATA>
7
+ <MAXROWS/>
8
+ </RETS>
@@ -0,0 +1,17 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
2
+
3
+ require 'test/unit'
4
+ require 'rets4r/client/parser/rexml'
5
+ require 'test/client/test_parser'
6
+
7
+ module RETS4R
8
+ class Client
9
+ class TestRParser < Test::Unit::TestCase
10
+ include TestParser
11
+
12
+ def setup
13
+ @parser = Parser::REXML.new
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
2
+
3
+ require 'test/unit'
4
+ require 'rets4r/client/parser/xmlparser'
5
+ require 'test/client/test_parser'
6
+
7
+ module RETS4R
8
+ class Client
9
+ if Module.constants.include?('XMLParser') && SUPPORTED_PARSERS.include?(Parser::XMLParser)
10
+ class TestCParser < Test::Unit::TestCase
11
+ include TestParser
12
+
13
+ def setup
14
+ @parser = Parser::XMLParser.new
15
+ end
16
+ end
17
+ else
18
+ puts "Skipping RETS4R XMLParser testing because XMLParser is not available."
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
2
+
3
+ require 'rets4r/auth'
4
+ require 'test/unit'
5
+
6
+ module RETS4R
7
+ class TestAuth < Test::Unit::TestCase
8
+ def setup
9
+ @useragent = 'TestAgent/0.00'
10
+ @username = 'username'
11
+ @password = 'password'
12
+ @realm = 'REALM'
13
+ @nonce = '2006-03-03T17:37:10'
14
+ end
15
+
16
+ def test_authenticate
17
+ response = {
18
+ 'www-authenticate' => 'Digest qop="auth",realm="'+ @realm +'",nonce="'+ @nonce +'",opaque="",stale="false",domain="\my\test\domain"'
19
+ }
20
+
21
+ Auth.authenticate(response, @username, @password, '/my/rets/url', 'GET', Auth.request_id, @useragent)
22
+ end
23
+
24
+ def test_parse_auth_header
25
+ header = 'Digest qop="auth",realm="'+ @realm +'",nonce="'+ @nonce +'",opaque="",stale="false",domain="\my\test\domain"'
26
+
27
+ results = Auth.parse_header(header)
28
+
29
+ assert_equal('auth', results['qop'])
30
+ assert_equal('REALM', results['realm'])
31
+ assert_equal('2006-03-03T17:37:10', results['nonce'])
32
+ assert_equal('', results['opaque'])
33
+ assert_equal('false', results['stale'])
34
+ assert_equal('\my\test\domain', results['domain'])
35
+ end
36
+
37
+ def test_calculate_digest
38
+ # with qop
39
+ assert_equal('c5f9ef280f0ca78ed7a488158fc2f4cc', Auth.calculate_digest(@username, \
40
+ @password, @realm, 'test', 'GET', '/my/rets/url', true, 'test'))
41
+
42
+ # without qop
43
+ assert_equal('bceafa34467a3519c2f6295d4800f4ea', Auth.calculate_digest(@username, \
44
+ @password, @realm, 'test', 'GET', '/my/rets/url', false))
45
+ end
46
+
47
+ def test_request_id
48
+ assert_not_nil(true, Auth.request_id)
49
+ end
50
+
51
+ def test_cnonce
52
+ # We call cnonce with a static request ID so that we have a consistent result with which
53
+ # to test against
54
+ assert_equal('d5cdfa1acffde590d263689fb40cf53c', Auth.cnonce(@useragent, @password, 'requestId', @nonce))
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,268 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
2
+
3
+ require 'rets4r/client'
4
+ require 'test/unit'
5
+ require 'stringio'
6
+ require 'logger'
7
+ require 'rubygems' rescue nil
8
+ require 'mocha'
9
+
10
+ module RETS4R
11
+ class Client
12
+ public :process_content_type
13
+ end
14
+
15
+ class TestClientGetMetadata < Test::Unit::TestCase
16
+ RETS_PORT = '9080'
17
+ RETS_URL = "http://localhost:#{RETS_PORT}"
18
+ RETS_LOGIN = 'login'
19
+ RETS_PASSWORD = 'password'
20
+
21
+ class CustomError < StandardError; end
22
+
23
+ def setup
24
+ @logfile = StringIO.open
25
+ @rets = RETS4R::Client.new(RETS_URL)
26
+ @rets.logger = Logger.new(@logfile)
27
+ @rets.logger.level = Logger::DEBUG
28
+
29
+ @rets.stubs(:request).returns(@response = mock("response"))
30
+ @response.stubs(:body).returns(:body)
31
+ @rets.stubs(:parse).returns(@results = mock("results"))
32
+ end
33
+
34
+ def teardown
35
+ @logfile.close
36
+ end
37
+
38
+ def test_get_metadata_yields_the_results_if_given_a_block
39
+ @rets.expects(:parse).returns(@results = mock("results"))
40
+
41
+ in_block = false
42
+ @rets.get_metadata do |results|
43
+ in_block = true
44
+ assert_equal @results, results
45
+ end
46
+
47
+ assert in_block, "Block was never yielded to"
48
+ end
49
+
50
+ def test_get_metadata_returns_the_metadata_when_no_block_given
51
+ rval = @rets.get_metadata
52
+
53
+ assert_equal @results, rval
54
+ end
55
+
56
+ def test_get_metadata_returns_the_blocks_value_when_given_a_block
57
+ rval = @rets.get_metadata do |results|
58
+ :block_value
59
+ end
60
+
61
+ assert_equal :block_value, rval
62
+ end
63
+ end
64
+
65
+ class TestClientGetObject < Test::Unit::TestCase
66
+ RETS_PORT = '9080'
67
+ RETS_URL = "http://localhost:#{RETS_PORT}"
68
+ RETS_LOGIN = 'login'
69
+ RETS_PASSWORD = 'password'
70
+
71
+ class CustomError < StandardError; end
72
+
73
+ def setup
74
+ @logfile = StringIO.open
75
+ @rets = RETS4R::Client.new(RETS_URL)
76
+ @rets.logger = Logger.new(@logfile)
77
+ @rets.logger.level = Logger::DEBUG
78
+
79
+ @rets.stubs(:request).returns(@response = mock("response"))
80
+ end
81
+
82
+ def test_returns_multipart_parallel_objects_in_a_single_array
83
+ @response.expects(:[]).with('content-type').at_least_once.returns("multipart/parallel; boundary=1231")
84
+ @response.expects(:body).returns("\r\n--1231\r\nContent-ID: 392103\r\nObject-ID: 1\r\nContent-Type: image/jpeg\r\n\r\n" + "\000"*120 + "\r\n--1231\r\nContent-ID: 392103\r\nObject-ID: 2\r\nContent-Type: image/gif\r\n\r\n" + "\000"*140 + "\r\n--1231--")
85
+ results = @rets.get_object("Property", "Photo", "392103:*")
86
+ assert_equal 2, results.size, "Client parsed two objects out of the request"
87
+ assert_kind_of RETS4R::Client::DataObject, results[0], "First result isn't a DataObject"
88
+ assert_kind_of RETS4R::Client::DataObject, results[1], "Second result isn't a DataObject"
89
+ assert_equal "image/jpeg", results[0].type["Content-Type"], "First object isn't an image/jpeg"
90
+ assert_equal 120, results[0].data.size, "First object isn't 120 bytes in length"
91
+ assert_equal "image/gif", results[1].type["Content-Type"], "Second object isn't an image/gif"
92
+ assert_equal 140, results[1].data.size, "Second object isn't 140 bytes in length"
93
+ end
94
+
95
+ def test_returns_single_entity_object_in_a_single_element_array
96
+ @response.expects(:[]).with('content-type').at_least_once.returns("image/jpeg")
97
+ @response.expects(:[]).with('Content-Length').at_least_once.returns(241)
98
+ @response.expects(:[]).with('Object-ID').at_least_once.returns("25478")
99
+ @response.expects(:[]).with('Content-ID').at_least_once.returns("5589")
100
+ @response.expects(:body).returns("\000"*241)
101
+
102
+ results = @rets.get_object("Property", "Photo", "392103:*")
103
+ assert_equal 1, results.size, "Client parsed two objects out of the request"
104
+ assert_kind_of RETS4R::Client::DataObject, results[0], "First result isn't a DataObject"
105
+ assert_equal "image/jpeg", results[0].type["Content-Type"], "Content-Type not copied"
106
+ assert_equal "5589", results[0].type["Content-ID"], "Content-ID not copied"
107
+ assert_equal "25478", results[0].type["Object-ID"], "Object-ID not copied"
108
+ assert_equal 241, results[0].data.size, "First object isn't 241 bytes in length"
109
+ end
110
+
111
+ def test_yields_data_objects_to_block_and_returns_blocks_value
112
+ @response.expects(:[]).with('content-type').at_least_once.returns("image/jpeg")
113
+ @response.expects(:[]).with('Content-Length').at_least_once.returns(241)
114
+ @response.expects(:[]).with('Object-ID').at_least_once.returns("25478")
115
+ @response.expects(:[]).with('Content-ID').at_least_once.returns("5589")
116
+ @response.expects(:body).returns("\000"*241)
117
+
118
+ yielded_count = 0
119
+
120
+ value = @rets.get_object("Property", "VRImage", "912:0") do |result|
121
+ assert_kind_of RETS4R::Client::DataObject, result
122
+ yielded_count += 1
123
+ :return_value
124
+ end
125
+
126
+ assert_equal yielded_count, value
127
+ end
128
+ end
129
+
130
+ class TestClientLogin < Test::Unit::TestCase
131
+ RETS_PORT = '9080'
132
+ RETS_URL = "http://localhost:#{RETS_PORT}"
133
+ RETS_LOGIN = 'login'
134
+ RETS_PASSWORD = 'password'
135
+
136
+ class CustomError < StandardError; end
137
+
138
+ def setup
139
+ @logfile = StringIO.open
140
+ @rets = RETS4R::Client.new(RETS_URL)
141
+ @rets.logger = Logger.new(@logfile)
142
+ @rets.logger.level = Logger::DEBUG
143
+
144
+ @rets.stubs(:request).returns(@response = mock("response"))
145
+ @response.stubs(:body).returns(:body)
146
+ @rets.stubs(:parse).returns(@results = mock("results"))
147
+ @results.stubs(:success?).returns(true)
148
+ @results.stubs(:response).returns(Hash.new)
149
+ @results.stubs(:secondary_response=)
150
+ end
151
+
152
+ def teardown
153
+ @logfile.close
154
+ end
155
+
156
+ def test_successful_login_yields_the_results_to_the_block
157
+ @rets.expects(:request).with {|arg| arg.kind_of?(URI)}.returns(@response)
158
+ @rets.expects(:parse).with(:body, RETS4R::Client::OUTPUT_RUBY).returns(@results)
159
+ @results.expects(:success?).returns(true)
160
+ @rets.expects(:logout)
161
+
162
+ in_block = false
163
+ @rets.login("user", "pass") do |results|
164
+ assert_equal @results, results
165
+ in_block = true
166
+ end
167
+
168
+ assert in_block, "Block was never yielded to"
169
+ end
170
+
171
+ def test_logout_called_after_block_execution_if_block_raises
172
+ assert_raises(CustomError) do
173
+ @rets.expects(:logout)
174
+ @rets.login("user", "pass") do |results|
175
+ raise CustomError
176
+ end
177
+ end
178
+ end
179
+
180
+ def test_login_returns_the_blocks_value
181
+ rval = @rets.login("user", "pass") do |results|
182
+ :value
183
+ end
184
+
185
+ assert_equal :value, rval
186
+ end
187
+
188
+ def test_login_without_a_block_returns_the_results
189
+ results = @rets.login("user", "pass")
190
+ assert_equal @results, results
191
+ end
192
+ end
193
+
194
+ class TestClient < Test::Unit::TestCase
195
+ RETS_PORT = '9080'
196
+ RETS_URL = "http://localhost:#{RETS_PORT}"
197
+ RETS_LOGIN = 'login'
198
+ RETS_PASSWORD = 'password'
199
+
200
+ def setup
201
+ @logfile = StringIO.open
202
+ @rets = RETS4R::Client.new(RETS_URL)
203
+ @rets.logger = Logger.new(@logfile)
204
+ @rets.logger.level = Logger::DEBUG
205
+ end
206
+
207
+ def teardown
208
+ @logfile.close
209
+ end
210
+
211
+ def test_setup
212
+ assert_nothing_raised() { @rets.set_user_agent('ACK/2.1') }
213
+ assert_equal('ACK/2.1', @rets.user_agent)
214
+
215
+ assert_nothing_raised() { @rets.user_agent = 'SPRETS/0.1' }
216
+ assert_nothing_raised() { @rets.set_request_method('GET') }
217
+
218
+ assert_raise(RETS4R::Client::Unsupported) { @rets.set_rets_version('1.4.0') }
219
+ assert_nothing_raised() { @rets.set_rets_version('1.5') }
220
+ assert_equal("1.5", @rets.rets_version)
221
+ assert_equal("RETS/1.5", @rets.get_header("RETS-Version"))
222
+ assert_nothing_raised() { @rets.rets_version = '1.7' }
223
+ assert_equal("RETS/1.7", @rets.get_header("RETS-Version"))
224
+
225
+ assert_equal('SPRETS/0.1', @rets.get_user_agent)
226
+ assert_equal('GET', @rets.get_request_method)
227
+ assert_equal('1.7', @rets.get_rets_version)
228
+
229
+ assert_nothing_raised() { @rets.request_method = 'POST' }
230
+
231
+ assert_equal('POST', @rets.request_method)
232
+
233
+ assert_nothing_raised() { @rets.set_parser_class(Client::Parser::REXML) }
234
+ assert_raise(Client::Unsupported) { @rets.parser_class = MockParser }
235
+ assert_nothing_raised() { @rets.set_parser_class(MockParser, true) }
236
+ assert_equal(MockParser, @rets.parser_class)
237
+
238
+ assert_nothing_raised() { @rets.set_output(RETS4R::Client::OUTPUT_RAW) }
239
+ assert_equal(RETS4R::Client::OUTPUT_RAW, @rets.output)
240
+ assert_nothing_raised() { @rets.output = RETS4R::Client::OUTPUT_RUBY }
241
+ assert_equal(RETS4R::Client::OUTPUT_RUBY, @rets.get_output)
242
+
243
+ # Check that our changes were logged when in debug mode
244
+ assert @logfile.length > 0
245
+ end
246
+
247
+ # Just to make sure that we're okay when we don't have a logger, we set it to nil and
248
+ # make a change that would trigger a debug mode log.
249
+ def test_without_logger
250
+ @rets.logger = nil
251
+
252
+ assert_nothing_raised() { @rets.set_request_method('GET') }
253
+ end
254
+
255
+ def test_content_type_parsing
256
+ ct = 'multipart/parallel; boundary=cc2631bb.0165.3b32.8a7d.a8453f662101; charset=utf-8'
257
+
258
+ results = @rets.process_content_type(ct)
259
+
260
+ assert_equal('cc2631bb.0165.3b32.8a7d.a8453f662101', results['boundary'])
261
+ assert_equal('multipart/parallel', results['content-type'])
262
+ assert_equal('utf-8', results['charset'])
263
+ end
264
+
265
+ class MockParser
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "../..", "lib")
2
+
3
+ require 'rets4r/client/metadataindex'
4
+ require 'rets4r/client/transaction'
5
+ require 'rets4r/client/metadata'
6
+ require 'test/unit'
7
+
8
+ module RETS4R
9
+ class TestMetadataIndex < Test::Unit::TestCase
10
+
11
+ def test_truth
12
+ end
13
+
14
+ =begin
15
+ def setup
16
+ File.open('tests/rets/data/metadata.marshal') do |file|
17
+ @trans = Marshal.load(file)
18
+ end
19
+
20
+ @index = MetadataIndex.new(@trans.data)
21
+ end
22
+
23
+ # Ensure that our lookup and search functions, although different, will return the same data
24
+ # for the same criteria.
25
+ def test_lookup_search
26
+ assert_equal("Club House", @index.lookup('METADATA-LOOKUP_TYPE', 'Property', 'HOAMENITIS_Lkp_2')[0]['LongValue'])
27
+
28
+ puts @index.search('METADATA-LOOKUP_TYPE', {'Resource' => 'Property', 'Lookup' => 'HOAMENITIS_Lkp_2'}).inspect
29
+ assert_equal( \
30
+ @index.lookup('METADATA-LOOKUP_TYPE', 'Property', 'HOAMENITIS_Lkp_2'), \
31
+ @index.search('METADATA-LOOKUP_TYPE', {'Resource' => 'Property', 'Lookup' => 'HOAMENITIS_Lkp_2'}).inspect \
32
+ )
33
+ end
34
+ =end
35
+ end
36
+ end