spark_api 1.3.24 → 1.3.25

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTQ2YzBjNTczYWI1YTdjMDA1OTkzMDZiYTAzZjc3ZjUxMjY0NGFlMA==
4
+ ZTVmZTkxOTdiYjI5YmE1N2UwN2Q5ZjQ3MmMxNDg1OTU2Njk4M2I0MQ==
5
5
  data.tar.gz: !binary |-
6
- YWE2YjQ2ZDAyOTVhZDk5YzNjMGZmOTY2ZjNmYzI4MDA1MTg1MWM1YQ==
6
+ OWIyNTk5YjliMGVjM2RlNjM3M2IzZDAxY2JjYjUxYzRlNTYyYTUzMw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OGYyNTM1ZGE2YTRhZmMzYjUwYmExMjljMmI3NjZjOGU3ZTM2ZmZkMmFkYWI4
10
- ZTUwNDEwZTFiODk4NTY1N2NjZWFmMzEzN2E0ZmMzNGEzMzEyMTg4NGJlMzRk
11
- M2YxMDgzOTMyMDg2MzE2NDA3YzQ3MzJhNDBhYjJmYjM0NmZhOGM=
9
+ YjM2OWFhMDdhZDQ0MWQzZGZjYTVkODgyZGIxMmI2NTg1MzRmMWMwNDU4ZTQ3
10
+ ZGViMzU3MjhhODQyNWUxYzAwYzY4YzJhZTQzOTNhMzliM2M0OGJlNjQyNjAw
11
+ OGQ2YThjMzMxNDUxM2MwNDQxOGRiZWZhNDkyMWJlODg5NmJlMWU=
12
12
  data.tar.gz: !binary |-
13
- YTQxZTNmYmQzNjE2ZTY3NmNiYTkzOGU0ODc4MGQyNTg5YzFjZDVjYzAwM2Qz
14
- NDY5YWQ3ZmNmNTE4ZGE5ZjhhYzM0MzY5YmM2N2Y1ZWNjMTQ4YTZmODkwYzVm
15
- MTY3YzAzYmJmMWMyMmEwN2E2ZDE5NmQzYWJlNmZhMzU3ZWM3ODE=
13
+ NTk1Y2Y3ZDZiZjg2ODJiZDg2YjBmZTJjMjVhNjI0MjJkNThhMTQ0ZmRmY2Q4
14
+ OTg5OWIzMTdkNjZjMmU2MGZjODdmYjVjZDhlZDlmZGQ0YjIwYTFmY2MzM2Mw
15
+ NjcyZDUxYjI4M2JkYzk0MzlhMTUxZGJiNWQ0MGFiMThiMjgwOTk=
data/Rakefile CHANGED
@@ -1,9 +1,15 @@
1
1
  require "rubygems"
2
2
 
3
3
  require 'rubygems/user_interaction'
4
- require 'flexmls_gems/tasks'
5
- require 'flexmls_gems/tasks/spec'
6
- require 'flexmls_gems/tasks/rdoc'
4
+ require 'rspec'
5
+ require 'rspec/core/rake_task'
6
+ require 'ci/reporter/rake/rspec'
7
+ require 'bundler/gem_tasks'
8
+
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.rspec_opts = ["-c", "-f progress"]
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ end
7
13
 
8
14
  desc "Run all the tests"
9
15
  task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.24
1
+ 1.3.25
@@ -24,11 +24,13 @@ require 'spark_api/models/notification'
24
24
  require 'spark_api/models/open_house'
25
25
  require 'spark_api/models/photo'
26
26
  require 'spark_api/models/portal'
27
+ require 'spark_api/models/portal_listing_cart'
27
28
  require 'spark_api/models/property_types'
28
29
  require 'spark_api/models/rental_calendar'
29
30
  require 'spark_api/models/saved_search'
30
31
  require 'spark_api/models/search_template/quick_search'
31
32
  require 'spark_api/models/shared_listing'
33
+ require 'spark_api/models/sort'
32
34
  require 'spark_api/models/standard_fields'
33
35
  require 'spark_api/models/system_info'
34
36
  require 'spark_api/models/tour_of_home'
@@ -129,6 +129,19 @@ module SparkApi
129
129
  attributes['Id']
130
130
  end
131
131
 
132
+ def to_partial_path
133
+ "#{underscore(resource_pluralized)}/#{underscore(self.class.name.split('::').last)}"
134
+ end
135
+
136
+ # can be overridden
137
+ def resource_pluralized
138
+ resource = self.class.name.split('::').last
139
+ unless resource.split('').last == "s"
140
+ resource = resource + "s"
141
+ end
142
+ resource
143
+ end
144
+
132
145
  protected
133
146
 
134
147
  def write_attribute(attribute, value)
@@ -139,6 +152,16 @@ module SparkApi
139
152
  end
