hallon 0.8.0 → 0.9.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.
- data/.travis.yml +2 -0
- data/CHANGELOG +43 -0
- data/Gemfile +2 -0
- data/README.markdown +21 -13
- data/Rakefile +84 -23
- data/dev/login.rb +16 -0
- data/examples/adding_tracks_to_playlist.rb +49 -0
- data/examples/logging_in.rb +1 -6
- data/examples/show_published_playlists_of_user.rb +9 -19
- data/hallon.gemspec +1 -1
- data/lib/hallon.rb +3 -2
- data/lib/hallon/album.rb +55 -41
- data/lib/hallon/album_browse.rb +41 -37
- data/lib/hallon/artist.rb +30 -21
- data/lib/hallon/artist_browse.rb +59 -41
- data/lib/hallon/base.rb +68 -5
- data/lib/hallon/enumerator.rb +1 -0
- data/lib/hallon/error.rb +3 -0
- data/lib/hallon/ext/spotify.rb +169 -36
- data/lib/hallon/image.rb +30 -44
- data/lib/hallon/link.rb +29 -43
- data/lib/hallon/linkable.rb +68 -20
- data/lib/hallon/observable.rb +0 -1
- data/lib/hallon/player.rb +21 -7
- data/lib/hallon/playlist.rb +291 -0
- data/lib/hallon/playlist_container.rb +27 -0
- data/lib/hallon/search.rb +52 -45
- data/lib/hallon/session.rb +129 -81
- data/lib/hallon/toplist.rb +37 -19
- data/lib/hallon/track.rb +68 -45
- data/lib/hallon/user.rb +69 -33
- data/lib/hallon/version.rb +1 -1
- data/spec/hallon/album_browse_spec.rb +15 -9
- data/spec/hallon/album_spec.rb +15 -15
- data/spec/hallon/artist_browse_spec.rb +28 -9
- data/spec/hallon/artist_spec.rb +30 -14
- data/spec/hallon/enumerator_spec.rb +0 -1
- data/spec/hallon/hallon_spec.rb +20 -1
- data/spec/hallon/image_spec.rb +18 -41
- data/spec/hallon/link_spec.rb +10 -12
- data/spec/hallon/linkable_spec.rb +37 -18
- data/spec/hallon/player_spec.rb +8 -0
- data/spec/hallon/playlist_container_spec.rb +75 -0
- data/spec/hallon/playlist_spec.rb +204 -0
- data/spec/hallon/search_spec.rb +19 -16
- data/spec/hallon/session_spec.rb +61 -29
- data/spec/hallon/spotify_spec.rb +30 -0
- data/spec/hallon/toplist_spec.rb +22 -14
- data/spec/hallon/track_spec.rb +62 -21
- data/spec/hallon/user_spec.rb +47 -36
- data/spec/mockspotify.rb +35 -10
- data/spec/mockspotify/mockspotify_spec.rb +22 -0
- data/spec/spec_helper.rb +7 -3
- data/spec/support/common_objects.rb +91 -16
- data/spec/support/shared_for_linkable_objects.rb +39 -0
- metadata +30 -20
- data/Termfile +0 -7
- data/lib/hallon/synchronizable.rb +0 -32
- data/spec/hallon/synchronizable_spec.rb +0 -19
data/lib/hallon/toplist.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
module Hallon
|
2
3
|
# Toplists are what they sound like. They’re collections of
|
3
4
|
# artists, albums or tracks popular in a certain area either
|
@@ -13,6 +14,15 @@ module Hallon
|
|
13
14
|
# @overload initialize(type, country)
|
14
15
|
# @overload initialize(type)
|
15
16
|
#
|
17
|
+
# @example with a given username
|
18
|
+
# toplist = Hallon::Toplist.new(:artists, "burgestrand")
|
19
|
+
#
|
20
|
+
# @example with a given country
|
21
|
+
# toplist = Hallon::Toplist.new(:tracks, :se)
|
22
|
+
#
|
23
|
+
# @example everywhere
|
24
|
+
# toplist = Hallon::Toplist.new(:albums)
|
25
|
+
#
|
16
26
|
# @param [Symbol] type one of :artists, :albums or :tracks
|
17
27
|
# @param [String, Symbol, nil] region username, 2-letter country code or nil
|
18
28
|
def initialize(type, region = nil)
|
@@ -21,53 +31,61 @@ module Hallon
|
|
21
31
|
user = region
|
22
32
|
region = :user
|
23
33
|
when NilClass
|
24
|
-
region = :
|
34
|
+
region = :everywhere
|
25
35
|
when Symbol
|
26
36
|
region = to_country(region)
|
27
37
|
end
|
28
38
|
|
29
39
|
@callback = proc { trigger(:load) }
|
30
|
-
pointer
|
31
|
-
@pointer = Spotify::Pointer.new(pointer, :toplistbrowse, false)
|
40
|
+
@pointer = Spotify.toplistbrowse_create!(session.pointer, type, region, user, @callback, nil)
|
32
41
|
end
|
33
42
|
|
34
|
-
# @return [Boolean] true if the toplist is loaded
|
43
|
+
# @return [Boolean] true if the toplist is loaded.
|
35
44
|
def loaded?
|
36
|
-
Spotify.toplistbrowse_is_loaded(
|
45
|
+
Spotify.toplistbrowse_is_loaded(pointer)
|
37
46
|
end
|
38
47
|
|
39
|
-
# @
|
40
|
-
|
41
|
-
|
48
|
+
# @see Error.explain
|
49
|
+
# @return [Symbol] toplist error status.
|
50
|
+
def status
|
51
|
+
Spotify.toplistbrowse_error(pointer)
|
42
52
|
end
|
43
53
|
|
44
|
-
# @return [Enumerator<Artist>]
|
54
|
+
# @return [Enumerator<Artist>] a list of artists.
|
45
55
|
def artists
|
46
|
-
size = Spotify.toplistbrowse_num_artists(
|
56
|
+
size = Spotify.toplistbrowse_num_artists(pointer)
|
47
57
|
Enumerator.new(size) do |i|
|
48
|
-
artist = Spotify.toplistbrowse_artist(
|
58
|
+
artist = Spotify.toplistbrowse_artist!(pointer, i)
|
49
59
|
Artist.new(artist)
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
53
|
-
# @return [Enumerator<Album>]
|
63
|
+
# @return [Enumerator<Album>] a list of albums.
|
54
64
|
def albums
|
55
|
-
size = Spotify.toplistbrowse_num_albums(
|
65
|
+
size = Spotify.toplistbrowse_num_albums(pointer)
|
56
66
|
Enumerator.new(size) do |i|
|
57
|
-
album = Spotify.toplistbrowse_album(
|
58
|
-
|
67
|
+
album = Spotify.toplistbrowse_album!(pointer, i)
|
68
|
+
Album.new(album)
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
62
|
-
# @return [Enumerator<Track>]
|
72
|
+
# @return [Enumerator<Track>] a list of tracks.
|
63
73
|
def tracks
|
64
|
-
size = Spotify.toplistbrowse_num_tracks(
|
74
|
+
size = Spotify.toplistbrowse_num_tracks(pointer)
|
65
75
|
Enumerator.new(size) do |i|
|
66
|
-
track = Spotify.toplistbrowse_track(
|
67
|
-
|
76
|
+
track = Spotify.toplistbrowse_track!(pointer, i)
|
77
|
+
Track.new(track)
|
68
78
|
end
|
69
79
|
end
|
70
80
|
|
81
|
+
# @note If the object is not loaded, the result is undefined.
|
82
|
+
# @note Returns nil if the request was served from the local libspotify cache.
|
83
|
+
# @return [Rational, nil] time it took for the toplistbrowse request to complete (in seconds).
|
84
|
+
def request_duration
|
85
|
+
duration = Spotify.toplistbrowse_backend_request_duration(pointer)
|
86
|
+
Rational(duration, 1000) if duration > 0
|
87
|
+
end
|
88
|
+
|
71
89
|
private
|
72
90
|
# Convert a given two-character region to a Spotify
|
73
91
|
# compliant region (encoded in a 16bit integer).
|
data/lib/hallon/track.rb
CHANGED
@@ -13,12 +13,13 @@ module Hallon
|
|
13
13
|
# Overriden to use default parameter.
|
14
14
|
# @see #to_link
|
15
15
|
alias_method :_to_link, :to_link
|
16
|
+
|
16
17
|
# Create a Link to the current track and offset in seconds.
|
17
18
|
#
|
18
19
|
# @param [Float] offset offset into track in seconds
|
19
20
|
# @return [Hallon::Link]
|
20
21
|
def to_link(offset = offset)
|
21
|
-
_to_link
|
22
|
+
_to_link((offset * 1000).to_i)
|
22
23
|
end
|
23
24
|
|
24
25
|
# Offset into track in seconds this track was created with.
|
@@ -31,7 +32,7 @@ module Hallon
|
|
31
32
|
# @param [String, Link, FFI::Pointer] link
|
32
33
|
def initialize(link)
|
33
34
|
FFI::MemoryPointer.new(:int) do |ptr|
|
34
|
-
@pointer =
|
35
|
+
@pointer = to_pointer(link, :track, ptr)
|
35
36
|
@offset = Rational(ptr.read_int, 1000)
|
36
37
|
end
|
37
38
|
end
|
@@ -44,14 +45,14 @@ module Hallon
|
|
44
45
|
# @param [Integer] length
|
45
46
|
# @return [Track]
|
46
47
|
def self.local(title, artist, album = nil, length = nil)
|
47
|
-
track = Spotify.localtrack_create(artist, title, album || "", length || -1)
|
48
|
+
track = Spotify.localtrack_create!(artist, title, album || "", length || -1)
|
48
49
|
new(track)
|
49
50
|
end
|
50
51
|
|
51
52
|
# @note This’ll be an empty string unless the track is loaded.
|
52
53
|
# @return [String]
|
53
54
|
def name
|
54
|
-
Spotify.track_name(
|
55
|
+
Spotify.track_name(pointer)
|
55
56
|
end
|
56
57
|
|
57
58
|
# Duration of the track in seconds.
|
@@ -59,7 +60,7 @@ module Hallon
|
|
59
60
|
# @note This’ll be `0` unless the track is loaded.
|
60
61
|
# @return [Rational]
|
61
62
|
def duration
|
62
|
-
Rational(Spotify.track_duration(
|
63
|
+
Rational(Spotify.track_duration(pointer), 1000)
|
63
64
|
end
|
64
65
|
|
65
66
|
# Track popularity, between 0 and 1.
|
@@ -67,97 +68,119 @@ module Hallon
|
|
67
68
|
# @note This’ll be `0` unless the track is loaded.
|
68
69
|
# @return [Rational]
|
69
70
|
def popularity
|
70
|
-
Rational(Spotify.track_popularity(
|
71
|
+
Rational(Spotify.track_popularity(pointer), 100)
|
71
72
|
end
|
72
73
|
|
73
74
|
# Disc number this track appears in.
|
74
75
|
#
|
75
76
|
# @note This function is a bit special. See libspotify docs for details.
|
76
77
|
def disc
|
77
|
-
Spotify.track_disc(
|
78
|
+
Spotify.track_disc(pointer)
|
78
79
|
end
|
79
80
|
|
80
|
-
# Position of track on its’ disc.
|
81
|
-
#
|
82
81
|
# @note This function is a bit special. See libspotify docs for details.
|
82
|
+
# @return [Integer] position of track on its’ disc.
|
83
83
|
def index
|
84
|
-
Spotify.track_index(
|
84
|
+
Spotify.track_index(pointer)
|
85
85
|
end
|
86
86
|
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# @return [Symbol]
|
87
|
+
# @see Error.explain
|
88
|
+
# @return [Symbol] track error status.
|
90
89
|
def status
|
91
|
-
Spotify.track_error(
|
90
|
+
Spotify.track_error(pointer)
|
92
91
|
end
|
93
92
|
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# @return [Boolean]
|
93
|
+
# @return [Boolean] true if track is loaded.
|
97
94
|
def loaded?
|
98
|
-
Spotify.track_is_loaded(
|
95
|
+
Spotify.track_is_loaded(pointer)
|
99
96
|
end
|
100
97
|
|
101
|
-
#
|
98
|
+
# @note Track does not have to be loaded for this to return a useful value.
|
99
|
+
#
|
100
|
+
# @note Placeholder tracks are not really tracks, but merely containers
|
101
|
+
# for other objects to allow storing them in playlists such as the inbox.
|
102
102
|
#
|
103
|
+
# @return [Boolean] true if the track is a placeholder.
|
104
|
+
# @see unwrap
|
105
|
+
def placeholder?
|
106
|
+
Spotify.track_is_placeholder(pointer)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Unwraps a {#placeholder?} Track into its’ real object.
|
110
|
+
#
|
111
|
+
# @see placeholder?
|
112
|
+
# @return [Track, Artist, Album, Playlist]
|
113
|
+
def unwrap
|
114
|
+
return self unless placeholder?
|
115
|
+
|
116
|
+
case (link = to_link).type
|
117
|
+
when :playlist
|
118
|
+
Playlist.new(link)
|
119
|
+
when :album
|
120
|
+
Album.new(link)
|
121
|
+
when :artist
|
122
|
+
Artist.new(link)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# @return [Symbol] track offline status.
|
127
|
+
def offline_status
|
128
|
+
Spotify.track_offline_get_status(pointer)
|
129
|
+
end
|
130
|
+
|
103
131
|
# @note This’ll be `nil` unless the track is loaded.
|
104
|
-
# @return [Hallon::Album]
|
132
|
+
# @return [Hallon::Album] album this track belongs to.
|
105
133
|
def album
|
106
|
-
album = Spotify.track_album(
|
134
|
+
album = Spotify.track_album!(pointer)
|
107
135
|
Album.new(album) unless album.null?
|
108
136
|
end
|
109
137
|
|
110
|
-
# Artist who performed this Track.
|
111
|
-
#
|
112
138
|
# @note There may be more than one artist, see {#artists} for retrieving them all!
|
113
139
|
# @see #artists
|
114
|
-
# @return [Hallon::Artist, nil]
|
140
|
+
# @return [Hallon::Artist, nil] artist who performed this track.
|
115
141
|
def artist
|
116
142
|
artists.first
|
117
143
|
end
|
118
144
|
|
119
|
-
# All {Artist}s who performed this Track.
|
120
|
-
#
|
121
145
|
# @note Track must be loaded, or you’ll get zero artists.
|
122
|
-
# @return [Hallon::Enumerator<Artist>]
|
146
|
+
# @return [Hallon::Enumerator<Artist>] all {Artist}s who performed this Track.
|
123
147
|
def artists
|
124
|
-
size = Spotify.track_num_artists(
|
148
|
+
size = Spotify.track_num_artists(pointer)
|
125
149
|
Enumerator.new(size) do |i|
|
126
|
-
artist = Spotify.track_artist(
|
127
|
-
Artist.new(artist)
|
150
|
+
artist = Spotify.track_artist!(pointer, i)
|
151
|
+
Artist.new(artist)
|
128
152
|
end
|
129
153
|
end
|
130
154
|
|
131
|
-
# True if the Track is available.
|
132
|
-
#
|
133
155
|
# @note This’ll always return false unless the track is loaded.
|
134
|
-
# @return [Boolean]
|
156
|
+
# @return [Boolean] true if {#availability} is available.
|
135
157
|
def available?
|
136
|
-
|
158
|
+
availability == :available
|
137
159
|
end
|
138
160
|
|
139
|
-
#
|
161
|
+
# Track availability.
|
140
162
|
#
|
163
|
+
# @return [Symbol] :unavailable, :available, :not_streamable, :banned_by_artist
|
164
|
+
def availability
|
165
|
+
Spotify.track_get_availability(session.pointer, pointer)
|
166
|
+
end
|
167
|
+
|
141
168
|
# @note This’ll always return false unless the track is loaded.
|
142
|
-
# @return [Boolean]
|
169
|
+
# @return [Boolean] true if the track is a local track.
|
143
170
|
def local?
|
144
|
-
Spotify.track_is_local(session.pointer,
|
171
|
+
Spotify.track_is_local(session.pointer, pointer)
|
145
172
|
end
|
146
173
|
|
147
|
-
# True if the Track is autolinked.
|
148
|
-
#
|
149
174
|
# @note This’ll always return false unless the track is loaded.
|
150
|
-
# @return [Boolean]
|
175
|
+
# @return [Boolean] true if the track is autolinked.
|
151
176
|
def autolinked?
|
152
|
-
Spotify.track_is_autolinked(session.pointer,
|
177
|
+
Spotify.track_is_autolinked(session.pointer, pointer)
|
153
178
|
end
|
154
179
|
|
155
|
-
# True if the track is starred.
|
156
|
-
#
|
157
180
|
# @note This’ll always return false unless the track is loaded.
|
158
|
-
# @return [Boolean]
|
181
|
+
# @return [Boolean] true if the track is starred.
|
159
182
|
def starred?
|
160
|
-
Spotify.track_is_starred(session.pointer,
|
183
|
+
Spotify.track_is_starred(session.pointer, pointer)
|
161
184
|
end
|
162
185
|
|
163
186
|
# Set {#starred?} status of current track.
|
data/lib/hallon/user.rb
CHANGED
@@ -9,60 +9,96 @@ module Hallon
|
|
9
9
|
class User < Base
|
10
10
|
extend Linkable
|
11
11
|
|
12
|
-
#
|
13
|
-
# Given a Link, get its’ underlying pointer.
|
12
|
+
# A Post is created upon sending tracks (with an optional message) to a user.
|
14
13
|
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
# @see http://developer.spotify.com/en/libspotify/docs/group__inbox.html
|
15
|
+
class Post < Base
|
16
|
+
include Observable
|
17
|
+
|
18
|
+
# @param [Spotify::Pointer<inbox>]
|
19
|
+
def initialize(username, message, tracks, &block)
|
20
|
+
@callback = proc { trigger(:load) }
|
21
|
+
|
22
|
+
FFI::MemoryPointer.new(:pointer, tracks.length) do |ary|
|
23
|
+
ary.write_array_of_pointer tracks.map(&:pointer)
|
24
|
+
@pointer = Spotify.inbox_post_tracks!(session.pointer, username, ary, tracks.length, message, @callback, nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @see Error.explain
|
29
|
+
# @return [Symbol] error status of inbox post
|
30
|
+
def status
|
31
|
+
Spotify.inbox_error(pointer)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
19
35
|
from_link :profile do |link|
|
20
|
-
Spotify.link_as_user(link)
|
36
|
+
Spotify.link_as_user!(link)
|
21
37
|
end
|
22
38
|
|
23
|
-
# @macro [attach] to_link
|
24
|
-
# Create a Link to the current object.
|
25
|
-
#
|
26
|
-
# @method to_link
|
27
|
-
# @scope instance
|
28
|
-
# @return [Hallon::Link]
|
29
39
|
to_link :from_user
|
30
40
|
|
31
41
|
# Construct a new instance of User.
|
32
42
|
#
|
33
|
-
# @
|
43
|
+
# @example from a canonical username
|
44
|
+
# Hallon::User.new("burgestrand")
|
45
|
+
#
|
46
|
+
# @example from a spotify URI
|
47
|
+
# Hallon::User.new("spotify:user:burgestrand")
|
48
|
+
#
|
49
|
+
# @note You can also instantiate User with a canonical username
|
50
|
+
# @param [String, Link, Spotify::Pointer] link
|
34
51
|
def initialize(link)
|
35
|
-
@pointer =
|
52
|
+
@pointer = to_pointer(link, :user) do
|
53
|
+
if link.is_a?(String) and link !~ /\Aspotify:user:/
|
54
|
+
to_pointer("spotify:user:#{link}", :user)
|
55
|
+
end
|
56
|
+
end
|
36
57
|
end
|
37
58
|
|
38
59
|
# @return [Boolean] true if the user is loaded
|
39
60
|
def loaded?
|
40
|
-
Spotify.user_is_loaded(
|
61
|
+
Spotify.user_is_loaded(pointer)
|
41
62
|
end
|
42
63
|
|
43
|
-
# Retrieve the name of the
|
64
|
+
# Retrieve the canonical name of the User.
|
44
65
|
#
|
45
|
-
# @note Unless the user is {User#loaded?} only the canonical name is accessible
|
46
|
-
# @param [Symbol] type one of :canonical, :display, :full
|
47
66
|
# @return [String]
|
48
|
-
def name
|
49
|
-
|
50
|
-
when :display
|
51
|
-
Spotify.user_display_name(@pointer)
|
52
|
-
when :full
|
53
|
-
Spotify.user_full_name(@pointer)
|
54
|
-
when :canonical
|
55
|
-
Spotify.user_canonical_name(@pointer)
|
56
|
-
else
|
57
|
-
raise ArgumentError, "expected type to be :display, :full or :canonical, but was #{type}"
|
58
|
-
end.to_s
|
67
|
+
def name
|
68
|
+
Spotify.user_canonical_name(pointer)
|
59
69
|
end
|
60
70
|
|
61
|
-
# Retrieve the
|
71
|
+
# Retrieve the dispaly name of the User.
|
62
72
|
#
|
73
|
+
# @note Unless {#loaded?} is true, this will return the same thing as {#name}.
|
63
74
|
# @return [String]
|
64
|
-
def
|
65
|
-
Spotify.
|
75
|
+
def display_name
|
76
|
+
Spotify.user_display_name(pointer)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Retrieve the users’ starred playlist.
|
80
|
+
#
|
81
|
+
# @note Returns nil unless {User#loaded?}
|
82
|
+
# @return [Playlist, nil]
|
83
|
+
def starred
|
84
|
+
playlist = Spotify.session_starred_for_user_create!(session.pointer, name)
|
85
|
+
Playlist.new(playlist) unless playlist.null?
|
86
|
+
end
|
87
|
+
|
88
|
+
# Send tracks to this users’ inbox, with an optional message.
|
89
|
+
#
|
90
|
+
# @overload post(message, tracks)
|
91
|
+
# @param [#to_s] message
|
92
|
+
# @param [Array<Track>] tracks
|
93
|
+
#
|
94
|
+
# @overload post(tracks)
|
95
|
+
# @param [Array<Track>] tracks
|
96
|
+
#
|
97
|
+
# @return [Post, nil]
|
98
|
+
def post(message = nil, tracks)
|
99
|
+
message &&= message.encode('UTF-8')
|
100
|
+
post = Post.new(name, message, tracks)
|
101
|
+
post unless post.pointer.null?
|
66
102
|
end
|
67
103
|
end
|
68
104
|
end
|
data/lib/hallon/version.rb
CHANGED
@@ -1,20 +1,26 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
describe Hallon::AlbumBrowse do
|
3
|
-
|
4
|
-
|
5
|
-
album = Hallon::Album.new(mock_album)
|
6
|
-
Spotify.should_receive(:albumbrowse_create).and_return(mock_albumbrowse)
|
7
|
-
Hallon::AlbumBrowse.new(album)
|
8
|
-
end
|
9
|
-
end
|
3
|
+
let(:browse) { mock_session { Hallon::AlbumBrowse.new(mock_album) } }
|
4
|
+
subject { browse }
|
10
5
|
|
11
6
|
it { should be_loaded }
|
12
|
-
its(:
|
7
|
+
its(:status) { should eq :ok }
|
13
8
|
its(:album) { should eq Hallon::Album.new(mock_album) }
|
14
9
|
its(:artist) { should eq Hallon::Artist.new(mock_artist) }
|
15
10
|
its('copyrights.size') { should eq 2 }
|
16
11
|
its('copyrights.to_a') { should eq %w[Kim Elin] }
|
17
12
|
its('tracks.size') { should eq 2 }
|
18
|
-
its('tracks.to_a') { should eq
|
13
|
+
its('tracks.to_a') { should eq instantiate(Hallon::Track, mock_track, mock_track_two) }
|
19
14
|
its(:review) { should eq "This album is AWESOME" }
|
15
|
+
|
16
|
+
describe "#request_duration" do
|
17
|
+
it "should return the request duration in seconds" do
|
18
|
+
browse.request_duration.should eq 2.751
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be nil if the request was fetched from local cache" do
|
22
|
+
Spotify.should_receive(:albumbrowse_backend_request_duration).and_return(-1)
|
23
|
+
browse.request_duration.should be_nil
|
24
|
+
end
|
25
|
+
end
|
20
26
|
end
|