hallon 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/CHANGELOG.md +40 -0
  2. data/README.markdown +1 -1
  3. data/dev/application_key_converter.rb +11 -0
  4. data/examples/example_support.rb +4 -0
  5. data/examples/playing_audio.rb +1 -1
  6. data/lib/hallon.rb +11 -0
  7. data/lib/hallon/album_browse.rb +3 -3
  8. data/lib/hallon/artist_browse.rb +20 -4
  9. data/lib/hallon/blob.rb +11 -0
  10. data/lib/hallon/enumerator.rb +5 -0
  11. data/lib/hallon/ext/spotify.rb +2 -0
  12. data/lib/hallon/image.rb +7 -1
  13. data/lib/hallon/link.rb +5 -2
  14. data/lib/hallon/observable.rb +48 -1
  15. data/lib/hallon/player.rb +15 -26
  16. data/lib/hallon/playlist.rb +16 -25
  17. data/lib/hallon/playlist_container.rb +38 -0
  18. data/lib/hallon/search.rb +75 -4
  19. data/lib/hallon/session.rb +31 -42
  20. data/lib/hallon/toplist.rb +3 -3
  21. data/lib/hallon/track.rb +28 -10
  22. data/lib/hallon/version.rb +1 -1
  23. data/spec/hallon/album_browse_spec.rb +68 -18
  24. data/spec/hallon/album_spec.rb +62 -27
  25. data/spec/hallon/artist_browse_spec.rb +106 -31
  26. data/spec/hallon/artist_spec.rb +32 -18
  27. data/spec/hallon/blob_spec.rb +6 -0
  28. data/spec/hallon/enumerator_spec.rb +10 -0
  29. data/spec/hallon/error_spec.rb +4 -4
  30. data/spec/hallon/hallon_spec.rb +1 -1
  31. data/spec/hallon/image_spec.rb +58 -47
  32. data/spec/hallon/link_spec.rb +51 -43
  33. data/spec/hallon/observable/album_browse_spec.rb +1 -1
  34. data/spec/hallon/observable/artist_browse_spec.rb +1 -1
  35. data/spec/hallon/observable/image_spec.rb +1 -1
  36. data/spec/hallon/observable/playlist_container_spec.rb +4 -4
  37. data/spec/hallon/observable/playlist_spec.rb +14 -14
  38. data/spec/hallon/observable/post_spec.rb +1 -1
  39. data/spec/hallon/observable/search_spec.rb +1 -1
  40. data/spec/hallon/observable/session_spec.rb +17 -17
  41. data/spec/hallon/observable/toplist_spec.rb +1 -1
  42. data/spec/hallon/observable_spec.rb +40 -6
  43. data/spec/hallon/player_spec.rb +1 -1
  44. data/spec/hallon/playlist_container_spec.rb +96 -13
  45. data/spec/hallon/playlist_spec.rb +180 -45
  46. data/spec/hallon/search_spec.rb +211 -28
  47. data/spec/hallon/session_spec.rb +44 -38
  48. data/spec/hallon/toplist_spec.rb +31 -14
  49. data/spec/hallon/track_spec.rb +159 -50
  50. data/spec/hallon/user_post_spec.rb +10 -5
  51. data/spec/hallon/user_spec.rb +60 -50
  52. data/spec/spec_helper.rb +40 -15
  53. data/spec/support/album_mocks.rb +30 -0
  54. data/spec/support/artist_mocks.rb +36 -0
  55. data/spec/support/common_objects.rb +0 -201
  56. data/spec/support/image_mocks.rb +34 -0
  57. data/spec/support/playlist_container_mocks.rb +36 -0
  58. data/spec/support/playlist_mocks.rb +70 -0
  59. data/spec/support/search_mocks.rb +23 -0
  60. data/spec/support/session_mocks.rb +33 -0
  61. data/spec/support/toplist_mocks.rb +19 -0
  62. data/spec/support/track_mocks.rb +28 -0
  63. data/spec/support/user_mocks.rb +20 -0
  64. metadata +40 -18
  65. data/spec/support/context_stub_session.rb +0 -5
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
  describe Hallon::Player do
3
- let(:player) { Hallon::Player.new(session, AudioDriverMock) }
3
+ let(:player) { Hallon::Player.new(AudioDriverMock) }
4
4
  let(:track) { Hallon::Track.new(mock_track) }
5
5
  let(:driver) { player.instance_variable_get('@driver') }
