spark_api 1.4.31 → 1.5.2
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 +4 -4
- data/README.md +1 -1
- data/VERSION +1 -1
- data/lib/spark_api.rb +1 -0
- data/lib/spark_api/authentication/api_auth.rb +1 -1
- data/lib/spark_api/authentication/oauth2.rb +1 -1
- data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +1 -1
- data/lib/spark_api/client.rb +2 -2
- data/lib/spark_api/models.rb +2 -0
- data/lib/spark_api/models/floplan.rb +24 -0
- data/lib/spark_api/models/listing.rb +11 -1
- data/lib/spark_api/models/media.rb +30 -0
- data/lib/spark_api/models/subresource.rb +2 -2
- data/lib/spark_api/models/video.rb +108 -0
- data/lib/spark_api/models/virtual_tour.rb +16 -0
- data/lib/spark_api/request.rb +1 -1
- data/spec/fixtures/listings/floplans_index.json +15 -0
- data/spec/spec_helper.rb +9 -4
- data/spec/unit/spark_api/authentication/api_auth_spec.rb +21 -22
- data/spec/unit/spark_api/authentication/base_auth_spec.rb +3 -3
- data/spec/unit/spark_api/authentication/oauth2_impl/faraday_middleware_spec.rb +1 -1
- data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb +1 -1
- data/spec/unit/spark_api/authentication/oauth2_impl/single_session_provider_spec.rb +2 -2
- data/spec/unit/spark_api/authentication/oauth2_spec.rb +40 -40
- data/spec/unit/spark_api/authentication_spec.rb +2 -2
- data/spec/unit/spark_api/configuration/yaml_spec.rb +44 -44
- data/spec/unit/spark_api/configuration_spec.rb +56 -57
- data/spec/unit/spark_api/faraday_middleware_spec.rb +12 -12
- data/spec/unit/spark_api/models/account_spec.rb +20 -20
- data/spec/unit/spark_api/models/activity_spec.rb +5 -5
- data/spec/unit/spark_api/models/base_spec.rb +32 -32
- data/spec/unit/spark_api/models/concerns/destroyable_spec.rb +2 -2
- data/spec/unit/spark_api/models/concerns/savable_spec.rb +19 -19
- data/spec/unit/spark_api/models/connect_prefs_spec.rb +1 -1
- data/spec/unit/spark_api/models/constraint_spec.rb +1 -1
- data/spec/unit/spark_api/models/contact_spec.rb +50 -50
- data/spec/unit/spark_api/models/dirty_spec.rb +12 -12
- data/spec/unit/spark_api/models/document_spec.rb +3 -3
- data/spec/unit/spark_api/models/fields_spec.rb +17 -17
- data/spec/unit/spark_api/models/finders_spec.rb +7 -7
- data/spec/unit/spark_api/models/floplan_spec.rb +24 -0
- data/spec/unit/spark_api/models/listing_cart_spec.rb +46 -46
- data/spec/unit/spark_api/models/listing_meta_translations_spec.rb +6 -6
- data/spec/unit/spark_api/models/listing_spec.rb +91 -91
- data/spec/unit/spark_api/models/message_spec.rb +10 -10
- data/spec/unit/spark_api/models/note_spec.rb +10 -10
- data/spec/unit/spark_api/models/notification_spec.rb +6 -6
- data/spec/unit/spark_api/models/open_house_spec.rb +4 -4
- data/spec/unit/spark_api/models/photo_spec.rb +8 -8
- data/spec/unit/spark_api/models/portal_spec.rb +4 -4
- data/spec/unit/spark_api/models/property_types_spec.rb +5 -5
- data/spec/unit/spark_api/models/rental_calendar_spec.rb +13 -11
- data/spec/unit/spark_api/models/rule_spec.rb +2 -2
- data/spec/unit/spark_api/models/saved_search_spec.rb +33 -33
- data/spec/unit/spark_api/models/search_template/quick_search_spec.rb +5 -5
- data/spec/unit/spark_api/models/shared_listing_spec.rb +12 -12
- data/spec/unit/spark_api/models/sort_spec.rb +3 -3
- data/spec/unit/spark_api/models/standard_fields_spec.rb +12 -12
- data/spec/unit/spark_api/models/subresource_spec.rb +33 -15
- data/spec/unit/spark_api/models/system_info_spec.rb +7 -7
- data/spec/unit/spark_api/models/tour_of_home_spec.rb +3 -3
- data/spec/unit/spark_api/models/video_spec.rb +9 -9
- data/spec/unit/spark_api/models/virtual_tour_spec.rb +7 -7
- data/spec/unit/spark_api/models/vow_account_spec.rb +8 -8
- data/spec/unit/spark_api/multi_client_spec.rb +14 -14
- data/spec/unit/spark_api/options_hash_spec.rb +4 -4
- data/spec/unit/spark_api/paginate_spec.rb +71 -71
- data/spec/unit/spark_api/primary_array_spec.rb +5 -5
- data/spec/unit/spark_api/request_spec.rb +60 -60
- data/spec/unit/spark_api_spec.rb +6 -6
- metadata +172 -237
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9dfabf550d6eea2fb80a30b047b5c0fb4a5aa95f4bad6ee2fd9135acc21ce479
|
|
4
|
+
data.tar.gz: 8587cc4fa49929d9286ec6ac37c9d97259e6fbdf2d7b583716edc5d67068d47f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e0467d03ebcac984dd9ba6dbd0b120e60d1ef1c340d1972145140678a84b405567114a4af2eaba8776c8e9a20cc556dafada327cb9d86c9ad95dbec8ca2a1f5
|
|
7
|
+
data.tar.gz: 6b9107aa27eed9afd313b34144c1f2b22425fa421568d6b496edb7d96b9828313568651457b3cd3f71085c7b3d09ecfd7d7595cced256cdc0a01775edf46b308
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Spark API
|
|
2
2
|
=====================
|
|
3
|
-
|
|
3
|
+
 
