rspotify 2.10.1 → 2.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +1 -1
  4. data/lib/rspotify/episode.rb +84 -0
  5. data/lib/rspotify/oauth.rb +5 -0
  6. data/lib/rspotify/playlist.rb +1 -1
  7. data/lib/rspotify/show.rb +100 -0
  8. data/lib/rspotify/version.rb +1 -1
  9. data/lib/rspotify.rb +2 -0
  10. data/rspotify.gemspec +1 -1
  11. data/spec/lib/rspotify/episode_spec.rb +118 -0
  12. data/spec/lib/rspotify/show_spec.rb +138 -0
  13. data/spec/vcr_cassettes/episode_find_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
  14. data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_ES.yml +66 -0
  15. data/spec/vcr_cassettes/episode_find_5NxzDE5TmviUV8te2eZjMP_market_KG.yml +66 -0
  16. data/spec/vcr_cassettes/episode_find_array_18RPZgmvEGKtEC2WMTHghd.yml +66 -0
  17. data/spec/vcr_cassettes/episode_find_array_512ojhOuo1ktJprKbVcKyQ.yml +66 -0
  18. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas.yml +64 -0
  19. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10.yml +64 -0
  20. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_limit_10_offset_10.yml +64 -0
  21. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_market_CA.yml +694 -0
  22. data/spec/vcr_cassettes/episode_search_Tredje_rikets_knarkande_granskas_offset_10.yml +64 -0
  23. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe.yml +66 -0
  24. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes.yml +66 -0
  25. data/spec/vcr_cassettes/show_find_5CfCWKI5pZ28U0uOzXkDHe_episodes_market_ES.yml +66 -0
  26. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe.yml +64 -0
  27. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ.yml +64 -0
  28. data/spec/vcr_cassettes/show_find_many_5CfCWKI5pZ28U0uOzXkDHe_5as3aKmN2k11yfDDDSrvaZ_market_CA.yml +64 -0
  29. data/spec/vcr_cassettes/show_search_without_fail.yml +64 -0
  30. data/spec/vcr_cassettes/show_search_without_fail_limit_10.yml +64 -0
  31. data/spec/vcr_cassettes/show_search_without_fail_market_ES.yml +64 -0
  32. data/spec/vcr_cassettes/show_search_without_fail_offset_10.yml +64 -0
  33. data/spec/vcr_cassettes/show_search_without_fail_offset_10_limit_10.yml +64 -0
  34. metadata +52 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d19f6d23158c4ece9b8ede71d1b0ed2ed71598baad04895b62dc209f0147f556
4
- data.tar.gz: 0c3b328c9b8f3ff4d87041c0d749fef09689bf922b4f7f4c9f5aa958a2d27587
3
+ metadata.gz: 0d9d7a49993e755934d77091d568c04862f676c0b52ffe14ab80355cf38c17c1
4
+ data.tar.gz: 13d0709271280fb895df8f8941915a3090e426d020013552fb0af50656e21f3d
5
5
  SHA512:
6
- metadata.gz: 636252d2d8d95caf3f8b07187b97fcefe22f6e6a052400d48ab200c2db47451934e37e7c4b25aa08bfddf1c0c1daf6b61fc7b0f2af19e54f25edcc0836da8731
7
- data.tar.gz: fed825f00b36af6c3c9e2df6a6312b09219ea6d68b8136085b13ddcfa0764b747b1489a7afb1d73236a769f2fe1571617c49d709e199f7e58f1990a9bb4272e9
6
+ metadata.gz: def7d61e7f73af6ff9f03bdfbe562c21b462a6820778d76437a6c660bbeb3d3e4f23f11e6ab6c349abb8458da6ad769545e2edc0de3caf563c653ff069c14ee0
7
+ data.tar.gz: d79c15a25e18878e3a27cba75e0e41a7fab88ecd430e25ae9183c97a88a6d6ff46d9001326d848fe16ed77094a7e8e4a680dd1e0ace6b6271684b728131fc4c4
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  .bundle
2
+ .idea
3
+ .rakeTasks
2
4
  .yardoc
3
5
  doc
4
6
  pkg