6
6
  let(:queue) { player.instance_variable_get('@queue') } # black box? WHAT?
@@ -1,14 +1,48 @@
1
1
  # coding: utf-8
2
2
  describe Hallon::PlaylistContainer do
3
- it { should be_a Hallon::Loadable }
3
+ let(:container) do
4
+ Hallon::PlaylistContainer.new(mock_containers[:default])
5
+ end
6
+
7
+ let(:empty_container) do
8
+ Hallon::PlaylistContainer.new(mock_containers[:empty])
9
+ end
10
+
11
+ let(:empty_playlist) do
12
+ Hallon::Playlist.new(mock_playlists[:empty])
13
+ end
14
+
15
+ let(:playlist) do
16
+ Hallon::Playlist.new(mock_playlists[:default])
17
+ end
4
18
 
5
- let(:container) { Hallon::PlaylistContainer.new(mock_container) }
19
+ specify { container.should be_a Hallon::Loadable }
6
20
 
7
- subject { container }
21
+ describe "#loaded?" do
22
+ it "returns true if the playlist container is loaded" do
23
+ container.should be_loaded
24
+ end
25
+ end
8
26
 
9
- it { should be_loaded }
10
- its(:owner) { should eq Hallon::User.new("burgestrand") }
11
- its(:size) { should eq 4 }
27
+ describe "#owner" do
28
+ it "returns the playlist container’s owner" do
29
+ container.owner.should eq Hallon::User.new("burgestrand")
30
+ end
31
+
32
+ it "returns nil if the playlist container is not loaded" do
33
+ empty_container.owner.should be_nil
34
+ end
35
+ end
36
+
37
+ describe "#size" do
38
+ it "returns the number of playlists inside the container" do
39
+ container.size.should eq 4
40
+ end
41
+
42
+ it "returns zero if the container is empty" do
43
+ empty_container.size.should eq 0
44
+ end
45
+ end
12
46
 
13
47
  describe "#add" do
14
48
  context "given a string that’s not a valid spotify playlist uri" do
@@ -29,7 +63,7 @@ describe Hallon::PlaylistContainer do
29
63
  context "given a string that’s a valid spotify playlist uri" do
30
64
  it "should add the existing Playlist at the end of the container" do
31
65
  playlist_uri = "spotify:user:burgestrand:playlist:07AX9IY9Hqmj1RqltcG0fi"
32
- playlist = mock_session { Hallon::Playlist.new(playlist_uri) }
66
+ playlist = Hallon::Playlist.new(playlist_uri)
33
67
 
34
68
  expect do
35
69
  new_playlist = container.add(playlist_uri)
@@ -169,13 +203,31 @@ describe Hallon::PlaylistContainer do
169
203
  end
170
204
 
171
205
  describe Hallon::PlaylistContainer::Folder do
172
- subject { container.contents[1] }
173
- let(:folder) { subject }
206
+ let(:folder) { container.contents[1] }
207
+
208
+ describe "#id" do
209
+ it "returns the folder’s ID" do
210
+ folder.id.should eq 1337
211
+ end
212
+ end
213
+
214
+ describe "#name" do
215
+ it "returns the folder’s name" do
216
+ folder.name.should eq "Boogie"
217
+ end
218
+ end
219
+
220
+ describe "#begin" do
221
+ it "returns the folder’s starting index" do
222
+ folder.begin.should eq 1
223
+ end
224
+ end
174
225
 
175
- its(:id) { should be 1337 }
176
- its(:name) { should eq "Boogie" }
177
- its(:begin) { should be 1 }
178
- its(:end) { should be 3 }
226
+ describe "#end" do
227
+ it "returns the folder’s ending index" do
228
+ folder.end.should eq 3
229
+ end
230
+ end
179
231
 
180
232
  describe "#moved?" do
181
233
  it "should return true if the folder has moved" do
@@ -222,4 +274,35 @@ describe Hallon::PlaylistContainer do
222
274
  end
223
275
  end
224
276
  end
