rets4r 0.8.5 → 1.1.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.document +5 -0
  2. data/{test/client/data/1.5/metadata.xml → .gemtest} +0 -0
  3. data/CHANGELOG +611 -66
  4. data/CONTRIBUTORS +6 -2
  5. data/Gemfile +1 -0
  6. data/LICENSE +22 -0
  7. data/MANIFEST +63 -0
  8. data/NEWS +203 -0
  9. data/{README → README.rdoc} +11 -4
  10. data/RUBYS +7 -7
  11. data/Rakefile +48 -0
  12. data/TODO +5 -1
  13. data/examples/client_get_object.rb +31 -42
  14. data/examples/client_login.rb +20 -18
  15. data/examples/client_mapper.rb +17 -0
  16. data/examples/client_metadata.rb +28 -28
  17. data/examples/client_parser.rb +9 -0
  18. data/examples/client_search.rb +25 -27
  19. data/examples/settings.yml +114 -0
  20. data/lib/rets4r.rb +14 -1
  21. data/lib/rets4r/auth.rb +70 -66
  22. data/lib/rets4r/client.rb +470 -650
  23. data/lib/rets4r/client/data.rb +13 -13
  24. data/lib/rets4r/client/dataobject.rb +27 -19
  25. data/lib/rets4r/client/exceptions.rb +116 -0
  26. data/lib/rets4r/client/links.rb +32 -0
  27. data/lib/rets4r/client/metadata.rb +12 -12
  28. data/lib/rets4r/client/parsers/compact.rb +42 -0
  29. data/lib/rets4r/client/parsers/compact_nokogiri.rb +91 -0
  30. data/lib/rets4r/client/parsers/metadata.rb +92 -0
  31. data/lib/rets4r/client/parsers/response_parser.rb +100 -0
  32. data/lib/rets4r/client/requester.rb +143 -0
  33. data/lib/rets4r/client/transaction.rb +30 -33
  34. data/lib/rets4r/core_ext/array/extract_options.rb +15 -0
  35. data/lib/rets4r/core_ext/class/attribute_accessors.rb +58 -0
  36. data/lib/rets4r/core_ext/hash/keys.rb +46 -0
  37. data/lib/rets4r/core_ext/hash/slice.rb +39 -0
  38. data/lib/rets4r/listing_mapper.rb +17 -0
  39. data/lib/rets4r/listing_service.rb +35 -0
  40. data/lib/rets4r/loader.rb +8 -0
  41. data/lib/tasks/annotations.rake +121 -0
  42. data/lib/tasks/coverage.rake +13 -0
  43. data/rets4r.gemspec +24 -0
  44. data/spec/rets4r_compact_data_parser_spec.rb +7 -0
  45. data/test/data/1.5/bad_compact.xml +7 -0
  46. data/test/data/1.5/count_only_compact.xml +3 -0
  47. data/test/{client/data → data}/1.5/error.xml +0 -0
  48. data/test/{client/data → data}/1.5/invalid_compact.xml +0 -0
  49. data/test/{client/data → data}/1.5/login.xml +0 -0
  50. data/test/data/1.5/metadata.xml +0 -0
  51. data/test/{client/data → data}/1.5/search_compact.xml +0 -0
  52. data/test/data/1.5/search_compact_big.xml +136 -0
  53. data/test/{client/data → data}/1.5/search_unescaped_compact.xml +0 -0
  54. data/test/data/listing_service.yml +36 -0
  55. data/test/test_auth.rb +68 -0
  56. data/test/test_client.rb +342 -0
  57. data/test/test_client_links.rb +39 -0
  58. data/test/test_compact_nokogiri.rb +64 -0
  59. data/test/test_helper.rb +12 -0
  60. data/test/test_listing_mapper.rb +112 -0
  61. data/test/test_loader.rb +24 -0
  62. data/test/test_parser.rb +96 -0
  63. data/test/test_quality.rb +57 -0
  64. metadata +168 -53
  65. data/GPL +0 -340
  66. data/examples/metadata.xml +0 -42
  67. data/lib/rets4r/client/metadataindex.rb +0 -82
  68. data/lib/rets4r/client/parser.rb +0 -141
  69. data/lib/rets4r/client/parser/rexml.rb +0 -75
  70. data/lib/rets4r/client/parser/xmlparser.rb +0 -95
  71. data/test/client/parser/tc_rexml.rb +0 -17
  72. data/test/client/parser/tc_xmlparser.rb +0 -21
  73. data/test/client/tc_auth.rb +0 -68
  74. data/test/client/tc_client.rb +0 -320
  75. data/test/client/tc_metadataindex.rb +0 -36
  76. data/test/client/test_parser.rb +0 -128
  77. data/test/client/ts_all.rb +0 -8
  78. data/test/ts_all.rb +0 -1
  79. data/test/ts_client.rb +0 -1
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "."))
3
+ require 'test_helper'
4
+
5
+ module RETS4R
6
+ class Client
7
+ public :process_content_type
8
+ end
9
+
10
+ class TestClientGetMetadata < Test::Unit::TestCase
11
+ RETS_PORT = '9080'
12
+ RETS_URL = "http://localhost:#{RETS_PORT}"
13
+ RETS_LOGIN = 'login'
14
+ RETS_PASSWORD = 'password'
15
+
16
+ class CustomError < StandardError; end
17
+
18
+ def setup
19
+ @logfile = StringIO.open
20
+ @rets = RETS4R::Client.new(RETS_URL)
21
+ @rets.logger = Logger.new(@logfile)
22
+ @rets.logger.level = Logger::DEBUG
23
+
24
+ @rets.stubs(:request).returns(@response = mock("response"))
25
+ @response.stubs(:body).returns(:body)
26
+ @rets.stubs(:parse).returns(@results = mock("results"))
27
+ Client::ResponseParser.any_instance.stubs(:parse_metadata).returns(@results = mock("results"))
28
+ end
29
+
30
+ def teardown
31
+ @logfile.close
32
+ end
33
+
34
+ def test_get_metadata_yields_the_results_if_given_a_block
35
+ in_block = false
36
+ @rets.get_metadata do |results|
37
+ in_block = true
38
+ assert_equal @results, results
39
+ end
40
+
41
+ assert in_block, "Block was never yielded to"
42
+ end
43
+
44
+ def test_useragent
45
+ assert_match /^rets4r/, RETS4R::Client::Requester::DEFAULT_USER_AGENT
46
+ assert_match /#{::RETS4R::VERSION}/, RETS4R::Client::Requester::DEFAULT_USER_AGENT
47
+ end
48
+
49
+ def test_get_metadata_returns_the_metadata_when_no_block_given
50
+ rval = @rets.get_metadata
51
+
52
+ assert_equal @results, rval
53
+ end
54
+
55
+ def test_get_metadata_returns_the_blocks_value_when_given_a_block
56
+ rval = @rets.get_metadata do |results|
57
+ :block_value
58
+ end
59
+
60
+ assert_equal :block_value, rval
61
+ end
62
+ end
63
+
64
+ class TestClientGetObject < Test::Unit::TestCase
65
+ RETS_PORT = '9080'
66
+ RETS_URL = "http://localhost:#{RETS_PORT}"
67
+ RETS_LOGIN = 'login'
68
+ RETS_PASSWORD = 'password'
69
+
70
+ class CustomError < StandardError; end
71
+
72
+ def setup
73
+ @logfile = StringIO.open
74
+ @rets = RETS4R::Client.new(RETS_URL)
75
+ @rets.logger = Logger.new(@logfile)
76
+ @rets.logger.level = Logger::DEBUG
77
+
78
+ @rets.stubs(:request).returns(@response = mock("response"))
79
+ end
80
+
81
+ def test_returns_multipart_parallel_objects_in_a_single_array(boundary = "1231")
82
+ @response.expects(:[]).with('content-type').at_least_once.returns("multipart/parallel; boundary=#{boundary}")
83
+ @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--")
84
+ results = @rets.get_object("Property", "Photo", "392103:*")
85
+ assert_equal 2, results.size, "Client should parse two objects out of the request"
86
+ assert_kind_of RETS4R::Client::DataObject, results[0], "First result isn't a DataObject"
87
+ assert_kind_of RETS4R::Client::DataObject, results[1], "Second result isn't a DataObject"
88
+ assert_equal "image/jpeg", results[0].type["Content-Type"], "First object isn't an image/jpeg"
89
+ assert_equal 120, results[0].data.size, "First object isn't 120 bytes in length"
90
+ assert_equal "image/gif", results[1].type["Content-Type"], "Second object isn't an image/gif"
91
+ assert_equal 140, results[1].data.size, "Second object isn't 140 bytes in length"
92
+ end
93
+
94
+ def test_returns_multipart_parallel_objects_in_a_single_array_boundary_with_double_quotes
95
+ test_returns_multipart_parallel_objects_in_a_single_array('"1231"')
96
+ end
97
+
98
+ def test_returns_multipart_parallel_objects_in_a_single_array_boundary_with_single_quotes
99
+ test_returns_multipart_parallel_objects_in_a_single_array("'1231'")
100
+ end
101
+
102
+ def test_returns_single_entity_object_in_a_single_element_array
103
+ @response.expects(:[]).with('content-type').at_least_once.returns("image/jpeg")
104
+ @response.expects(:[]).with('Transfer-Encoding').at_least_once.returns("")
105
+ @response.expects(:[]).with('Content-Length').at_least_once.returns(241)
106
+ @response.expects(:[]).with('Object-ID').at_least_once.returns("25478")
107
+ @response.expects(:[]).with('Content-ID').at_least_once.returns("5589")
108
+ @response.expects(:body).returns("\000"*241)
109
+
110
+ results = @rets.get_object("Property", "Photo", "392103:*")
111
+ assert_equal 1, results.size, "Client parsed one object out of the request"
112
+ assert_kind_of RETS4R::Client::DataObject, results[0], "First result isn't a DataObject"
113
+ assert_equal "image/jpeg", results[0].type["Content-Type"], "Content-Type not copied"
114
+ assert_equal "5589", results[0].type["Content-ID"], "Content-ID not copied"
115
+ assert_equal "25478", results[0].type["Object-ID"], "Object-ID not copied"
116
+ assert_equal 241, results[0].data.size, "First object isn't 241 bytes in length"
117
+ end
118
+
119
+ def test_returns_single_entity_object_as_chunked_encoding_in_a_single_element_array
120
+ @response.expects(:[]).with('content-type').at_least_once.returns("image/jpeg")
121
+ @response.expects(:[]).with('Transfer-Encoding').at_least_once.returns("chunked")
122
+ @response.expects(:[]).with('Object-ID').at_least_once.returns("25478")
123
+ @response.expects(:[]).with('Content-ID').at_least_once.returns("5589")
124
+ @response.expects(:body).returns("\000"*241)
125
+
126
+ results = @rets.get_object("Property", "Photo", "392103:*")
127
+ assert_equal 1, results.size, "Client parsed one object out of the request"
128
+ assert_kind_of RETS4R::Client::DataObject, results[0], "First result isn't a DataObject"
129
+ assert_equal "image/jpeg", results[0].type["Content-Type"], "Content-Type not copied"
130
+ assert_equal "5589", results[0].type["Content-ID"], "Content-ID not copied"
131
+ assert_equal "25478", results[0].type["Object-ID"], "Object-ID not copied"
132
+ assert_equal 241, results[0].data.size, "First object isn't 241 bytes in length"
133
+ end
134
+
135
+ def test_yields_data_objects_to_block_and_returns_blocks_value
136
+ @response.expects(:[]).with('content-type').at_least_once.returns("image/jpeg")
137
+ @response.expects(:[]).with('Transfer-Encoding').at_least_once.returns("")
138
+ @response.expects(:[]).with('Content-Length').at_least_once.returns(241)
139
+ @response.expects(:[]).with('Object-ID').at_least_once.returns("25478")
140
+ @response.expects(:[]).with('Content-ID').at_least_once.returns("5589")
141
+ @response.expects(:body).returns("\000"*241)
142
+
143
+ yielded_count = 0
144
+
145
+ value = @rets.get_object("Property", "VRImage", "912:0") do |result|
146
+ assert_kind_of RETS4R::Client::DataObject, result
147
+ yielded_count += 1
148
+ :return_value
149
+ end
150
+
151
+ assert_equal yielded_count, value
152
+ end
153
+ def test_correcly_handles_location_header_url
154
+ @response.expects(:[]).with('content-type').at_least_once.returns("multipart/parallel; boundary='1231'")
155
+ @response.expects(:body).returns(
156
+ "\r\n--1231\r\nContent-ID: 392103\r\nObject-ID: 1\r\nContent-Type: image/jpeg\r\nLocation: http://example.com/391203-1.jpg\r\n\r\n" +
157
+ "\000"*120 +
158
+ "\r\n--1231\r\nContent-ID: 392103\r\nObject-ID: 2\r\nContent-Type: image/gif\r\nLocation: http://example.com/391203-2.gif\r\n\r\n" +
159
+ "\000"*140 +
160
+ "\r\n--1231--"
161
+ )
162
+ results = @rets.get_object("Property", "Photo", "392103:*", true)
163
+
164
+ assert_equal 'http://example.com/391203-1.jpg', results.first.info['Location'], "incorrect location"
165
+ assert_equal 'http://example.com/391203-2.gif', results.last.info['Location'], "incorrect location"
166
+ end
167
+ end
168
+
169
+ class TestClientLogin < Test::Unit::TestCase
170
+ RETS_PORT = '9080'
171
+ RETS_URL = "http://localhost:#{RETS_PORT}"
172
+ RETS_LOGIN = 'login'
173
+ RETS_PASSWORD = 'password'
174
+
175
+ class CustomError < StandardError; end
176
+
177
+ def setup
178
+ @logfile = StringIO.open
179
+ @rets = RETS4R::Client.new(RETS_URL)
180
+ @rets.logger = Logger.new(@logfile)
181
+ @rets.logger.level = Logger::DEBUG
182
+
183
+ @rets.stubs(:request).returns(@response = mock("response"))
184
+ @response.stubs(:body).returns(:body)
185
+ Client::ResponseParser.any_instance.stubs(:parse_key_value).returns(@results = mock("results"))
186
+ @results.stubs(:success?).returns(true)
187
+ @results.stubs(:response).returns(Hash.new)
188
+ @results.stubs(:secondary_response=)
189
+ end
190
+
191
+ def teardown
192
+ @logfile.close
193
+ end
194
+
195
+ def test_successful_login_yields_the_results_to_the_block
196
+ @rets.expects(:request).with {|arg| arg.kind_of?(URI)}.returns(@response)
197
+ Client::ResponseParser.any_instance.expects(:parse_key_value).returns(@results)
198
+ @results.expects(:success?).returns(true)
199
+ @rets.expects(:logout)
200
+
201
+ in_block = false
202
+ @rets.login("user", "pass") do |results|
203
+ assert_equal @results, results
204
+ in_block = true
205
+ end
206
+
207
+ assert in_block, "Block was never yielded to"
208
+ end
209
+
210
+ def test_logout_called_after_block_execution_if_block_raises
211
+ assert_raises(CustomError) do
212
+ @rets.expects(:logout)
213
+ @rets.login("user", "pass") do |results|
214
+ raise CustomError
215
+ end
216
+ end
217
+ end
218
+
219
+ def test_login_returns_the_blocks_value
220
+ rval = @rets.login("user", "pass") do |results|
221
+ :value
222
+ end
223
+
224
+ assert_equal :value, rval
225
+ end
226
+
227
+ def test_login_without_a_block_returns_the_results
228
+ results = @rets.login("user", "pass")
229
+ assert_equal @results, results
230
+ end
231
+ end
232
+
233
+ class TestClient < Test::Unit::TestCase
234
+ RETS_PORT = '9080'
235
+ RETS_URL = "http://localhost:#{RETS_PORT}"
236
+ RETS_LOGIN = 'login'
237
+ RETS_PASSWORD = 'password'
238
+
239
+ def setup
240
+ @logfile = StringIO.open
241
+ @rets = RETS4R::Client.new(RETS_URL)
242
+ @rets.logger = Logger.new(@logfile)
243
+ @rets.logger.level = Logger::DEBUG
244
+ end
245
+
246
+ def teardown
247
+ @logfile.close
248
+ end
249
+
250
+ def test_setup
251
+ assert_nothing_raised() { @rets.user_agent = 'ACK/2.1' }
252
+ assert_equal('ACK/2.1', @rets.user_agent)
253
+
254
+ assert_nothing_raised() { @rets.user_agent = 'SPRETS/0.1' }
255
+ assert_nothing_raised() { @rets.request_method = 'GET' }
256
+
257
+ assert_raise(RETS4R::Client::Unsupported) { @rets.rets_version = '1.4.0' }
258
+ assert_nothing_raised() { @rets.rets_version = '1.5' }
259
+ assert_equal("1.5", @rets.rets_version)
260
+ assert_equal("RETS/1.5", @rets.get_header("RETS-Version"))
261
+ assert_nothing_raised() { @rets.rets_version = '1.7' }
262
+ assert_equal("RETS/1.7", @rets.get_header("RETS-Version"))
263
+
264
+ assert_equal('SPRETS/0.1', @rets.user_agent)
265
+ assert_equal('GET', @rets.request_method)
266
+ assert_equal('1.7', @rets.rets_version)
267
+
268
+ assert_nothing_raised() { @rets.request_method = 'POST' }
269
+
270
+ assert_equal('POST', @rets.request_method)
271
+
272
+
273
+ # Check that our changes were logged when in debug mode
274
+ assert @logfile.length > 0
275
+ end
276
+
277
+ # Just to make sure that we're okay when we don't have a logger, we set it to nil and
278
+ # make a change that would trigger a debug mode log.
279
+ def test_without_logger
280
+ @rets.logger = nil
281
+
282
+ assert_nothing_raised() { @rets.request_method = 'GET' }
283
+ end
284
+
285
+ def test_content_type_parsing
286
+ ct = 'multipart/parallel; boundary=cc2631bb.0165.3b32.8a7d.a8453f662101; charset=utf-8'
287
+
288
+ results = @rets.process_content_type(ct)
289
+
290
+ assert_equal('cc2631bb.0165.3b32.8a7d.a8453f662101', results['boundary'])
291
+ assert_equal('multipart/parallel', results['content-type'])
292
+ assert_equal('utf-8', results['charset'])
293
+ end
294
+
295
+ def test_performs_get_request
296
+ assert_nothing_raised() {@rets.request_method = 'GET'}
297
+ assert_equal('GET', @rets.request_method)
298
+
299
+ http = mock('http')
300
+ response = mock('response')
301
+ response.stubs(:to_hash).returns({})
302
+ response.stubs(:code).returns('500')
303
+ response.stubs(:message).returns('Move along, nothing to see here.')
304
+
305
+ http.expects(:get).with('', {'User-Agent' => @rets.user_agent, 'RETS-Version' => "RETS/#{@rets.rets_version}", 'Accept' => '*/*'}).at_least_once.returns(response)
306
+ http.expects(:post).never
307
+ Net::HTTP.any_instance.expects(:start).at_least_once.yields(http)
308
+
309
+ assert_raises(RETS4R::Client::HTTPError) {@rets.login('user', 'pass')}
310
+ end
311
+
312
+ def test_performs_post_request
313
+ assert_nothing_raised() {@rets.request_method = 'POST'}
314
+ assert_equal('POST', @rets.request_method)
315
+
316
+ http = mock('http')
317
+ response = mock('response')
318
+ response.stubs(:to_hash).returns({})
319
+ response.stubs(:code).returns('500')
320
+ response.stubs(:message).returns('Move along, nothing to see here.')
321
+
322
+ http.expects(:post).with('', '', {'User-Agent' => @rets.user_agent, 'RETS-Version' => "RETS/#{@rets.rets_version}", 'Accept' => '*/*'}).at_least_once.returns(response)
323
+ http.expects(:get).never
324
+ Net::HTTP.any_instance.expects(:start).at_least_once.yields(http)
325
+
326
+ assert_raises(RETS4R::Client::HTTPError) {@rets.login('user', 'pass')}
327
+ end
328
+
329
+ def test_search_without_query_should_not_raise_no_metho_error
330
+ client = RETS4R::Client.new('http://demo.crt.realtors.org:6103/rets/login')
331
+ client.login('Joe', 'Schmoe')
332
+ begin
333
+ client.search('', '', nil)
334
+ # search_uri = URI.parse("http://demo.crt.realtors.org:6103/rets/search")
335
+ # client.send :request, search_uri,
336
+ # {"Query"=>nil, "Format"=>"COMPACT", "Count"=>"0", "QueryType"=>"DMQL2", "Class"=>"", "SearchType"=>""}
337
+ rescue Exception => e
338
+ assert_not_equal "NoMethodError", e.class.to_s
339
+ end
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,39 @@
1
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "test"))
3
+ require 'test_helper'
4
+ require 'rets4r/client/links'
5
+
6
+ class TestClientLinks < Test::Unit::TestCase
7
+ def setup
8
+ @links = RETS4R::Client::Links.from_login_url('http://example.com/login')
9
+ @links['Logout'] = URI.parse('http://example.com/logout')
10
+ @links['GetMetadata'] = URI.parse('http://example.com/metadata')
11
+ @links['GetObject'] = URI.parse('http://example.com/objects')
12
+ @links['Search'] = URI.parse('http://example.com/search')
13
+ @links['Action'] = URI.parse('http://example.com/action')
14
+ end
15
+ def test_should_build_from_login_url
16
+ assert_equal normalize_url('http://example.com/login'), @links['Login'].to_s
17
+ end
18
+ def test_should_access_login
19
+ assert_equal normalize_url('http://example.com/login'), @links.login.to_s
20
+ end
21
+ def test_should_access_logout
22
+ assert_equal normalize_url('http://example.com/logout'), @links.logout.to_s
23
+ end
24
+ def test_should_access_metadata
25
+ assert_equal normalize_url('http://example.com/metadata'), @links.metadata.to_s
26
+ end
27
+ def test_should_access_object
28
+ assert_equal normalize_url('http://example.com/objects'), @links.objects.to_s
29
+ end
30
+ def test_should_access_search
31
+ assert_equal normalize_url('http://example.com/search'), @links.search.to_s
32
+ end
33
+ def test_should_access_action
34
+ assert_equal normalize_url('http://example.com/action'), @links.action.to_s
35
+ end
36
+ def normalize_url(url)
37
+ URI.parse(url).to_s
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "."))
3
+ require 'test_helper'
4
+
5
+ class CompactNokogiriTest < Test::Unit::TestCase
6
+ def test_should_do_stuff
7
+ file = File.expand_path(File.join('test', 'data', '1.5', 'search_compact.xml'))
8
+ listings = RETS4R::Client::CompactNokogiriParser.new(open(file)).to_a
9
+ assert_equal({"Third"=>"Datum3", "Second"=>"Datum2", "First"=>"Datum1"}, listings[0])
10
+ assert_equal({"Third"=>"Datum6", "Second"=>"Datum5", "First"=>"Datum4"}, listings[1])
11
+ end
12
+ def test_should_handle_big_data
13
+ file = File.expand_path(File.join('test', 'data', '1.5', 'bad_compact.xml'))
14
+ listings = RETS4R::Client::CompactNokogiriParser.new(open(file)).to_a
15
+ assert_equal 1, listings.length
16
+ assert_equal 79, listings.first.keys.length
17
+ end
18
+ def test_each_should_yield_between_results
19
+ file = File.expand_path(
20
+ File.join('test', 'data', '1.5', 'search_compact_big.xml'))
21
+ stat = File::Stat.new(file)
22
+ unless stat.size > stat.blksize
23
+ flunk "This test probably won't work on this machine.
24
+ It needs a test input file larger than the native block size."
25
+ end
26
+ stream = open(file)
27
+ positions = []
28
+ listings = RETS4R::Client::CompactNokogiriParser.new(stream).each do |row|
29
+ positions << stream.pos
30
+ end
31
+ assert positions.first < positions.last,
32
+ "data was yielded durring the reading of the stream"
33
+ end
34
+ def test_should_not_include_column_elements_in_keys
35
+ response = "<RETS ReplyCode=\"0\" ReplyText=\"Operation Successful\">\r\n<DELIMITER value=\"09\" />\r\n<COLUMNS>\tDISPLAYORDER\tINPUTDATE\tMEDIADESCR\tMEDIANAME\tMEDIASOURCE\tMEDIATYPE\tMODIFIED\tPICCOUNT\tPRIMARYPIC\tTABLEUID\tUID\t</COLUMNS>\r\n<DATA>\t7\t2009-09-17 07:08:19 \t\tNew 023.jpg\t3155895-11.jpg\tpic\t2009-09-17 07:09:32 \t11\tn\t3155895\t9601458\t</DATA>\r\n<MAXROWS />\r\n</RETS>\r\n"
36
+
37
+ assert RETS4R::Client::CompactNokogiriParser.new(StringIO.new(response)).map.first.keys.grep( /COLUMN/ ).empty?
38
+ end
39
+ context 'non-zero reply code' do
40
+ setup do
41
+ @response = <<-BODY
42
+ <?xml version="1.0"?>
43
+ <RETS ReplyCode="20203" ReplyText="User does not have access to Class named RES. Reference ID: 3fe82558-8015-4d9d-ab0c-776d9e4b5943" />
44
+ BODY
45
+ @parser = RETS4R::Client::CompactNokogiriParser.new(StringIO.new(@response))
46
+ end
47
+ should "raise the execption" do
48
+ assert_raise RETS4R::Client::MiscellaneousSearchErrorException do
49
+ @parser.to_a
50
+ end
51
+ end
52
+ context 'when i parse' do
53
+ should "contain the reply text in the exception message" do
54
+ message = ''
55
+ begin
56
+ @parser.to_a
57
+ rescue Exception => e
58
+ message = e.message
59
+ end
60
+ assert_equal "User does not have access to Class named RES. Reference ID: 3fe82558-8015-4d9d-ab0c-776d9e4b5943", message
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'test/unit'
4
+ require 'rets4r'
5
+ require 'mocha'
6
+ require 'shoulda'
7
+ require 'rubygems'
8
+
9
+ # Configure ListingService
10
+ listing_service_config_file = File.expand_path(File.join('test', 'data', 'listing_service.yml'))
11
+ RETS4R::ListingService.configurations = YAML.load_file(listing_service_config_file)
12
+ RETS4R::ListingService.env = 'test'