spotify 12.5.3 → 12.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +20 -5
  4. data/CHANGELOG.md +29 -1
  5. data/Gemfile +5 -0
  6. data/MIT-LICENSE +21 -0
  7. data/README.markdown +75 -50
  8. data/Rakefile +1 -1
  9. data/examples/example-audio_delivery_speed.rb +48 -0
  10. data/examples/{audio-stream_example.rb → example-audio_stream.rb} +14 -29
  11. data/examples/example-console.rb +9 -0
  12. data/examples/example-listing_playlists.rb +89 -0
  13. data/examples/example-loading_object.rb +25 -0
  14. data/examples/example-random_related_artists.rb +53 -0
  15. data/examples/support.rb +106 -0
  16. data/lib/spotify.rb +36 -55
  17. data/lib/spotify/api.rb +54 -26
  18. data/lib/spotify/api/album.rb +45 -2
  19. data/lib/spotify/api/album_browse.rb +81 -3
  20. data/lib/spotify/api/artist.rb +21 -2
  21. data/lib/spotify/api/artist_browse.rb +121 -3
  22. data/lib/spotify/api/error.rb +5 -1
  23. data/lib/spotify/api/image.rb +72 -6
  24. data/lib/spotify/api/inbox.rb +33 -4
  25. data/lib/spotify/api/link.rb +117 -4
  26. data/lib/spotify/api/miscellaneous.rb +12 -0
  27. data/lib/spotify/api/playlist.rb +321 -16
  28. data/lib/spotify/api/playlist_container.rb +168 -9
  29. data/lib/spotify/api/search.rb +156 -3
  30. data/lib/spotify/api/session.rb +390 -26
  31. data/lib/spotify/api/toplist_browse.rb +74 -3
  32. data/lib/spotify/api/track.rb +134 -4
  33. data/lib/spotify/api/user.rb +18 -2
  34. data/lib/spotify/api_helpers.rb +47 -0
  35. data/lib/spotify/data_converters.rb +7 -0
  36. data/lib/spotify/{types → data_converters}/best_effort_string.rb +1 -1
  37. data/lib/spotify/{types → data_converters}/byte_string.rb +0 -0
  38. data/lib/spotify/data_converters/country_code.rb +30 -0
  39. data/lib/spotify/{types → data_converters}/image_id.rb +1 -1
  40. data/lib/spotify/{type_safety.rb → data_converters/type_safety.rb} +0 -0
  41. data/lib/spotify/{types → data_converters}/utf8_string.rb +2 -2
  42. data/lib/spotify/{types → data_converters}/utf8_string_pointer.rb +2 -2
  43. data/lib/spotify/error.rb +180 -47
  44. data/lib/spotify/managed_pointer.rb +32 -12
  45. data/lib/spotify/monkey_patches/ffi_buffer.rb +11 -0
  46. data/lib/spotify/monkey_patches/ffi_enums.rb +4 -0
  47. data/lib/spotify/monkey_patches/ffi_pointer.rb +1 -0
  48. data/lib/spotify/structs.rb +4 -0
  49. data/lib/spotify/structs/session_callbacks.rb +97 -26
  50. data/lib/spotify/structs/session_config.rb +1 -1
  51. data/lib/spotify/structs/subscribers.rb +4 -3
  52. data/lib/spotify/types.rb +104 -5
  53. data/lib/spotify/{objects → types}/album.rb +0 -0
  54. data/lib/spotify/{objects → types}/album_browse.rb +0 -0
  55. data/lib/spotify/{objects → types}/artist.rb +0 -0
  56. data/lib/spotify/{objects → types}/artist_browse.rb +0 -0
  57. data/lib/spotify/{objects → types}/image.rb +0 -0
  58. data/lib/spotify/{objects → types}/inbox.rb +0 -0
  59. data/lib/spotify/{objects → types}/link.rb +0 -0
  60. data/lib/spotify/{objects → types}/playlist.rb +0 -0
  61. data/lib/spotify/{objects → types}/playlist_container.rb +0 -0
  62. data/lib/spotify/{objects → types}/search.rb +0 -0
  63. data/lib/spotify/{objects → types}/session.rb +0 -0
  64. data/lib/spotify/{objects → types}/toplist_browse.rb +0 -0
  65. data/lib/spotify/{objects → types}/track.rb +0 -0
  66. data/lib/spotify/{objects → types}/user.rb +0 -0
  67. data/lib/spotify/util.rb +38 -35
  68. data/lib/spotify/version.rb +1 -1
  69. data/spec/spec_helper.rb +24 -13
  70. data/spec/spotify/api/image_spec.rb +32 -0
  71. data/spec/spotify/api/inbox_spec.rb +34 -0
  72. data/spec/spotify/api/link_spec.rb +40 -0
  73. data/spec/spotify/api/playlist_spec.rb +99 -0
  74. data/spec/spotify/api/playlistcontainer_spec.rb +82 -0
  75. data/spec/spotify/api/session_spec.rb +97 -0
  76. data/spec/spotify/api/track_spec.rb +29 -0
  77. data/spec/spotify/api_error_spec.rb +55 -0
  78. data/spec/spotify/api_spec.rb +17 -11
  79. data/spec/spotify/{types → data_converters}/best_effort_string_spec.rb +4 -4
  80. data/spec/spotify/{types → data_converters}/byte_string_spec.rb +0 -0
  81. data/spec/spotify/data_converters/country_code_spec.rb +16 -0
  82. data/spec/spotify/{types → data_converters}/image_id_spec.rb +1 -1
  83. data/spec/spotify/{type_safety_spec.rb → data_converters/type_safety_spec.rb} +0 -0
  84. data/spec/spotify/{types → data_converters}/utf8_string_pointer_spec.rb +0 -0
  85. data/spec/spotify/{types → data_converters}/utf8_string_spec.rb +1 -1
  86. data/spec/spotify/{api/functions_spec.rb → functions_spec.rb} +2 -0
  87. data/spec/spotify/managed_pointer_spec.rb +13 -13
  88. data/spec/spotify/structs/subscribers_spec.rb +5 -3
  89. data/spec/spotify/{defines_spec.rb → types_spec.rb} +16 -3
  90. data/spec/spotify/util_spec.rb +24 -0
  91. data/spec/spotify_spec.rb +74 -0
  92. data/spec/support/spotify_util.rb +6 -2
  93. data/spec/support/spy_output.rb +16 -0
  94. data/spotify.gemspec +4 -2
  95. metadata +111 -71
  96. data/examples/README.md +0 -15
  97. data/examples/console_example.rb +0 -22
  98. data/examples/example_support.rb +0 -66
  99. data/examples/loading-object_example.rb +0 -43
  100. data/examples/logging-in_example.rb +0 -58
  101. data/lib/spotify/defines.rb +0 -109
  102. data/lib/spotify/objects.rb +0 -17
  103. data/spec/spotify/enums_spec.rb +0 -9
  104. data/spec/spotify/spotify_spec.rb +0 -69