277
+
278
+ describe "#unseen_tracks_count_for" do
279
+ it "returns the number of unseen tracks for the given playlist" do
280
+ container.unseen_tracks_count_for(playlist).should eq 4
281
+ end
282
+
283
+ it "raises an error if the result was an error" do
284
+ expect { container.unseen_tracks_count_for(empty_playlist) }.to raise_error(Hallon::OperationFailedError)
285
+ end
286
+ end
287
+
288
+ describe "#unseen_tracks_for" do
289
+ it "returns an array of unseen tracks" do
290
+ container.unseen_tracks_for(playlist).should eq playlist.tracks.to_a
291
+ end
292
+
293
+ it "returns an array of unseen tracks, no bigger than the given count" do
294
+ container.unseen_tracks_for(playlist, 2).should eq playlist.tracks.to_a[0, 2]
295
+ end
296
+
297
+ it "raises an error if the result was an error (but count was not)" do
298
+ Spotify.should_receive(:playlistcontainer_get_unseen_tracks).and_return(4, -1)
299
+ expect { container.unseen_tracks_for(empty_playlist) }.to raise_error(Hallon::OperationFailedError)
300
+ end
301
+ end
302
+
303
+ describe "#clear_unseen_tracks_for" do
304
+ it "raises an error if the operation failed" do
305
+ expect { container.clear_unseen_tracks_for(empty_playlist) }.to raise_error(Hallon::OperationFailedError)
306
+ end
307
+ end
225
308
  end
@@ -2,16 +2,19 @@
2
2
  require 'time'
3
3
 
4
4
  describe Hallon::Playlist do
5
- it { should be_a Hallon::Loadable }
5
+ let(:playlist) do
6
+ Hallon::Playlist.new(mock_playlists[:default])
7
+ end
6
8
 
7
- it_should_behave_like "a Linkable object" do
8
- let(:spotify_uri) { "spotify:user:burgestrand:playlist:07AX9IY9Hqmj1RqltcG0fi" }
9
- let(:described_class) { stub_session(Hallon::Playlist) }
9
+ let(:empty_playlist) do
10
+ Hallon::Playlist.new(mock_playlists[:empty])
10
11
  end
11
12
 
12
- subject { playlist }
13
- let(:playlist) do
14
- Hallon::Playlist.new(mock_playlist)
13
+ specify { playlist.should be_a Hallon::Loadable }
14
+
15
+ it_should_behave_like "a Linkable object" do
16
+ let(:spotify_uri) { "spotify:user:burgestrand:playlist:07AX9IY9Hqmj1RqltcG0fi" }
17
+ let(:described_class) { Hallon::Playlist }
15
18
  end
16
19
 
17
20
  describe ".invalid_name?" do
@@ -28,31 +31,164 @@ describe Hallon::Playlist do
28
31
  end
29
32
  end
30
33
 