|
|
4
4
|
|
|
5
5
|
A Ruby wrapper for the Spark REST API. Loosely based on ActiveResource to provide models to interact with remote services.
|
|
6
6
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.5.2
|
data/lib/spark_api.rb
CHANGED
|
@@ -40,7 +40,7 @@ module SparkApi
|
|
|
40
40
|
|
|
41
41
|
# Perform an HTTP request (no data)
|
|
42
42
|
def request(method, path, body, options={})
|
|
43
|
-
escaped_path = URI.escape(path)
|
|
43
|
+
escaped_path = Addressable::URI.escape(path)
|
|
44
44
|
connection = @client.connection(true) # SSL Only!
|
|
45
45
|
connection.headers.merge!(self.auth_header)
|
|
46
46
|
|
|
@@ -45,7 +45,7 @@ module SparkApi
|
|
|
45
45
|
response.expires_in = provider.session_timeout if response.expires_in.nil?
|
|
46
46
|
SparkApi.logger.debug { "[oauth2] New session created #{response}" }
|
|
47
47
|
response
|
|
48
|
-
rescue Faraday::
|
|
48
|
+
rescue Faraday::ConnectionFailed => e
|
|
49
49
|
if @client.ssl_verify && e.message =~ /certificate verify failed/
|
|
50
50
|
SparkApi.logger.error { SparkApi::Errors.ssl_verification_error }
|
|
51
51
|
end
|
data/lib/spark_api/client.rb
CHANGED
|
@@ -2,7 +2,7 @@ module SparkApi
|
|
|
2
2
|
# =API Client
|
|
3
3
|
# Main class to setup and run requests on the API. A default client is accessible globally as
|
|
4
4
|
# SparkApi::client if the global configuration has been set as well. Otherwise, this class may
|
|
5
|
-
# be
|
|
5
|
+
# be instantiated separately with the configuration information.
|
|
6
6
|
class Client
|
|
7
7
|
include Connection
|
|
8
8
|
include Authentication
|
|
@@ -21,7 +21,7 @@ module SparkApi
|
|
|
21
21
|
Configuration::VALID_OPTION_KEYS.each do |key|
|
|
22
22
|
send("#{key}=", options[key])
|
|
23
23
|
end
|
|
24
|
-
#
|
|
24
|
+
# Instantiate the authentication class passed in.
|
|
25
25
|
@authenticator = authentication_mode.send("new", self)
|
|
26
26
|
end
|
|
27
27
|
|
data/lib/spark_api/models.rb
CHANGED
|
@@ -20,10 +20,12 @@ require 'spark_api/models/fields'
|
|
|
20
20
|
require 'spark_api/models/idx'
|
|
21
21
|
require 'spark_api/models/idx_link'
|
|
22
22
|
require 'spark_api/models/incomplete_listing'
|
|
23
|
+
require 'spark_api/models/floplan'
|
|
23
24
|
require 'spark_api/models/listing'
|
|
24
25
|
require 'spark_api/models/listing_cart'
|
|
25
26
|
require 'spark_api/models/listing_meta_translations'
|
|
26
27
|
require 'spark_api/models/market_statistics'
|
|
28
|
+
require 'spark_api/models/media'
|
|
27
29
|
require 'spark_api/models/message'
|
|
28
30
|
require 'spark_api/models/news_feed_meta'
|
|
29
31
|
require 'spark_api/models/newsfeed'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
module Models
|
|
3
|
+
class FloPlan < Base
|
|
4
|
+
extend Subresource
|
|
5
|
+
self.element_name = 'floplans'
|
|
6
|
+
|
|
7
|
+
attr_accessor :images, :thumbnails
|
|
8
|
+
|
|
9
|
+
def initialize(attributes={})
|
|
10
|
+
@images = []
|
|
11
|
+
@thumbnails = []
|
|
12
|
+
|
|
13
|
+
attributes['Images'].each do |img|
|
|
14
|
+
if img["Type"].include?('thumbnail')
|
|
15
|
+
@thumbnails << img
|
|
16
|
+
else
|
|
17
|
+
@images << img
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
super(attributes)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -2,7 +2,7 @@ module SparkApi
|
|
|
2
2
|
module Models
|
|
3
3
|
class Listing < Base
|
|
4
4
|
extend Finders
|
|
5
|
-
attr_accessor :photos, :videos, :virtual_tours, :documents, :open_houses, :tour_of_homes, :rental_calendars
|
|
5
|
+
attr_accessor :photos, :videos, :virtual_tours, :documents, :open_houses, :tour_of_homes, :rental_calendars, :floplans
|
|
6
6
|
attr_accessor :constraints
|
|
7
7
|
self.element_name="listings"
|
|
8
8
|
DATA_MASK = "********"
|
|
@@ -17,6 +17,7 @@ module SparkApi
|
|
|
17
17
|
@constraints = []
|
|
18
18
|
@tour_of_homes = []
|
|
19
19
|
@open_houses = []
|
|
20
|
+
@floplans = []
|
|
20
21
|
|
|
21
22
|
if attributes.has_key?('StandardFields')
|
|
22
23
|
pics, vids, tours, docs, ohouses, tourhomes = attributes['StandardFields'].values_at('Photos','Videos', 'VirtualTours', 'Documents', 'OpenHouses', 'TourOfHomes')
|
|
@@ -26,6 +27,10 @@ module SparkApi
|
|
|
26
27
|
rentalcalendars = attributes['RentalCalendar']
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
if attributes.has_key?('FloPlans')
|
|
31
|
+
floplans = attributes['FloPlans']
|
|
32
|
+
end
|
|
33
|
+
|
|
29
34
|
if pics != nil
|
|
30
35
|
setup_attribute(@photos, pics, Photo)
|
|
31
36
|
attributes['StandardFields'].delete('Photos')
|
|
@@ -61,6 +66,11 @@ module SparkApi
|
|
|
61
66
|
attributes.delete('RentalCalendar')
|
|
62
67
|
end
|
|
63
68
|
|
|
69
|
+
if floplans != nil
|
|
70
|
+
setup_attribute(@floplans, floplans, FloPlan)
|
|
71
|
+
attributes.delete('FloPlans')
|
|
72
|
+
end
|
|
73
|
+
|
|
64
74
|
super(attributes)
|
|
65
75
|
end
|
|
66
76
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
module Models
|
|
3
|
+
module Media
|
|
4
|
+
# This module is effectively an interface and helper to combine common media
|
|
5
|
+
# actions and information. Media types (videos, virtual tours, etc)
|
|
6
|
+
# should include this module and implement the methods contained
|
|
7
|
+
|
|
8
|
+
def url
|
|
9
|
+
raise "Not Implemented"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def description
|
|
13
|
+
raise "Not Implemented"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def private?
|
|
17
|
+
attributes['Privacy'] == 'Private'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def public?
|
|
21
|
+
attributes['Privacy'] == 'Public'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def automatic?
|
|
25
|
+
attributes['Privacy'] == 'Automatic'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -16,10 +16,10 @@ module SparkApi
|
|
|
16
16
|
|
|
17
17
|
def parse_date_start_and_end_times(attributes)
|
|
18
18
|
# Transform the date strings
|
|
19
|
-
unless attributes['Date'].nil?
|
|
19
|
+
unless attributes['Date'].nil? || attributes['Date'].empty?
|
|
20
20
|
date = Date.strptime attributes['Date'], '%m/%d/%Y'
|
|
21
21
|
['StartTime','EndTime'].each do |time|
|
|
22
|
-
next if attributes[time].nil?
|
|
22
|
+
next if attributes[time].nil? || attributes[time].empty?
|
|
23
23
|
formatted_date = "#{attributes['Date']}T#{attributes[time]}"
|
|
24
24
|
datetime = nil
|
|
25
25
|
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
require 'net/http'
|
|
1
2
|
module SparkApi
|
|
2
3
|
module Models
|
|
3
4
|
class Video < Base
|
|
4
5
|
extend Subresource
|
|
6
|
+
include Media
|
|
7
|
+
include Concerns::Savable,
|
|
8
|
+
Concerns::Destroyable
|
|
9
|
+
|
|
5
10
|
self.element_name = 'videos'
|
|
6
11
|
|
|
7
12
|
def branded?
|
|
@@ -11,6 +16,109 @@ module SparkApi
|
|
|
11
16
|
def unbranded?
|
|
12
17
|
attributes['Type'] == 'unbranded'
|
|
13
18
|
end
|
|
19
|
+
|
|
20
|
+
def url
|
|
21
|
+
attributes['ObjectHtml']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def description
|
|
25
|
+
attributes['Name']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Some youtube URLS are youtu.be instead of youtube
|
|
29
|
+
SUPPORTED_VIDEO_TYPES = %w[vimeo youtu].freeze
|
|
30
|
+
|
|
31
|
+
def is_supported_type?
|
|
32
|
+
# Unfortunately there are so many formats of vimeo videos that we canot support all vimeo videos
|
|
33
|
+
# Therefore, we need to do a little more checking here and validate that we can get video codes out of the urls
|
|
34
|
+
(self.ObjectHtml.include?('youtu') && youtube_video_code.present?) || (self.ObjectHtml.include?('vimeo') && vimeo_video_code.present?)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def is_valid_iframe?
|
|
38
|
+
self.ObjectHtml.include?('<iframe') && self.ObjectHtml.include?('</iframe>')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# gets the thumbnail to be shown on supported (Vimeo and Youtube) videos
|
|
42
|
+
# YouTube provides a predictable url for each video's images
|
|
43
|
+
# for Vimeo, a get request is necessary
|
|
44
|
+
def display_image
|
|
45
|
+
url = self.video_link
|
|
46
|
+
if url
|
|
47
|
+
if(url.include?('youtube'))
|
|
48
|
+
youtube_thumbnail_url
|
|
49
|
+
else
|
|
50
|
+
vimeo_thumbnail_url
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def video_link
|
|
56
|
+
return nil unless is_supported_type?
|
|
57
|
+
|
|
58
|
+
if self.ObjectHtml.include?('youtu')
|
|
59
|
+
youtube_link
|
|
60
|
+
elsif self.ObjectHtml.include?('vimeo')
|
|
61
|
+
vimeo_link
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def vimeo_video_code
|
|
68
|
+
html = self.ObjectHtml
|
|
69
|
+
if html.match(/(src=)('|")((https:)?\/\/player\.vimeo\.com\/video\/)/)
|
|
70
|
+
new_url = html.split(/(src=')|(src=")/)
|
|
71
|
+
if new_url[2]
|
|
72
|
+
html = new_url[2].split(/("|')/)[0]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
if html.match(/(?:.+?)?(player\.vimeo\.com|vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|)(\d+)(?:$|\/|\?))/)
|
|
76
|
+
code = html.split('/').last.split('?').first
|
|
77
|
+
# Vimeo Ids are always numerical
|
|
78
|
+
code.to_i.to_s === code ? code : nil
|
|
79
|
+
else
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# This if correctly embedded by the user is an embed
|
|
85
|
+
# If not, it could be pretty much anything
|
|
86
|
+
def youtube_video_code
|
|
87
|
+
html = self.ObjectHtml
|
|
88
|
+
if html.match(/(?:.+?)?(?:\/v\/|watch\/|\?v=|\&v=|youtu\.be\/|\/v=|^youtu\.be\/|embed\/|watch\%3Fv\%3D)([a-zA-Z0-9_-]{11})/) || html.match(/(iframe)(.*)(src=)('|")(https:\/\/www\.youtube\.com\/embed)/)
|
|
89
|
+
html.split(/([a-zA-Z0-9_-]{11})/)[1]
|
|
90
|
+
else
|
|
91
|
+
nil
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def youtube_link
|
|
96
|
+
normalize_youtube_url
|
|
97
|
+
code = youtube_video_code
|
|
98
|
+
code ? "https://www.youtube.com/watch?v=#{code}" : nil
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def vimeo_link
|
|
102
|
+
code = vimeo_video_code
|
|
103
|
+
code ? "https://vimeo.com/#{code}" : nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def youtube_thumbnail_url
|
|
107
|
+
code = youtube_video_code
|
|
108
|
+
code ? "https://i1.ytimg.com/vi/#{code}/hqdefault.jpg" : nil
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def vimeo_thumbnail_url
|
|
112
|
+
# due to the rate limiting issue that surfaced shortly before launch,
|
|
113
|
+
# we will temporarily not return vimeo thumbnails until
|
|
114
|
+
# there is bandwidth to implement the solution in FLEX-9959
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def normalize_youtube_url
|
|
119
|
+
self.ObjectHtml.sub!('-nocookie', '')
|
|
120
|
+
end
|
|
121
|
+
|
|
14
122
|
end
|
|
15
123
|
end
|
|
16
124
|
end
|
|
@@ -2,6 +2,10 @@ module SparkApi
|
|
|
2
2
|
module Models
|
|
3
3
|
class VirtualTour < Base
|
|
4
4
|
extend Subresource
|
|
5
|
+
include Media
|
|
6
|
+
include Concerns::Savable,
|
|
7
|
+
Concerns::Destroyable
|
|
8
|
+
|
|
5
9
|
self.element_name="virtualtours"
|
|
6
10
|
|
|
7
11
|
|
|
@@ -13,6 +17,18 @@ module SparkApi
|
|
|
13
17
|
attributes["Type"] == "unbranded"
|
|
14
18
|
end
|
|
15
19
|
|
|
20
|
+
def url
|
|
21
|
+
attributes['Uri']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def description
|
|
25
|
+
attributes['Name']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def display_image
|
|
29
|
+
# Currently we have no universally good mechanism to get images for virtual tours
|
|
30
|
+
return nil
|
|
31
|
+
end
|
|
16
32
|
end
|
|
17
33
|
end
|
|
18
34
|
end
|
data/lib/spark_api/request.rb
CHANGED
|
@@ -99,7 +99,7 @@ module SparkApi
|
|
|
99
99
|
else
|
|
100
100
|
return response.body
|
|
101
101
|
end
|
|
102
|
-
rescue Faraday::
|
|
102
|
+
rescue Faraday::ConnectionFailed => e
|
|
103
103
|
if self.ssl_verify && e.message =~ /certificate verify failed/
|
|
104
104
|
SparkApi.logger.error { SparkApi::Errors.ssl_verification_error }
|
|
105
105
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -11,7 +11,6 @@ end
|
|
|
11
11
|
|
|
12
12
|
require "rubygems"
|
|
13
13
|
require "rspec"
|
|
14
|
-
require 'rspec/autorun'
|
|
15
14
|
require 'webmock/rspec'
|
|
16
15
|
require "json"
|
|
17
16
|
require 'multi_json'
|
|
@@ -22,6 +21,13 @@ require path + '/spark_api'
|
|
|
22
21
|
|
|
23
22
|
require 'spark_api'
|
|
24
23
|
|
|
24
|
+
if ENV['COVERAGE'] == "on"
|
|
25
|
+
require 'simplecov'
|
|
26
|
+
require 'simplecov-rcov'
|
|
27
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
|
28
|
+
SimpleCov.start { add_filter %w(/vendor /spec /test) }
|
|
29
|
+
end
|
|
30
|
+
|
|
25
31
|
FileUtils.mkdir 'log' unless File.exists? 'log'
|
|
26
32
|
|
|
27
33
|
module SparkApi
|
|
@@ -48,17 +54,16 @@ end
|
|
|
48
54
|
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
|
|
49
55
|
|
|
50
56
|
RSpec.configure do |config|
|
|
51
|
-
|
|
57
|
+
|
|
52
58
|
config.include WebMock::API
|
|
53
59
|
config.include StubApiRequests
|
|
54
60
|
|
|
55
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
|
56
61
|
config.alias_example_to :on_get_it, :method => 'GET'
|
|
57
62
|
config.alias_example_to :on_put_it, :method => 'PUT'
|
|
58
63
|
config.alias_example_to :on_post_it, :method => 'POST'
|
|
59
64
|
config.alias_example_to :on_delete_it, :method => 'DELETE'
|
|
60
65
|
config.before(:all) { reset_config }
|
|
61
|
-
config.
|
|
66
|
+
config.color = true
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
def jruby?
|
|
@@ -4,15 +4,14 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
4
4
|
subject {SparkApi::Authentication::ApiAuth.new(nil) }
|
|
5
5
|
describe "build_param_hash" do
|
|
6
6
|
it "should return a blank string when passed nil" do
|
|
7
|
-
subject.build_param_string(nil).
|
|
7
|
+
expect(subject.build_param_string(nil)).to be_empty
|
|
8
8
|
end
|
|
9
9
|
it "should return a correct param string for one item" do
|
|
10
|
-
subject.build_param_string({:foo => "bar"}).
|
|
10
|
+
expect(subject.build_param_string({:foo => "bar"})).to match("foobar")
|
|
11
11
|
end
|
|
12
12
|
it "should alphabatize the param names by key first, then by value" do
|
|
13
|
-
subject.build_param_string({:zoo => "zar", :ooo => "car"}).
|
|
14
|
-
subject.build_param_string({:Akey => "aValue", :aNotherkey => "AnotherValue"}).
|
|
15
|
-
match "AkeyaValueaNotherkeyAnotherValue"
|
|
13
|
+
expect(subject.build_param_string({:zoo => "zar", :ooo => "car"})).to match("ooocarzoozar")
|
|
14
|
+
expect(subject.build_param_string({:Akey => "aValue", :aNotherkey => "AnotherValue"})).to match("AkeyaValueaNotherkeyAnotherValue")
|
|
16
15
|
end
|
|
17
16
|
end
|
|
18
17
|
|
|
@@ -33,7 +32,7 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
33
32
|
stub_request(:post, "https://api.sparkapi.com/#{SparkApi.version}/session").
|
|
34
33
|
with(:query => {:ApiKey => "my_key", :ApiSig => "c731cf2455fbc7a4ef937b2301108d7a"}).
|
|
35
34
|
to_return(:body => fixture("authentication_failure.json"), :status=>401)
|
|
36
|
-
expect {subject.authenticate()}.to raise_error(SparkApi::ClientError){ |e| e.status.
|
|
35
|
+
expect {subject.authenticate()}.to raise_error(SparkApi::ClientError){ |e| expect(e.status).to eq(401) }
|
|
37
36
|
end
|
|
38
37
|
end
|
|
39
38
|
|
|
@@ -41,16 +40,16 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
41
40
|
let(:session) { Object.new }
|
|
42
41
|
it "should return true when session is active" do
|
|
43
42
|
subject.session = session
|
|
44
|
-
session.
|
|
45
|
-
subject.authenticated
|
|
43
|
+
allow(session).to receive(:expired?) { false }
|
|
44
|
+
expect(subject.authenticated?).to eq(true)
|
|
46
45
|
end
|
|
47
46
|
it "should return false when session is expired" do
|
|
48
47
|
subject.session = session
|
|
49
|
-
session.
|
|
50
|
-
subject.authenticated
|
|
48
|
+
allow(session).to receive(:expired?) { true }
|
|
49
|
+
expect(subject.authenticated?).to eq(false)
|
|
51
50
|
end
|
|
52
51
|
it "should return false when session is uninitialized" do
|
|
53
|
-
subject.authenticated
|
|
52
|
+
expect(subject.authenticated?).to eq(false)
|
|
54
53
|
end
|
|
55
54
|
end
|
|
56
55
|
|
|
@@ -61,14 +60,14 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
61
60
|
it "should logout when there is an active session" do
|
|
62
61
|
logged_out = false
|
|
63
62
|
subject.session = session
|
|
64
|
-
client.
|
|
63
|
+
allow(client).to receive(:delete).with("/session/1234") { logged_out = true }
|
|
65
64
|
subject.logout
|
|
66
|
-
subject.session.
|
|
67
|
-
logged_out.
|
|
65
|
+
expect(subject.session).to eq(nil)
|
|
66
|
+
expect(logged_out).to eq(true)
|
|
68
67
|
end
|
|
69
68
|
it "should skip logging out when there is no active session information" do
|
|
70
|
-
client.
|
|
71
|
-
subject.logout.
|
|
69
|
+
allow(client).to receive(:delete) { raise "Should not be called" }
|
|
70
|
+
expect(subject.logout).to eq(nil)
|
|
72
71
|
end
|
|
73
72
|
end
|
|
74
73
|
|
|
@@ -98,7 +97,7 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
98
97
|
:AuthToken => "1234"}.merge(args)).
|
|
99
98
|
to_return(:body => fixture("listings/no_subresources.json"))
|
|
100
99
|
subject.session = session
|
|
101
|
-
subject.request(:get, "/#{SparkApi.version}/listings", nil, args).status.
|
|
100
|
+
expect(subject.request(:get, "/#{SparkApi.version}/listings", nil, args).status).to eq(200)
|
|
102
101
|
end
|
|
103
102
|
it "should handle a post request" do
|
|
104
103
|
stub_auth_request
|
|
@@ -118,14 +117,14 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
118
117
|
}]}
|
|
119
118
|
}',
|
|
120
119
|
:status=>201)
|
|
121
|
-
subject.request(:post, "/#{SparkApi.version}/contacts", contact, args).status.
|
|
120
|
+
expect(subject.request(:post, "/#{SparkApi.version}/contacts", contact, args).status).to eq(201)
|
|
122
121
|
end
|
|
123
122
|
end
|
|
124
123
|
|
|
125
124
|
describe "sign" do
|
|
126
125
|
it "should sign the auth parameters correctly" do
|
|
127
126
|
sign_token = "my_secretApiKeymy_key"
|
|
128
|
-
subject.sign(sign_token).
|
|
127
|
+
expect(subject.sign(sign_token)).to eq("c731cf2455fbc7a4ef937b2301108d7a")
|
|
129
128
|
end
|
|
130
129
|
end
|
|
131
130
|
|
|
@@ -134,7 +133,7 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
134
133
|
subject {SparkApi::Authentication::ApiAuth.new(client) }
|
|
135
134
|
it "should fully sign the token" do
|
|
136
135
|
parms = {:AuthToken => "1234", :ApiUser => "CoolAsIce"}
|
|
137
|
-
subject.sign_token("/test", parms).
|
|
136
|
+
expect(subject.sign_token("/test", parms)).to eq("7bbe3384a8b64368357f8551cab271e3")
|
|
138
137
|
end
|
|
139
138
|
end
|
|
140
139
|
|
|
@@ -160,8 +159,8 @@ describe SparkApi::Authentication::ApiAuth do
|
|
|
160
159
|
to_return(:body => fixture('listings/with_documents.json'))
|
|
161
160
|
l = Listing.find('1234', :_expand => "Documents")
|
|
162
161
|
|
|
163
|
-
count.
|
|
164
|
-
SparkApi.client.session.expired
|
|
162
|
+
expect(count).to eq(2)
|
|
163
|
+
expect(SparkApi.client.session.expired?).to eq(false)
|
|
165
164
|
end
|
|
166
165
|
end
|
|
167
166
|
|