hallon 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/lib/hallon/album.rb +4 -4
- data/lib/hallon/album_browse.rb +3 -1
- data/lib/hallon/artist.rb +2 -2
- data/lib/hallon/artist_browse.rb +2 -0
- data/lib/hallon/linkable.rb +6 -10
- data/lib/hallon/playlist.rb +48 -38
- data/lib/hallon/playlist_container.rb +46 -2
- data/lib/hallon/user.rb +11 -10
- data/lib/hallon/version.rb +1 -1
- data/spec/hallon/album_browse_spec.rb +12 -1
- data/spec/hallon/album_spec.rb +3 -0
- data/spec/hallon/artist_browse_spec.rb +7 -0
- data/spec/hallon/artist_spec.rb +5 -5
- data/spec/hallon/linkable_spec.rb +13 -0
- data/spec/hallon/playlist_container_spec.rb +35 -7
- data/spec/hallon/playlist_spec.rb +20 -11
- data/spec/hallon/session_spec.rb +1 -2
- data/spec/hallon/user_spec.rb +15 -0
- data/spec/mockspotify.rb +14 -3
- data/spec/support/common_objects.rb +11 -2
- metadata +14 -14
data/CHANGELOG
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
Hallon’s Changelog
|
2
2
|
==================
|
3
3
|
|
4
|
+
v0.9.1
|
5
|
+
------------------
|
6
|
+
[ Added ]
|
7
|
+
- PlaylistContainer#size
|
8
|
+
- User#published
|
9
|
+
- PlaylistContainer#contents (only for playlists)
|
10
|
+
- PlaylistContainer#add (existing playlist, new playlist)
|
11
|
+
|
12
|
+
[ Changed ]
|
13
|
+
- Playlist#seen now moved to Playlist::Track#seen=
|
14
|
+
|
15
|
+
[ Fixed ]
|
16
|
+
- Album#cover null pointer issue (https://github.com/Burgestrand/Hallon/issues/53)
|
17
|
+
- Various possible null pointer bugs
|
18
|
+
|
19
|
+
|
4
20
|
v0.9.0
|
5
21
|
------------------
|
6
22
|
- Upgraded to libspotify *v10*
|
data/lib/hallon/album.rb
CHANGED
@@ -83,11 +83,11 @@ module Hallon
|
|
83
83
|
# @return [Image, Link, nil] album cover, the link to it, or nil.
|
84
84
|
def cover(as_image = true)
|
85
85
|
if as_image
|
86
|
-
|
87
|
-
Image.new
|
86
|
+
cover = Spotify.album_cover(pointer)
|
87
|
+
Image.new cover.read_string(20) unless cover.null?
|
88
88
|
else
|
89
|
-
|
90
|
-
Link.new
|
89
|
+
cover = Spotify.link_create_from_album_cover!(pointer)
|
90
|
+
Link.new cover unless cover.null?
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
data/lib/hallon/album_browse.rb
CHANGED
@@ -24,6 +24,8 @@ module Hallon
|
|
24
24
|
|
25
25
|
@callback = proc { trigger(:load) }
|
26
26
|
@pointer = Spotify.albumbrowse_create!(session.pointer, pointer, @callback, nil)
|
27
|
+
|
28
|
+
raise FFI::NullPointerError, "album browsing failed" if @pointer.null?
|
27
29
|
end
|
28
30
|
|
29
31
|
# @return [Boolean] true if the album browser is loaded.
|
@@ -75,7 +77,7 @@ module Hallon
|
|
75
77
|
size = Spotify.albumbrowse_num_tracks(pointer)
|
76
78
|
Enumerator.new(size) do |i|
|
77
79
|
track = Spotify.albumbrowse_track!(pointer, i)
|
78
|
-
Track.new(track)
|
80
|
+
Track.new(track)
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
data/lib/hallon/artist.rb
CHANGED
@@ -49,10 +49,10 @@ module Hallon
|
|
49
49
|
def portrait(as_image = true)
|
50
50
|
if as_image
|
51
51
|
portrait = Spotify.artist_portrait(pointer)
|
52
|
-
Image.new
|
52
|
+
Image.new portrait.read_bytes(20) unless portrait.null?
|
53
53
|
else
|
54
54
|
portrait = Spotify.link_create_from_artist_portrait!(pointer)
|
55
|
-
Link.new
|
55
|
+
Link.new portrait unless portrait.null?
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
data/lib/hallon/artist_browse.rb
CHANGED
@@ -28,6 +28,8 @@ module Hallon
|
|
28
28
|
|
29
29
|
@callback = proc { trigger(:load) }
|
30
30
|
@pointer = Spotify.artistbrowse_create!(session.pointer, pointer, type, @callback, nil)
|
31
|
+
|
32
|
+
raise FFI::NullPointerError, "artist browsing failed" if @pointer.null?
|
31
33
|
end
|
32
34
|
|
33
35
|
# @return [Boolean] true if the artist browser is loaded.
|
data/lib/hallon/linkable.rb
CHANGED
@@ -65,15 +65,11 @@ module Hallon
|
|
65
65
|
type = as_object.to_s[/^(as_)?([^_]+)/, 2].to_sym
|
66
66
|
|
67
67
|
define_method(:from_link) do |link, *args|
|
68
|
-
|
69
|
-
link
|
70
|
-
else
|
71
|
-
unless Spotify::Pointer.typechecks?(link, :link)
|
72
|
-
link = Link.new(link).pointer(type)
|
73
|
-
end
|
74
|
-
|
75
|
-
instance_exec(link, *args, &block)
|
68
|
+
unless Spotify::Pointer.typechecks?(link, :link)
|
69
|
+
link = Link.new(link).pointer(type)
|
76
70
|
end
|
71
|
+
|
72
|
+
instance_exec(link, *args, &block)
|
77
73
|
end
|
78
74
|
|
79
75
|
private :from_link
|
@@ -94,11 +90,11 @@ module Hallon
|
|
94
90
|
# end
|
95
91
|
#
|
96
92
|
# @param [Symbol] cmethod name of the C method, say `from_artist` in `Spotify.link_create_from_artist`.
|
97
|
-
# @return [Link]
|
93
|
+
# @return [Link, nil]
|
98
94
|
def to_link(cmethod)
|
99
95
|
define_method(:to_link) do |*args|
|
100
96
|
link = Spotify.__send__(:"link_create_#{cmethod}!", pointer, *args)
|
101
|
-
Link.new(link)
|
97
|
+
Link.new(link) unless link.null?
|
102
98
|
end
|
103
99
|
end
|
104
100
|
|
data/lib/hallon/playlist.rb
CHANGED
@@ -17,15 +17,16 @@ module Hallon
|
|
17
17
|
# There is no way to refresh the information. You’ll have to retrieve the
|
18
18
|
# track again.
|
19
19
|
class Track < Hallon::Track
|
20
|
-
def initialize(playlist, index)
|
21
|
-
super
|
20
|
+
def initialize(pointer, playlist, index)
|
21
|
+
super(pointer)
|
22
22
|
|
23
23
|
@index = index
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
24
|
+
@playlist = playlist
|
25
|
+
@create_time = Time.at Spotify.playlist_track_create_time(playlist.pointer, index)
|
26
|
+
@message = Spotify.playlist_track_message(playlist.pointer, index)
|
27
|
+
@seen = Spotify.playlist_track_seen(playlist.pointer, index)
|
27
28
|
@creator = begin
|
28
|
-
creator = Spotify.playlist_track_creator!(playlist, index)
|
29
|
+
creator = Spotify.playlist_track_creator!(playlist.pointer, index)
|
29
30
|
User.new(creator) unless creator.null?
|
30
31
|
end
|
31
32
|
end
|
@@ -34,26 +35,42 @@ module Hallon
|
|
34
35
|
# @return [Integer] index this track was created with.
|
35
36
|
attr_reader :index
|
36
37
|
|
38
|
+
# @return [Playlist] playlist this track was created from.
|
39
|
+
attr_reader :playlist
|
40
|
+
|
37
41
|
# @return [Time] time when track at {#index} was added to playlist.
|
38
|
-
|
39
|
-
@create_time
|
40
|
-
end
|
42
|
+
attr_reader :create_time
|
41
43
|
|
42
44
|
# @return [User, nil] person who added track at {#index} to this playlist.
|
43
|
-
|
44
|
-
@creator
|
45
|
-
end
|
45
|
+
attr_reader :creator
|
46
46
|
|
47
47
|
# @return [String] message attached to this track at {#index}.
|
48
|
-
|
49
|
-
@message
|
50
|
-
end
|
48
|
+
attr_reader :message
|
51
49
|
|
52
50
|
# @see Playlist#seen
|
53
51
|
# @return [Boolean] true if track at {#index} has been seen.
|
54
52
|
def seen?
|
55
53
|
@seen
|
56
54
|
end
|
55
|
+
|
56
|
+
# Set seen status of the Playlist::Track at the given index.
|
57
|
+
#
|
58
|
+
# @note Word of warning; this method will update the value you get from {#seen?}!
|
59
|
+
# @raise [IndexError] if the underlying track has moved
|
60
|
+
# @raise [Error] if the operation could not be completed
|
61
|
+
#
|
62
|
+
# @param [Integer] index
|
63
|
+
# @param [Boolean] seen true if the track is now seen
|
64
|
+
# @return [Playlist::Track] track at the given index
|
65
|
+
def seen=(seen)
|
66
|
+
unless Spotify.playlist_track(playlist.pointer, index) == pointer
|
67
|
+
raise IndexError, "track has moved from #{index}"
|
68
|
+
end
|
69
|
+
|
70
|
+
error = Spotify.playlist_track_set_seen(playlist.pointer, index, !! seen)
|
71
|
+
Error.maybe_raise(error)
|
72
|
+
@seen = Spotify.playlist_track_seen(playlist.pointer, index)
|
73
|
+
end
|
57
74
|
end
|
58
75
|
|
59
76
|
from_link :playlist do |pointer|
|
@@ -176,16 +193,19 @@ module Hallon
|
|
176
193
|
# libspotify does not store more than 500 subscriber names
|
177
194
|
# @return [Array<String>] list of canonical usernames
|
178
195
|
def subscribers
|
179
|
-
ptr
|
180
|
-
struct = Spotify::Subscribers.new(ptr)
|
196
|
+
ptr = Spotify.playlist_subscribers(pointer)
|
181
197
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
struct[:
|
186
|
-
|
187
|
-
|
188
|
-
|
198
|
+
begin
|
199
|
+
struct = Spotify::Subscribers.new(ptr)
|
200
|
+
|
201
|
+
if struct[:count].zero?
|
202
|
+
[]
|
203
|
+
else
|
204
|
+
struct[:subscribers].map(&:read_string)
|
205
|
+
end
|
206
|
+
ensure
|
207
|
+
Spotify.playlist_subscribers_free(ptr)
|
208
|
+
end unless ptr.null?
|
189
209
|
end
|
190
210
|
|
191
211
|
# @return [Integer] total number of subscribers.
|
@@ -223,20 +243,10 @@ module Hallon
|
|
223
243
|
#
|
224
244
|
# @return [Enumerable<Playlist::Track>] a list of playlist tracks.
|
225
245
|
def tracks
|
226
|
-
Enumerator.new(size)
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
#
|
231
|
-
# @see #tracks
|
232
|
-
# @raise [Error] if the operation could not be completed
|
233
|
-
# @param [Integer] index
|
234
|
-
# @param [Boolean] seen true if the track is now seen
|
235
|
-
# @return [Playlist::Track] track at the given index
|
236
|
-
def seen(index, seen)
|
237
|
-
error = Spotify.playlist_track_set_seen(pointer, index, !! seen)
|
238
|
-
Error.maybe_raise(error)
|
239
|
-
tracks[index]
|
246
|
+
Enumerator.new(size) do |index|
|
247
|
+
track = Spotify.playlist_track!(pointer, index)
|
248
|
+
Playlist::Track.new(track, self, index) unless track.null?
|
249
|
+
end
|
240
250
|
end
|
241
251
|
|
242
252
|
# Add a list of tracks to the playlist starting at given position.
|
@@ -13,15 +13,59 @@ module Hallon
|
|
13
13
|
@pointer = to_pointer(pointer, :playlistcontainer)
|
14
14
|
end
|
15
15
|
|
16
|
-
# @return [Boolean] true if the container is loaded
|
16
|
+
# @return [Boolean] true if the container is loaded.
|
17
17
|
def loaded?
|
18
18
|
Spotify.playlistcontainer_is_loaded(pointer)
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [User, nil] owner of the container (nil if unknown or no owner)
|
21
|
+
# @return [User, nil] owner of the container (nil if unknown or no owner).
|
22
22
|
def owner
|
23
23
|
owner = Spotify.playlistcontainer_owner!(pointer)
|
24
24
|
User.new(owner) unless owner.null?
|
25
25
|
end
|
26
|
+
|
27
|
+
# @return [Integer] number of playlists and folders in this container.
|
28
|
+
def size
|
29
|
+
Spotify.playlistcontainer_num_playlists(pointer)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Enumerator<Playlist, Folder, nil>] an enumerator of folders and playlists.
|
33
|
+
def contents
|
34
|
+
Enumerator.new(size) do |i|
|
35
|
+
type = Spotify.playlistcontainer_playlist_type(pointer, i)
|
36
|
+
|
37
|
+
case type
|
38
|
+
when :playlist
|
39
|
+
playlist = Spotify.playlistcontainer_playlist!(pointer, i)
|
40
|
+
Playlist.new(playlist)
|
41
|
+
when :start_folder
|
42
|
+
when :end_folder
|
43
|
+
else # :unknown
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @overload add(name)
|
49
|
+
# Create a new playlist at the end of the container with the given name.
|
50
|
+
#
|
51
|
+
# @param [String] name
|
52
|
+
# @return [Playlist, nil] the new playlist, or nil if the operation failed
|
53
|
+
#
|
54
|
+
# @overload add(playlist)
|
55
|
+
# Add the given playlist to the end of the container.
|
56
|
+
#
|
57
|
+
# @param [Playlist, Link, #to_link] playlist
|
58
|
+
# @return [Playlist, nil] the added playlist, or nil if the operation failed
|
59
|
+
def add(name_or_playlist)
|
60
|
+
playlist = if name_or_playlist.is_a?(String)
|
61
|
+
Spotify.playlistcontainer_add_new_playlist!(pointer, name_or_playlist)
|
62
|
+
else
|
63
|
+
link = name_or_playlist
|
64
|
+
link = link.to_link unless link.is_a?(Link)
|
65
|
+
Spotify.playlistcontainer_add_playlist!(pointer, link.pointer)
|
66
|
+
end
|
67
|
+
|
68
|
+
Playlist.new(playlist) unless playlist.null?
|
69
|
+
end
|
26
70
|
end
|
27
71
|
end
|
data/lib/hallon/user.rb
CHANGED
@@ -56,35 +56,36 @@ module Hallon
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
# @return [Boolean] true if the user is loaded
|
59
|
+
# @return [Boolean] true if the user is loaded.
|
60
60
|
def loaded?
|
61
61
|
Spotify.user_is_loaded(pointer)
|
62
62
|
end
|
63
63
|
|
64
|
-
#
|
65
|
-
#
|
66
|
-
# @return [String]
|
64
|
+
# @return [String] canonical name of the User.
|
67
65
|
def name
|
68
66
|
Spotify.user_canonical_name(pointer)
|
69
67
|
end
|
70
68
|
|
71
|
-
# Retrieve the dispaly name of the User.
|
72
|
-
#
|
73
69
|
# @note Unless {#loaded?} is true, this will return the same thing as {#name}.
|
74
|
-
# @return [String]
|
70
|
+
# @return [String] display name of the User.
|
75
71
|
def display_name
|
76
72
|
Spotify.user_display_name(pointer)
|
77
73
|
end
|
78
74
|
|
79
|
-
# Retrieve the users’ starred playlist.
|
80
|
-
#
|
81
75
|
# @note Returns nil unless {User#loaded?}
|
82
|
-
# @return [Playlist, nil]
|
76
|
+
# @return [Playlist, nil] starred playlist of the User.
|
83
77
|
def starred
|
84
78
|
playlist = Spotify.session_starred_for_user_create!(session.pointer, name)
|
85
79
|
Playlist.new(playlist) unless playlist.null?
|
86
80
|
end
|
87
81
|
|
82
|
+
# @note Returns nil unless {#loaded?}
|
83
|
+
# @return [PlaylistContainer, nil] published playlists of the User.
|
84
|
+
def published
|
85
|
+
container = Spotify.session_publishedcontainer_for_user_create!(session.pointer, name)
|
86
|
+
PlaylistContainer.new(container) unless container.null?
|
87
|
+
end
|
88
|
+
|
88
89
|
# Send tracks to this users’ inbox, with an optional message.
|
89
90
|
#
|
90
91
|
# @overload post(message, tracks)
|
data/lib/hallon/version.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
describe Hallon::AlbumBrowse do
|
3
|
-
|
3
|
+
describe ".new" do
|
4
|
+
it "should raise an error if the browse request failed" do
|
5
|
+
Spotify.should_receive(:albumbrowse_create).and_return(null_pointer)
|
6
|
+
expect { mock_session { Hallon::AlbumBrowse.new(mock_album) } }.to raise_error(FFI::NullPointerError)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:browse) do
|
11
|
+
album = Hallon::Album.new(mock_album)
|
12
|
+
mock_session { Hallon::AlbumBrowse.new(album) }
|
13
|
+
end
|
14
|
+
|
4
15
|
subject { browse }
|
5
16
|
|
6
17
|
it { should be_loaded }
|
data/spec/hallon/album_spec.rb
CHANGED
@@ -32,6 +32,9 @@ describe Hallon::Album do
|
|
32
32
|
it "should be nil if there is no image" do
|
33
33
|
Spotify.should_receive(:album_cover).and_return(null_pointer)
|
34
34
|
album.cover.should be_nil
|
35
|
+
|
36
|
+
Spotify.should_receive(:link_create_from_album_cover).and_return(null_pointer)
|
37
|
+
album.cover(false).should be_nil
|
35
38
|
end
|
36
39
|
|
37
40
|
it "should be an image if it exists" do
|
@@ -1,5 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
describe Hallon::ArtistBrowse do
|
3
|
+
describe ".new" do
|
4
|
+
it "should raise an error if the browse request failed" do
|
5
|
+
Spotify.should_receive(:artistbrowse_create).and_return(null_pointer)
|
6
|
+
expect { mock_session { Hallon::ArtistBrowse.new(mock_artist) } }.to raise_error(FFI::NullPointerError)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
let(:browse) do
|
4
11
|
artist = Hallon::Artist.new(mock_artist)
|
5
12
|
mock_session { Hallon::ArtistBrowse.new(artist) }
|
data/spec/hallon/artist_spec.rb
CHANGED
@@ -30,19 +30,19 @@ describe Hallon::Artist do
|
|
30
30
|
let(:link) { Hallon::Link.new(mock_image_uri) }
|
31
31
|
|
32
32
|
specify "as an image" do
|
33
|
-
|
34
|
-
|
35
|
-
subject.portrait.should eq Hallon::Image.new(mock_image_id)
|
33
|
+
mock_session(2) { artist.portrait.should eq Hallon::Image.new(mock_image_id) }
|
36
34
|
end
|
37
35
|
|
38
36
|
specify "as a link" do
|
39
|
-
|
37
|
+
artist.portrait(false).should eq Hallon::Link.new(mock_image_uri)
|
40
38
|
end
|
41
39
|
|
42
40
|
it "should be nil if an image is not available" do
|
43
41
|
Spotify.should_receive(:artist_portrait).and_return(null_pointer)
|
42
|
+
artist.portrait.should be_nil
|
44
43
|
|
45
|
-
|
44
|
+
Spotify.should_receive(:link_create_from_artist_portrait).and_return(null_pointer)
|
45
|
+
artist.portrait(false).should be_nil
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -22,6 +22,19 @@ describe Hallon::Linkable do
|
|
22
22
|
object.respond_to?(:from_link, true).should be_true
|
23
23
|
end
|
24
24
|
|
25
|
+
describe "#to_link" do
|
26
|
+
it "should return nil if link creation failed" do
|
27
|
+
Spotify.should_receive(:link_create_from_user).and_return(null_pointer)
|
28
|
+
|
29
|
+
klass.instance_eval do
|
30
|
+
to_link(:from_user)
|
31
|
+
attr_reader :pointer
|
32
|
+
end
|
33
|
+
|
34
|
+
object.to_link.should be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
25
38
|
describe "#from_link" do
|
26
39
|
it "should call the appropriate Spotify function" do
|
27
40
|
Spotify.should_receive(:link_as_search!).and_return(pointer)
|
@@ -6,14 +6,44 @@ describe Hallon::PlaylistContainer do
|
|
6
6
|
|
7
7
|
it { should be_loaded }
|
8
8
|
its(:owner) { should eq Hallon::User.new("burgestrand") }
|
9
|
+
its(:size) { should eq 1 }
|
9
10
|
|
10
11
|
describe "#add" do
|
11
|
-
|
12
|
+
context "given a string" do
|
13
|
+
it "should create a new Playlist at the end of the playlist" do
|
14
|
+
expect do
|
15
|
+
playlist = container.add("Bogus")
|
16
|
+
|
17
|
+
playlist.name.should eq "Bogus"
|
18
|
+
container.contents[-1].should eq playlist
|
19
|
+
end.to change{ container.size }.by(1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should add the given Playlist to the end of the container" do
|
24
|
+
expect do
|
25
|
+
playlist = container.add Hallon::Playlist.new(mock_playlist)
|
26
|
+
container.contents[-1].should eq Hallon::Playlist.new(mock_playlist)
|
27
|
+
end.to change{ container.size }.by(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should add the given Playlist Link to the end of the container" do
|
31
|
+
expect do
|
32
|
+
playlist = container.add Hallon::Link.new("spotify:user:burgestrand:playlist:07AX9IY9Hqmj1RqltcG0fi")
|
33
|
+
container.contents[-1].should eq Hallon::Playlist.new(mock_playlist)
|
34
|
+
end.to change{ container.size }.by(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return nil when failing to add the item" do
|
38
|
+
Spotify.should_receive(:playlistcontainer_add_playlist).and_return(null_pointer)
|
39
|
+
playlist = container.add Hallon::Link.new("spotify:user:burgestrand")
|
40
|
+
playlist.should be_nil
|
41
|
+
end
|
12
42
|
end
|
13
43
|
|
14
44
|
describe "#insert" do
|
15
45
|
it "should add the given Playlist to the given index"
|
16
|
-
it "should add the given Folder to the given index"
|
46
|
+
it "should add the given Folder to the given index"
|
17
47
|
end
|
18
48
|
|
19
49
|
describe "#remove" do
|
@@ -50,12 +80,10 @@ describe Hallon::PlaylistContainer do
|
|
50
80
|
# (8) Playlist #8
|
51
81
|
#
|
52
82
|
it "should be a collection of folders and playlists"
|
53
|
-
end
|
54
83
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
its(:name) { should be "Awesome playlist" }
|
84
|
+
it "should support retrieving playlists" do
|
85
|
+
container.contents[0].should eq Hallon::Playlist.new(mock_playlist)
|
86
|
+
end
|
59
87
|
end
|
60
88
|
|
61
89
|
describe Hallon::PlaylistContainer::Folder, :pending do
|
@@ -31,26 +31,30 @@ describe Hallon::Playlist do
|
|
31
31
|
its(:size) { should eq 4 }
|
32
32
|
|
33
33
|
its('tracks.size') { should eq 4 }
|
34
|
-
its('tracks.to_a') { should eq instantiate(Hallon::Playlist::Track,
|
34
|
+
its('tracks.to_a') { should eq instantiate(Hallon::Playlist::Track, *(0...4).map { |index| [Spotify.playlist_track!(playlist.pointer, index), playlist, index] }) }
|
35
|
+
|
35
36
|
describe "tracks#[]" do
|
37
|
+
let(:track) { subject }
|
36
38
|
subject { playlist.tracks[0] }
|
37
39
|
|
38
40
|
it { should be_seen }
|
39
41
|
its(:create_time) { should eq Time.parse("2009-11-04") }
|
40
42
|
its(:creator) { should eq Hallon::User.new(mock_user) }
|
41
43
|
its(:message) { should eq "message this, YO!" }
|
42
|
-
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
describe "#seen=" do
|
46
|
+
it "should raise an error if the track has moved" do
|
47
|
+
track.should be_seen
|
48
|
+
track.playlist.move(1, 0)
|
49
|
+
expect { track.seen = false }.to raise_error(IndexError)
|
50
|
+
track.should be_seen
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
it "should update the value of #seen?" do
|
54
|
+
track.should be_seen
|
55
|
+
track.seen = false
|
56
|
+
track.should_not be_seen
|
57
|
+
end
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
@@ -63,6 +67,11 @@ describe Hallon::Playlist do
|
|
63
67
|
Spotify.should_receive(:playlist_subscribers).and_return(mock_empty_subscribers)
|
64
68
|
subject.subscribers.should eq []
|
65
69
|
end
|
70
|
+
|
71
|
+
it "should return nil when subscriber fetching failed" do
|
72
|
+
Spotify.should_receive(:playlist_subscribers).and_return(null_pointer)
|
73
|
+
playlist.subscribers.should be_nil
|
74
|
+
end
|
66
75
|
end
|
67
76
|
|
68
77
|
describe "#insert" do
|
data/spec/hallon/session_spec.rb
CHANGED
@@ -54,8 +54,7 @@ describe Hallon::Session do
|
|
54
54
|
describe "#container" do
|
55
55
|
it "should return the sessions’ playlist container" do
|
56
56
|
session.login 'burgestrand', 'pass'
|
57
|
-
session.container.should
|
58
|
-
session.container.owner.should eq session.user
|
57
|
+
session.container.should eq Hallon::PlaylistContainer.new(mock_container)
|
59
58
|
end
|
60
59
|
|
61
60
|
it "should return nil if not logged in" do
|
data/spec/hallon/user_spec.rb
CHANGED
@@ -70,5 +70,20 @@ describe Hallon::User do
|
|
70
70
|
mock_session { user.starred.should be_nil }
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
describe "#published" do
|
75
|
+
let(:published) { Hallon::PlaylistContainer.new(mock_container) }
|
76
|
+
|
77
|
+
it "should return the playlist container of the user" do
|
78
|
+
Spotify.registry_add("spotify:container:%s" % user.name, mock_container)
|
79
|
+
|
80
|
+
session.login('burgestrand', '')
|
81
|
+
mock_session { user.published.should eq published }
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return nil if not logged in" do
|
85
|
+
mock_session { user.published.should be_nil }
|
86
|
+
end
|
87
|
+
end
|
73
88
|
end
|
74
89
|
end
|
data/spec/mockspotify.rb
CHANGED
@@ -26,13 +26,24 @@ module Spotify
|
|
26
26
|
require 'spotify'
|
27
27
|
|
28
28
|
module Mock
|
29
|
+
def self.find_type(*args, &block)
|
30
|
+
Spotify.find_type(*args, &block)
|
31
|
+
end
|
32
|
+
|
29
33
|
class PlaylistTrack < FFI::Struct
|
30
|
-
layout :track, :
|
34
|
+
layout :track, :track,
|
31
35
|
:create_time, :int,
|
32
|
-
:creator, :
|
36
|
+
:creator, :user,
|
33
37
|
:message, :pointer,
|
34
38
|
:seen, :bool
|
35
39
|
end
|
40
|
+
|
41
|
+
class PlaylistContainerItem < FFI::Struct
|
42
|
+
layout :playlist, :playlist,
|
43
|
+
:type, :playlist_type,
|
44
|
+
:folder_name, :pointer,
|
45
|
+
:folder_id, :uint64
|
46
|
+
end
|
36
47
|
end
|
37
48
|
|
38
49
|
old_verbose, $VERBOSE = $VERBOSE, true
|
@@ -61,7 +72,7 @@ module Spotify
|
|
61
72
|
attach_function :mock_toplistbrowse, :mocksp_toplistbrowse_create, [:error, :int, :int, :array, :int, :array, :int, :array], :toplistbrowse
|
62
73
|
|
63
74
|
attach_mock_function :mock_playlist, :mocksp_playlist_create, [:string, :bool, :user, :bool, :string, :image_id, :bool, :uint, Spotify::Subscribers, :bool, :playlist_offline_status, :int, :int, :array], :playlist
|
64
|
-
attach_mock_function :mock_playlistcontainer, :mocksp_playlistcontainer_create, [:user, :bool], :playlistcontainer
|
75
|
+
attach_mock_function :mock_playlistcontainer, :mocksp_playlistcontainer_create, [:user, :bool, :int, :array, PlaylistContainerCallbacks, :userdata], :playlistcontainer
|
65
76
|
attach_function :mock_search, :mocksp_search_create, [:error, :string, :string, :int, :int, :array, :int, :int, :array, :int, :int, :array, :search_complete_cb, :pointer], :search
|
66
77
|
attach_function :mock_subscribers, :mocksp_subscribers, [:int, :array], Spotify::Subscribers
|
67
78
|
|
@@ -146,14 +146,23 @@ RSpec::Core::ExampleGroup.instance_eval do
|
|
146
146
|
end
|
147
147
|
|
148
148
|
let(:mock_container) do
|
149
|
-
|
150
|
-
|
149
|
+
num_items = 1
|
150
|
+
items_ptr = FFI::MemoryPointer.new(Spotify::Mock::PlaylistTrack, num_items)
|
151
|
+
items = num_items.times.map do |i|
|
152
|
+
Spotify::Mock::PlaylistContainerItem.new(items_ptr + Spotify::Mock::PlaylistContainerItem.size * i)
|
153
|
+
end
|
154
|
+
|
155
|
+
items[0][:playlist] = mock_playlist
|
156
|
+
items[0][:type] = :playlist
|
157
|
+
|
158
|
+
Spotify.mock_playlistcontainer(mock_user, true, num_items, items_ptr, nil, nil)
|
151
159
|
end
|
152
160
|
end
|
153
161
|
|
154
162
|
RSpec.configure do |config|
|
155
163
|
config.before do
|
156
164
|
Spotify.registry_add mock_image_uri, mock_image
|
165
|
+
Spotify.registry_add 'spotify:container:burgestrand', mock_container
|
157
166
|
Spotify.registry_add 'spotify:albumbrowse:1xvnWMz2PNFf7mXOSRuLws', mock_albumbrowse
|
158
167
|
Spotify.registry_add 'spotify:artistbrowse:3bftcFwl4vqRNNORRsqm1G', mock_artistbrowse
|
159
168
|
Spotify.registry_add 'spotify:artist:3bftcFwl4vqRNNORRsqm1G', mock_artist
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hallon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: spotify
|
16
|
-
requirement: &
|
16
|
+
requirement: &70199932063240 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 10.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70199932063240
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &70199932060440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70199932060440
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &70199932058360 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0.8'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70199932058360
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70199932057240 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '2'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70199932057240
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: yard
|
60
|
-
requirement: &
|
60
|
+
requirement: &70199932056420 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70199932056420
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rdiscount
|
71
|
-
requirement: &
|
71
|
+
requirement: &70199932055320 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70199932055320
|
80
80
|
description:
|
81
81
|
email: kim@burgestrand.se
|
82
82
|
executables: []
|