140
153
  end
141
154
 
155
+ private
156
+
157
+ def underscore(string)
158
+ string.to_s.gsub(/::/, '/').
159
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
160
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
161
+ tr("-", "_").
162
+ downcase
163
+ end
164
+
142
165
  end
143
166
  end
144
167
  end
@@ -22,12 +22,17 @@ module SparkApi
22
22
 
23
23
  def create!(arguments = {})
24
24
  results = connection.post self.path, post_data.merge(params_for_save), arguments
25
- update_attributes(results.first)
25
+ update_attributes_after_create(results.first)
26
26
  reset_dirty
27
27
  params_for_save.clear
28
28
  true
29
29
  end
30
30
 
31
+ def update_attributes(attrs = {})
32
+ attrs.each{|k,v| public_send(:"#{k}=", v)}
33
+ save!
34
+ end
35
+
31
36
  def update!(arguments = {})
32
37
  return true unless changed? && persisted?
33
38
  connection.put resource_uri, dirty_attributes, arguments
@@ -48,21 +53,12 @@ module SparkApi
48
53
 
49
54
  private
50
55
 
51
- def update_attributes(result)
56
+ def update_attributes_after_create(result)
52
57
  attributes['Id'] = result['Id'] ? result['Id'] : parse_id(result['ResourceUri'])
53
58
  result.delete('Id')
54
59
  attributes.merge! result
55
60
  end
56
61
 
57
- # can be overridden
58
- def resource_pluralized
59
- resource = self.class.name.split('::').last
60
- unless resource.split('').last == "s"
61
- resource = resource + "s"
62
- end
63
- resource
64
- end
65
-
66
62
  end
67
63
 
68
64
  end
@@ -1,6 +1,9 @@
1
1
  module SparkApi
2
2
  module Models
3
3
  class IdxLink < Base
4
+
5
+ extend Finders
6
+
4
7
  self.element_name="idxlinks"
5
8
 
6
9
  LINK_TYPES = ["QuickSearch", "SavedSearch", "MyListings", "Roster"]
@@ -34,14 +37,6 @@ module SparkApi
34
37
 
35
38
  private
36
39
 
37
- def self.find_every(options)
38
- raise NotImplementedError # TODO
39
- end
40
-
41
- def self.find_one(options)
42
- raise NotImplementedError # TODO
43
- end
44
-
45
40
  def self.find_single(scope, options)
46
41
  resp = SparkApi.client.get("/idxlinks/#{scope}", options)
47
42
  new(resp.first)
@@ -191,7 +191,26 @@ module SparkApi
191
191
  results = connection.put "#{self.class.path}/#{self.Id}/photos", arguments
192
192
  true
193
193
  end
194
-
194
+
195
+ def reorder_photo(photo_id, index)
196
+ unless Integer(index)
197
+ raise ArgumentError, "Photo reorder failed. '#{index}' is not a number."
198
+ end
199
+
200
+ begin
201
+ return reorder_photo!(photo_id, index)
202
+ rescue BadResourceRequest => e
203
+ SparkApi.logger.warn { "Failed to save resource #{self}: #{e.message}" }
204
+ rescue NotFound => e
205
+ SparkApi.logger.error { "Failed to save resource #{self}: #{e.message}" }
206
+ end
207
+ false
208
+ end
209
+ def reorder_photo!(photo_id, index)
210
+ connection.put "#{self.class.path}/#{self.Id}/photos/#{photo_id}", "Photos" => [{"Order"=>index}]
211
+ true
212
+ end
213
+
195
214
  def editable?(editable_settings = [])
196
215
  settings = Array(editable_settings)
197
216
  editable = attributes.include?("Permissions") && self.Permissions["Editable"] == true
@@ -15,11 +15,12 @@ module SparkApi
15
15
  def ListingIds=(listing_ids)
16
16
  write_attribute("ListingIds", Array(listing_ids))
17
17
  end
18
+
18
19
  def Name=(name)
19
20
  write_attribute("Name", name)
20
21
  end
21
22
 
22
- def path
23
+ def self.path
23
24
  if @contact_id
24
25
  "/contacts/#{@contact_id}/listingcarts"
25
26
  else
@@ -27,6 +28,15 @@ module SparkApi
27
28
  end
28
29
  end
29
30
 
31
+ def filter
32
+ "ListingCart Eq '#{self.Id}'"
33
+ end
34
+
35
+ def listings(args = {})
36
+ return [] if attributes["ListingIds"].nil?
37
+ Listing.collect(connection.get("#{self.path}/#{self.Id}/listings", args))
38
+ end
39
+
30
40
  def add_listing(listing)
31
41
  ids = listing.respond_to?(:Id) ? listing.Id : listing
32
42
  results = connection.post("#{self.resource_uri}", {"ListingIds" => Array(ids)})
