rets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,452 @@
1
+ require "helper"
2
+
3
+ class TestMetadata < Test::Unit::TestCase
4
+ def setup
5
+ @root = Rets::Metadata::Root.new
6
+ end
7
+
8
+ def test_metadata_root_fetch_sources_returns_hash_of_metadata_types
9
+ types = []
10
+ fake_fetcher = lambda do |type|
11
+ types << type
12
+ end
13
+
14
+ @root.fetch_sources(&fake_fetcher)
15
+
16
+ assert_equal(Rets::Metadata::METADATA_TYPES, types)
17
+ end
18
+
19
+ def test_metadata_root_intialized_with_block
20
+ external = false
21
+ Rets::Metadata::Root.new { |source| external = true }
22
+ assert external
23
+ end
24
+
25
+ def test_metadata_root_build_tree
26
+ resource = stub(:id => "X")
27
+ Rets::Metadata::Resource.stubs(:build => resource)
28
+ resource_fragment = stub(:resource_fragment)
29
+ resource_container = stub(:rows => [resource_fragment])
30
+ @root.stubs(:metadata_types => { :resource => [resource_container] })
31
+ assert_equal({"x" => resource}, @root.build_tree)
32
+ assert_equal(resource, @root.build_tree["X"])
33
+ end
34
+
35
+ def test_metadata_root_version
36
+ @root.instance_variable_set("@metadata_types", {:system => [stub(:version => "1")]})
37
+ assert_equal "1", @root.version
38
+ end
39
+
40
+ def test_metadata_root_date
41
+ @root.instance_variable_set("@metadata_types", {:system => [stub(:date => "1")]})
42
+ assert_equal "1", @root.date
43
+ end
44
+
45
+ def test_metadata_root_different_version
46
+ @root.stubs(:version).returns("1.2.2")
47
+ @root.stubs(:date).returns("1")
48
+
49
+ current_version = "1.2.3"
50
+ current_timestamp = "1"
51
+
52
+ assert !@root.current?(current_timestamp, current_version)
53
+ end
54
+
55
+ def test_metadata_root_same_version
56
+ @root.stubs(:version).returns("1.2.2")
57
+ @root.stubs(:date).returns("1")
58
+
59
+ current_version = "1.2.2"
60
+ current_timestamp = "2"
61
+
62
+ assert @root.current?(current_timestamp, current_version)
63
+ end
64
+
65
+ def test_metadata_root_no_version_same_timestamp
66
+ @root.stubs(:version).returns("")
67
+ @root.stubs(:date).returns("1")
68
+
69
+ current_version = "1.2.3"
70
+ current_timestamp = "1"
71
+
72
+ assert @root.current?(current_timestamp, current_version)
73
+ end
74
+
75
+ def test_metadata_root_current
76
+ @root.stubs(:version).returns("1.2.2")
77
+ @root.stubs(:date).returns("1")
78
+
79
+ current_timestamp = "1"
80
+ current_version = "1.2.2"
81
+
82
+ assert @root.current?(current_timestamp, current_version)
83
+ end
84
+
85
+ # missing timestamp - this happens in violation of the spec.
86
+ def test_metadata_root_current_ignores_missing_timestamp
87
+ @root.stubs(:version).returns("1.2.2")
88
+ @root.stubs(:date).returns("1")
89
+
90
+ current_timestamp = nil
91
+ current_version = "1.2.2"
92
+
93
+ assert @root.current?(current_timestamp, current_version)
94
+ end
95
+
96
+ # missing version - this happens in violation of the spec.
97
+ def test_metadata_root_current_ignores_missing_version
98
+ @root.stubs(:version).returns("1.2.2")
99
+ @root.stubs(:date).returns("1")
100
+
101
+ current_timestamp = "1"
102
+ current_version = nil
103
+
104
+ assert @root.current?(current_timestamp, current_version)
105
+ end
106
+
107
+ def test_metadata_root_metadata_types_constructs_a_hash_of_metadata_types_from_sources
108
+ test_sources = { "X" => "Y", "Z" => "W" }
109
+ @root.stubs(:sources => test_sources, :build_containers => "Y--")
110
+ @root.metadata_types = nil
111
+ Nokogiri.stubs(:parse => "Y-")
112
+ assert_equal({:x => "Y--", :z => "Y--"}, @root.metadata_types)
113
+ end
114
+
115
+ def test_metadata_root_build_containers_selects_correct_tags
116
+ doc = "<RETS><METADATA-FOO></METADATA-FOO><MET-FOO></MET-FOO><METADATA-BAR /></RETS>"
117
+
118
+ @root.expects(:build_container).with { |fragment| fragment.name == "METADATA-FOO" }
119
+ @root.expects(:build_container).with { |fragment| fragment.name == "METADATA-BAR" }
120
+
121
+ @root.build_containers(Nokogiri.parse(doc))
122
+ end
123
+
124
+ def test_metadata_root_build_container_uses_row_containers_for_resource
125
+ doc = Nokogiri.parse(METADATA_RESOURCE).xpath("//METADATA-RESOURCE").first
126
+
127
+ container = @root.build_container(doc)
128
+
129
+ assert_instance_of Rets::Metadata::Containers::ResourceContainer, container
130
+
131
+ assert_equal 13, container.resources.size
132
+
133
+ resource = container.resources.first
134
+
135
+ assert_equal "ActiveAgent", resource["StandardName"]
136
+ end
137
+
138
+ def test_metadata_root_build_container_uses_system_container_for_system
139
+ doc = Nokogiri.parse(METADATA_SYSTEM).xpath("//METADATA-SYSTEM").first
140
+
141
+ container = @root.build_container(doc)
142
+ assert_instance_of Rets::Metadata::Containers::SystemContainer, container
143
+ end
144
+
145
+ def test_metadata_root_build_container_uses_base_container_for_unknown_metadata_types
146
+ doc = Nokogiri.parse(METADATA_UNKNOWN).xpath("//METADATA-FOO").first
147
+
148
+ container = @root.build_container(doc)
149
+ assert_instance_of Rets::Metadata::Containers::Container, container
150
+ end
151
+
152
+ def test_metadata_uses
153
+ #TODO
154
+ end
155
+
156
+ def test_resource_initialize
157
+ fragment = { "ResourceID" => 'r' }
158
+ resource = Rets::Metadata::Resource.new(fragment)
159
+ assert_equal('r', resource.id)
160
+ assert_equal([], resource.rets_classes)
161
+ end
162
+
163
+ def test_resource_build_lookup_tree
164
+ metadata = stub(:metadata)
165
+ resource = stub(:resource)
166
+
167
+ Rets::Metadata::Resource.expects(:find_lookup_containers).
168
+ with(metadata, resource).
169
+ returns([stub(:lookups => [{"LookupName" => "Foo"}])])
170
+
171
+ Rets::Metadata::Resource.expects(:find_lookup_type_containers).
172
+ with(metadata, resource, "Foo").
173
+ returns([stub(:lookup_types => [{"Value" => "111", "LongValue" => "Bar"}])])
174
+
175
+ tree = Rets::Metadata::Resource.build_lookup_tree(resource, metadata)
176
+
177
+ assert_equal ["Foo"], tree.keys
178
+ assert_equal 1, tree["Foo"].size
179
+
180
+ lookup_type = tree["Foo"].first
181
+
182
+ assert_equal "111", lookup_type.value
183
+ assert_equal "Bar", lookup_type.long_value
184
+ end
185
+
186
+ def test_resource_build_classes
187
+ resource = stub(:resource)
188
+ metadata = stub(:metadata)
189
+ rets_class = stub(:rets_class)
190
+ rets_class_fragment = stub(:rets_class_fragment)
191
+
192
+ Rets::Metadata::RetsClass.expects(:build).with(rets_class_fragment, resource, metadata).returns(rets_class)
193
+ Rets::Metadata::Resource.expects(:find_rets_classes).with(metadata, resource).returns([rets_class_fragment])
194
+
195
+ classes = Rets::Metadata::Resource.build_classes(resource, metadata)
196
+ assert([rets_class], classes)
197
+ end
198
+
199
+ def test_resource_build
200
+ fragment = { "ResourceID" => "test" }
201
+
202
+ lookup_types = stub(:lookup_types)
203
+ classes = stub(:classes)
204
+ metadata = stub(:metadata)
205
+
206
+ Rets::Metadata::Resource.stubs(:build_lookup_tree => lookup_types)
207
+ Rets::Metadata::Resource.stubs(:build_classes => classes)
208
+
209
+ resource = Rets::Metadata::Resource.build(fragment, metadata)
210
+
211
+ assert_equal(lookup_types, resource.lookup_types)
212
+ assert_equal(classes, resource.rets_classes)
213
+ end
214
+
215
+ def test_resource_find_lookup_containers
216
+ resource = stub(:id => "id")
217
+ metadata = { :lookup => [stub(:resource => "id"), stub(:resource => "id"), stub(:resource => "a")] }
218
+
219
+ lookup_containers = Rets::Metadata::Resource.find_lookup_containers(metadata, resource)
220
+
221
+ assert_equal(2, lookup_containers.size)
222
+ assert_equal(["id", "id"], lookup_containers.map(&:resource))
223
+ end
224
+
225
+ def test_resource_find_lookup_type_containers
226
+ resource = stub(:id => "id")
227
+ metadata = { :lookup_type => [stub(:resource => "id", :lookup => "look"),
228
+ stub(:resource => "id", :lookup => "look"),
229
+ stub(:resource => "id", :lookup => "not_look"),
230
+ stub(:resource => "a", :lookup => "look"),
231
+ stub(:resource => "a", :lookup => "not_look")
232
+ ]}
233
+
234
+ lookup_type_containers = Rets::Metadata::Resource.find_lookup_type_containers(metadata, resource, "look")
235
+
236
+ assert_equal(2, lookup_type_containers.size)
237
+ assert_equal(["id", "id"], lookup_type_containers.map(&:resource))
238
+ end
239
+
240
+ def test_resource_find_rets_classes
241
+ resource = stub(:id => "id")
242
+ rets_classes = stub(:rets_classes)
243
+
244
+ metadata = { :class => [stub(:resource => "id", :classes => rets_classes),
245
+ stub(:resource => "id", :classes => rets_classes),
246
+ stub(:resource => "a")]}
247
+
248
+ assert_equal(rets_classes, Rets::Metadata::Resource.find_rets_classes(metadata, resource))
249
+ end
250
+
251
+ def test_resource_find_rets_class
252
+ resource = Rets::Metadata::Resource.new({})
253
+ value = mock(:name => "test")
254
+
255
+ resource.expects(:rets_classes).returns([value])
256
+ assert_equal(value, resource.find_rets_class("test"))
257
+ end
258
+
259
+ def test_lookup_type_initialize
260
+ fragment = { "Value" => 'a', "ShortValue" => 'b', "LongValue" => 'c' }
261
+
262
+ lookup_type = Rets::Metadata::LookupType.new(fragment)
263
+
264
+ assert_equal('a', lookup_type.value)
265
+ assert_equal('b', lookup_type.short_value)
266
+ assert_equal('c', lookup_type.long_value)
267
+ end
268
+ def test_rets_class_find_table
269
+ rets_class = Rets::Metadata::RetsClass.new({}, "resource")
270
+ value = mock(:name => "test")
271
+
272
+ rets_class.expects(:tables).returns([value])
273
+ assert_equal(value, rets_class.find_table("test"))
274
+ end
275
+
276
+ def test_rets_class_find_table_container
277
+ resource = mock(:id => "a")
278
+ rets_class = mock(:name => "b")
279
+ table = mock(:resource => "a", :class => "b")
280
+
281
+ metadata = { :table => [table] }
282
+
283
+ assert_equal(table, Rets::Metadata::RetsClass.find_table_container(metadata, resource, rets_class))
284
+ end
285
+
286
+ def test_rets_class_build
287
+ resource = stub(:resource)
288
+ table_fragment = stub(:fragment)
289
+ table_container = stub(:tables => [table_fragment])
290
+ table = stub(:table)
291
+
292
+ Rets::Metadata::TableFactory.expects(:build).with(table_fragment, resource).returns(table)
293
+ Rets::Metadata::RetsClass.expects(:find_table_container).returns(table_container)
294
+
295
+ rets_class = Rets::Metadata::RetsClass.build({}, resource, "")
296
+
297
+ assert_equal(rets_class.tables, [table])
298
+ end
299
+
300
+ def test_rets_class_build_when_find_table_container_returns_nil
301
+ new_rets_class = stub(:new_rets_class)
302
+ Rets::Metadata::RetsClass.stubs(:new => new_rets_class)
303
+ Rets::Metadata::RetsClass.stubs(:find_table_container => nil)
304
+ Rets::Metadata::RetsClass.build({}, "", "")
305
+ end
306
+
307
+
308
+ def test_rets_class_initialize
309
+ fragment = { "ClassName" => "A" }
310
+ rets_class = Rets::Metadata::RetsClass.new(fragment, "resource")
311
+
312
+ assert_equal("A", rets_class.name)
313
+ assert_equal("resource", rets_class.resource)
314
+ assert_equal([], rets_class.tables)
315
+ end
316
+
317
+ def test_table_factory_creates_lookup_table
318
+ assert_instance_of Rets::Metadata::LookupTable, Rets::Metadata::TableFactory.build({"LookupName" => "Foo", "Interpretation" => "Lookup"}, nil)
319
+ end
320
+
321
+ def test_table_factory_creates_table
322
+ assert_instance_of Rets::Metadata::Table, Rets::Metadata::TableFactory.build({"LookupName" => "", "Interpretation" => ""}, nil)
323
+ end
324
+
325
+ def test_table_factory_enum
326
+ assert Rets::Metadata::TableFactory.enum?("LookupName" => "Foo", "Interpretation" => "Lookup")
327
+ assert !Rets::Metadata::TableFactory.enum?("LookupName" => "", "Interpretation" => "SomethingElse")
328
+ assert !Rets::Metadata::TableFactory.enum?("LookupName" => "Foo", "Interpretation" => "")
329
+ assert !Rets::Metadata::TableFactory.enum?("LookupName" => "", "Interpretation" => "SomethingElse")
330
+ end
331
+
332
+ def test_lookup_table_initialize
333
+ fragment = { "SystemName" => "A", "Interpretation" => "B", "LookupName" => "C" }
334
+
335
+ lookup_table = Rets::Metadata::LookupTable.new(fragment, "Foo")
336
+
337
+ assert_equal("Foo", lookup_table.resource)
338
+ assert_equal("A", lookup_table.name)
339
+ assert_equal("C", lookup_table.lookup_name)
340
+ assert_equal("B", lookup_table.interpretation)
341
+ end
342
+
343
+ def test_lookup_table_resolve_returns_empty_array_when_value_is_empty_and_is_multi?
344
+
345
+ lookup_table = Rets::Metadata::LookupTable.new({}, nil)
346
+ lookup_table.stubs(:multi? => true)
347
+
348
+ assert_equal [], lookup_table.resolve("")
349
+ end
350
+
351
+ def test_lookup_table_resolve_returns_single_value_if_not_multi
352
+ lookup_table = Rets::Metadata::LookupTable.new({}, nil)
353
+ lookup_table.stubs(:multi? => false)
354
+
355
+ lookup_table.expects(:lookup_type).with("A,B").returns(mock(:long_value => "AaaBbb"))
356
+
357
+ assert_equal "AaaBbb", lookup_table.resolve("A,B")
358
+ end
359
+
360
+ def test_lookup_table_resolve_returns_multi_value_array_when_multi
361
+ fragment = { "Interpretation" => "LookupMulti" }
362
+
363
+ lookup_table = Rets::Metadata::LookupTable.new(fragment, nil)
364
+
365
+ lookup_table.expects(:lookup_type).with("A").returns(mock(:long_value => "Aaa"))
366
+ lookup_table.expects(:lookup_type).with("B").returns(mock(:long_value => "Bbb"))
367
+
368
+ assert_equal ["Aaa", "Bbb"], lookup_table.resolve("A,B")
369
+ end
370
+
371
+ #Sandicor does this :|
372
+ def test_lookup_table_resolve_returns_multi_value_array_when_multi_with_quoted_values
373
+ fragment = { "Interpretation" => "LookupMulti" }
374
+
375
+ lookup_table = Rets::Metadata::LookupTable.new(fragment, nil)
376
+
377
+ lookup_table.expects(:lookup_type).with("A").returns(mock(:long_value => "Aaa"))
378
+ lookup_table.expects(:lookup_type).with("B").returns(mock(:long_value => "Bbb"))
379
+
380
+ assert_equal ["Aaa", "Bbb"], lookup_table.resolve(%q["A","B"])
381
+ end
382
+
383
+ # This scenario is unfortunately common.
384
+ def test_lookup_table_resolve_returns_nil_when_lookup_type_is_not_present_for_multi_value
385
+ fragment = { "Interpretation" => "LookupMulti" }
386
+
387
+ lookup_table = Rets::Metadata::LookupTable.new(fragment, nil)
388
+
389
+ lookup_table.expects(:lookup_type).with("A").returns(mock(:long_value => "Aaa"))
390
+ lookup_table.expects(:lookup_type).with("B").returns(nil)
391
+
392
+ lookup_table.expects(:warn).with("Discarding unmappable value of #{"B".inspect}")
393
+
394
+ assert_equal ["Aaa", ""], lookup_table.resolve("A,B")
395
+ end
396
+
397
+ # This scenario is unfortunately common.
398
+ def test_lookup_table_resolve_returns_nil_when_lookup_type_is_not_present_for_single_value
399
+
400
+ lookup_table = Rets::Metadata::LookupTable.new({}, nil)
401
+ lookup_table.stubs(:multi? => true)
402
+
403
+ lookup_table.expects(:lookup_type).with("A").returns(nil)
404
+
405
+ lookup_table.expects(:warn).with("Discarding unmappable value of #{"A".inspect}")
406
+
407
+ assert_equal [""], lookup_table.resolve("A")
408
+ end
409
+
410
+ def test_table_initialize
411
+ fragment = { "DataType" => "A", "SystemName" => "B" }
412
+
413
+ table = Rets::Metadata::Table.new(fragment)
414
+ assert_equal("A", table.type)
415
+ assert_equal("B", table.name)
416
+ end
417
+
418
+ def test_table_resolve_returns_empty_string_when_value_nil
419
+ table = Rets::Metadata::Table.new({})
420
+
421
+ assert_equal "", table.resolve(nil)
422
+ end
423
+
424
+ def test_table_resolve_passes_values_straight_through
425
+ table = Rets::Metadata::Table.new({})
426
+
427
+ assert_equal "Foo", table.resolve("Foo")
428
+ end
429
+
430
+ def test_table_resolve_passes_values_strips_extra_whitspace
431
+ table = Rets::Metadata::Table.new({})
432
+
433
+ assert_equal "Foo", table.resolve(" Foo ")
434
+ end
435
+
436
+ def test_root_can_be_serialized
437
+ sources = { :x => "a" }
438
+
439
+ @root.sources = sources
440
+
441
+ assert_equal sources, @root.marshal_dump
442
+ end
443
+
444
+ def test_root_can_be_unserialized
445
+ sources = { :x => "a" }
446
+
447
+ @root.marshal_load(sources)
448
+
449
+ assert_equal sources, @root.sources
450
+ end
451
+
452
+ end
@@ -0,0 +1,71 @@
1
+ require "helper"
2
+
3
+ class TestParserCompact < Test::Unit::TestCase
4
+ def test_parse_document_raises_on_invalid_delimiter
5
+ assert_raise 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_example
60
+ rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT))
61
+
62
+ assert_equal "7", rows.first["MetadataEntryID"]
63
+ end
64
+
65
+ def test_parse_example_2
66
+ rows = Rets::Parser::Compact.parse_document(Nokogiri.parse(SAMPLE_COMPACT_2))
67
+
68
+ assert_equal "", rows.first["ModTimeStamp"]
69
+ end
70
+
71
+ end