spark_api 1.0.0

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.
Files changed (257) hide show
  1. data/History.txt +139 -0
  2. data/LICENSE +14 -0
  3. data/README.md +153 -0
  4. data/Rakefile +18 -0
  5. data/VERSION +1 -0
  6. data/bin/spark_api +8 -0
  7. data/bin/spark_api~ +8 -0
  8. data/lib/spark_api.rb +46 -0
  9. data/lib/spark_api/authentication.rb +55 -0
  10. data/lib/spark_api/authentication/api_auth.rb +104 -0
  11. data/lib/spark_api/authentication/api_auth.rb~ +104 -0
  12. data/lib/spark_api/authentication/base_auth.rb +47 -0
  13. data/lib/spark_api/authentication/base_auth.rb~ +47 -0
  14. data/lib/spark_api/authentication/oauth2.rb +198 -0
  15. data/lib/spark_api/authentication/oauth2.rb~ +199 -0
  16. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +87 -0
  17. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb~ +87 -0
  18. data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb +48 -0
  19. data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb~ +49 -0
  20. data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb +44 -0
  21. data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb~ +45 -0
  22. data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb +35 -0
  23. data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb~ +36 -0
  24. data/lib/spark_api/authentication/oauth2_impl/middleware.rb +38 -0
  25. data/lib/spark_api/authentication/oauth2_impl/middleware.rb~ +39 -0
  26. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb +24 -0
  27. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb~ +25 -0
  28. data/lib/spark_api/cli.rb +158 -0
  29. data/lib/spark_api/cli.rb~ +158 -0
  30. data/lib/spark_api/cli/api_auth.rb +8 -0
  31. data/lib/spark_api/cli/api_auth.rb~ +8 -0
  32. data/lib/spark_api/cli/oauth2.rb +14 -0
  33. data/lib/spark_api/cli/oauth2.rb~ +14 -0
  34. data/lib/spark_api/cli/setup.rb +47 -0
  35. data/lib/spark_api/cli/setup.rb~ +47 -0
  36. data/lib/spark_api/client.rb +27 -0
  37. data/lib/spark_api/configuration.rb +54 -0
  38. data/lib/spark_api/configuration.rb~ +54 -0
  39. data/lib/spark_api/configuration/yaml.rb +101 -0
  40. data/lib/spark_api/configuration/yaml.rb~ +101 -0
  41. data/lib/spark_api/connection.rb +42 -0
  42. data/lib/spark_api/faraday.rb +64 -0
  43. data/lib/spark_api/faraday.rb~ +64 -0
  44. data/lib/spark_api/models.rb +33 -0
  45. data/lib/spark_api/models.rb~ +33 -0
  46. data/lib/spark_api/models/account.rb +115 -0
  47. data/lib/spark_api/models/account.rb~ +115 -0
  48. data/lib/spark_api/models/base.rb +118 -0
  49. data/lib/spark_api/models/base.rb~ +118 -0
  50. data/lib/spark_api/models/connect_prefs.rb +10 -0
  51. data/lib/spark_api/models/connect_prefs.rb~ +10 -0
  52. data/lib/spark_api/models/constraint.rb +16 -0
  53. data/lib/spark_api/models/constraint.rb~ +16 -0
  54. data/lib/spark_api/models/contact.rb +49 -0
  55. data/lib/spark_api/models/contact.rb~ +49 -0
  56. data/lib/spark_api/models/custom_fields.rb +12 -0
  57. data/lib/spark_api/models/custom_fields.rb~ +12 -0
  58. data/lib/spark_api/models/document.rb +11 -0
  59. data/lib/spark_api/models/document.rb~ +11 -0
  60. data/lib/spark_api/models/finders.rb +45 -0
  61. data/lib/spark_api/models/finders.rb~ +45 -0
  62. data/lib/spark_api/models/idx_link.rb +47 -0
  63. data/lib/spark_api/models/idx_link.rb~ +47 -0
  64. data/lib/spark_api/models/listing.rb +197 -0
  65. data/lib/spark_api/models/listing.rb~ +197 -0
  66. data/lib/spark_api/models/listing_cart.rb +72 -0
  67. data/lib/spark_api/models/listing_cart.rb~ +72 -0
  68. data/lib/spark_api/models/market_statistics.rb +33 -0
  69. data/lib/spark_api/models/market_statistics.rb~ +33 -0
  70. data/lib/spark_api/models/message.rb +21 -0
  71. data/lib/spark_api/models/message.rb~ +21 -0
  72. data/lib/spark_api/models/note.rb +41 -0
  73. data/lib/spark_api/models/note.rb~ +41 -0
  74. data/lib/spark_api/models/notification.rb +42 -0
  75. data/lib/spark_api/models/notification.rb~ +42 -0
  76. data/lib/spark_api/models/open_house.rb +24 -0
  77. data/lib/spark_api/models/open_house.rb~ +24 -0
  78. data/lib/spark_api/models/photo.rb +70 -0
  79. data/lib/spark_api/models/photo.rb~ +70 -0
  80. data/lib/spark_api/models/property_types.rb +7 -0
  81. data/lib/spark_api/models/property_types.rb~ +7 -0
  82. data/lib/spark_api/models/saved_search.rb +16 -0
  83. data/lib/spark_api/models/saved_search.rb~ +16 -0
  84. data/lib/spark_api/models/shared_listing.rb +35 -0
  85. data/lib/spark_api/models/shared_listing.rb~ +35 -0
  86. data/lib/spark_api/models/standard_fields.rb +50 -0
  87. data/lib/spark_api/models/standard_fields.rb~ +50 -0
  88. data/lib/spark_api/models/subresource.rb +19 -0
  89. data/lib/spark_api/models/subresource.rb~ +19 -0
  90. data/lib/spark_api/models/system_info.rb +14 -0
  91. data/lib/spark_api/models/system_info.rb~ +14 -0
  92. data/lib/spark_api/models/tour_of_home.rb +24 -0
  93. data/lib/spark_api/models/tour_of_home.rb~ +24 -0
  94. data/lib/spark_api/models/video.rb +16 -0
  95. data/lib/spark_api/models/video.rb~ +16 -0
  96. data/lib/spark_api/models/virtual_tour.rb +18 -0
  97. data/lib/spark_api/models/virtual_tour.rb~ +18 -0
  98. data/lib/spark_api/multi_client.rb +59 -0
  99. data/lib/spark_api/multi_client.rb~ +59 -0
  100. data/lib/spark_api/paginate.rb +109 -0
  101. data/lib/spark_api/paginate.rb~ +109 -0
  102. data/lib/spark_api/primary_array.rb +29 -0
  103. data/lib/spark_api/primary_array.rb~ +29 -0
  104. data/lib/spark_api/request.rb +96 -0
  105. data/lib/spark_api/request.rb~ +96 -0
  106. data/lib/spark_api/response.rb +70 -0
  107. data/lib/spark_api/response.rb~ +70 -0
  108. data/lib/spark_api/version.rb +4 -0
  109. data/lib/spark_api/version.rb~ +4 -0
  110. data/script/console +6 -0
  111. data/script/console~ +6 -0
  112. data/script/example.rb +27 -0
  113. data/script/example.rb~ +27 -0
  114. data/spec/fixtures/accounts/all.json +160 -0
  115. data/spec/fixtures/accounts/my.json +74 -0
  116. data/spec/fixtures/accounts/my_portal.json +20 -0
  117. data/spec/fixtures/accounts/my_put.json +5 -0
  118. data/spec/fixtures/accounts/my_save.json +5 -0
  119. data/spec/fixtures/accounts/office.json +142 -0
  120. data/spec/fixtures/accounts/password_save.json +6 -0
  121. data/spec/fixtures/authentication_failure.json +7 -0
  122. data/spec/fixtures/base.json +13 -0
  123. data/spec/fixtures/contacts/contacts.json +28 -0
  124. data/spec/fixtures/contacts/my.json +19 -0
  125. data/spec/fixtures/contacts/new.json +11 -0
  126. data/spec/fixtures/contacts/new_empty.json +8 -0
  127. data/spec/fixtures/contacts/new_notify.json +11 -0
  128. data/spec/fixtures/contacts/post.json +10 -0
  129. data/spec/fixtures/contacts/tags.json +11 -0
  130. data/spec/fixtures/count.json +10 -0
  131. data/spec/fixtures/empty.json +3 -0
  132. data/spec/fixtures/errors/expired.json +7 -0
  133. data/spec/fixtures/errors/failure.json +5 -0
  134. data/spec/fixtures/errors/failure_with_constraint.json +17 -0
  135. data/spec/fixtures/errors/failure_with_msg.json +7 -0
  136. data/spec/fixtures/generic_delete.json +1 -0
  137. data/spec/fixtures/generic_failure.json +5 -0
  138. data/spec/fixtures/listing_carts/add_listing.json +13 -0
  139. data/spec/fixtures/listing_carts/add_listing_post.json +5 -0
  140. data/spec/fixtures/listing_carts/empty.json +5 -0
  141. data/spec/fixtures/listing_carts/listing_cart.json +19 -0
  142. data/spec/fixtures/listing_carts/new.json +12 -0
  143. data/spec/fixtures/listing_carts/post.json +10 -0
  144. data/spec/fixtures/listing_carts/remove_listing.json +13 -0
  145. data/spec/fixtures/listings/constraints.json +18 -0
  146. data/spec/fixtures/listings/constraints_with_pagination.json +24 -0
  147. data/spec/fixtures/listings/document_index.json +19 -0
  148. data/spec/fixtures/listings/multiple.json +69 -0
  149. data/spec/fixtures/listings/no_subresources.json +38 -0
  150. data/spec/fixtures/listings/open_houses.json +21 -0
  151. data/spec/fixtures/listings/photos/index.json +469 -0
  152. data/spec/fixtures/listings/photos/new.json +12 -0
  153. data/spec/fixtures/listings/photos/post.json +20 -0
  154. data/spec/fixtures/listings/put.json +5 -0
  155. data/spec/fixtures/listings/put_expiration_date.json +5 -0
  156. data/spec/fixtures/listings/saved_search.json +17 -0
  157. data/spec/fixtures/listings/shared_listing_get.json +14 -0
  158. data/spec/fixtures/listings/shared_listing_new.json +9 -0
  159. data/spec/fixtures/listings/shared_listing_post.json +10 -0
  160. data/spec/fixtures/listings/tour_of_homes.json +23 -0
  161. data/spec/fixtures/listings/videos_index.json +18 -0
  162. data/spec/fixtures/listings/virtual_tours_index.json +42 -0
  163. data/spec/fixtures/listings/with_documents.json +52 -0
  164. data/spec/fixtures/listings/with_permissions.json +44 -0
  165. data/spec/fixtures/listings/with_photos.json +110 -0
  166. data/spec/fixtures/listings/with_supplement.json +39 -0
  167. data/spec/fixtures/listings/with_videos.json +54 -0
  168. data/spec/fixtures/listings/with_vtour.json +48 -0
  169. data/spec/fixtures/logo_fbs.png +0 -0
  170. data/spec/fixtures/messages/new.json +14 -0
  171. data/spec/fixtures/messages/new_empty.json +7 -0
  172. data/spec/fixtures/messages/new_with_recipients.json +15 -0
  173. data/spec/fixtures/messages/post.json +5 -0
  174. data/spec/fixtures/notes/add.json +11 -0
  175. data/spec/fixtures/notes/agent_shared.json +11 -0
  176. data/spec/fixtures/notes/agent_shared_empty.json +7 -0
  177. data/spec/fixtures/notes/new.json +5 -0
  178. data/spec/fixtures/notifications/mark_read.json +1 -0
  179. data/spec/fixtures/notifications/new.json +8 -0
  180. data/spec/fixtures/notifications/new_empty.json +7 -0
  181. data/spec/fixtures/notifications/notifications.json +43 -0
  182. data/spec/fixtures/notifications/post.json +10 -0
  183. data/spec/fixtures/notifications/unread.json +10 -0
  184. data/spec/fixtures/oauth2/access.json +3 -0
  185. data/spec/fixtures/oauth2/access_with_old_refresh.json +5 -0
  186. data/spec/fixtures/oauth2/access_with_refresh.json +5 -0
  187. data/spec/fixtures/oauth2/authorization_code_body.json +7 -0
  188. data/spec/fixtures/oauth2/error.json +3 -0
  189. data/spec/fixtures/oauth2/password_body.json +7 -0
  190. data/spec/fixtures/oauth2/refresh_body.json +7 -0
  191. data/spec/fixtures/oauth2_error.json +3 -0
  192. data/spec/fixtures/property_types/property_types.json +31 -0
  193. data/spec/fixtures/session.json +10 -0
  194. data/spec/fixtures/standardfields/city.json +1031 -0
  195. data/spec/fixtures/standardfields/nearby.json +53 -0
  196. data/spec/fixtures/standardfields/standardfields.json +188 -0
  197. data/spec/fixtures/standardfields/stateorprovince.json +36 -0
  198. data/spec/fixtures/success.json +5 -0
  199. data/spec/json_helper.rb +76 -0
  200. data/spec/mock_helper.rb +124 -0
  201. data/spec/oauth2_helper.rb +68 -0
  202. data/spec/spec_helper.rb +48 -0
  203. data/spec/unit/flexmls_api_spec.rb~ +23 -0
  204. data/spec/unit/spark_api/authentication/api_auth_spec.rb +169 -0
  205. data/spec/unit/spark_api/authentication/api_auth_spec.rb~ +169 -0
  206. data/spec/unit/spark_api/authentication/base_auth_spec.rb +10 -0
  207. data/spec/unit/spark_api/authentication/base_auth_spec.rb~ +10 -0
  208. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb +10 -0
  209. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb~ +10 -0
  210. data/spec/unit/spark_api/authentication/oauth2_spec.rb +205 -0
  211. data/spec/unit/spark_api/authentication/oauth2_spec.rb~ +205 -0
  212. data/spec/unit/spark_api/authentication_spec.rb +38 -0
  213. data/spec/unit/spark_api/authentication_spec.rb~ +38 -0
  214. data/spec/unit/spark_api/configuration/yaml_spec.rb +72 -0
  215. data/spec/unit/spark_api/configuration/yaml_spec.rb~ +72 -0
  216. data/spec/unit/spark_api/configuration_spec.rb +122 -0
  217. data/spec/unit/spark_api/configuration_spec.rb~ +122 -0
  218. data/spec/unit/spark_api/faraday_spec.rb +90 -0
  219. data/spec/unit/spark_api/faraday_spec.rb~ +90 -0
  220. data/spec/unit/spark_api/models/account_spec.rb +176 -0
  221. data/spec/unit/spark_api/models/base_spec.rb +106 -0
  222. data/spec/unit/spark_api/models/connect_prefs_spec.rb +9 -0
  223. data/spec/unit/spark_api/models/constraint_spec.rb +19 -0
  224. data/spec/unit/spark_api/models/contact_spec.rb +108 -0
  225. data/spec/unit/spark_api/models/contact_spec.rb~ +108 -0
  226. data/spec/unit/spark_api/models/document_spec.rb +32 -0
  227. data/spec/unit/spark_api/models/listing_cart_spec.rb +127 -0
  228. data/spec/unit/spark_api/models/listing_cart_spec.rb~ +127 -0
  229. data/spec/unit/spark_api/models/listing_spec.rb +320 -0
  230. data/spec/unit/spark_api/models/listing_spec.rb~ +320 -0
  231. data/spec/unit/spark_api/models/message_spec.rb +47 -0
  232. data/spec/unit/spark_api/models/message_spec.rb~ +47 -0
  233. data/spec/unit/spark_api/models/note_spec.rb +63 -0
  234. data/spec/unit/spark_api/models/note_spec.rb~ +63 -0
  235. data/spec/unit/spark_api/models/notification_spec.rb +62 -0
  236. data/spec/unit/spark_api/models/notification_spec.rb~ +62 -0
  237. data/spec/unit/spark_api/models/open_house_spec.rb +39 -0
  238. data/spec/unit/spark_api/models/photo_spec.rb +92 -0
  239. data/spec/unit/spark_api/models/property_types_spec.rb +33 -0
  240. data/spec/unit/spark_api/models/saved_search_spec.rb +40 -0
  241. data/spec/unit/spark_api/models/shared_listing_spec.rb +45 -0
  242. data/spec/unit/spark_api/models/shared_listing_spec.rb~ +45 -0
  243. data/spec/unit/spark_api/models/standard_fields_spec.rb +60 -0
  244. data/spec/unit/spark_api/models/system_info_spec.rb +83 -0
  245. data/spec/unit/spark_api/models/tour_of_home_spec.rb +44 -0
  246. data/spec/unit/spark_api/models/video_spec.rb +36 -0
  247. data/spec/unit/spark_api/models/virtual_tour_spec.rb +44 -0
  248. data/spec/unit/spark_api/multi_client_spec.rb +56 -0
  249. data/spec/unit/spark_api/multi_client_spec.rb~ +56 -0
  250. data/spec/unit/spark_api/paginate_spec.rb +224 -0
  251. data/spec/unit/spark_api/paginate_spec.rb~ +224 -0
  252. data/spec/unit/spark_api/primary_array_spec.rb +41 -0
  253. data/spec/unit/spark_api/primary_array_spec.rb~ +41 -0
  254. data/spec/unit/spark_api/request_spec.rb +344 -0
  255. data/spec/unit/spark_api/request_spec.rb~ +344 -0
  256. data/spec/unit/spark_api_spec.rb +23 -0
  257. metadata +725 -0