@@ -52,6 +62,10 @@ module SparkApi
52
62
  collect(connection.get("/#{self.element_name}/portal", arguments))
53
63
  end
54
64
 
65
+ def deletable?
66
+ !attributes.has_key?("PortalCartType") || self.PortalCartType == "Custom"
67
+ end
68
+
55
69
  end
56
70
  end
57
71
  end
@@ -0,0 +1,13 @@
1
+ module SparkApi
2
+ module Models
3
+
4
+ class PortalListingCart < ListingCart
5
+
6
+ def self.find(contact_id, *arguments)
7
+ @contact_id = contact_id
8
+ super(*arguments)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -8,6 +8,11 @@ module SparkApi
8
8
 
9
9
  attr_accessor :newsfeeds
10
10
 
11
+ # Newsfeed restriction criteria for saved searches:
12
+ # http://alpha.sparkplatform.com/docs/api_services/newsfeed/restrictions#criteria
13
+ QUALIFYING_FIELDS_FOR_NEWSFEED = %w(BathsTotal BedsTotal City CountyOrParish ListPrice Location MlsStatus
14
+ PostalCode PropertyType RoomsTotal State)
15
+
11
16
  self.element_name="savedsearches"
12
17
 
13
18
  def initialize(attributes={})
@@ -19,12 +24,6 @@ module SparkApi
19
24
  Class.new(self).tap do |provided|
20
25
  provided.element_name = '/savedsearches'
21
26
  provided.prefix = '/provided'
22
- def provided_search?
23
- true
24
- end
25
- def newsfeeds
26
- []
27
- end
28
27
  SparkApi.logger.info("#{self.name}.path: #{provided.path}")
29
28
  end
30
29
  end
@@ -33,6 +32,10 @@ module SparkApi
33
32
  collect(connection.get("/#{self.element_name}/tags/#{tag}", arguments))
34
33
  end
35
34
 
35
+ def favorite?
36
+ @attributes["Tags"] && @attributes["Tags"].include?( "Favorites")
37
+ end
38
+
36
39
  # list contacts (private role)
37
40
  def contacts
38
41
  return [] unless persisted?
@@ -63,36 +66,23 @@ module SparkApi
63
66
  end
64
67
 
65
68
  def listings(args = {})
66
- arguments = {:_filter => self.Filter}
67
- arguments.merge!(:RequestMode => 'permissive') if provided_search?
69
+ arguments = {:_filter => "SavedSearch Eq '#{self.Id}'"}
70
+ arguments.merge!(:RequestMode => 'permissive') if Provided?
68
71
  @listings ||= Listing.collect(connection.get("/listings", arguments.merge(args)))
69
72
  end
70
73
 
71
74
  def newsfeeds
72
- if @newsfeeds.nil?
73
- response = SparkApi.client.get("/savedsearches/#{@attributes["Id"]}", :_expand => "NewsFeeds").first["NewsFeeds"]
74
- # the response from the api is just a bunch of hashes, but we can turn them into Newsfeed instances
75
- @newsfeeds = response.map { |hash| Newsfeed.new(hash) }
76
- end
77
- @newsfeeds
78
- end
79
-
80
- def provided_search?
81
- false
75
+ Newsfeed.collect(connection.get("#{self.class.path}/#{@attributes["Id"]}",
76
+ :_expand => "NewsFeeds").first["NewsFeeds"])
82
77
  end
83
78
 
84
79
  def can_have_newsfeed?
85
80
 
86
- return false if provided_search?
87
81
  return true if has_active_newsfeed? || has_inactive_newsfeed?
88
82
 
89
- # Newsfeed restriction criteria for saved searches:
90
- # http://alpha.sparkplatform.com/docs/api_services/newsfeed/restrictions#criteria
91
- standard_fields = %w(BathsTotal BedsTotal City CountyOrParish ListPrice Location MlsStatus PostalCode PropertyType RoomsTotal State)
92
-
93
83
  number_of_filters = 0
94
84
 
95
- standard_fields.each do |field|
85
+ QUALIFYING_FIELDS_FOR_NEWSFEED.each do |field|
96
86
  number_of_filters += 1 if self.Filter.include? field
97
87
  end
98
88
 
@@ -101,24 +91,22 @@ module SparkApi
101
91
  end
102
92
 
103
93
  def has_active_newsfeed?
104
- return false if provided_search?
105
-
106
94
  if self.respond_to? "NewsFeedSubscriptionSummary"
107
95
  self.NewsFeedSubscriptionSummary['ActiveSubscription']
108
96
  else
