spark_api 1.3.24 → 1.3.25

Sign up to get free protection for your applications and to get access to all the features.
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