31
- it { should be_loaded }
32
- it { should be_collaborative }
33
- it { should_not be_pending }
34
- it { stub_session { should be_in_ram } }
35
- it { stub_session { should_not be_available_offline } }
34
+ describe "#loaded?" do
35
+ it "is true when the playlist is loaded" do
36
+ playlist.should be_loaded
37
+ end
38
+
39
+ it "is false when the playlist is not loaded" do
40
+ empty_playlist.should_not be_loaded
41
+ end
42
+ end
43
+
44
+ describe "#name" do
45
+ it "returns the playlist’s name as a string" do
46
+ playlist.name.should eq "Megaplaylist"
47
+ end
48
+
49
+ it "returns an empty string when the playlist is not loaded" do
50
+ empty_playlist.name.should be_empty
51
+ end
52
+ end
53
+
54
+ describe "#owner" do
55
+ it "returns the playlist’s owner" do
56
+ playlist.owner.should eq Hallon::User.new(mock_user)
57
+ end
58
+
59
+ it "returns nil when the playlist is not loaded" do
60
+ empty_playlist.owner.should be_nil
61
+ end
62
+ end
63
+
64
+ describe "#description" do
65
+ it "returns the playlist’s description" do
66
+ playlist.description.should eq "Playlist description...?"
67
+ end
68
+
69
+ it "returns an empty string if the playlist is not loaded" do
70
+ empty_playlist.description.should be_empty
71
+ end
72
+ end
73
+
74
+ describe "#image" do
75
+ it "returns the playlists’s image as an image" do
76
+ playlist.image.should eq Hallon::Image.new("spotify:image:3ad93423add99766e02d563605c6e76ed2b0e400")
77
+ end
78
+
79
+ it "returns nil if the playlist is not loaded" do
80
+ empty_playlist.image.should be_nil
81
+ end
82
+ end
83
+
84
+ describe "#total_subscribers" do
85
+ it "returns the total number of subscribers to the playlist" do
86
+ playlist.total_subscribers.should eq 1000
87
+ end
88
+
89
+ it "returns zero if the playlist is not loaded" do
90
+ empty_playlist.total_subscribers.should eq 0
91
+ end
92
+ end
93
+
94
+ describe "#sync_progress" do
95
+ it "returns the completed percentage of the playlist download" do
96
+ playlist.sync_progress.should eq 67
97
+ end
98
+
99
+ it "returns zero if the playlist is not loaded" do
100
+ empty_playlist.sync_progress.should eq 0
101
+ end
102
+ end
103
+
104
+ describe "#size" do
105
+ it "returns the number of tracks in the playlist" do
106
+ playlist.size.should eq 4
107
+ end
108
+
109
+ it "returns zero if the playlist is not loaded" do
110
+ empty_playlist.size.should eq 0
111
+ end
112
+ end
113
+
114
+ describe "#collaborative?" do
115
+ it "is true when the playlist is set to be collaborative" do
116
+ playlist.should be_collaborative
117
+ end
118
+ end
119
+
120
+ describe "#pending?" do
121
+ it "is false when the playlist does not have pending updates" do
122
+ playlist.should_not be_pending
123
+ end
124
+ end
125
+
126
+ describe "#in_ram?" do
127
+ it "is true when the playlist is loaded in memory" do
128
+ playlist.should be_in_ram
129
+ end
130
+ end
131
+
132
+ describe "#available_offline?" do
133
+ it "is false when the playlist is not enabled for offline use" do
134
+ playlist.should_not be_available_offline
135
+ end
136
+ end
137
+
138
+ describe "#tracks" do
139
+ it "returns an enumerator of the playlist’s tracks" do
140
+ playlist.tracks.to_a.should eq instantiate(Hallon::Playlist::Track, *(0...4).map { |index| [Spotify.playlist_track!(playlist.pointer, index), playlist.pointer, index] })
141
+ end
142
+
143
+ it "returns an empty enumerator if the playlist has no tracks" do
144
+ empty_playlist.tracks.should be_empty
145
+ end
146
+ end
147
+
148
+ describe "#tracks entries" do
149
+ let(:track) do
150
+ playlist.tracks[0]
151
+ end
152
+
153
+ let(:empty_track) do
154
+ playlist.tracks[3]
155
+ end
156
+
157
+ describe "#seen?" do
158
+ it "returns true if the track is seen" do
159
+ track.should be_seen
160
+ end
161
+ end
162
+
163
+ describe "#create_time" do
164
+ it "returns the time the track was added to the playlist" do
165
+ track.added_at.should eq Time.parse("2009-11-04")
166
+ end
36
167
 
37
- its(:name) { should eq "Megaplaylist" }
38
- its(:owner) { should eq Hallon::User.new(mock_user) }
39
- its(:description) { should eq "Playlist description...?" }
40
- its(:image) { stub_session { should eq Hallon::Image.new(mock_image_id) } }
41
- its(:total_subscribers) { should eq 1000 }
42
- its(:sync_progress) { stub_session { should eq 67 } }
43
- its(:size) { should eq 4 }
168
+ it "returns the time in UTC" do
169
+ track.added_at.utc_offset.should eq 0
170
+ end
171
+ end
44
172
 
45
- its('tracks.size') { should eq 4 }
46
- its('tracks.to_a') { should eq instantiate(Hallon::Playlist::Track, *(0...4).map { |index| [Spotify.playlist_track!(playlist.pointer, index), playlist.pointer, index] }) }
173
+ describe "#creator" do
174
+ it "returns the track’s creator" do
175
+ track.adder.should eq Hallon::User.new(mock_user)
176
+ end
47
177
 
48
- describe "tracks#[]" do
49
- let(:track) { subject }
50
- subject { playlist.tracks[0] }
178
+ it "returns nil if there is no track creator available" do
179
+ empty_track.adder.should be_nil
180
+ end
181
+ end
51
182
 
52
- it { should be_seen }
53
- its(:create_time) { should eq Time.parse("2009-11-04") }
54
- its(:creator) { should eq Hallon::User.new(mock_user) }
55
- its(:message) { should eq "message this, YO!" }
183
+ describe "#message" do
184
+ it "returns the message attached to the track" do
185
+ track.message.should eq "message this, YO!"
186
+ end
187
+
188
+ it "returns an empty message if there is none for the given track" do
189
+ empty_track.message.should be_empty
190
+ end
191
+ end
56
192
 