@@ -1,7 +1,7 @@
1
1
  module Spotify
2
2
  # @note See README for versioning policy.
3
3
  # @return [String] Spotify gem version.
4
- VERSION = '12.5.3'
4
+ VERSION = '12.6.0'
5
5
 
6
6
  # @return [String] Compatible libspotify API version.
7
7
  API_VERSION = '12.1.51'
@@ -1,24 +1,36 @@
1
1
  # encoding: utf-8
2
2
  require "rbgccxml"
3
3
  require "rspec"
4
- require "pry"
5
4
  require "stringio"
6
5
 
7
6
  require "spec/support/hook_spotify"
8
7
  require "spec/support/spotify_util"
8
+ require "spec/support/spy_output"
9
9
 
10
10
  # You can pregenerate new XML files through:
11
11
  # gccxml spec/api-mac.h -fxml=spec/api-mac.xml
12
12
  # gccxml spec/api-linux.h -fxml=spec/api-linux.xml
13
- API_H_PATH = File.expand_path("../support/api-#{Spotify.platform}.h", __FILE__)
13
+ API_H_PATH = File.expand_path("../support/api-#{Spotify::Util.platform}.h", __FILE__)
14
14
  API_H_SRC = File.read(API_H_PATH)
15
15
  API_H_XML = RbGCCXML.parse_xml(API_H_PATH.sub('.h', '.xml'))
16
16
 
17
+ class << Spotify
18
+ attr_accessor :performer
19
+ end
20
+
17
21
  RSpec.configure do |config|