109
- saved_search = SavedSearch.find( self.Id, {"_expand" => "NewsFeedSubscriptionSummary"})
110
- saved_search.NewsFeedSubscriptionSummary['ActiveSubscription']
97
+ search = connection.get "#{self.class.path}/#{@attributes['Id']}",
98
+ {"_expand" => "NewsFeedSubscriptionSummary"}
99
+ search.first["NewsFeedSubscriptionSummary"]["ActiveSubscription"]
111
100
  end
112
101
  end
113
102
 
114
103
  def has_inactive_newsfeed?
115
- return false if provided_search?
116
-
117
- if self.respond_to? "NewsFeedSubscriptionSummary"
118
- !self.NewsFeedSubscriptionSummary['ActiveSubscription']
104
+ if self.respond_to?("NewsFeeds") && self.respond_to?("NewsFeedSubscriptionSummary")
105
+ self.NewsFeeds.any? && !self.NewsFeedSubscriptionSummary['ActiveSubscription']
119
106
  else
120
- saved_search = SavedSearch.find( self.Id, {"_expand" => "NewsFeedSubscriptionSummary"})
121
- !saved_search.NewsFeedSubscriptionSummary['ActiveSubscription']
107
+ search = connection.get("#{self.class.path}/#{@attributes['Id']}",
108
+ {"_expand" => "NewsFeedSubscriptionSummary, NewsFeeds"}).first
109
+ search["NewsFeeds"].any? && !search["NewsFeedSubscriptionSummary"]["ActiveSubscription"]
122
110
  end
123
111
  end
124
112
 
