rspotify 1.24.0 → 1.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rspotify.rb +1 -0
- data/lib/rspotify/album.rb +6 -3
- data/lib/rspotify/base.rb +8 -5
- data/lib/rspotify/track.rb +10 -2
- data/lib/rspotify/track_link.rb +19 -0
- data/lib/rspotify/user.rb +1 -1
- data/lib/rspotify/version.rb +1 -1
- data/spec/lib/rspotify/album_spec.rb +50 -0
- data/spec/lib/rspotify/playlist_spec.rb +8 -0
- data/spec/lib/rspotify/track_spec.rb +43 -9
- data/spec/vcr_cassettes/album_find_2agWNCZl5Ts9W05mij8EPh_market_ES.yml +145 -0
- data/spec/vcr_cassettes/album_find_2js3lkzAjWpD656NK7ZaJX.yml +185 -0
- data/spec/vcr_cassettes/album_find_2js3lkzAjWpD656NK7ZaJX_tracks.yml +110 -0
- data/spec/vcr_cassettes/album_find_2js3lkzAjWpD656NK7ZaJX_tracks_market_ES.yml +124 -0
- data/spec/vcr_cassettes/album_find_5bU1XKYxHhEwukllT20xtk_market_ES.yml +111 -0
- data/spec/vcr_cassettes/playlist_find_00wHcTN0zQiun4xri9pmvX_market_ES.yml +623 -0
- data/spec/vcr_cassettes/track_find_3jfr0TF6DQcOLat8gGn7E2_market_ES.yml +75 -0
- data/spec/vcr_cassettes/track_find_4oI9kesyxHUr8fqiLd6uO9_market_ES.yml +75 -0
- data/spec/vcr_cassettes/track_find_6fi8e1nv4QBqODf9puRcyX_market_ES.yml +75 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 943084e2909b53a19452860de7622fdd2b560fcd
|
4
|
+
data.tar.gz: a3949ea7c84455b591823b2771403053df0cbbe6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f317d488ee29a682d3aaf5e0af397057017ff1852a61d98ad2cb38b26d32097623aeddb410034e6911af65f9a5b6640d6533f861b44742afa6b0d8626999b53
|
7
|
+
data.tar.gz: 6cc388d0d04d78f07b47002f439b358865f1f4dce1fcb21bc24642f107ed2579691f360281565b6fa6073b8ff42f2332dfd0be551b32583a10161cd91e6269b1
|
data/lib/rspotify.rb
CHANGED
@@ -7,6 +7,7 @@ module RSpotify
|
|
7
7
|
autoload :AudioFeatures, 'rspotify/audio_features'
|
8
8
|
autoload :Base, 'rspotify/base'
|
9
9
|
autoload :Category, 'rspotify/category'
|
10
|
+
autoload :TrackLink, 'rspotify/track_link'
|
10
11
|
autoload :Playlist, 'rspotify/playlist'
|
11
12
|
autoload :Recommendations, 'rspotify/recommendations'
|
12
13
|
autoload :RecommendationSeed, 'rspotify/recommendation_seed'
|
data/lib/rspotify/album.rb
CHANGED
@@ -17,6 +17,7 @@ module RSpotify
|
|
17
17
|
# Returns Album object(s) with id(s) provided
|
18
18
|
#
|
19
19
|
# @param ids [String, Array] Maximum: 20 IDs
|
20
|
+
# @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
20
21
|
# @return [Album, Array<Album>]
|
21
22
|
#
|
22
23
|
# @example
|
@@ -28,8 +29,8 @@ module RSpotify
|
|
28
29
|
# albums = RSpotify::Album.find(ids)
|
29
30
|
# albums.class #=> Array
|
30
31
|
# albums.first.class #=> RSpotify::Album
|
31
|
-
def self.find(ids)
|
32
|
-
super(ids, 'album')
|
32
|
+
def self.find(ids, market: nil)
|
33
|
+
super(ids, 'album', market: market)
|
33
34
|
end
|
34
35
|
|
35
36
|
# Get a list of new album releases featured in Spotify (shown, for example, on a Spotify player’s “Browse” tab).
|
@@ -99,18 +100,20 @@ module RSpotify
|
|
99
100
|
#
|
100
101
|
# @param limit [Integer] Maximum number of tracks to return. Maximum: 50. Default: 50.
|
101
102
|
# @param offset [Integer] The index of the first track to return. Use with limit to get the next set of objects. Default: 0.
|
103
|
+
# @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}. Default: nil.
|
102
104
|
# @return [Array<Track>]
|
103
105
|
#
|
104
106
|
# @example
|
105
107
|
# album = RSpotify::Album.find('41vPD50kQ7JeamkxQW7Vuy')
|
106
108
|
# album.tracks.first.name #=> "Do I Wanna Know?"
|
107
|
-
def tracks(limit: 50, offset: 0)
|
109
|
+
def tracks(limit: 50, offset: 0, market: nil)
|
108
110
|
last_track = offset + limit - 1
|
109
111
|
if @tracks_cache && last_track < 50 && !RSpotify.raw_response
|
110
112
|
return @tracks_cache[offset..last_track]
|
111
113
|
end
|
112
114
|
|
113
115
|
url = "albums/#{@id}/tracks?limit=#{limit}&offset=#{offset}"
|
116
|
+
url << "&market=#{market}" if market
|
114
117
|
response = RSpotify.get(url)
|
115
118
|
json = RSpotify.raw_response ? JSON.parse(response) : response
|
116
119
|
|
data/lib/rspotify/base.rb
CHANGED
@@ -11,6 +11,7 @@ module RSpotify
|
|
11
11
|
#
|
12
12
|
# @param ids [String, Array]
|
13
13
|
# @param type [String]
|
14
|
+
# @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
14
15
|
# @return [Album, Artist, Track, User, Array<Album>, Array<Artist>, Array<Track>]
|
15
16
|
#
|
16
17
|
# @example
|
@@ -22,7 +23,7 @@ module RSpotify
|
|
22
23
|
# tracks = RSpotify::Base.find(ids, 'track')
|
23
24
|
# tracks.class #=> Array
|
24
25
|
# tracks.first.class #=> RSpotify::Track
|
25
|
-
def self.find(ids, type)
|
26
|
+
def self.find(ids, type, market: nil)
|
26
27
|
case ids
|
27
28
|
when Array
|
28
29
|
if type == 'user'
|
@@ -30,16 +31,17 @@ module RSpotify
|
|
30
31
|
return false
|
31
32
|
end
|
32
33
|
limit = (type == 'album' ? 20 : 50)
|
33
|
-
find_many(ids, type)
|
34
|
+
find_many(ids, type, market: market)
|
34
35
|
when String
|
35
36
|
id = ids
|
36
|
-
find_one(id, type)
|
37
|
+
find_one(id, type, market: market)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
def self.find_many(ids, type)
|
41
|
+
def self.find_many(ids, type, market: nil)
|
41
42
|
type_class = RSpotify.const_get(type.capitalize)
|
42
43
|
path = "#{type}s?ids=#{ids.join ','}"
|
44
|
+
path << "&market=#{market}" if market
|
43
45
|
|
44
46
|
response = RSpotify.get path
|
45
47
|
return response if RSpotify.raw_response
|
@@ -47,9 +49,10 @@ module RSpotify
|
|
47
49
|
end
|
48
50
|
private_class_method :find_many
|
49
51
|
|
50
|
-
def self.find_one(id, type)
|
52
|
+
def self.find_one(id, type, market: nil)
|
51
53
|
type_class = RSpotify.const_get(type.capitalize)
|
52
54
|
path = "#{type}s/#{id}"
|
55
|
+
path << "?market=#{market}" if market
|
53
56
|
|
54
57
|
response = RSpotify.get path
|
55
58
|
return response if RSpotify.raw_response
|
data/lib/rspotify/track.rb
CHANGED
@@ -13,11 +13,14 @@ module RSpotify
|
|
13
13
|
# @attr [Integer] track_number The number of the track. If an album has several discs, the track number is the number on the specified disc
|
14
14
|
# @attr [String] played_at The date and time the track was played. Only present when pulled from /recently-played
|
15
15
|
# @attr [String] context_type The context the track was played from. Only present when pulled from /recently-played
|
16
|
+
# @attr [Boolean] is_playable Whether or not the track is playable in the given market. Only present when track relinking is applied by specifying a market when looking up the track
|
17
|
+
# @attr [TrackLink] linked_from Details of the requested track. Only present when track relinking is applied and the returned track is different to the one requested because the latter is not available in the given market
|
16
18
|
class Track < Base
|
17
19
|
|
18
20
|
# Returns Track object(s) with id(s) provided
|
19
21
|
#
|
20
22
|
# @param ids [String, Array] Maximum: 50 IDs
|
23
|
+
# @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
|
21
24
|
# @return [Track, Array<Track>]
|
22
25
|
#
|
23
26
|
# @example
|
@@ -29,8 +32,8 @@ module RSpotify
|
|
29
32
|
# tracks = RSpotify::Base.find(ids, 'track')
|
30
33
|
# tracks.class #=> Array
|
31
34
|
# tracks.first.class #=> RSpotify::Track
|
32
|
-
def self.find(ids)
|
33
|
-
super(ids, 'track')
|
35
|
+
def self.find(ids, market: nil)
|
36
|
+
super(ids, 'track', market: market)
|
34
37
|
end
|
35
38
|
|
36
39
|
# Returns array of Track objects matching the query, ordered by popularity. It's also possible to find the total number of search results for the query
|
@@ -69,6 +72,7 @@ module RSpotify
|
|
69
72
|
@track_number = options['track_number']
|
70
73
|
@played_at = options['played_at']
|
71
74
|
@context_type = options['context_type']
|
75
|
+
@is_playable = options['is_playable']
|
72
76
|
|
73
77
|
@album = if options['album']
|
74
78
|
Album.new options['album']
|
@@ -78,6 +82,10 @@ module RSpotify
|
|
78
82
|
options['artists'].map { |a| Artist.new a }
|
79
83
|
end
|
80
84
|
|
85
|
+
@linked_from = if options['linked_from']
|
86
|
+
TrackLink.new options['linked_from']
|
87
|
+
end
|
88
|
+
|
81
89
|
super(options)
|
82
90
|
end
|
83
91
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [Hash] external_urls Known external URLs for this playlist
|
4
|
+
# @attr [String] href A link to the Web API endpoint
|
5
|
+
# @attr [String] id The {https://developer.spotify.com/web-api/user-guide/#spotify-uris-and-ids Spotify ID} for the track
|
6
|
+
# @attr [String] type The object type: "track"
|
7
|
+
# @attr [String] uri The {https://developer.spotify.com/web-api/user-guide/#spotify-uris-and-ids Spotify URI} for the object
|
8
|
+
class TrackLink
|
9
|
+
attr_reader :external_urls, :href, :id, :type, :uri
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@external_urls = options['external_urls']
|
13
|
+
@href = options['href']
|
14
|
+
@id = options['id']
|
15
|
+
@type = options['type']
|
16
|
+
@uri = options['uri']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rspotify/user.rb
CHANGED
@@ -53,7 +53,7 @@ module RSpotify
|
|
53
53
|
|
54
54
|
def self.oauth_send(user_id, verb, path, *params)
|
55
55
|
RSpotify.send(:send_request, verb, path, *params)
|
56
|
-
rescue RestClient::
|
56
|
+
rescue RestClient::Exception => e
|
57
57
|
raise e if e.response !~ /access token expired/
|
58
58
|
refresh_token(user_id)
|
59
59
|
params[-1] = oauth_header(user_id)
|
data/lib/rspotify/version.rb
CHANGED
@@ -43,6 +43,17 @@ describe RSpotify::Album do
|
|
43
43
|
expect(tracks.first) .to be_an RSpotify::Track
|
44
44
|
expect(tracks.map(&:name)) .to include('Do I Wanna Know?', 'R U Mine?', 'Arabella', 'Fireside')
|
45
45
|
end
|
46
|
+
|
47
|
+
it 'should find an album with tracks available in the given market' do
|
48
|
+
album = VCR.use_cassette('album:find:5bU1XKYxHhEwukllT20xtk:market:ES') do
|
49
|
+
RSpotify::Album.find('5bU1XKYxHhEwukllT20xtk', market: 'ES')
|
50
|
+
end
|
51
|
+
|
52
|
+
tracks = album.tracks
|
53
|
+
expect(album.id) .to eq '5bU1XKYxHhEwukllT20xtk'
|
54
|
+
expect(tracks.size) .to eq 12
|
55
|
+
expect(tracks.first.id) .to eq '5FVd6KXrgO9B3JPmC8OPst'
|
56
|
+
end
|
46
57
|
end
|
47
58
|
|
48
59
|
describe 'Album::find receiving array of ids' do
|
@@ -64,6 +75,15 @@ describe RSpotify::Album do
|
|
64
75
|
expect(albums.first.name) .to eq 'The Next Day Extra'
|
65
76
|
expect(albums.last.name) .to eq 'A Beard Of Stars (Deluxe Edition)'
|
66
77
|
end
|
78
|
+
|
79
|
+
it 'should find albums with tracks available in the given market' do
|
80
|
+
albums = VCR.use_cassette('album:find:2agWNCZl5Ts9W05mij8EPh:market:ES') do
|
81
|
+
RSpotify::Album.find(['2agWNCZl5Ts9W05mij8EPh'], market: 'ES')
|
82
|
+
end
|
83
|
+
|
84
|
+
expect(albums.first.id) .to eq '2agWNCZl5Ts9W05mij8EPh'
|
85
|
+
expect(albums.first.tracks.first.id) .to eq '1CFz8ZV88CFLwmggjGrW4c'
|
86
|
+
end
|
67
87
|
end
|
68
88
|
|
69
89
|
describe 'Album::new_releases' do
|
@@ -149,6 +169,36 @@ describe RSpotify::Album do
|
|
149
169
|
end
|
150
170
|
end
|
151
171
|
|
172
|
+
describe '#tracks' do
|
173
|
+
it 'should fetch more tracks' do
|
174
|
+
album = VCR.use_cassette('album:find:2js3lkzAjWpD656NK7ZaJX') do
|
175
|
+
RSpotify::Album.find('2js3lkzAjWpD656NK7ZaJX')
|
176
|
+
end
|
177
|
+
|
178
|
+
tracks = VCR.use_cassette('album:find:2js3lkzAjWpD656NK7ZaJX:tracks') do
|
179
|
+
album.tracks(offset: 50, limit: 50)
|
180
|
+
end
|
181
|
+
|
182
|
+
expect(tracks) .to be_an Array
|
183
|
+
expect(tracks.size) .to eq 19
|
184
|
+
expect(tracks.first.name) .to eq 'Acoustic Guitar'
|
185
|
+
expect(tracks.first.id) .to eq '4l4IytuWNPZaN5EU80TTCO'
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should find tracks available in the given market" do
|
189
|
+
album = VCR.use_cassette('album:find:2js3lkzAjWpD656NK7ZaJX') do
|
190
|
+
RSpotify::Album.find('2js3lkzAjWpD656NK7ZaJX')
|
191
|
+
end
|
192
|
+
|
193
|
+
tracks = VCR.use_cassette('album:find:2js3lkzAjWpD656NK7ZaJX:tracks:market:ES') do
|
194
|
+
album.tracks(offset: 50, limit: 50, market: 'ES')
|
195
|
+
end
|
196
|
+
|
197
|
+
expect(tracks.first.name) .to eq 'Acoustic Guitar'
|
198
|
+
expect(tracks.first.id) .to eq '0wNeMTVk7bFbDj8YFIq0kY'
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
152
202
|
describe '.embed' do
|
153
203
|
before(:each) do
|
154
204
|
@album = VCR.use_cassette('album:find:5bU1XKYxHhEwukllT20xtk') do
|
@@ -111,6 +111,14 @@ describe RSpotify::Playlist do
|
|
111
111
|
expect(tracks_is_local[track_id]).to eq false
|
112
112
|
end
|
113
113
|
|
114
|
+
it 'should find playlist tracks that are available in the given market' do
|
115
|
+
playlist_in_market = VCR.use_cassette('playlist:find:00wHcTN0zQiun4xri9pmvX:market:ES') do
|
116
|
+
RSpotify::Playlist.find('wizzler', '00wHcTN0zQiun4xri9pmvX', market: 'ES')
|
117
|
+
end
|
118
|
+
|
119
|
+
expect(playlist_in_market.tracks[1].id) .to eq '6roJqzCHo3nZBI1TrbsKhn'
|
120
|
+
end
|
121
|
+
|
114
122
|
context 'starred playlist' do
|
115
123
|
it "should support starred playlists" do
|
116
124
|
expect(starred_playlist.name) .to eq 'Starred'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
describe RSpotify::Track do
|
2
|
-
|
2
|
+
|
3
3
|
describe 'Track::find receiving id as a string' do
|
4
|
-
|
4
|
+
|
5
5
|
before(:each) do
|
6
6
|
# Get Arctic Monkeys's "Do I Wanna Know?" track as a testing sample
|
7
7
|
@track = VCR.use_cassette('track:find:3jfr0TF6DQcOLat8gGn7E2') do
|
@@ -40,12 +40,35 @@ describe RSpotify::Track do
|
|
40
40
|
expect(artists.first) .to be_an RSpotify::Artist
|
41
41
|
expect(artists.map(&:name)) .to include('Arctic Monkeys')
|
42
42
|
end
|
43
|
+
|
44
|
+
it 'should find a track available in the given market' do
|
45
|
+
track = VCR.use_cassette('track:find:3jfr0TF6DQcOLat8gGn7E2:market:ES') do
|
46
|
+
RSpotify::Track.find('3jfr0TF6DQcOLat8gGn7E2', market: 'ES')
|
47
|
+
end
|
48
|
+
|
49
|
+
expect(track.id) .to eq '5FVd6KXrgO9B3JPmC8OPst'
|
50
|
+
expect(track.is_playable) .to be true
|
51
|
+
expect(track.linked_from.id) .to eq '3jfr0TF6DQcOLat8gGn7E2'
|
52
|
+
expect(track.linked_from.href) .to eq 'https://api.spotify.com/v1/tracks/3jfr0TF6DQcOLat8gGn7E2'
|
53
|
+
expect(track.linked_from.type) .to eq 'track'
|
54
|
+
expect(track.linked_from.uri) .to eq 'spotify:track:3jfr0TF6DQcOLat8gGn7E2'
|
55
|
+
expect(track.linked_from.external_urls) .to eq('spotify' => 'https://open.spotify.com/track/3jfr0TF6DQcOLat8gGn7E2')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should find a track which is unavailable in the given market' do
|
59
|
+
track = VCR.use_cassette('track:find:6fi8e1nv4QBqODf9puRcyX:market:ES') do
|
60
|
+
RSpotify::Track.find('6fi8e1nv4QBqODf9puRcyX', market: 'ES')
|
61
|
+
end
|
62
|
+
|
63
|
+
expect(track.id) .to eq '6fi8e1nv4QBqODf9puRcyX'
|
64
|
+
expect(track.is_playable) .to be false
|
65
|
+
end
|
43
66
|
end
|
44
67
|
|
45
68
|
describe 'Track::find receiving array of ids' do
|
46
69
|
it 'should find the right tracks' do
|
47
70
|
ids = ['4oI9kesyxHUr8fqiLd6uO9']
|
48
|
-
tracks = VCR.use_cassette('track:find:4oI9kesyxHUr8fqiLd6uO9') do
|
71
|
+
tracks = VCR.use_cassette('track:find:4oI9kesyxHUr8fqiLd6uO9') do
|
49
72
|
RSpotify::Track.find(ids)
|
50
73
|
end
|
51
74
|
expect(tracks) .to be_an Array
|
@@ -53,7 +76,7 @@ describe RSpotify::Track do
|
|
53
76
|
expect(tracks.first.name) .to eq 'The Next Day'
|
54
77
|
|
55
78
|
ids << '7D8BAYkrR9peCB9XSKCADc'
|
56
|
-
tracks = VCR.use_cassette('track:find:7D8BAYkrR9peCB9XSKCADc') do
|
79
|
+
tracks = VCR.use_cassette('track:find:7D8BAYkrR9peCB9XSKCADc') do
|
57
80
|
RSpotify::Track.find(ids)
|
58
81
|
end
|
59
82
|
expect(tracks) .to be_an Array
|
@@ -61,11 +84,22 @@ describe RSpotify::Track do
|
|
61
84
|
expect(tracks.first.name) .to eq 'The Next Day'
|
62
85
|
expect(tracks.last.name) .to eq 'Sunday'
|
63
86
|
end
|
87
|
+
|
88
|
+
it 'should find tracks available in the given market' do
|
89
|
+
ids = ['4oI9kesyxHUr8fqiLd6uO9']
|
90
|
+
tracks = VCR.use_cassette('track:find:4oI9kesyxHUr8fqiLd6uO9:market:ES') do
|
91
|
+
RSpotify::Track.find(ids, market: 'ES')
|
92
|
+
end
|
93
|
+
expect(tracks) .to be_an Array
|
94
|
+
expect(tracks.size) .to eq 1
|
95
|
+
expect(tracks.first.id) .to eq '1CFz8ZV88CFLwmggjGrW4c'
|
96
|
+
expect(tracks.first.linked_from.id) .to eq '4oI9kesyxHUr8fqiLd6uO9'
|
97
|
+
end
|
64
98
|
end
|
65
99
|
|
66
100
|
describe 'Track::search' do
|
67
101
|
it 'should search for the right tracks' do
|
68
|
-
tracks = VCR.use_cassette('track:search:Wanna Know') do
|
102
|
+
tracks = VCR.use_cassette('track:search:Wanna Know') do
|
69
103
|
RSpotify::Track.search('Wanna Know')
|
70
104
|
end
|
71
105
|
expect(tracks) .to be_an Array
|
@@ -76,19 +110,19 @@ describe RSpotify::Track do
|
|
76
110
|
end
|
77
111
|
|
78
112
|
it 'should accept additional options' do
|
79
|
-
tracks = VCR.use_cassette('track:search:Wanna Know:limit:10') do
|
113
|
+
tracks = VCR.use_cassette('track:search:Wanna Know:limit:10') do
|
80
114
|
RSpotify::Track.search('Wanna Know', limit: 10)
|
81
115
|
end
|
82
116
|
expect(tracks.size) .to eq 10
|
83
117
|
expect(tracks.map(&:name)) .to include('Do I Wanna Know?', 'I Wanna Know')
|
84
118
|
|
85
|
-
tracks = VCR.use_cassette('track:search:Wanna Know:offset:10') do
|
119
|
+
tracks = VCR.use_cassette('track:search:Wanna Know:offset:10') do
|
86
120
|
RSpotify::Track.search('Wanna Know', offset: 10)
|
87
121
|
end
|
88
122
|
expect(tracks.size) .to eq 20
|
89
123
|
expect(tracks.map(&:name)) .to include('Wanna Know')
|
90
124
|
|
91
|
-
tracks = VCR.use_cassette('track:search:Wanna Know:limit:10:offset:10') do
|
125
|
+
tracks = VCR.use_cassette('track:search:Wanna Know:limit:10:offset:10') do
|
92
126
|
RSpotify::Track.search('Wanna Know', limit: 10, offset: 10)
|
93
127
|
end
|
94
128
|
expect(tracks.size) .to eq 10
|
@@ -123,7 +157,7 @@ describe RSpotify::Track do
|
|
123
157
|
track.audio_features
|
124
158
|
end
|
125
159
|
|
126
|
-
expect(audio_features.acousticness).to eq 0.186
|
160
|
+
expect(audio_features.acousticness).to eq 0.186
|
127
161
|
expect(audio_features.analysis_url).to eq 'https://api.spotify.com/v1/audio-analysis/3jfr0TF6DQcOLat8gGn7E2'
|
128
162
|
expect(audio_features.danceability).to eq 0.548
|
129
163
|
expect(audio_features.duration_ms).to eq 272394
|
@@ -0,0 +1,145 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.spotify.com/v1/albums?ids=2agWNCZl5Ts9W05mij8EPh&market=ES
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
accept:
|
11
|
+
- "*/*; q=0.5, application/xml"
|
12
|
+
accept-encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
authorization:
|
15
|
+
- Bearer BQA0P-TuSn2tg__j7GK4WEjMYUp_fS4F3NdPPGjXkKS4Alhv-ywIaEEVBvpPlX7rKHkZyVtRSYObRpTb1sz9CQ
|
16
|
+
user-agent:
|
17
|
+
- Ruby
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
server:
|
24
|
+
- nginx
|
25
|
+
date:
|
26
|
+
- Thu, 28 Sep 2017 10:05:18 GMT
|
27
|
+
content-type:
|
28
|
+
- application/json; charset=utf-8
|
29
|
+
transfer-encoding:
|
30
|
+
- chunked
|
31
|
+
connection:
|
32
|
+
- keep-alive
|
33
|
+
keep-alive:
|
34
|
+
- timeout=600
|
35
|
+
cache-control:
|
36
|
+
- public, max-age=7200
|
37
|
+
access-control-allow-origin:
|
38
|
+
- "*"
|
39
|
+
access-control-allow-methods:
|
40
|
+
- GET, POST, OPTIONS, PUT, DELETE
|
41
|
+
access-control-allow-credentials:
|
42
|
+
- 'true'
|
43
|
+
access-control-max-age:
|
44
|
+
- '604800'
|
45
|
+
access-control-allow-headers:
|
46
|
+
- Accept, Authorization, Origin, Content-Type
|
47
|
+
content-encoding:
|
48
|
+
- gzip
|
49
|
+
x-content-type-options:
|
50
|
+
- nosniff
|
51
|
+
strict-transport-security:
|
52
|
+
- max-age=31536000;
|
53
|
+
body:
|
54
|
+
encoding: ASCII-8BIT
|
55
|
+
string: !binary |-
|
56
|
+
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
|
92
|
+
UBzDtACGF0fJFsPvCcMC4c1PliDg5KAXnwZdrzPcG/ilftK5wcfFB+qyZTMG
|
93
|
+
6pYbvgUMo+R6TKql2vXgJO6U0H651rlsX6wFw3Oks5w+j+nrMbysbZkYrhrr
|
94
|
+
UziwyjKwmlpbJ3p1ECPb5hxKB2Bma5tpSg0W2kXMaC4NMwgKW9kGFwYxKzJe
|
95
|
+
tzBOtiB+RyBGiAi68eIwGEKMxuNhcjXqVxqViwfVK7eTwiCeIzsL4hyGbwHE
|
96
|
+
5LjD41rbrbj79XhEmS+GsWOvZ7wuWzpzvC6H6QrjdUvalg3iX5XVkElHR1ZJ
|
97
|
+
W4feTWd1EhvhGEkNNdwljgMcGyoDJUWOYZNZFNIWRgDCSWES8wIkXhwoWxK/
|
98
|
+
JxITwTY/cwK47fYY+WK3DyPUbdzYlTNYuy9O4mzZDBIvN3wLJKZnN2f3rc4u
|
99
|
+
hpWDIb4/2m0eHlRv11OZyJbOrEzkMF2hMrGkbZkkLoVxbNVNoVyYQ9sRjrKJ
|
100
|
+
SxTUrgCOy2zGJVQaSMKI6xrkMqf47GFRhMALA2RL4PdEYAAZ2XhRAtHzshqA
|
101
|
+
Uun+DpW9/dNmq1mCYWECz5GdJXAOw7dAYDRqXt18UrXuLqi33arPQ5xcResp
|
102
|
+
SmRLZxYlcpiuUJRY0rbs2cMycL3gZjpprRpYzb50C7DYBbbA3NET7CI6mUzM
|
103
|
+
NXUIA9pxMWU2Z9BABXjxlRygAIwXx8oWxu8JxulX2OZnTOAWqJqzrvMwGFSG
|
104
|
+
tEzI6Tis0uITibNlZ2Gcw/AtwJjc8r2ufXJ6IXaDexIfjlizxNazlGOOdGZh
|
105
|
+
IofpCoWJJW3LhPFhOLT2Qh1bkxnFB5FMk+ODqNDECZbSVipHupQRB0DKeJos
|
106
|
+
Y+hQyYAN009FpW1bK1AcyEXW1i2Oly2Q3xOQIUKbX1sH4uuG5knJYxe73L1u
|
107
|
+
XY6CEjkpXp/Ils2oTyw3fAtApt0uOGwDu3wwkkN1QY936wf1T+upT2RLZ9Yn
|
108
|
+
cpiuUJ9Y0rZMIP82GbBreb7/u9XUyRTLrTDylVUPrH0vKpApG1elEFZQOlJy
|
109
|
+
zNL8mGIjJeHIIZBCBCkSjsJucTAXWXK3OG62YH5PYGaMgY2XLXAbN71uuZXI
|
110
|
+
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
|
142
|
+
M2lDev+//PN/AAAA//8DANVuwcZIhwAA
|
143
|
+
http_version: '1.1'
|
144
|
+
recorded_at: Thu, 28 Sep 2017 10:05:18 GMT
|
145
|
+
recorded_with: VCR 2.9.3
|