18
22
  def api
19
23
  Spotify::API
20
24
  end
21
25
 
26
+ config.expect_with :rspec do |c|
27
+ c.syntax = [:should, :expect]
28
+ end
29
+
30
+ config.mock_with :rspec do |c|
31
+ c.syntax = [:should, :expect]
32
+ end
33
+
22
34
  config.filter_run_excluding(engine: ->(engine) do
23
35
  ! Array(engine).include?(RUBY_ENGINE)
24
36
  end)
@@ -30,17 +42,16 @@ RSpec.configure do |config|
30
42
  end)
31
43
 
32
44
  config.around(:each) do |test|
33
- stderr, $stderr = $stderr, StringIO.new("")
34
- begin
35
- test.run
36
- $stderr.rewind
37
- warnings = $stderr.read
38
- if warnings =~ %r"lib/spotify"
39
- stderr.write(warnings)
40
- raise "#{example.description.inspect} caused a warning, #{warnings.inspect}"
41
- end
42
- ensure
43
- $stderr = stderr
45
+ _, warnings = spy_output { test.run }
46
+ if warnings =~ %r"lib/spotify" and not $DEBUG
47
+ raise "#{example.description.inspect} caused a warning, #{warnings.inspect}"
44
48
  end
45
49
  end
50
+
51
+ config.around(:each) do |example|
52
+ Spotify.performer = Performer.new
53
+ example.run
54
+ task = Spotify.performer.shutdown
55
+ task.value # wait for shutdown
56
+ end
46
57
  end