@@ -0,0 +1,320 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe Listing do
4
+ before(:each) do
5
+
6
+ @listing = Listing.new({
7
+ "ResourceUri"=>"/v1/listings/20080619000032866372000000",
8
+ "StandardFields"=>{
9
+ "StreetNumber"=>"100",
10
+ "ListingId"=>"07-32",
11
+ "City"=>"Fargo",
12
+ "Longitude"=>"",
13
+ "StreetName"=>"Someone's",
14
+ "YearBuilt"=>nil,
15
+ "BuildingAreaTotal"=>"1321.0",
16
+ "PublicRemarks"=>nil,
17
+ "PostalCode"=>"55320",
18
+ "ListPrice"=>"100000.0",
19
+ "BathsThreeQuarter"=>nil,
20
+ "Latitude"=>"",
21
+ "StreetDirPrefix"=>nil,
22
+ "StreetAdditionalInfo"=>"********",
23
+ "PropertyType"=>"A",
24
+ "StateOrProvince"=>"ND",
25
+ "BathsTotal"=>"0.0",
26
+ "BathsFull"=>nil,
27
+ "ListingKey"=>"20080619000032866372000000",
28
+ "StreetSuffix"=>"St",
29
+ "StreetDirSuffix"=>"********",
30
+ "BedsTotal"=>2,
31
+ "ModificationTimestamp"=>"2010-11-22T23:36:42Z",
32
+ "BathsHalf"=>nil,
33
+ "CountyOrParish"=>nil,
34
+ "Photos" => [{
35
+ "Uri300"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000.jpg",
36
+ "ResourceUri"=>"/v1/listings/20080619000032866372000000/photos/20101115201631519737000000",
37
+ "Name"=>"Designer Entry w/14' Ceilings",
38
+ "Primary"=>true,
39
+ "Id"=>"20101115201631519737000000",
40
+ "Uri800"=>"http=>//devresize.flexmls.com/fgo/800x600/true/20101115201631519737000000-o.jpg",
41
+ "Uri1024"=>"http=>//devresize.flexmls.com/fgo/1024x768/true/20101115201631519737000000-o.jpg",
42
+ "UriLarge"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000-o.jpg",
43
+ "Caption"=>"apostrophe test for CUR-10508",
44
+ "Uri1280"=>"http=>//devresize.flexmls.com/fgo/1280x1024/true/20101115201631519737000000-o.jpg",
45
+ "UriThumb"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000-t.jpg",
46
+ "Uri640"=>"http=>//devresize.flexmls.com/fgo/640x480/true/20101115201631519737000000-o.jpg"
47
+ }]
48
+ },
49
+ "Id"=>"20080619000032866372000000"
50
+ })
51
+
52
+ end
53
+
54
+ describe "attributes" do
55
+ it "should allow access to fields" do
56
+ @listing.StandardFields.should be_a(Hash)
57
+ @listing.StandardFields['ListingId'].should be_a(String)
58
+ @listing.StandardFields['ListPrice'].should match(@listing.ListPrice)
59
+ @listing.photos.should be_a(Array)
60
+ end
61
+
62
+ it "should not respond to removed attributes" do
63
+ @listing.should_not respond_to(:Photos)
64
+ @listing.should_not respond_to(:Documents)
65
+ @listing.should_not respond_to(:VirtualTours)
66
+ @listing.should_not respond_to(:Videos)
67
+ end
68
+
69
+ it "should return street address" do
70
+ @listing.street_address.should eq("100 Someone's St")
71
+ end
72
+
73
+ it "should return the regional address" do
74
+ @listing.region_address.should eq("Fargo, ND 55320")
75
+ end
76
+
77
+ it "should return full address" do
78
+ @listing.full_address.should eq("100 Someone's St, Fargo, ND 55320")
79
+ end
80
+ end
81
+
82
+ describe "class methods" do
83
+ it "should respond to find" do
84
+ Listing.should respond_to(:find)
85
+ end
86
+
87
+ it "should respond to first" do
88
+ Listing.should respond_to(:first)
89
+ end
90
+
91
+ it "should respond to last" do
92
+ Listing.should respond_to(:last)
93
+ end
94
+
95
+ it "should respond to my" do
96
+ Listing.should respond_to(:my)
97
+ end
98
+
99
+ it "should respond to find_by_cart_id" do
100
+ Listing.should respond_to(:find_by_cart_id)
101
+ end
102
+
103
+ it "should respond to count" do
104
+ Listing.should respond_to(:count)
105
+ end
106
+ end
107
+
108
+ describe "URIs" do
109
+ before(:each) do
110
+ stub_auth_request
111
+ end
112
+
113
+ context "/listings", :support do
114
+ on_get_it "should return listings" do
115
+ filter_string = "PostalCode Eq '83805'"
116
+ stub_api_get('/listings', 'listings/multiple.json', {:_filter => filter_string})
117
+
118
+ listings = Listing.find(:all, :_filter => filter_string)
119
+ listings.should be_an(Array)
120
+ listings.count.should eq(2)
121
+ end
122
+
123
+ on_get_it "should return the count" do
124
+ stub_api_get("/listings", 'count.json', { :_pagination => "count"})
125
+ count = Listing.count()
126
+ count.should == 2001
127
+ end
128
+ end
129
+
130
+ context "/listings/<listing_id>", :support do
131
+ on_get_it "should return a listing" do
132
+ stub_api_get("/listings/20060725224713296297000000", 'listings/no_subresources.json')
133
+
134
+ l = Listing.find('20060725224713296297000000')
135
+ l.videos.length.should == 0
136
+ l.photos.length.should == 0
137
+ l.documents.length.should == 0
138
+ l.Id.should eq('20060725224713296297000000')
139
+ end
140
+
141
+ on_put_it "should save a listing that has modified ListPrice" do
142
+ list_id = "20060725224713296297000000"
143
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
144
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'success.json')
145
+ l = Listing.find(list_id)
146
+ l.ListPrice = 10000.0
147
+ l.save.should be(true)
148
+ end
149
+
150
+ on_put_it "should save a listing that has modified ExpirationDate" do
151
+ list_id = "20060725224713296297000000"
152
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
153
+ stub_api_put("/listings/#{list_id}", 'listings/put_expiration_date.json', 'success.json')
154
+ l = Listing.find(list_id)
155
+ l.ExpirationDate = "2011-10-04"
156
+ l.save.should be(true)
157
+ end
158
+
159
+ it "should not save a listing that does not exist", :method => 'PUT' do
160
+ list_id = "20060725224713296297000000"
161
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
162
+ stub_api_put("/listings/lolwut", 'listings/put.json') do |request|
163
+ request.to_return(:status => 400, :body => fixture('errors/failure.json'))
164
+ end
165
+ l = Listing.find(list_id)
166
+ l.Id = "lolwut"
167
+ l.ListPrice = 10000.0
168
+ l.save.should be(false)
169
+ expect{ l.save! }.to raise_error(SparkApi::ClientError){ |e| e.status.should == 400 }
170
+ end
171
+
172
+ on_put_it "should save a listing with constraints" do
173
+ list_id = "20060725224713296297000000"
174
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
175
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'listings/constraints.json')
176
+ l = Listing.find(list_id)
177
+ l.ListPrice = 10000.0
178
+ l.save.should be(true)
179
+ l.constraints.size.should eq(1)
180
+ l.constraints.first.RuleName.should eq("MaxValue")
181
+ end
182
+
183
+ on_put_it "should fail saving a listing with constraints and provide the constraints" do
184
+ list_id = "20060725224713296297000000"
185
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
186
+ stub_api_put("/listings/#{list_id}", 'listings/put.json') do |request|
187
+ request.to_return(:status => 400, :body => fixture('errors/failure_with_constraint.json'))
188
+ end
189
+
190
+ l = Listing.find(list_id)
191
+ l.ListPrice = 10000.0
192
+ l.save.should be_false
193
+ l.constraints.size.should eq(1)
194
+ l.constraints.first.RuleName.should eq("MaxIncreasePercent")
195
+ l.errors.size.should eq(1)
196
+ end
197
+
198
+ context "with pagination" do
199
+ # This is really a bogus call, but we should make sure our
200
+ # pagination collection impl still behaves sanely
201
+ on_put_it "should save a listing with constraints" do
202
+ list_id = "20060725224713296297000000"
203
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
204
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'listings/constraints_with_pagination.json', :_pagination => '1')
205
+ l = Listing.find(list_id)
206
+ l.ListPrice = 10000.0
207
+ l.save(:_pagination => '1').should be(true)
208
+ l.constraints.size.should eq(1)
209
+ l.constraints.first.RuleName.should eq("MaxValue")
210
+ end
211
+ end
212
+
213
+ context "subresources" do
214
+ on_get_it "should return an array of photos" do
215
+ stub_api_get("/listings/1234", 'listings/with_photos.json', { :_expand => "Photos" })
216
+
217
+ l = Listing.find('1234', :_expand => "Photos")
218
+ l.photos.length.should == 5
219
+ l.documents.length.should == 0
220
+ l.videos.length.should == 0
221
+ l.virtual_tours.length.should == 0
222
+ end
223
+
224
+ on_get_it "should return an array of documents" do
225
+ stub_api_get("/listings/1234", 'listings/with_documents.json', { :_expand => "Documents" })
226
+
227
+ l = Listing.find('1234', :_expand => "Documents")
228
+ l.photos.length.should == 0
229
+ l.documents.length.should == 2
230
+ l.videos.length.should == 0
231
+ l.virtual_tours.length.should == 0
232
+ end
233
+
234
+ on_get_it "should return an array of virtual tours" do
235
+ stub_api_get("/listings/1234", 'listings/with_vtour.json', { :_expand => "VirtualTours" })
236
+
237
+ l = Listing.find('1234', :_expand => "VirtualTours")
238
+ l.virtual_tours.length.should == 1
239
+ l.photos.length.should == 0
240
+ l.documents.length.should == 0
241
+ l.videos.length.should == 0
242
+ end
243
+
244
+ on_get_it "should return an array of videos" do
245
+ stub_api_get("/listings/1234", 'listings/with_videos.json', { :_expand => "Videos" })
246
+
247
+ l = Listing.find('1234', :_expand => "Videos")
248
+ l.videos.length.should == 2
249
+ l.virtual_tours.length.should == 0
250
+ l.photos.length.should == 0
251
+ l.documents.length.should == 0
252
+ end
253
+
254
+ on_get_it "should return tour of homes" do
255
+ stub_api_get("/listings/20060725224713296297000000", 'listings/no_subresources.json')
256
+ stub_api_get("/listings/20060725224713296297000000/tourofhomes", 'listings/tour_of_homes.json')
257
+
258
+ l = Listing.find('20060725224713296297000000')
259
+ l.tour_of_homes().length.should == 2
260
+ l.videos.length.should == 0
261
+ l.photos.length.should == 0
262
+ l.documents.length.should == 0
263
+ end
264
+
265
+ on_get_it "should return permissions" do
266
+ stub_api_get("/listings/20060725224713296297000000", 'listings/with_permissions.json', { :_expand => "Permissions" })
267
+ l = Listing.find('20060725224713296297000000', :_expand => "Permissions")
268
+ l.Permissions["Editable"].should eq(true)
269
+ l.editable?().should eq(true)
270
+ l.editable?(:PriceChange).should eq(true)
271
+ l.editable?(:Photos).should eq(false)
272
+ end
273
+ end
274
+ end
275
+
276
+ context "/my/listings", :support do
277
+ on_get_it "should return my listings" do
278
+ stub_api_get('/my/listings', 'listings/multiple.json')
279
+
280
+ listings = Listing.my
281
+ listings.should be_an(Array)
282
+ listings.count.should eq(2)
283
+ end
284
+ end
285
+
286
+ context "/office/listings", :support do
287
+ on_get_it "GET should return office listings" do
288
+ stub_api_get('/office/listings', 'listings/multiple.json')
289
+
290
+ listings = Listing.office
291
+ listings.should be_an(Array)
292
+ listings.count.should eq(2)
293
+ end
294
+ end
295
+
296
+ context "/company/listings", :support do
297
+ on_get_it "should return company listings" do
298
+ stub_api_get('/company/listings', 'listings/multiple.json')
299
+
300
+ listings = Listing.company
301
+ listings.should be_an(Array)
302
+ listings.count.should eq(2)
303
+ end
304
+ end
305
+
306
+ context "/listings/nearby", :support do
307
+ on_get_it "should return nearby homes" do
308
+ stub_api_get("/listings/nearby",
309
+ 'listings/no_subresources.json', {:Lat => "45.45", :Lon => "-93.98"})
310
+ l = Listing.nearby(45.45, -93.98)
311
+ l.length.should == 1
312
+ end
313
+ end
314
+ end
315
+
316
+ after(:each) do
317
+ @listing = nil
318
+ end
319
+
320
+ end
@@ -0,0 +1,320 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe Listing do
4
+ before(:each) do
5
+
6
+ @listing = Listing.new({
7
+ "ResourceUri"=>"/v1/listings/20080619000032866372000000",
8
+ "StandardFields"=>{
9
+ "StreetNumber"=>"100",
10
+ "ListingId"=>"07-32",
11
+ "City"=>"Fargo",
12
+ "Longitude"=>"",
13
+ "StreetName"=>"Someone's",
14
+ "YearBuilt"=>nil,
15
+ "BuildingAreaTotal"=>"1321.0",
16
+ "PublicRemarks"=>nil,
17
+ "PostalCode"=>"55320",
18
+ "ListPrice"=>"100000.0",
19
+ "BathsThreeQuarter"=>nil,
20
+ "Latitude"=>"",
21
+ "StreetDirPrefix"=>nil,
22
+ "StreetAdditionalInfo"=>"********",
23
+ "PropertyType"=>"A",
24
+ "StateOrProvince"=>"ND",
25
+ "BathsTotal"=>"0.0",
26
+ "BathsFull"=>nil,
27
+ "ListingKey"=>"20080619000032866372000000",
28
+ "StreetSuffix"=>"St",
29
+ "StreetDirSuffix"=>"********",
30
+ "BedsTotal"=>2,
31
+ "ModificationTimestamp"=>"2010-11-22T23:36:42Z",
32
+ "BathsHalf"=>nil,
33
+ "CountyOrParish"=>nil,
34
+ "Photos" => [{
35
+ "Uri300"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000.jpg",
36
+ "ResourceUri"=>"/v1/listings/20080619000032866372000000/photos/20101115201631519737000000",
37
+ "Name"=>"Designer Entry w/14' Ceilings",
38
+ "Primary"=>true,
39
+ "Id"=>"20101115201631519737000000",
40
+ "Uri800"=>"http=>//devresize.flexmls.com/fgo/800x600/true/20101115201631519737000000-o.jpg",
41
+ "Uri1024"=>"http=>//devresize.flexmls.com/fgo/1024x768/true/20101115201631519737000000-o.jpg",
42
+ "UriLarge"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000-o.jpg",
43
+ "Caption"=>"apostrophe test for CUR-10508",
44
+ "Uri1280"=>"http=>//devresize.flexmls.com/fgo/1280x1024/true/20101115201631519737000000-o.jpg",
45
+ "UriThumb"=>"http=>//images.dev.fbsdata.com/fgo/20101115201631519737000000-t.jpg",
46
+ "Uri640"=>"http=>//devresize.flexmls.com/fgo/640x480/true/20101115201631519737000000-o.jpg"
47
+ }]
48
+ },
49
+ "Id"=>"20080619000032866372000000"
50
+ })
51
+
52
+ end
53
+
54
+ describe "attributes" do
55
+ it "should allow access to fields" do
56
+ @listing.StandardFields.should be_a(Hash)
57
+ @listing.StandardFields['ListingId'].should be_a(String)
58
+ @listing.StandardFields['ListPrice'].should match(@listing.ListPrice)
59
+ @listing.photos.should be_a(Array)
60
+ end
61
+
62
+ it "should not respond to removed attributes" do
63
+ @listing.should_not respond_to(:Photos)
64
+ @listing.should_not respond_to(:Documents)
65
+ @listing.should_not respond_to(:VirtualTours)
66
+ @listing.should_not respond_to(:Videos)
67
+ end
68
+
69
+ it "should return street address" do
70
+ @listing.street_address.should eq("100 Someone's St")
71
+ end
72
+
73
+ it "should return the regional address" do
74
+ @listing.region_address.should eq("Fargo, ND 55320")
75
+ end
76
+
77
+ it "should return full address" do
78
+ @listing.full_address.should eq("100 Someone's St, Fargo, ND 55320")
79
+ end
80
+ end
81
+
82
+ describe "class methods" do
83
+ it "should respond to find" do
84
+ Listing.should respond_to(:find)
85
+ end
86
+
87
+ it "should respond to first" do
88
+ Listing.should respond_to(:first)
89
+ end
90
+
91
+ it "should respond to last" do
92
+ Listing.should respond_to(:last)
93
+ end
94
+
95
+ it "should respond to my" do
96
+ Listing.should respond_to(:my)
97
+ end
98
+
99
+ it "should respond to find_by_cart_id" do
100
+ Listing.should respond_to(:find_by_cart_id)
101
+ end
102
+
103
+ it "should respond to count" do
104
+ Listing.should respond_to(:count)
105
+ end
106
+ end
107
+
108
+ describe "URIs" do
109
+ before(:each) do
110
+ stub_auth_request
111
+ end
112
+
113
+ context "/listings", :support do
114
+ on_get_it "should return listings" do
115
+ filter_string = "PostalCode Eq '83805'"
116
+ stub_api_get('/listings', 'listings/multiple.json', {:_filter => filter_string})
117
+
118
+ listings = Listing.find(:all, :_filter => filter_string)
119
+ listings.should be_an(Array)
120
+ listings.count.should eq(2)
121
+ end
122
+
123
+ on_get_it "should return the count" do
124
+ stub_api_get("/listings", 'count.json', { :_pagination => "count"})
125
+ count = Listing.count()
126
+ count.should == 2001
127
+ end
128
+ end
129
+
130
+ context "/listings/<listing_id>", :support do
131
+ on_get_it "should return a listing" do
132
+ stub_api_get("/listings/20060725224713296297000000", 'listings/no_subresources.json')
133
+
134
+ l = Listing.find('20060725224713296297000000')
135
+ l.videos.length.should == 0
136
+ l.photos.length.should == 0
137
+ l.documents.length.should == 0
138
+ l.Id.should eq('20060725224713296297000000')
139
+ end
140
+
141
+ on_put_it "should save a listing that has modified ListPrice" do
142
+ list_id = "20060725224713296297000000"
143
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
144
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'success.json')
145
+ l = Listing.find(list_id)
146
+ l.ListPrice = 10000.0
147
+ l.save.should be(true)
148
+ end
149
+
150
+ on_put_it "should save a listing that has modified ExpirationDate" do
151
+ list_id = "20060725224713296297000000"
152
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
153
+ stub_api_put("/listings/#{list_id}", 'listings/put_expiration_date.json', 'success.json')
154
+ l = Listing.find(list_id)
155
+ l.ExpirationDate = "2011-10-04"
156
+ l.save.should be(true)
157
+ end
158
+
159
+ it "should not save a listing that does not exist", :method => 'PUT' do
160
+ list_id = "20060725224713296297000000"
161
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
162
+ stub_api_put("/listings/lolwut", 'listings/put.json') do |request|
163
+ request.to_return(:status => 400, :body => fixture('errors/failure.json'))
164
+ end
165
+ l = Listing.find(list_id)
166
+ l.Id = "lolwut"
167
+ l.ListPrice = 10000.0
168
+ l.save.should be(false)
169
+ expect{ l.save! }.to raise_error(FlexmlsApi::ClientError){ |e| e.status.should == 400 }
170
+ end
171
+
172
+ on_put_it "should save a listing with constraints" do
173
+ list_id = "20060725224713296297000000"
174
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
175
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'listings/constraints.json')
176
+ l = Listing.find(list_id)
177
+ l.ListPrice = 10000.0
178
+ l.save.should be(true)
179
+ l.constraints.size.should eq(1)
180
+ l.constraints.first.RuleName.should eq("MaxValue")
181
+ end
182
+
183
+ on_put_it "should fail saving a listing with constraints and provide the constraints" do
184
+ list_id = "20060725224713296297000000"
185
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
186
+ stub_api_put("/listings/#{list_id}", 'listings/put.json') do |request|
187
+ request.to_return(:status => 400, :body => fixture('errors/failure_with_constraint.json'))
188
+ end
189
+
190
+ l = Listing.find(list_id)
191
+ l.ListPrice = 10000.0
192
+ l.save.should be_false
193
+ l.constraints.size.should eq(1)
194
+ l.constraints.first.RuleName.should eq("MaxIncreasePercent")
195
+ l.errors.size.should eq(1)
196
+ end
197
+
198
+ context "with pagination" do
199
+ # This is really a bogus call, but we should make sure our
200
+ # pagination collection impl still behaves sanely
201
+ on_put_it "should save a listing with constraints" do
202
+ list_id = "20060725224713296297000000"
203
+ stub_api_get("/listings/#{list_id}", 'listings/no_subresources.json')
204
+ stub_api_put("/listings/#{list_id}", 'listings/put.json', 'listings/constraints_with_pagination.json', :_pagination => '1')
205
+ l = Listing.find(list_id)
206
+ l.ListPrice = 10000.0
207
+ l.save(:_pagination => '1').should be(true)
208
+ l.constraints.size.should eq(1)
209
+ l.constraints.first.RuleName.should eq("MaxValue")
210
+ end
211
+ end
212
+
213
+ context "subresources" do
214
+ on_get_it "should return an array of photos" do
215
+ stub_api_get("/listings/1234", 'listings/with_photos.json', { :_expand => "Photos" })
216
+
217
+ l = Listing.find('1234', :_expand => "Photos")
218
+ l.photos.length.should == 5
219
+ l.documents.length.should == 0
220
+ l.videos.length.should == 0
221
+ l.virtual_tours.length.should == 0
222
+ end
223
+
224
+ on_get_it "should return an array of documents" do
225
+ stub_api_get("/listings/1234", 'listings/with_documents.json', { :_expand => "Documents" })
226
+
227
+ l = Listing.find('1234', :_expand => "Documents")
228
+ l.photos.length.should == 0
229
+ l.documents.length.should == 2
230
+ l.videos.length.should == 0
231
+ l.virtual_tours.length.should == 0
232
+ end
233
+
234
+ on_get_it "should return an array of virtual tours" do
235
+ stub_api_get("/listings/1234", 'listings/with_vtour.json', { :_expand => "VirtualTours" })
236
+
237
+ l = Listing.find('1234', :_expand => "VirtualTours")
238
+ l.virtual_tours.length.should == 1
239
+ l.photos.length.should == 0
240
+ l.documents.length.should == 0
241
+ l.videos.length.should == 0
242
+ end
243
+
244
+ on_get_it "should return an array of videos" do
245
+ stub_api_get("/listings/1234", 'listings/with_videos.json', { :_expand => "Videos" })
246
+
247
+ l = Listing.find('1234', :_expand => "Videos")
248
+ l.videos.length.should == 2
249
+ l.virtual_tours.length.should == 0
250
+ l.photos.length.should == 0
251
+ l.documents.length.should == 0
252
+ end
253
+
254
+ on_get_it "should return tour of homes" do
255
+ stub_api_get("/listings/20060725224713296297000000", 'listings/no_subresources.json')
256
+ stub_api_get("/listings/20060725224713296297000000/tourofhomes", 'listings/tour_of_homes.json')
257
+
258
+ l = Listing.find('20060725224713296297000000')
259
+ l.tour_of_homes().length.should == 2
260
+ l.videos.length.should == 0
261
+ l.photos.length.should == 0
262
+ l.documents.length.should == 0
263
+ end
264
+
265
+ on_get_it "should return permissions" do
266
+ stub_api_get("/listings/20060725224713296297000000", 'listings/with_permissions.json', { :_expand => "Permissions" })
267
+ l = Listing.find('20060725224713296297000000', :_expand => "Permissions")
268
+ l.Permissions["Editable"].should eq(true)
269
+ l.editable?().should eq(true)
270
+ l.editable?(:PriceChange).should eq(true)
271
+ l.editable?(:Photos).should eq(false)
272
+ end
273
+ end
274
+ end
275
+
276
+ context "/my/listings", :support do
277
+ on_get_it "should return my listings" do
278
+ stub_api_get('/my/listings', 'listings/multiple.json')
279
+
280
+ listings = Listing.my
281
+ listings.should be_an(Array)
282
+ listings.count.should eq(2)
283
+ end
284
+ end
285
+
286
+ context "/office/listings", :support do
287
+ on_get_it "GET should return office listings" do
288
+ stub_api_get('/office/listings', 'listings/multiple.json')
289
+
290
+ listings = Listing.office
291
+ listings.should be_an(Array)
292
+ listings.count.should eq(2)
293
+ end
294
+ end
295
+
296
+ context "/company/listings", :support do
297
+ on_get_it "should return company listings" do
298
+ stub_api_get('/company/listings', 'listings/multiple.json')
299
+
300
+ listings = Listing.company
301
+ listings.should be_an(Array)
302
+ listings.count.should eq(2)
303
+ end
304
+ end
305
+
306
+ context "/listings/nearby", :support do
307
+ on_get_it "should return nearby homes" do
308
+ stub_api_get("/listings/nearby",
309
+ 'listings/no_subresources.json', {:Lat => "45.45", :Lon => "-93.98"})
310
+ l = Listing.nearby(45.45, -93.98)
311
+ l.length.should == 1
312
+ end
313
+ end
314
+ end
315
+
316
+ after(:each) do
317
+ @listing = nil
318
+ end
319
+
320
+ end