@@ -0,0 +1,11 @@
1
+ module SparkApi
2
+ module Models
3
+ class Sort < Base
4
+ extend Finders
5
+
6
+ self.element_name="/sorts"
7
+ self.prefix="/searchtemplates"
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby -v
4
+ echo "==> Installing gems..."
5
+ bundle check --path vendor/bundle 2>&1 > /dev/null || {
6
+ bundle install --quiet --path vendor/bundle
7
+ }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ script/bootstrap
5
+
6
+
7
+ export COVERAGE=on # build rcov report when running tests
8
+ export CI_REPORTS=test/reports # output JUnit reports to std location
9
+
10
+ echo "==> Running tests..."
11
+ bundle exec rake ci:setup:rspec spec
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ rm -rf pkg/*
5
+ bundle exec rake build
6
+ gem push pkg/*.gem --key rubygems_production_key
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "Photos": [{"Order" : "2"}]
4
+ }
5
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "D": {
3
+ "Results": [
4
+ {
5
+ "Uri300": "http://photos.flexmls.com/fgo/20050505220032167405000000.jpg",
6
+ "ResourceUri": "/v1/listings/20050505200220759069000000/photos/20050505220032167405000000",
7
+ "Name": "Front",
8
+ "Primary": true,
9
+ "Uri800": "http://cdn.resize.flexmls.com/fgo/800x600/true/20050505220032167405000000-o.jpg",
10
+ "Id": "20050505220032167405000000",
11
+ "UriLarge": "http://photos.flexmls.com/fgo/20050505220032167405000000-o.jpg",
12
+ "Uri1024": "http://cdn.resize.flexmls.com/fgo/1024x768/true/20050505220032167405000000-o.jpg",
13
+ "Caption": "",
14
+ "Uri1280": "http://cdn.resize.flexmls.com/fgo/1280x1024/true/20050505220032167405000000-o.jpg",
15
+ "Uri640": "http://cdn.resize.flexmls.com/fgo/640x480/true/20050505220032167405000000-o.jpg",
16
+ "UriThumb": "http://photos.flexmls.com/fgo/20050505220032167405000000-t.jpg"
17
+ }
18
+ ]
19
+ }
20
+ }
@@ -9,7 +9,8 @@
9
9
  "Filter": "City Eq 'Moorhead' And MlsStatus Eq 'Active' And PropertyType Eq 'A'",
10
10
  "ContactIds": [
11
11
  "20100815220615294367000000"
12
- ]
12
+ ],
13
+ "Provided": false
13
14
  },
14
15
  {
15
16
  "ResourceUri": "/v1/savedsearches/20100615220615292711000000",
@@ -0,0 +1,22 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/savedsearches/20100815220615294367000000",
7
+ "Id": "20100815220615294367000000",
8
+ "Name": "Search name here",
9
+ "Filter": "City Eq 'Moorhead' And MlsStatus Eq 'Active' And PropertyType Eq 'A'",
10
+ "ContactIds": [
11
+ "20100815220615294367000000"
12
+ ],
13
+ "Provided": true
14
+ },
15
+ {
16
+ "ResourceUri": "/v1/savedsearches/20100615220615292711000000",
17
+ "Id": "20100615220615292711000000",
18
+ "Name": "Second search name here"
19
+ }
20
+ ]
21
+ }
22
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/savedsearches/20100815220615294367000000",
7
+ "Id": "20100815220615294367000000",
8
+ "Name": "Search name here",
9
+ "ContactIds": [
10
+ "20100815220615294367000000"
11
+ ],
12
+ "NewsFeedSubscriptionSummary": {
13
+ "ActiveSubscription": false
14
+ },
15
+ "NewsFeeds": []
16
+ }
17
+
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "D": {
3
+ "Results": [
4
+ {
5
+ "ResourceUri": "/v1/searchtemplates/sorts/20120717212004874996000000",
6
+ "Id": "20130717212004874996000000",
7
+ "Name": "My Custom Listing Sort",
8
+ "OwnerId": "20000426173054342350000000",
9
+ "MlsId": "20000426143505724628000000",
10
+ "Inheritable": true,
11
+ "Inherited": false,
12
+ "Fields": [
13
+ {
14
+ "Domain": "StandardFields",
15
+ "GroupField": null,
16
+ "Field": "ListPrice",
17
+ "SortType": "Ascending"
18
+ },
19
+ {
20
+ "Domain": "StandardFields",
21
+ "GroupField": null,
22
+ "Field": "MlsStatus",
23
+ "SortType": "Descending"
24
+ }
25
+ ],
26
+ "ModificationTimestamp": "2013-07-09T15:31:47Z"
27
+ }
28
+ ],
29
+ "Success": true
30
+ }
31
+ }
@@ -1,5 +1,15 @@
1
- require "rubygems"
1
+ if ENV['COVERAGE'] == "on"
2
+ require 'simplecov'
3
+ require 'simplecov-rcov'
4
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
5
+ SimpleCov.start do
6
+ add_filter '/vendor'
7
+ add_filter '/spec'
8
+ add_filter '/test'
9
+ end
10
+ end
2
11
 
12
+ require "rubygems"
3
13
  require "rspec"
4
14
  require 'rspec/autorun'
5
15
  require 'webmock/rspec'
@@ -1,9 +1,13 @@
1
1
  require './spec/spec_helper'
2
2
 
3
3
  # Sample resource models for testing the base class
4
- class MyExampleModel < Base
5
- self.element_name = "example"
6
- self.prefix = "/test/"
4
+ module SparkApi
5
+ module Models
6
+ class MyExampleModel < Base
7
+ self.element_name = "example"
8
+ self.prefix = "/test/"
9
+ end
10
+ end
7
11
  end
8
12
 
9
13
  class MyDefaultModel < Base
@@ -153,4 +157,11 @@ describe Base, "Base model" do
153
157
 
154
158
  end
155
159
 
160
+ describe "to_partial_path" do
161
+ it "should return the partial path" do
162
+ model = MyExampleModel.new()
163
+ model.to_partial_path.should eq("my_example_models/my_example_model")
164
+ end
165
+ end
166
+
156
167
  end
@@ -133,4 +133,43 @@ describe ListingCart do
133
133
  end
134
134
  end
135
135
 
136
+ describe "#listings" do
137
+ it "should return the listings in the cart" do
138
+ resource = subject.class.new Id: 5, ListingIds: ["1234"]
139
+ stub_api_get("/#{subject.class.element_name}/#{resource.Id}/listings", 'listings/multiple.json')
140
+ resource.listings.should be_a(Array)
141
+ resource.listings.first.should be_a(Listing)
142
+ end
143
+
144
+ it "should return an empty array if there aren't any listings" do
145
+ resource = subject.class.new Id: 5
146
+ resource.listings.should be_a(Array)
147
+ resource.listings.count.should === 0
148
+ end
149
+ end
150
+
151
+ describe "filter" do
152
+ it "should return a filter string for the cart" do
153
+ resource = subject.class.new Id: 5
154
+ resource.filter.should eq("ListingCart Eq '5'")
155
+ end
156
+ end
157
+
158
+ describe "#deletable?" do
159
+ it "should return true for private custom carts" do
160
+ resource = subject.class.new
161
+ expect(resource.deletable?).to be_true
162
+ end
163
+
164
+ it "should return true for custom vow carts" do
165
+ resource = subject.class.new PortalCartType: "Custom"
166
+ expect(resource.deletable?).to be_true
167
+ end
168
+
169
+ it "should return false for vow carts" do
170
+ resource = subject.class.new PortalCartType: "Favorites"
171
+ expect(resource.deletable?).to be_false
172
+ end
173
+ end
174
+
136
175
  end
@@ -251,6 +251,23 @@ describe Listing do
251
251
  l.errors.size.should eq(1)
252
252
  end
253
253
 
254
+ on_put_it "should reorder a photo" do
255
+ list_id = "20060725224713296297000000"
256
+ stub_api_get("/listings/#{list_id}", 'listings/with_photos.json')
257
+ stub_api_put("/listings/#{list_id}/photos/20110826220032167405000000", 'listings/put_reorder_photo.json', 'listings/reorder_photo.json')
258
+ l = Listing.find(list_id)
259
+ l.reorder_photo("20110826220032167405000000", "2")
260
+ l.photos.size.should eq(5)
261
+ end
262
+
263
+ on_put_it "should raise an exception when an index is not an Integer" do
264
+ list_id = "20060725224713296297000000"
265
+ stub_api_get("/listings/#{list_id}", 'listings/with_photos.json')
266
+ stub_api_put("/listings/#{list_id}/photos/2011082622003216740500000", 'listings/put_reorder_photo.json', 'listings/reorder_photo.json')
267
+ l = Listing.find(list_id)
268
+ expect{ l.reorder_photo("2011082622003216740500000", "asdf") }.to raise_error(ArgumentError)
269
+ end
270
+
254
271
  context "with pagination" do
255
272
  # This is really a bogus call, but we should make sure our
256
273
  # pagination collection impl still behaves sanely
@@ -104,25 +104,24 @@ describe SavedSearch do
104
104
  it "should return the searches listings" do
105
105
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
106
106
  stub_api_get("/listings", 'listings/multiple.json',
107
- {:_filter => "City Eq 'Moorhead' And MlsStatus Eq 'Active' And PropertyType Eq 'A'"})
107
+ {:_filter => "SavedSearch Eq '#{id}'"})
108
108
  listings = subject.class.find(id).listings
109
109
  listings.should be_an(Array)
110
110
  listings[0].should be_a(Listing)
111
111
  end
112
112
 
113
113
  it "should include the permissive parameter for provided searches" do
114
- stub_api_get("/provided/savedsearches/#{id}", 'saved_searches/get.json')
114
+ stub_api_get("/provided/savedsearches/#{id}", 'saved_searches/get_provided.json')
115
115
  resource = subject.class.provided.find(id)
116
116
  expect(SparkApi.client).to receive(:get).with("/listings",
117
- {:_filter => resource.Filter, :RequestMode => 'permissive'})
117
+ {:_filter => "SavedSearch Eq '#{id}'", :RequestMode => 'permissive'})
118
118
  resource.listings
119
119
  end
120
120
 
121
121
  it "should not include the permissive parameter for saved searches" do
122
122
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
123
123
  resource = subject.class.find(id)
124
- resource.stub(:provided_search?) { false }
125
- expect(SparkApi.client).to receive(:get).with("/listings", {:_filter => resource.Filter})
124
+ expect(SparkApi.client).to receive(:get).with("/listings", {:_filter => "SavedSearch Eq '#{id}'"})
126
125
  resource.listings
127
126
  end
128
127
 
@@ -165,17 +164,25 @@ describe SavedSearch do
165
164
  end
166
165
  end
167
166
 
168
- describe "can_have_newsfeed?" do
167
+ describe "favorite?" do
168
+ it "should return true if the search has been tagged as a favorite" do
169
+ search = SavedSearch.new(Tags: ["Favorites"])
170
+ search.should be_favorite
171
+ end
169
172
 
170
- it "should return false for a provided search" do
171
- stub_api_get("/provided/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
172
- resource = subject.class.provided.find(id)
173
- resource.can_have_newsfeed?.should == false
173
+ it "should return false if the search has not been tagged as a favorite" do
174
+ search = SavedSearch.new
175
+ search.should_not be_favorite
174
176
  end
177
+ end
178
+
179
+ describe "can_have_newsfeed?" do
175
180
 
176
181
  it "should return false without at least three filter parameters" do
177
182
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
178
183
  resource = subject.class.find(id)
184
+ resource.stub(:has_active_newsfeed?) { false }
185
+ resource.stub(:has_inactive_newsfeed?) { false }
179
186
  resource.Filter = "City Eq 'Moorhead' And MlsStatus Eq 'Active'"
180
187
  resource.can_have_newsfeed?.should == false
181
188
  end
@@ -183,7 +190,6 @@ describe SavedSearch do
183
190
  it "should return true with three filter parameters" do
184
191
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
185
192
  resource = subject.class.find(id)
186
- resource.stub(:provided_search?) { false }
187
193
  resource.stub(:has_active_newsfeed?) { false }
188
194
  resource.stub(:has_inactive_newsfeed?) { false }
189
195
  resource.can_have_newsfeed?.should == true
@@ -197,13 +203,14 @@ describe SavedSearch do
197
203
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/with_newsfeed.json',
198
204
  { "_expand" => "NewsFeedSubscriptionSummary" } )
199
205
  resource = subject.class.find(id)
200
- resource.stub(:provided_search?) { false }
201
206
  resource.has_active_newsfeed?.should == true
202
207
  end
203
208
 
204
- it "should return false for a provided search" do
205
- stub_api_get("/provided/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
206
- resource = subject.class.provided.find(id)
209
+ it "should return false if the search doesn't have a newsfeed" do
210
+ stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
211
+ stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/without_newsfeed.json',
212
+ { "_expand" => "NewsFeedSubscriptionSummary" } )
213
+ resource = subject.class.find(id)
207
214
  resource.has_active_newsfeed?.should == false
208
215
  end
209
216
  end
@@ -214,15 +221,17 @@ describe SavedSearch do
214
221
  stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/with_inactive_newsfeed.json',
215
222
  { "_expand" => "NewsFeedSubscriptionSummary" } )
216
223
  resource = subject.class.find(id)
217
- resource.stub(:provided_search?) { false }
218
224
  resource.has_inactive_newsfeed?.should == true
219
225
  end
220
226
 
221
- it "should return false for a provided search" do
222
- stub_api_get("/provided/#{subject.class.element_name}/#{id}", 'saved_searches/with_inactive_newsfeed.json')
223
- resource = subject.class.provided.find(id)
227
+ it "should return false if the search doesn't have a newsfeed" do
228
+ stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
229
+ stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/without_newsfeed.json',
230
+ { "_expand" => "NewsFeedSubscriptionSummary, NewsFeeds" } )
231
+ resource = subject.class.find(id)
224
232
  resource.has_inactive_newsfeed?.should == false
225
233
  end
234
+
226
235
  end
227
236
 
228
237
  describe "newsfeed" do
@@ -235,4 +244,10 @@ describe SavedSearch do
235
244
  end
236
245
  end
237
246
 
247
+ describe "QUALIFYING_FIELDS_FOR_NEWSFEED" do
248
+ it "should return an array" do
249
+ subject.class::QUALIFYING_FIELDS_FOR_NEWSFEED.should be_an(Array)
250
+ end
251
+ end
252
+
238
253
  end
@@ -0,0 +1,19 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe Sort do
4
+ before(:each) do
5
+ stub_auth_request
6
+ end
7
+
8
+ it "should include the finders module" do
9
+ Sort.should respond_to(:find)
10
+ end
11
+
12
+ it "should return sorts" do
13
+ stub_api_get("/searchtemplates/sorts", 'sorts/get.json')
14
+ sorts = Sort.find(:all)
15
+ sorts.should be_an(Array)
16
+ sorts.length.should eq(1)
17
+ end
18
+
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spark_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.24
4
+ version: 1.3.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Hornseth
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-02-17 00:00:00.000000000 Z
12
+ date: 2015-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -192,21 +192,21 @@ dependencies:
192
192
  - !ruby/object:Gem::Version
193
193
  version: 0.9.9
194
194
  - !ruby/object:Gem::Dependency
195
- name: flexmls_gems
195
+ name: rb-readline
196
196
  requirement: !ruby/object:Gem::Requirement
197
197
  requirements:
198
- - - ~>
198
+ - - ! '>='
199
199
  - !ruby/object:Gem::Version
200
- version: 0.2.5
200
+ version: '0'
201
201
  type: :development
202
202
  prerelease: false
203
203
  version_requirements: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - ~>
205
+ - - ! '>='
206
206
  - !ruby/object:Gem::Version
207
- version: 0.2.5
207
+ version: '0'
208
208
  - !ruby/object:Gem::Dependency
209
- name: rb-readline
209
+ name: rb-fsevent
210
210
  requirement: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - ! '>='
@@ -220,7 +220,21 @@ dependencies:
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  - !ruby/object:Gem::Dependency
223
- name: rb-fsevent
223
+ name: simplecov
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ! '>='
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ type: :development
230
+ prerelease: false
231
+ version_requirements: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ! '>='
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ - !ruby/object:Gem::Dependency
237
+ name: simplecov-rcov
224
238
  requirement: !ruby/object:Gem::Requirement
225
239
  requirements:
226
240
  - - ! '>='
@@ -300,11 +314,13 @@ files:
300
314
  - lib/spark_api/models/open_house.rb
301
315
  - lib/spark_api/models/photo.rb
302
316
  - lib/spark_api/models/portal.rb
317
+ - lib/spark_api/models/portal_listing_cart.rb
303
318
  - lib/spark_api/models/property_types.rb
304
319
  - lib/spark_api/models/rental_calendar.rb
305
320
  - lib/spark_api/models/saved_search.rb
306
321
  - lib/spark_api/models/search_template/quick_search.rb
307
322
  - lib/spark_api/models/shared_listing.rb
323
+ - lib/spark_api/models/sort.rb
308
324
  - lib/spark_api/models/standard_fields.rb
309
325
  - lib/spark_api/models/subresource.rb
310
326
  - lib/spark_api/models/system_info.rb
@@ -319,10 +335,13 @@ files:
319
335
  - lib/spark_api/request.rb
320
336
  - lib/spark_api/response.rb
321
337
  - lib/spark_api/version.rb
338
+ - script/bootstrap
339
+ - script/ci_build
322
340
  - script/combined_flow_example.rb
323
341
  - script/console
324
342
  - script/example.rb
325
343
  - script/oauth2_example.rb
344
+ - script/release
326
345
  - spec/fixtures/accounts/all.json
327
346
  - spec/fixtures/accounts/my.json
328
347
  - spec/fixtures/accounts/my_portal.json
@@ -387,7 +406,9 @@ files:
387
406
  - spec/fixtures/listings/photos/rotate.json
388
407
  - spec/fixtures/listings/put.json
389
408
  - spec/fixtures/listings/put_expiration_date.json
409
+ - spec/fixtures/listings/put_reorder_photo.json
390
410
  - spec/fixtures/listings/rental_calendar.json
411
+ - spec/fixtures/listings/reorder_photo.json
391
412
  - spec/fixtures/listings/shared_listing_get.json
392
413
  - spec/fixtures/listings/shared_listing_new.json
393
414
  - spec/fixtures/listings/shared_listing_post.json
@@ -437,13 +458,16 @@ files:
437
458
  - spec/fixtures/portal/post.json
438
459
  - spec/fixtures/property_types/property_types.json
439
460
  - spec/fixtures/saved_searches/get.json
461
+ - spec/fixtures/saved_searches/get_provided.json
440
462
  - spec/fixtures/saved_searches/new.json
441
463
  - spec/fixtures/saved_searches/post.json
442
464
  - spec/fixtures/saved_searches/update.json
443
465
  - spec/fixtures/saved_searches/with_inactive_newsfeed.json
444
466
  - spec/fixtures/saved_searches/with_newsfeed.json
467
+ - spec/fixtures/saved_searches/without_newsfeed.json
445
468
  - spec/fixtures/search_templates/quick_searches/get.json
446
469
  - spec/fixtures/session.json
470
+ - spec/fixtures/sorts/get.json
447
471
  - spec/fixtures/standardfields/city.json
448
472
  - spec/fixtures/standardfields/nearby.json
449
473
  - spec/fixtures/standardfields/standardfields.json
@@ -487,6 +511,7 @@ files:
487
511
  - spec/unit/spark_api/models/saved_search_spec.rb
488
512
  - spec/unit/spark_api/models/search_template/quick_search_spec.rb
489
513
  - spec/unit/spark_api/models/shared_listing_spec.rb
514
+ - spec/unit/spark_api/models/sort_spec.rb
490
515
  - spec/unit/spark_api/models/standard_fields_spec.rb
491
516
  - spec/unit/spark_api/models/subresource_spec.rb
492
517
  - spec/unit/spark_api/models/system_info_spec.rb
@@ -537,6 +562,7 @@ test_files:
537
562
  - spec/fixtures/fields/order.json
538
563
  - spec/fixtures/success.json
539
564
  - spec/fixtures/session.json
565
+ - spec/fixtures/sorts/get.json
540
566
  - spec/fixtures/oauth2_error.json
541
567
  - spec/fixtures/base.json
542
568
  - spec/fixtures/idx_links/get.json
@@ -597,6 +623,8 @@ test_files:
597
623
  - spec/fixtures/saved_searches/update.json
598
624
  - spec/fixtures/saved_searches/new.json
599
625
  - spec/fixtures/saved_searches/with_newsfeed.json
626
+ - spec/fixtures/saved_searches/get_provided.json
627
+ - spec/fixtures/saved_searches/without_newsfeed.json
600
628
  - spec/fixtures/saved_searches/get.json
601
629
  - spec/fixtures/saved_searches/with_inactive_newsfeed.json
602
630
  - spec/fixtures/messages/post.json
@@ -604,6 +632,8 @@ test_files:
604
632
  - spec/fixtures/messages/new.json
605
633
  - spec/fixtures/messages/new_empty.json
606
634
  - spec/fixtures/messages/get.json
635
+ - spec/fixtures/listings/put_reorder_photo.json
636
+ - spec/fixtures/listings/reorder_photo.json
607
637
  - spec/fixtures/listings/constraints.json
608
638
  - spec/fixtures/listings/tour_of_homes_search.json
609
639
  - spec/fixtures/listings/tour_of_homes.json
@@ -679,6 +709,7 @@ test_files:
679
709
  - spec/unit/spark_api/models/account_spec.rb
680
710
  - spec/unit/spark_api/models/listing_spec.rb
681
711
  - spec/unit/spark_api/models/video_spec.rb
712
+ - spec/unit/spark_api/models/sort_spec.rb
682
713
  - spec/unit/spark_api/models/saved_search_spec.rb
683
714
  - spec/unit/spark_api/models/contact_spec.rb
684
715
  - spec/unit/spark_api/models/portal_spec.rb