@@ -0,0 +1,32 @@
1
+ describe "Spotify::API" do
2
+ describe "#image_data" do
3
+ let(:image) { double }
4
+
5
+ it "reads the raw image data" do
6
+ api.should_receive(:sp_image_data) do |img, img_size_pointer|
7
+ img.should eq(image)
8
+ img_size_pointer.write_size_t(8)
9
+ FFI::MemoryPointer.from_string("image data")
10
+ end
11
+
12
+ api.image_data(image).should eq "image da"
13
+ end
14
+
15
+ it "is nil if image data is null" do
16
+ api.should_receive(:sp_image_data) do |img, img_size_pointer|
17
+ FFI::Pointer::NULL
18
+ end
19
+
20
+ api.image_data(image).should be_nil
21
+ end
22
+
23
+ it "is nil if image data size is 0" do
24
+ api.should_receive(:sp_image_data) do |img, img_size_pointer|
25
+ img_size_pointer.write_size_t(0)
26
+ FFI::MemoryPointer.from_string("image data")
27
+ end
28
+
29
+ api.image_data(image).should be_nil
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ describe "Spotify::API" do
2
+ describe "#inbox_post_tracks" do
3
+ let(:session) { double }
4
+ let(:callback) { lambda {} }
5
+ let(:track_a) { FFI::MemoryPointer.new(:pointer) }
6
+ let(:track_b) { FFI::MemoryPointer.new(:pointer) }
7
+ let(:tracks) { [track_a, track_b] }
8
+ let(:inbox) { double }
9
+
10
+ it "posts an array of tracks to a user's inbox" do
11
+ api.should_receive(:sp_inbox_post_tracks) do |ptr, username, buffer, buffer_size, message, ptr_callback, userdata|
12
+ ptr.should eq(session)
13
+ username.should eq("burgestrand")
14
+ buffer.read_array_of_pointer(buffer_size).should eq(tracks)
15
+ message.should eq("You must listen to these!")
16
+ ptr_callback.should eq(callback)
17
+ userdata.should eq(:userdata)
18
+ inbox
19
+ end
20
+
21
+ api.inbox_post_tracks(session, "burgestrand", tracks, "You must listen to these!", callback, :userdata).should eq(inbox)
22
+ end
23
+
24
+ it "casts a single track to an array" do
25
+ api.should_receive(:sp_inbox_post_tracks) do |ptr, username, buffer, buffer_size, message, ptr_callback, userdata|
26
+ buffer.read_array_of_pointer(1).should eq([track_a])
27
+ buffer_size.should eq(1)
28
+ inbox
29
+ end
30
+
31
+ api.inbox_post_tracks(session, "burgestrand", track_a, "You must listen to these!", callback, :userdata).should eq(inbox)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ describe "Spotify::API" do
2
+ describe "#link_as_string" do
3
+ let(:link) { double }
4
+
5
+ it "reads the link as an UTF-8 encoded string" do
6
+ api.should_receive(:sp_link_as_string).twice do |ptr, buffer, buffer_size|
7
+ ptr.should eq(link)
8
+ buffer.write_bytes("spotify:user:burgestrandX") if buffer
9
+ 24
10
+ end
11
+
12
+ string = api.link_as_string(link)
13
+ string.should eq "spotify:user:burgestrand"
14
+ string.encoding.should eq(Encoding::UTF_8)
15
+ end
16
+ end
17
+
18
+ describe "#link_as_track_and_offset" do
19
+ let(:link) { double }
20
+ let(:track) { double }
21
+
22
+ it "reads the link as a track with offset information" do
23
+ api.should_receive(:sp_link_as_track_and_offset) do |ptr, offset_pointer|
24
+ ptr.should eq(link)
25
+ offset_pointer.write_int(6000)
26
+ track
27
+ end
28
+
29
+ api.link_as_track_and_offset(link).should eq([track, 6000])
30
+ end
31
+
32
+ it "returns nil if the link is not a track link" do
33
+ api.should_receive(:sp_link_as_track_and_offset) do |ptr, offset_pointer|
34
+ nil
35
+ end
36
+
37
+ api.link_as_track_and_offset(link).should be_nil
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,99 @@
1
+ describe "Spotify::API" do
2
+ let(:playlist) { double }
3
+
4
+ describe "#playlist_get_image" do
5
+ let(:image_id) { "v\xE5\xAA\xD3F\xF8\xEE4G\xA1.D\x9C\x85 \xC5\xFD\x80]\x99".force_encoding(Encoding::BINARY) }
6
+
7
+ it "returns the image ID if playlist has an image" do
8
+ api.should_receive(:sp_playlist_get_image) do |ptr, image_id_pointer|
9
+ ptr.should eq(playlist)
10
+ image_id_pointer.write_bytes(image_id)
11
+ true
12
+ end
13
+
14
+ api.playlist_get_image(playlist).should eq(image_id)
15
+ end
16
+
17
+ it "returns nil if playlist has no image" do
18
+ api.should_receive(:sp_playlist_get_image) do |ptr, image_id_pointer|
19
+ false
20
+ end
21
+
22
+ api.playlist_get_image(playlist).should be_nil
23
+ end
24
+ end
25
+
26
+ describe "#playlist_add_tracks" do
27
+ let(:session) { double }
28
+ let(:track_a) { FFI::MemoryPointer.new(:pointer) }
29
+ let(:track_b) { FFI::MemoryPointer.new(:pointer) }
30
+ let(:tracks) { [track_a, track_b] }
31
+
32
+ it "adds an array of tracks to a playlist" do
33
+ api.should_receive(:sp_playlist_add_tracks) do |ptr, buffer, buffer_size, offset, ptr_session|
34
+ ptr.should eq(playlist)
35
+ buffer.read_array_of_pointer(buffer_size).should eq(tracks)
36
+ offset.should eq(2)
37
+ ptr_session.should eq(session)
38
+ :ok
39
+ end
40
+
41
+ api.playlist_add_tracks(playlist, tracks, 2, session).should eq(:ok)
42
+ end
43
+
44
+ it "casts a single track to an array" do
45
+ api.should_receive(:sp_playlist_add_tracks) do |ptr, buffer, buffer_size, offset, ptr_session|
46
+ buffer.read_array_of_pointer(1).should eq([track_a])
47
+ buffer_size.should eq(1)
48
+ :ok
49
+ end
50
+
51
+ api.playlist_add_tracks(playlist, track_a, 2, session).should eq(:ok)
52
+ end
53
+ end
54
+
55
+ describe "#playlist_remove_tracks" do
56
+ it "removes tracks from a playlist" do
57
+ api.should_receive(:sp_playlist_remove_tracks) do |ptr, buffer, buffer_size|
58
+ ptr.should eq(playlist)
59
+ buffer.read_array_of_int(buffer_size).should eq([1, 3, 7])
60
+ :ok
61
+ end
62
+
63
+ api.playlist_remove_tracks(playlist, [1, 3, 7]).should eq(:ok)
64
+ end
65
+
66
+ it "casts a single index to an array" do
67
+ api.should_receive(:sp_playlist_remove_tracks) do |ptr, buffer, buffer_size|
68
+ buffer.read_array_of_int(1).should eq([3])
69
+ buffer_size.should eq(1)
70
+ :ok
71
+ end
72
+
73
+ api.playlist_remove_tracks(playlist, 3).should eq(:ok)
74
+ end
75
+ end
76
+
77
+ describe "#playlist_reorder_tracks" do
78
+ it "reorders tracks from a playlist" do
79
+ api.should_receive(:sp_playlist_reorder_tracks) do |ptr, buffer, buffer_size, index|
80
+ ptr.should eq(playlist)
81
+ buffer.read_array_of_int(buffer_size).should eq([1, 3, 7])
82
+ index.should eq(3)
83
+ :ok
84
+ end
85
+
86
+ api.playlist_reorder_tracks(playlist, [1, 3, 7], 3).should eq(:ok)
87
+ end
88
+
89
+ it "casts a single index to an array" do
90
+ api.should_receive(:sp_playlist_reorder_tracks) do |ptr, buffer, buffer_size, index|
91
+ buffer.read_array_of_int(1).should eq([7])
92
+ buffer_size.should eq(1)
93
+ :ok
94
+ end
95
+
96
+ api.playlist_reorder_tracks(playlist, 7, 3).should eq(:ok)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,82 @@
1
+ describe "Spotify::API" do
2
+ let(:container) { double }
3
+
4
+ describe "#playlistcontainer_playlist_folder_name" do
5
+ let(:index) { 0 }
6
+
7
+ it "returns the folder name" do
8
+ api.should_receive(:sp_playlistcontainer_playlist_folder_name) do |ptr, index, name_pointer, name_pointer_size|
9
+ ptr.should eq(container)
10
+ name_pointer.write_bytes("Summer Playlists\x00")
11
+ :ok
12
+ end
13
+
14
+ folder_name = api.playlistcontainer_playlist_folder_name(container, index)
15
+ folder_name.should eq "Summer Playlists"
16
+ folder_name.encoding.should eq(Encoding::UTF_8)
17
+ end
18
+
19
+ it "returns nil if out of range" do
20
+ api.should_receive(:sp_playlistcontainer_playlist_folder_name) do |ptr, index, name_pointer, name_pointer_size|
21
+ :error_index_out_of_range
22
+ end
23
+
24
+ api.playlistcontainer_playlist_folder_name(container, index).should be_nil
25
+ end
26
+
27
+ it "returns nil if not a folder" do
28
+ api.should_receive(:sp_playlistcontainer_playlist_folder_name) do |ptr, index, name_pointer, name_pointer_size|
29
+ name_pointer.write_bytes("\x00")
30
+ :ok
31
+ end
32
+
33
+ api.playlistcontainer_playlist_folder_name(container, index).should be_nil
34
+ end
35
+ end
36
+
37
+ describe "#playlistcontainer_get_unseen_tracks" do
38
+ def track(id)
39
+ pointer = FFI::MemoryPointer.new(:int)
40
+ pointer.write_int(id.to_i)
41
+ pointer
42
+ end
43
+
44
+ let(:playlist) { double }
45
+ let(:track_a) { track(1337) }
46
+ let(:track_b) { track(7331) }
47
+
48
+ it "returns an array of unseen tracks" do
49
+ Spotify::Track.retaining_class.should_receive(:from_native).twice do |pointer, context|
50
+ pointer.read_int
51
+ end
52
+
53
+ api.should_receive(:sp_playlistcontainer_get_unseen_tracks).twice do |ptr, ptr_playlist, tracks_buffer, tracks_buffer_size|
54
+ ptr.should eq(container)
55
+ ptr_playlist.should eq(playlist)
56
+ if tracks_buffer
57
+ tracks_buffer.write_array_of_pointer([track_a, track_b])
58
+ tracks_buffer_size.should eq(2)
59
+ end
60
+ 2
61
+ end
62
+
63
+ api.playlistcontainer_get_unseen_tracks(container, playlist).should eq([1337, 7331])
64
+ end
65
+
66
+ it "returns an empty array when there are no unseen tracks" do
67
+ api.should_receive(:sp_playlistcontainer_get_unseen_tracks) do |ptr, playlist, tracks_buffer, tracks_buffer_size|
68
+ 0
69
+ end
70
+
71
+ api.playlistcontainer_get_unseen_tracks(container, playlist).should be_empty
72
+ end
73
+
74
+ it "returns an empty array on failure" do
75
+ api.should_receive(:sp_playlistcontainer_get_unseen_tracks) do |ptr, playlist, tracks_buffer, tracks_buffer_size|
76
+ -1
77
+ end
78
+
79
+ api.playlistcontainer_get_unseen_tracks(container, playlist).should be_empty
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,97 @@
1
+ describe "Spotify::API" do
2
+ let(:session) { double }
3
+
4
+ describe "#session_create" do
5
+ let(:config) do
6
+ {
7
+ user_agent: "This is a test",
8
+ callbacks: Spotify::SessionCallbacks.new(music_delivery: proc {})
9
+ }
10
+ end
11
+
12
+ let(:session_pointer) { FFI::MemoryPointer.new(:pointer) }
13
+
14
+ it "creates a session with the given configuration" do
15
+ api.should_receive(:sp_session_create) do |struct_config, ptr_session|
16
+ struct_config.should be_a(Spotify::SessionConfig)
17
+ struct_config[:user_agent].should eq("This is a test")
18
+ struct_config[:callbacks].should be_a(Spotify::SessionCallbacks)
19
+ ptr_session.write_pointer(session_pointer)
20
+ :ok
21
+ end
22
+
23
+ error, session = api.session_create(config)
24
+ error.should be_nil
25
+ session.should be_a(Spotify::Session)
26
+ session.address.should eq(session_pointer.address)
27
+ end
28
+
29
+ it "returns the error without session on failure" do
30
+ api.should_receive(:sp_session_create) do |struct_config, ptr_session|
31
+ :bad_api_version
32
+ end
33
+
34
+ error, session = api.session_create(config)
35
+ error.should eq(:bad_api_version)
36
+ session.should be_nil
37
+ end
38
+ end
39
+
40
+ describe "#session_process_events" do
41
+ it "returns time until session_process_events should be called again" do
42
+ api.should_receive(:sp_session_process_events) do |ptr, timeout_pointer|
43
+ ptr.should eq(session)
44
+ timeout_pointer.write_int(1337)
45
+ :ok
46
+ end
47
+
48
+ api.session_process_events(session).should eq(1337)
49
+ end
50
+ end
51
+
52
+ describe "#session_remembered_user" do
53
+ it "returns the name of the remembered user" do
54
+ api.should_receive(:sp_session_remembered_user).twice do |ptr, string_pointer, string_pointer_size|
55
+ ptr.should eq(session)
56
+ string_pointer.write_bytes("BurgeX") if string_pointer
57
+ 5
58
+ end
59
+
60
+ api.session_remembered_user(session).should eq("Burge")
61
+ end
62
+
63
+ it "returns nil if there is no remembered user" do
64
+ api.should_receive(:sp_session_remembered_user) do |ptr, string_pointer, string_pointer_size|
65
+ -1
66
+ end
67
+
68
+ api.session_remembered_user(session).should be_nil
69
+ end
70
+ end
71
+
72
+ describe "#session_is_scrobbling" do
73
+ it "returns the scrobbling state" do
74
+ api.should_receive(:sp_session_is_scrobbling) do |ptr, social_provider, state_pointer|
75
+ ptr.should eq(session)
76
+ social_provider.should eq(:spotify)
77
+ state_pointer.write_int(3)
78
+ :ok
79
+ end
80
+
81
+ api.session_is_scrobbling(session, :spotify).should eq(:global_enabled)
82
+ end
83
+ end
84
+
85
+ describe "#session_is_scrobbling_possible" do
86
+ it "returns true if scrobbling is possible" do
87
+ api.should_receive(:sp_session_is_scrobbling_possible) do |ptr, social_provider, buffer_out|
88
+ ptr.should eq(session)
89
+ social_provider.should eq(:spotify)
90
+ buffer_out.write_char(1)
91
+ :ok
92
+ end
93
+
94
+ api.session_is_scrobbling_possible(session, :spotify).should eq(true)
95
+ end
96
+ end
97
+ end