data/README.md CHANGED
@@ -155,7 +155,7 @@ Rails.application.config.middleware.use OmniAuth::Builder do
155
155
  end
156
156
  ```
157
157
 
158
- You should replace the scope values for the ones your own app will require from the user. You can see the list of available scopes in [here](https://developer.spotify.com/web-api/using-scopes).
158
+ You should replace the scope values for the ones your own app will require from the user. You can see the list of available scopes in [here](https://developer.spotify.com/documentation/general/guides/authorization/scopes/).
159
159
 
160
160
  Next, make a link so the user can log in with his Spotify account:
161
161
 
@@ -0,0 +1,84 @@
1
+ module RSpotify
2
+
3
+ # @attr [String] audio_preview_url A URL to a 30 second preview (MP3 format) of the episode. null if not available.
4
+ # @attr [String] description A description of the episode. HTML tags are stripped away from this field, use html_description field in case HTML tags are needed.
5
+ # @attr [Integer] duration_ms The episode length in milliseconds.
6
+ # @attr [Boolean] explicit Whether or not the episode has explicit content (true = yes it does; false = no it does not OR unknown).
7
+ # @attr [String] href A link to the Web API endpoint providing full details of the episode.
8
+ # @attr [String] html_description A description of the episode. This field may contain HTML tags.
9
+ # @attr [Array<Hash>] images The cover art for the episode in various sizes, widest first.
10
+ # @attr [Boolean] is_externally_hosted True if the episode is hosted outside of Spotify’s CDN.
11
+ # @attr [Boolean] is_playable True if the episode is playable in the given market. Otherwise false.
12
+ # @attr [String] language The language used in the episode, identified by a ISO 639 code. This field is deprecated and might be removed in the future. Please use the languages field instead.
13
+ # @attr [Array<String>] languages A list of the languages used in the episode, identified by their ISO 639-1 code.
14
+ # @attr [String] name The name of the episode.
15
+ # @attr [String] release_date The date the episode was first released, for example "1981-12-15". Depending on the precision, it might be shown as "1981" or "1981-12".
16
+ # @attr [String] release_date_precision The precision with which release_date value is known.
17
+ # @attr [Hash] restrictions Included in the response when a content restriction is applied.
18
+ # @attr [Hash] resume_point The user’s most recent position in the episode. Set if the supplied access token is a user token and has the scope ‘user-read-playback-position’.
19
+ class Episode < Base
20
+
21
+ # Returns Episode object(s) with id(s) provided
22
+ #
23
+ # @param ids [String, Array] Maximum: 50 IDs
24
+ # @param market [String] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
25
+ # @return [Episode, Array<Episode>]
26
+ #
27
+ # @example
28
+ # episode = RSpotify::Episode.find('512ojhOuo1ktJprKbVcKyQ')
29
+ # episode.class #=> RSpotify::Episode
30
+ # episode.name #=> "Do I Wanna Know?"
31
+ #
32
+ # ids = %w(512ojhOuo1ktJprKbVcKyQ 15tHEpY9pwbKC0QjpYCRB1)
33
+ # episodes = RSpotify::Base.find(ids, 'episode')
34
+ # episodes.class #=> Array
35
+ # episodes.first.class #=> RSpotify::Episode
36
+ def self.find(ids, market: nil)
37
+ super(ids, 'episode', market: market)
38
+ end
39
+
40
+ # Returns array of Episode objects matching the query. It's also possible to find the total number of search results for the query
41
+ #
42
+ # @param query [String] The search query's keywords. For details access {https://developer.spotify.com/web-api/search-item here} and look for the q parameter description.
43
+ # @param limit [Integer] Maximum number of episodes to return. Maximum: 50. Default: 20.
44
+ # @param offset [Integer] The index of the first episode to return. Use with limit to get the next set of episodes. Default: 0.
45
+ # @param market [String, Hash] Optional. An {http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code} or the hash { from: user }, where user is a RSpotify user authenticated using OAuth with scope *user-read-private*. This will take the user's country as the market value. For details access {https://developer.spotify.com/web-api/search-item here} and look for the market parameter description.
46
+ # @return [Array<Episode>]
47
+ #
48
+ # @example
49
+ # episodes = RSpotify::Episode.search('Vetenskapsradion Historia')
50
+ # episodes = RSpotify::Episode.search('Vetenskapsradion Historia', limit: 10, market: 'US')
51
+ # episodes = RSpotify::Episode.search('Vetenskapsradion Historia', market: { from: user })
52
+ #
53
+ # RSpotify::Episode.search('Vetenskapsradion Historia').total #=> 711
54
+ def self.search(query, limit: 20, offset: 0, market: nil )
55
+ super(query, 'episode', limit: limit, offset: offset, market: market)
56
+ end
57
+
58
+ def initialize(options = {})
59
+ @audio_preview_url = options['audio_preview_url']
60
+ @description = options['description']
61
+ @duration_ms = options['duration_ms']
62
+ @explicit = options['explicit']
63
+ @href = options['href']
64
+ @html_description = options['html_description']
65
+ @images = options['images']
66
+ @is_externally_hosted = options['is_externally_hosted']
67
+ @is_playable = options['is_playable']
68
+ @language = options['language']
69
+ @languages = options['languages']
70
+ @name = options['name']
71
+ @release_date = options['release_date']
72
+ @release_date_precision = options['release_date_precision']
73
+ @restrictions = options['restrictions'] || {}
74
+ @resume_point = options['resume_point'] || {}
75
+ @uri = options['uri']
76
+
77
+ @show = if options['show']
78
+ Show.new options['show']
79
+ end
80
+
81
+ super(options)
82
+ end
83
+ end
84
+ end
@@ -18,6 +18,11 @@ module OmniAuth
18
18
  def raw_info
19
19
  @raw_info ||= access_token.get('me').parsed
20
20
  end
21
+
22
+ # Fix for: https://github.com/guilhermesad/rspotify/issues/189
23
+ def callback_url
24
+ full_host + script_name + callback_path
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -315,7 +315,7 @@ module RSpotify
315
315
 
316
316
  params = {
317
317
  method: :delete,
318
- url: URI::encode(RSpotify::API_URI + @path + '/tracks'),
318
+ url: Addressable::URI.encode(RSpotify::API_URI + @path + '/tracks'),
319
319
  headers: User.send(:oauth_header, @owner.id),
320
320
  payload: positions ? { positions: positions } : { tracks: tracks }
321
321
  }
@@ -0,0 +1,100 @@
1
+ module RSpotify
2
+
3
+ # @attr [Array<String>] available_markets A list of the countries in which the show can be played, identified by their ISO 3166-1 alpha-2 code.
4
+ # @attr [Array<Hash>] copyrights The copyright statements of the show.
5
+ # @attr [String] description A description of the show. HTML tags are stripped away from this field, use html_description field in case HTML tags are needed.
6
+ # @attr [Boolean] explicit Whether or not the show has explicit content (true = yes it does; false = no it does not OR unknown).
7
+ # @attr [String] html_description A description of the show. This field may contain HTML tags.
8
+ # @attr [Array<Hash>] images The cover art for the show in various sizes, widest first.
9
+ # @attr [Boolean] is_externally_hosted True if all of the show’s episodes are hosted outside of Spotify’s CDN. This field might be null in some cases.
10
+ # @attr [Array<String>] languages A list of the languages used in the show, identified by their ISO 639 code.
11
+ # @attr [String] media_type The media type of the show.
12
+ # @attr [String] name The name of the show.
13
+ # @attr [String] publisher The publisher of the show.
14
+ class Show < Base
15
+
16
+ # Returns Show object(s) with id(s) provided
17
+ #
18
+ # @param id [String, Array] Maximum: 50 IDs
19
+ # @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
20
+ # @return [Show, Array<Show>]
21
+ #
22
+ # @example
23
+ # show = RSpotify::Show.find('3Z6JdCS2d0eFEpXHKI6WqH')
24
+ # show.class #=> RSpotify::Show
25
+ # show.name #=> "Consider This from NPR"
26
+ def self.find(ids, market: nil )
27
+ super(ids, 'show', market: market)
28
+ end
29
+
30
+ # Returns array of Show objects matching the query. It's also possible to find the total number of search results for the query
31
+ #
32
+ # @param query [String] The search query's keywords. See the q description in {https://developer.spotify.com/web-api/search-item here} for details.
33
+ # @param limit [Integer] Maximum number of shows to return. Maximum: 50. Default: 20.
34
+ # @param offset [Integer] The index of the first show to return. Use with limit to get the next set of shows. Default: 0.
35
+ # @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
36
+ # @return [Array<Show>]
37
+ #
38
+ # @example
39
+ # shows = RSpotify::Show.search('NPR')
40
+ # shows = RSpotify::Show.search('NPR', market: 'US', limit: 10)
41
+ #
42
+ # RSpotify::Show.search('NPR').total #=> 357
43
+ def self.search(query, limit: 20, offset: 0, market: nil)
44
+ super(query, 'show', limit: limit, offset: offset, market: market)
45
+ end
46
+
47
+ def initialize(options = {})
48
+ @available_markets = options['available_markets']
49
+ @copyrights = options['copyrights']
50
+ @description = options['description']
51
+ @explicit = options['explicit']
52
+ @html_description = options['html_description']
53
+ @images = options['images']
54
+ @is_externally_hosted = options['is_externally_hosted']
55
+ @languages = options['languages']
56
+ @media_type = options['media_type']
57
+ @name = options['name']
58
+ @publisher = options['publisher']
59
+
60
+ episodes = options['episodes']['items'] if options['episodes']
61
+
62
+ @episodes_cache = if episodes
63
+ episodes.map { |e| Episode.new e }
64
+ end
65
+
66
+ super(options)
67
+ end
68
+
69
+ # Returns array of episodes from the show
70
+ #
71
+ # @param limit [Integer] Maximum number of episodes to return. Maximum: 50. Default: 20.
72
+ # @param offset [Integer] The index of the first track to return. Use with limit to get the next set of objects. Default: 0.
73
+ # @param market [String] An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}.
74
+ # @return [Array<Episode>]
75
+ #
76
+ # @example
77
+ # show = RSpotify::Show.find('3Z6JdCS2d0eFEpXHKI6WqH')
78
+ # show.episodes.first.name #=> "Colin Powell's Complicated Legacy"
79
+ def episodes(limit: 20, offset: 0, market: nil )
80
+ last_episode = offset + limit - 1
81
+ if @episodes_cache && last_episode < 20 && !RSpotify.raw_response
82
+ return @episodes_cache[offset..last_episode]
83
+ end
84
+
85
+ url = "#{@href}/episodes?limit=#{limit}&offset=#{offset}"
86
+ url << "&market=#{market}" if market
87
+
88
+ response = RSpotify.get url
89
+
90
+ json = RSpotify.raw_response ? JSON.parse(response) : response
91
+ episodes = json['items']
92
+
93
+ episodes.map! { |e| Episode.new e }
94
+ @episodes_cache = episodes if limit == 20 && offset == 0
95
+ return response if RSpotify.raw_response
96
+ episodes
97
+ end
98
+
99
+ end
100
+ end
@@ -1,3 +1,3 @@
1
1
  module RSpotify
2
- VERSION = '2.10.1'.freeze
2
+ VERSION = '2.11.1'.freeze
3
3
  end
data/lib/rspotify.rb CHANGED
@@ -8,10 +8,12 @@ module RSpotify
8
8
  autoload :Base, 'rspotify/base'
9
9
  autoload :Category, 'rspotify/category'
10
10
  autoload :Device, 'rspotify/device'
11
+ autoload :Episode, 'rspotify/episode'
11
12
  autoload :Player, 'rspotify/player'
12
13
  autoload :Playlist, 'rspotify/playlist'
13
14
  autoload :Recommendations, 'rspotify/recommendations'
14
15
  autoload :RecommendationSeed, 'rspotify/recommendation_seed'
16
+ autoload :Show, 'rspotify/show'
15
17
  autoload :Track, 'rspotify/track'
16
18
  autoload :TrackLink, 'rspotify/track_link'
17
19
  autoload :User, 'rspotify/user'
data/rspotify.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_dependency 'omniauth-oauth2', '>= 1.6'
20
20
  spec.add_dependency 'rest-client', '~> 2.0.2'
21
- spec.add_dependency 'addressable', '~> 2.5.2'
21
+ spec.add_dependency 'addressable', '~> 2.8.0'
22
22
 
23
23
  spec.add_development_dependency 'bundler'
24
24
  spec.add_development_dependency 'webmock'
@@ -0,0 +1,118 @@
1
+ describe RSpotify::Episode do
2
+ describe 'Episode::find receiving id as a string' do
3
+ before(:each) do
4
+ @episode = VCR.use_cassette('episode:find:512ojhOuo1ktJprKbVcKyQ') do
5
+ RSpotify::Episode.find('512ojhOuo1ktJprKbVcKyQ')
6
+ end
7
+ end
8
+
9
+ it 'should find track with correct attributes' do
10
+ expect(@episode.audio_preview_url) .to eq "https://p.scdn.co/mp3-preview/566fcc94708f39bcddc09e4ce84a8e5db8f07d4d"
11
+ expect(@episode.description) .to start_with "En ny tysk bok granskar för första gången Tredje rikets drogberoende"
12
+ expect(@episode.duration_ms) .to eq 1_502_795
13
+ expect(@episode.explicit) .to eq false
14
+ expect(@episode.href) .to eq 'https://api.spotify.com/v1/episodes/512ojhOuo1ktJprKbVcKyQ'
15
+ expect(@episode.html_description) .to start_with "En ny tysk bok granskar för första gången Tredje rikets drogberoende"
16
+ expect(@episode.id) .to eq '512ojhOuo1ktJprKbVcKyQ'
17
+ expect(@episode.images.first["url"]) .to eq "https://i.scdn.co/image/de4a5f115ac6f6ca4cae4fb7aaf27bacac7a0b8a"
18
+ expect(@episode.images.size) .to eq 3
19
+ expect(@episode.is_externally_hosted) .to eq false
20
+ expect(@episode.is_playable) .to eq true
21
+ expect(@episode.language) .to eq 'sv'
22
+ expect(@episode.languages) .to eq ["sv"]
23
+ expect(@episode.name) .to eq 'Tredje rikets knarkande granskas'
24
+ expect(@episode.release_date_precision) .to eq 'day'
25
+ expect(@episode.release_date) .to eq '2015-10-01'
26
+ expect(@episode.restrictions) .to eq Hash.new
27
+ expect(@episode.resume_point) .to eq({"fully_played"=>false, "resume_position_ms"=>0})
28
+ expect(@episode.uri) .to eq 'spotify:episode:512ojhOuo1ktJprKbVcKyQ'
29
+ end
30
+
31
+ it 'should find the episode with correct show' do
32
+ show = @episode.show
33
+ expect(show) .to be_an RSpotify::Show
34
+ expect(show.id) .to eq '38bS44xjbVVZ3No3ByF1dJ'
35
+ expect(show.name) .to eq 'Vetenskapsradion Historia'
36
+ end
37
+
38
+ it 'should find an episode which is available in the given market' do
39
+ episode = VCR.use_cassette('episode:find:5NxzDE5TmviUV8te2eZjMP:market:ES') do
40
+ RSpotify::Episode.find('5NxzDE5TmviUV8te2eZjMP', market: 'ES')
41
+ end
42
+
43
+ expect(episode.id).to eq '5NxzDE5TmviUV8te2eZjMP'
44
+ expect(episode.is_playable). to eq true
45
+ end
46
+
47
+ it 'should not find an episode which is unavailable in the given market' do
48
+ episode = VCR.use_cassette('episode:find:5NxzDE5TmviUV8te2eZjMP:market:KG') do
49
+ RSpotify::Episode.find('5NxzDE5TmviUV8te2eZjMP', market: 'KG')
50
+ end
51
+
52
+ expect(episode.id).to eq '5NxzDE5TmviUV8te2eZjMP'
53
+ expect(episode.is_playable). to eq false
54
+ end
55
+ end
56
+
57
+ describe 'Episode::find receiving array of ids' do
58
+ it 'should find the right episodes' do
59
+ ids = ['512ojhOuo1ktJprKbVcKyQ']
60
+ episodes = VCR.use_cassette('episode:find_array:512ojhOuo1ktJprKbVcKyQ') do
61
+ RSpotify::Episode.find(ids)
62
+ end
63
+ expect(episodes) .to be_an Array
64
+ expect(episodes.size) .to eq 1
65
+ expect(episodes.first.name) .to eq 'Tredje rikets knarkande granskas'
66
+
67
+ ids << '18RPZgmvEGKtEC2WMTHghd'
68
+ episodes = VCR.use_cassette('episode:find_array:18RPZgmvEGKtEC2WMTHghd') do
69
+ RSpotify::Episode.find(ids)
70
+ end
71
+ expect(episodes) .to be_an Array
72
+ expect(episodes.size) .to eq 2
73
+ expect(episodes.first.name) .to eq 'Tredje rikets knarkande granskas'
74
+ expect(episodes.last.name) .to eq 'Han upptäckte vikingastaden Birka'
75
+ end
76
+ end
77
+
78
+ describe 'Episode::search' do
79
+ it 'should search for the right episodes' do
80
+ episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas') do
81
+ RSpotify::Episode.search('Tredje rikets knarkande granskas')
82
+ end
83
+
84
+ expect(episodes) .to be_an Array
85
+ expect(episodes.size) .to eq 20
86
+ expect(episodes.total) .to eq 527
87
+ expect(episodes.first) .to be_an RSpotify::Episode
88
+ expect(episodes.map(&:name)) .to include('Tredje rikets knarkande granskas', '"Tre skadade i grovt våldsbrott i Lycksele"')
89
+ end
90
+
91
+ it 'should accept additional options' do
92
+ episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:limit:10') do
93
+ RSpotify::Episode.search('Tredje rikets knarkande granskas', limit: 10)
94
+ end
95
+ expect(episodes.size) .to eq 10
96
+ expect(episodes.map(&:name)) .to include('Tredje rikets knarkande granskas', '14. Första världskrigets BÄSTA generaler ... och Conrad')
97
+
98
+ episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:offset:10') do
99
+ RSpotify::Episode.search('Tredje rikets knarkande granskas', offset: 10)
100
+ end
101
+ expect(episodes.size) .to eq 20
102
+ expect(episodes.map(&:name)) .to include('GIIA-avsnitt 2: Stefan Kronanders avsnitt – tyska underrättelse-fuckups')
103
+
104
+ episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:limit:10:offset:10') do
105
+ RSpotify::Episode.search('Tredje rikets knarkande granskas', limit: 10, offset: 10)
106
+ end
107
+ expect(episodes.size) .to eq 10
108
+ expect(episodes.map(&:name)) .to include('GIIA-avsnitt 2: Stefan Kronanders avsnitt – tyska underrättelse-fuckups')
109
+
110
+ episodes = VCR.use_cassette('episode:search:Tredje rikets knarkande granskas:market:CA') do
111
+ RSpotify::Episode.search('Tredje rikets knarkande granskas', market: 'CA')
112
+ CA_episodes = episodes.map { |e| e.show.available_markets == 'CA'}
113
+ end
114
+
115
+ expect(CA_episodes.length).to eq(episodes.length)
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,138 @@
1
+ describe RSpotify::Show do
2
+ describe 'Show::find receiving id as a string' do
3
+
4
+ before(:each) do
5
+ @show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
6
+ RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
7
+ end
8
+ end
9
+
10
+ it 'should find show with correct attributes' do
11
+ expect(@show.available_markets) .to be_an Array
12
+ expect(@show.copyrights) .to eq []
13
+ expect(@show.external_urls['spotify']) .to eq 'https://open.spotify.com/show/5CfCWKI5pZ28U0uOzXkDHe'
14
+ expect(@show.description) .to eq 'Candid conversations with entrepreneurs, artists, athletes, visionaries of all kinds—about their successes, and their failures, and what they learned from both. Hosted by Alex Blumberg, from Gimlet Media.'
15
+ expect(@show.explicit) .to eq true
16
+ expect(@show.html_description) .to eq '<p>Candid conversations with entrepreneurs, artists, athletes, visionaries of all kinds—about their successes, and their failures, and what they learned from both. Hosted by Alex Blumberg, from Gimlet Media.</p>'
17
+ expect(@show.href) .to eq 'https://api.spotify.com/v1/shows/5CfCWKI5pZ28U0uOzXkDHe'
18
+ expect(@show.id) .to eq '5CfCWKI5pZ28U0uOzXkDHe'
19
+ expect(@show.images) .to include ({'height' => 640, 'width' => 640, 'url' => 'https://i.scdn.co/image/ab6765630000ba8a9d827f6e7e311b5947cce059'})
20
+ expect(@show.is_externally_hosted) .to eq false
21
+ expect(@show.languages) .to eq ["en"]
22
+ expect(@show.media_type) .to eq "audio"
23
+ expect(@show.name) .to eq "Without Fail"
24
+ expect(@show.publisher) .to eq "Gimlet"
25
+ expect(@show.type) .to eq 'show'
26
+ expect(@show.uri) .to eq 'spotify:show:5CfCWKI5pZ28U0uOzXkDHe'
27
+ end
28
+
29
+ it 'should find show with correct episodes' do
30
+ episodes = @show.episodes
31
+ expect(episodes) .to be_an Array
32
+ expect(episodes.size) .to eq 20
33
+ expect(episodes.first) .to be_an RSpotify::Episode
34
+ expect(episodes.map(&:name)) .to include("Introducing Michelle Obama and Her Mentees")
35
+ end
36
+ end
37
+
38
+ describe 'Show::find receiving array of ids' do
39
+ it 'should find the right shows' do
40
+ ids = ['5CfCWKI5pZ28U0uOzXkDHe']
41
+ shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe') do
42
+ RSpotify::Show.find(ids)
43
+ end
44
+ expect(shows) .to be_an Array
45
+ expect(shows.size) .to eq 1
46
+ expect(shows.first) .to be_an RSpotify::Show
47
+ expect(shows.map(&:name)) .to include("Without Fail")
48
+
49
+ ids << '5as3aKmN2k11yfDDDSrvaZ'
50
+ shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe:5as3aKmN2k11yfDDDSrvaZ') do
51
+ RSpotify::Show.find(ids)
52
+ end
53
+ expect(shows) .to be_an Array
54
+ expect(shows.size) .to eq 2
55
+ expect(shows.first) .to be_an RSpotify::Show
56
+ expect(shows.map(&:name)) .to include("Giant Bombcast")
57
+ end
58
+
59
+ it 'should find shows available in the given market' do
60
+ ids = ['5CfCWKI5pZ28U0uOzXkDHe', '5as3aKmN2k11yfDDDSrvaZ']
61
+ shows = VCR.use_cassette('show:find_many:5CfCWKI5pZ28U0uOzXkDHe:5as3aKmN2k11yfDDDSrvaZ:market:CA') do
62
+ RSpotify::Show.find(ids, market: 'CA')
63
+ end
64
+
65
+ expect(shows) .to be_an Array
66
+ expect(shows.map(&:id)) .to include '5CfCWKI5pZ28U0uOzXkDHe'
67
+ end
68
+ end
69
+
70
+ describe 'Show::search' do
71
+ it 'should search for the right shows' do
72
+ shows = VCR.use_cassette('show:search:without fail') do
73
+ RSpotify::Show.search('Without Fail')
74
+ end
75
+ expect(shows) .to be_an Array
76
+ expect(shows.size) .to eq 20
77
+ expect(shows.total) .to eq 233
78
+ expect(shows.first) .to be_an RSpotify::Show
79
+ expect(shows.map(&:name)) .to include('Without Fail', 'Teach Without a Burden')
80
+ end
81
+
82
+ it 'should accept additional options' do
83
+ shows = VCR.use_cassette('show:search:without fail:limit:10') do
84
+ RSpotify::Show.search('Without Fail', limit: 10)
85
+ end
86
+ expect(shows.size) .to eq 10
87
+ expect(shows.map(&:name)) .to include('Without Fail', 'Teach Without a Burden')
88
+
89
+ shows = VCR.use_cassette('show:search:without fail:offset:10') do
90
+ RSpotify::Show.search('Without Fail', offset: 10)
91
+ end
92
+ expect(shows.size) .to eq 20
93
+ expect(shows.map(&:name)) .to include('Weight Loss Mindset', 'Two In The Think Tank')
94
+
95
+ shows = VCR.use_cassette('show:search:without fail:offset:10:limit:10') do
96
+ RSpotify::Show.search('Without Fail', limit: 10, offset: 10)
97
+ end
98
+ expect(shows.size) .to eq 10
99
+ expect(shows.map(&:name)) .to include('Two In The Think Tank')
100
+
101
+ shows = VCR.use_cassette('show:search:without fail:market:ES') do
102
+ RSpotify::Show.search('Without Fail', market: 'ES')
103
+ end
104
+ ES_shows = shows.select { |a| a.available_markets.include?('ES') }
105
+ expect(ES_shows.length).to eq(shows.length)
106
+ end
107
+ end
108
+
109
+ describe '#episodes' do
110
+ it 'should fetch more episodes' do
111
+ show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
112
+ RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
113
+ end
114
+
115
+ episodes = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe:episodes') do
116
+ show.episodes(offset: 20, limit: 20)
117
+ end
118
+
119
+ expect(episodes) .to be_an Array
120
+ expect(episodes.size) .to eq 20
121
+ expect(episodes.first.name) .to eq 'Being an A$$hole: The Final Frontier for Women on the Screen'
122
+ expect(episodes.first.id) .to eq '0DD6d3lmUjkIHzC13Z6fbs'
123
+ end
124
+
125
+ it "should find episodes available in the given market" do
126
+ show = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe') do
127
+ RSpotify::Show.find('5CfCWKI5pZ28U0uOzXkDHe')
128
+ end
129
+
130
+ episodes = VCR.use_cassette('show:find:5CfCWKI5pZ28U0uOzXkDHe:episodes:market:ES') do
131
+ show.episodes(offset: 20, limit: 20, market: 'ES')
132
+ end
133
+
134
+ expect(episodes.first.name) .to eq 'Being an A$$hole: The Final Frontier for Women on the Screen'
135
+ expect(episodes.first.id) .to eq '0DD6d3lmUjkIHzC13Z6fbs'
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,66 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.spotify.com/v1/episodes/512ojhOuo1ktJprKbVcKyQ
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - rest-client/2.0.2 (darwin20 x86_64) ruby/3.0.2p107
16
+ Authorization:
17
+ - Bearer BQBj_AiSFlKCkNIMbCWEYjuJLl6n76QmVsHU6MGDgTUBLZqNiKZ4ALs6Kvm6ulbsW9O81JDdIHyXBndXyhUOxg
18
+ Host:
19
+ - api.spotify.com
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Cache-Control:
28
+ - public, max-age=60
29
+ Etag:
30
+ - '"MC-IjA4NWQ2NDMxNjBiYjVmZjBiZmU1NTQxMGNmZjc3Y2Y3Ig=="'
31
+ X-Robots-Tag:
32
+ - noindex, nofollow
33
+ Access-Control-Allow-Origin:
34
+ - "*"
35
+ Access-Control-Allow-Headers:
36
+ - Accept, App-Platform, Authorization, Content-Type, Origin, Retry-After, Spotify-App-Version,
37
+ X-Cloud-Trace-Context, client-token, content-access-token
38
+ Access-Control-Allow-Methods:
39
+ - GET, POST, OPTIONS, PUT, DELETE, PATCH
40
+ Access-Control-Allow-Credentials:
41
+ - 'true'
42
+ Access-Control-Max-Age:
43
+ - '604800'
44
+ Content-Encoding:
45
+ - gzip
46
+ Strict-Transport-Security:
47
+ - max-age=31536000
48
+ X-Content-Type-Options:
49
+ - nosniff
50
+ Date:
51
+ - Wed, 20 Oct 2021 22:38:08 GMT
52
+ Server:
53
+ - envoy
54
+ Via:
55
+ - HTTP/2 edgeproxy, 1.1 google
56
+ Alt-Svc:
57
+ - clear
58
+ Transfer-Encoding:
59
+ - chunked
60
+ body:
61
+ encoding: ASCII-8BIT
62
+ string: !binary |-
63
+ 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
64
+ http_version:
65
+ recorded_at: Wed, 20 Oct 2021 22:38:08 GMT
66
+ recorded_with: VCR 3.0.3