57
193
  describe "#seen=" do
58
194
  it "should raise an error if the track has moved" do
@@ -78,34 +214,33 @@ describe Hallon::Playlist do
78
214
  end
79
215
  end
80
216
 
81
- describe "#upload", :stub_session do
217
+ describe "#upload" do
82
218
  around(:each) do |example|
83
- Timeout.timeout(1) { example.run }
219
+ Timeout.timeout(1, SlowTestError, &example)
84
220
  end
85
221
 
86
222
  it "should raise an error if the playlist takes too long to load" do
87
223
  playlist.stub(:pending? => true)
88
- expect { playlist.upload(0.01) }.to raise_error(Hallon::TimeoutError)
224
+ expect { playlist.upload(0.1) }.to raise_error(Hallon::TimeoutError)
89
225
  end
90
226
  end
91
227
 
92
228
  describe "#subscribers" do
93
229
  it "should return an array of names for the subscribers" do
94
- subject.subscribers.should eq %w[Kim Elin Ylva]
230
+ playlist.subscribers.should eq %w[Kim Elin Ylva]
95
231
  end
96
232
 
97
233
  it "should return an empty array when there are no subscribers" do
98
234
  Spotify.should_receive(:playlist_subscribers).and_return(mock_empty_subscribers)
99
- subject.subscribers.should eq []
235
+ playlist.subscribers.should eq []
100
236
  end
101
237
 
102
- it "should return nil when subscriber fetching failed" do
103
- Spotify.should_receive(:playlist_subscribers).and_return(null_pointer)
104
- playlist.subscribers.should be_nil
238
+ it "should return an empty array when subscriber fetching failed" do
239
+ empty_playlist.subscribers.should eq []
105
240
  end
106
241
  end
107
242
 
108
- describe "#insert", :stub_session do
243
+ describe "#insert" do
109
244
  let(:tracks) { instantiate(Hallon::Track, mock_track, mock_track_two) }
110
245
 
111
246
  it "should add the given tracks to the playlist at correct index" do
@@ -192,7 +327,7 @@ describe Hallon::Playlist do
192
327
  end
193
328
  end
194
329
 
195
- describe "#in_ram=", :stub_session do
330
+ describe "#in_ram=" do
196
331
  it "should set in_ram status" do
197
332
  playlist.should be_in_ram
198
333
  playlist.in_ram = false
@@ -200,7 +335,7 @@ describe Hallon::Playlist do
200
335
  end
201
336
  end
202
337
 
203
- describe "#offline_mode=", :stub_session do
338
+ describe "#offline_mode=" do
204
339
  it "should set offline mode" do
205
340
  playlist.should_not be_available_offline
206
341
  playlist.offline_mode = true
@@ -208,7 +343,7 @@ describe Hallon::Playlist do
208
343
  end
209
344
  end
210
345
 
211
- describe "#update_subscribers", :stub_session do
346
+ describe "#update_subscribers" do
212
347
  it "should ask libspotify to update the subscribers" do
213
348
  expect { playlist.update_subscribers }.to_not raise_error
214
349
  end
@@ -218,29 +353,29 @@ describe Hallon::Playlist do
218
353
  end
219
354
  end
220
355
 
221
- describe "offline status methods", :stub_session do
356
+ describe "offline status methods" do
222
357
  def symbol_for(number)
223
358
  Spotify.enum_type(:playlist_offline_status)[number]
224
359
  end
225
360
 
226
361
  specify "#available_offline?" do
227
362
  Spotify.should_receive(:playlist_get_offline_status).and_return symbol_for(1)
228
- should be_available_offline
363
+ playlist.should be_available_offline
229
364
  end
230
365
 
231
366
  specify "#syncing?" do
232
367
  Spotify.should_receive(:playlist_get_offline_status).and_return symbol_for(2)
233
- should be_syncing
368
+ playlist.should be_syncing
234
369
  end
235
370
 
236
371
  specify "#waiting?" do
237
372
  Spotify.should_receive(:playlist_get_offline_status).and_return symbol_for(3)
238
- should be_waiting
373
+ playlist.should be_waiting
239
374
  end
240
375
 
241
376
  specify "#offline_mode?" do
242
377
  Spotify.should_receive(:playlist_get_offline_status).and_return symbol_for(0)
243
- should_not be_offline_mode
378
+ playlist.should_not be_offline_mode
244
379
  end
245
380
  end
246
381
  end