1<?php
2class SpotifyWebAPITest extends PHPUnit\Framework\TestCase
3{
4    private $accessToken = 'access_token';
5
6    private function setupStub($expectedMethod, $expectedUri, $expectedParameters, $expectedHeaders, $expectedReturn)
7    {
8        $stub = $this->getMockBuilder('Request')
9                ->setMethods(['api', 'getLastResponse', 'setOptions'])
10                ->getMock();
11
12        $stub->expects($this->any())
13                 ->method('api')
14                 ->with(
15                     $this->equalTo($expectedMethod),
16                     $this->equalTo($expectedUri),
17                     $this->equalTo($expectedParameters),
18                     $this->equalTo($expectedHeaders)
19                 )
20                ->willReturn($expectedReturn);
21
22        $stub->expects($this->any())
23                ->method('getLastResponse')
24                ->willReturn($expectedReturn);
25
26        return $stub;
27    }
28
29    private function setupSessionStub()
30    {
31        $stub = $this->createMock(SpotifyWebAPI\Session::class);
32
33        $stub->method('getAccessToken')
34            ->willReturn($this->accessToken);
35
36        $stub->method('refreshAccessToken')
37            ->willReturn(true);
38
39        return $stub;
40    }
41
42    private function setupApi($expectedMethod, $expectedUri, $expectedParameters, $expectedHeaders, $expectedReturn)
43    {
44        $stub = $this->setupStub(
45            $expectedMethod,
46            $expectedUri,
47            $expectedParameters,
48            $expectedHeaders,
49            $expectedReturn
50        );
51
52        return new SpotifyWebAPI\SpotifyWebAPI([], null, $stub);
53    }
54
55    public function testConstructorRequest()
56    {
57        $request = new SpotifyWebAPI\Request();
58        $api = new SpotifyWebAPI\SpotifyWebAPI($request);
59
60        $this->assertSame($request, $api->getRequest());
61    }
62
63    public function testAutoRefreshOption()
64    {
65        $options = ['auto_refresh' => true];
66
67        $headers = ['Authorization' => 'Bearer ' . $this->accessToken];
68        $return = ['body' => get_fixture('track')];
69        $sessionStub = $this->setupSessionStub();
70        $stub = $this->setupStub(
71            'GET',
72            '/v1/tracks/0eGsygTp906u18L0Oimnem',
73            [],
74            $headers,
75            $return
76        );
77
78        $stub->expects($this->at(1))
79            ->method('api')
80            ->willThrowException(
81                new SpotifyWebAPI\SpotifyWebAPIException('The access token expired', 401)
82            );
83
84        $api = new SpotifyWebAPI\SpotifyWebAPI($options, $sessionStub, $stub);
85        $response = $api->getTrack('0eGsygTp906u18L0Oimnem');
86
87        $this->assertObjectHasAttribute('id', $response);
88    }
89
90    public function testAutoRetryOption()
91    {
92        $options = ['auto_retry' => true];
93
94        $headers = ['Authorization' => 'Bearer ' . $this->accessToken];
95        $return = [
96            'body' => get_fixture('track'),
97            'headers' => [
98                'Retry-After' => 3,
99            ],
100            'status' => 429,
101        ];
102
103        $stub = $this->setupStub(
104            'GET',
105            '/v1/tracks/0eGsygTp906u18L0Oimnem',
106            [],
107            $headers,
108            $return
109        );
110
111        $stub->expects($this->at(1))
112            ->method('api')
113            ->willThrowException(
114                new SpotifyWebAPI\SpotifyWebAPIException('API rate limit exceeded', 429)
115            );
116
117        $api = new SpotifyWebAPI\SpotifyWebAPI($options, null, $stub);
118        $api->setAccessToken($this->accessToken);
119
120        $response = $api->getTrack('0eGsygTp906u18L0Oimnem');
121
122        $this->assertObjectHasAttribute('id', $response);
123    }
124
125    public function testAutoRetryOptionFallback()
126    {
127        $options = ['auto_retry' => true];
128
129        $headers = ['Authorization' => 'Bearer ' . $this->accessToken];
130        $return = [
131            'body' => get_fixture('track'),
132            'headers' => [
133                'retry-after' => 3,
134            ],
135            'status' => 429,
136        ];
137
138        $stub = $this->setupStub(
139            'GET',
140            '/v1/tracks/0eGsygTp906u18L0Oimnem',
141            [],
142            $headers,
143            $return
144        );
145
146        $stub->expects($this->at(1))
147            ->method('api')
148            ->willThrowException(
149                new SpotifyWebAPI\SpotifyWebAPIException('API rate limit exceeded', 429)
150            );
151
152        $api = new SpotifyWebAPI\SpotifyWebAPI($options, null, $stub);
153        $api->setAccessToken($this->accessToken);
154
155        $response = $api->getTrack('0eGsygTp906u18L0Oimnem');
156
157        $this->assertObjectHasAttribute('id', $response);
158    }
159
160    public function testAddMyAlbums()
161    {
162        $albums = [
163            '1oR3KrPIp4CbagPa3PhtPp',
164            '6lPb7Eoon6QPbscWbMsk6a',
165            'spotify:album:1oR3KrPIp4CbagPa3PhtPp',
166        ];
167
168        $expected = json_encode([
169            '1oR3KrPIp4CbagPa3PhtPp',
170            '6lPb7Eoon6QPbscWbMsk6a',
171            '1oR3KrPIp4CbagPa3PhtPp',
172        ]);
173
174        $headers = ['Content-Type' => 'application/json'];
175        $return = ['status' => 200];
176        $api = $this->setupApi(
177            'PUT',
178            '/v1/me/albums',
179            $expected,
180            $headers,
181            $return
182        );
183
184        $this->assertTrue(
185            $api->addMyAlbums($albums)
186        );
187    }
188
189    public function testAddMyShows()
190    {
191        $shows = [
192            '2C6ups0LMt1G8n81XLlkbsPo',
193            'spotify:show:5AvwZVawapvyhJUIx71pdJ',
194        ];
195
196        $expected = json_encode([
197            '2C6ups0LMt1G8n81XLlkbsPo',
198            '5AvwZVawapvyhJUIx71pdJ',
199        ]);
200
201        $headers = ['Content-Type' => 'application/json'];
202        $return = ['status' => 200];
203        $api = $this->setupApi(
204            'PUT',
205            '/v1/me/shows',
206            $expected,
207            $headers,
208            $return
209        );
210
211        $this->assertTrue(
212            $api->addMyShows($shows)
213        );
214    }
215
216    public function testAddMyTracks()
217    {
218        $tracks = [
219            '1id6H6vcwSB9GGv9NXh5cl',
220            '3mqRLlD9j92BBv1ueFhJ1l',
221            'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
222        ];
223
224        $expected = json_encode([
225            '1id6H6vcwSB9GGv9NXh5cl',
226            '3mqRLlD9j92BBv1ueFhJ1l',
227            '1id6H6vcwSB9GGv9NXh5cl',
228        ]);
229
230        $headers = ['Content-Type' => 'application/json'];
231        $return = ['status' => 200];
232        $api = $this->setupApi(
233            'PUT',
234            '/v1/me/tracks',
235            $expected,
236            $headers,
237            $return
238        );
239
240        $this->assertTrue(
241            $api->addMyTracks($tracks)
242        );
243    }
244
245    public function testAddPlaylistTracks()
246    {
247        $tracks = [
248            'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
249            '3mqRLlD9j92BBv1ueFhJ1l',
250        ];
251
252        $options = [
253            'position' => 0,
254        ];
255
256        $expected = json_encode([
257            'position' => 0,
258            'uris' => [
259                'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
260                'spotify:track:3mqRLlD9j92BBv1ueFhJ1l',
261            ],
262        ]);
263
264        $headers = ['Content-Type' => 'application/json'];
265        $return = ['status' => 201];
266        $api = $this->setupApi(
267            'POST',
268            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
269            $expected,
270            $headers,
271            $return
272        );
273
274        $this->assertTrue(
275            $api->addPlaylistTracks(
276                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
277                $tracks,
278                $options
279            )
280        );
281    }
282
283    public function testChangeMyDevice()
284    {
285        $options = ['device_ids' => 'abc123'];
286
287        $expected = json_encode([
288            'device_ids' => ['abc123'],
289        ]);
290
291        $headers = ['Content-Type' => 'application/json'];
292        $return = ['status' => 204];
293        $api = $this->setupApi(
294            'PUT',
295            '/v1/me/player',
296            $expected,
297            $headers,
298            $return
299        );
300
301        $this->assertTrue(
302            $api->changeMyDevice($options)
303        );
304    }
305
306    public function testChangeVolume()
307    {
308        $options = ['volume_percent' => 100];
309
310        $return = ['status' => 204];
311        $api = $this->setupApi(
312            'PUT',
313            '/v1/me/player/volume?volume_percent=100',
314            [],
315            [],
316            $return
317        );
318
319        $this->assertTrue(
320            $api->changeVolume($options)
321        );
322    }
323
324    public function testCreatePlaylist()
325    {
326        $options = [
327            'name' => 'Test playlist',
328            'public' => false,
329        ];
330
331        $expected = json_encode($options);
332
333        $headers = ['Content-Type' => 'application/json'];
334        $return = ['body' => get_fixture('user-playlist')];
335        $api = $this->setupApi(
336            'POST',
337            '/v1/me/playlists',
338            $expected,
339            $headers,
340            $return
341        );
342
343        $response = $api->createPlaylist($options);
344
345        $this->assertObjectHasAttribute('id', $response);
346    }
347
348    public function testCurrentUserFollows()
349    {
350        $options = [
351            '74ASZWbe4lXaubB36ztrGX',
352            'spotify:artist:36QJpDe2go2KgaRleHCDTp',
353        ];
354
355        $expected = [
356            'ids' => '74ASZWbe4lXaubB36ztrGX,36QJpDe2go2KgaRleHCDTp',
357            'type' => 'artist',
358        ];
359
360        $return = ['body' => get_fixture('user-follows')];
361        $api = $this->setupApi(
362            'GET',
363            '/v1/me/following/contains',
364            $expected,
365            [],
366            $return
367        );
368
369        $response = $api->currentUserFollows('artist', $options);
370
371        $this->assertTrue($response[0]);
372    }
373
374    public function testDeleteMyAlbums()
375    {
376        $albums = [
377            '1oR3KrPIp4CbagPa3PhtPp',
378            '6lPb7Eoon6QPbscWbMsk6a',
379            'spotify:album:1oR3KrPIp4CbagPa3PhtPp'
380        ];
381
382        $expected = json_encode([
383            '1oR3KrPIp4CbagPa3PhtPp',
384            '6lPb7Eoon6QPbscWbMsk6a',
385            '1oR3KrPIp4CbagPa3PhtPp'
386        ]);
387
388        $headers = ['Content-Type' => 'application/json'];
389        $return = ['status' => 200];
390        $api = $this->setupApi(
391            'DELETE',
392            '/v1/me/albums',
393            $expected,
394            $headers,
395            $return
396        );
397
398        $this->assertTrue(
399            $api->deleteMyAlbums($albums)
400        );
401    }
402
403    public function testDeleteMyShows()
404    {
405        $shows = [
406            '1oR3KrPIp4CbagPa3PhtPp',
407            '6lPb7Eoon6QPbscWbMsk6a',
408            'spotify:show:1oR3KrPIp4CbagPa3PhtPp'
409        ];
410
411        $expected = json_encode([
412            '1oR3KrPIp4CbagPa3PhtPp',
413            '6lPb7Eoon6QPbscWbMsk6a',
414            '1oR3KrPIp4CbagPa3PhtPp'
415        ]);
416
417        $headers = ['Content-Type' => 'application/json'];
418        $return = ['status' => 200];
419        $api = $this->setupApi(
420            'DELETE',
421            '/v1/me/shows',
422            $expected,
423            $headers,
424            $return
425        );
426
427        $this->assertTrue(
428            $api->deleteMyShows($shows)
429        );
430    }
431
432    public function testDeleteMyTracks()
433    {
434        $tracks = [
435            '1id6H6vcwSB9GGv9NXh5cl',
436            '3mqRLlD9j92BBv1ueFhJ1l',
437            'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
438        ];
439
440        $expected = json_encode([
441            '1id6H6vcwSB9GGv9NXh5cl',
442            '3mqRLlD9j92BBv1ueFhJ1l',
443            '1id6H6vcwSB9GGv9NXh5cl',
444        ]);
445
446        $headers = ['Content-Type' => 'application/json'];
447        $return = ['status' => 200];
448        $api = $this->setupApi(
449            'DELETE',
450            '/v1/me/tracks',
451            $expected,
452            $headers,
453            $return
454        );
455
456        $this->assertTrue(
457            $api->deleteMyTracks($tracks)
458        );
459    }
460
461    public function testDeletePlaylistTracksTracks()
462    {
463        $tracks = [
464            'tracks' => [
465                [
466                    'id' => '1id6H6vcwSB9GGv9NXh5cl',
467                    'positions' => 0,
468                ],
469                [
470                    'id' => '3mqRLlD9j92BBv1ueFhJ1l',
471                    'positions' => [1, 2],
472                ],
473                [
474                    'id' => '4iV5W9uYEdYUVa79Axb7Rh',
475                ],
476                [
477                    'uri' => 'spotify:track:1hChLdk0hBQbapbpVUVlNa',
478                ],
479                [
480                    'uri' => 'spotify:episode:0Q86acNRm6V9GYx55SXKwf',
481                ],
482            ],
483        ];
484
485        $expected = json_encode([
486            'snapshot_id' => 'snapshot_id',
487            'tracks' => [
488                [
489                    'positions' => [0],
490                    'uri' => 'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
491                ],
492                [
493                    'positions' => [1, 2],
494                    'uri' => 'spotify:track:3mqRLlD9j92BBv1ueFhJ1l',
495                ],
496                [
497                    'uri' => 'spotify:track:4iV5W9uYEdYUVa79Axb7Rh',
498                ],
499                [
500                    'uri' => 'spotify:track:1hChLdk0hBQbapbpVUVlNa',
501                ],
502                [
503                    'uri' => 'spotify:episode:0Q86acNRm6V9GYx55SXKwf',
504                ],
505            ],
506        ]);
507
508        $headers = ['Content-Type' => 'application/json'];
509        $return = ['body' => get_fixture('snapshot-id')];
510        $api = $this->setupApi(
511            'DELETE',
512            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
513            $expected,
514            $headers,
515            $return
516        );
517
518        $this->assertNotFalse(
519            $api->deletePlaylistTracks(
520                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
521                $tracks,
522                'snapshot_id'
523            )
524        );
525    }
526
527    public function testDeletePlaylistTracksPositions()
528    {
529        $trackPositions = [
530            'positions' => [
531                0,
532                1,
533            ],
534        ];
535
536        $expected = json_encode([
537            'snapshot_id' => 'snapshot_id',
538            'positions' => [
539                0,
540                1,
541            ],
542        ]);
543
544        $headers = ['Content-Type' => 'application/json'];
545        $return = ['body' => get_fixture('snapshot-id')];
546        $api = $this->setupApi(
547            'DELETE',
548            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
549            $expected,
550            $headers,
551            $return
552        );
553
554        $this->assertNotFalse(
555            $api->deletePlaylistTracks(
556                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
557                $trackPositions,
558                'snapshot_id'
559            )
560        );
561    }
562
563    public function testFollowArtistsOrUsers()
564    {
565        $options = [
566            'spotify:artist:74ASZWbe4lXaubB36ztrGX',
567            '36QJpDe2go2KgaRleHCDTp'
568        ];
569
570        $expected = json_encode([
571            'ids' => [
572                '74ASZWbe4lXaubB36ztrGX',
573                '36QJpDe2go2KgaRleHCDTp',
574            ],
575        ]);
576
577        $headers = ['Content-Type' => 'application/json'];
578        $return = ['status' => 204];
579        $api = $this->setupApi(
580            'PUT',
581            '/v1/me/following?type=artist',
582            $expected,
583            $headers,
584            $return
585        );
586
587        $this->assertTrue($api->followArtistsOrUsers(
588            'artist',
589            $options
590        ));
591    }
592
593    public function testFollowPlaylistForCurrentUser()
594    {
595        $options = ['public' => false];
596        $expected = json_encode($options);
597
598        $headers = ['Content-Type' => 'application/json'];
599        $return = ['status' => 200];
600        $api = $this->setupApi(
601            'PUT',
602            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/followers',
603            $expected,
604            $headers,
605            $return
606        );
607
608        $this->assertTrue($api->followPlaylistForCurrentUser(
609            'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
610            $options
611        ));
612    }
613
614    public function testGetAlbum()
615    {
616        $options = ['market' => 'SE'];
617        $expected = ['market' => 'SE'];
618
619        $return = ['body' => get_fixture('album')];
620        $api = $this->setupApi(
621            'GET',
622            '/v1/albums/7u6zL7kqpgLPISZYXNTgYk',
623            $expected,
624            [],
625            $return
626        );
627
628        $response = $api->getAlbum('spotify:album:7u6zL7kqpgLPISZYXNTgYk', $options);
629
630        $this->assertObjectHasAttribute('id', $response);
631    }
632
633    public function testGetAlbums()
634    {
635        $albums = [
636            '1oR3KrPIp4CbagPa3PhtPp',
637            'spotify:album:6lPb7Eoon6QPbscWbMsk6a',
638        ];
639
640        $options = [
641            'market' => 'SE'
642        ];
643
644        $expected = [
645            'ids' => '1oR3KrPIp4CbagPa3PhtPp,6lPb7Eoon6QPbscWbMsk6a',
646            'market' => 'SE',
647        ];
648
649        $return = ['body' => get_fixture('albums')];
650        $api = $this->setupApi(
651            'GET',
652            '/v1/albums/',
653            $expected,
654            [],
655            $return
656        );
657
658        $response = $api->getAlbums($albums, $options);
659
660        $this->assertObjectHasAttribute('albums', $response);
661    }
662
663    public function testGetAlbumTracks()
664    {
665        $options = [
666            'limit' => 10,
667            'market' => 'SE',
668        ];
669
670        $expected = [
671            'limit' => 10,
672            'market' => 'SE',
673        ];
674
675        $return = ['body' => get_fixture('album-tracks')];
676        $api = $this->setupApi(
677            'GET',
678            '/v1/albums/1oR3KrPIp4CbagPa3PhtPp/tracks',
679            $expected,
680            [],
681            $return
682        );
683
684        $response = $api->getAlbumTracks('spotify:album:1oR3KrPIp4CbagPa3PhtPp', $options);
685
686        $this->assertObjectHasAttribute('items', $response);
687    }
688
689    public function testGetArtist()
690    {
691        $return = ['body' => get_fixture('artist')];
692        $api = $this->setupApi(
693            'GET',
694            '/v1/artists/36QJpDe2go2KgaRleHCDTp',
695            [],
696            [],
697            $return
698        );
699
700        $response = $api->getArtist('spotify:artist:36QJpDe2go2KgaRleHCDTp');
701
702        $this->assertObjectHasAttribute('id', $response);
703    }
704
705    public function testGetArtistRelatedArtists()
706    {
707        $return = ['body' => get_fixture('artist-related-artists')];
708        $api = $this->setupApi(
709            'GET',
710            '/v1/artists/36QJpDe2go2KgaRleHCDTp/related-artists',
711            [],
712            [],
713            $return
714        );
715
716        $response = $api->getArtistRelatedArtists('spotify:artist:36QJpDe2go2KgaRleHCDTp');
717
718        $this->assertObjectHasAttribute('artists', $response);
719    }
720
721    public function testGetArtists()
722    {
723        $artists = [
724            '6v8FB84lnmJs434UJf2Mrm',
725            'spotify:artist:6olE6TJLqED3rqDCT0FyPh',
726        ];
727
728        $expected = [
729            'ids' => '6v8FB84lnmJs434UJf2Mrm,6olE6TJLqED3rqDCT0FyPh',
730        ];
731
732        $return = ['body' => get_fixture('artists')];
733        $api = $this->setupApi(
734            'GET',
735            '/v1/artists/',
736            $expected,
737            [],
738            $return
739        );
740
741        $response = $api->getArtists($artists);
742
743        $this->assertObjectHasAttribute('artists', $response);
744    }
745
746    public function testGetArtistAlbums()
747    {
748        $options = [
749            'album_type' => ['album', 'single'],
750            'limit' => 10,
751            'market' => 'SE',
752        ];
753
754        $expected = [
755            'album_type' => 'album,single',
756            'market' => 'SE',
757            'limit' => 10,
758        ];
759
760        $return = ['body' => get_fixture('artist-albums')];
761        $api = $this->setupApi(
762            'GET',
763            '/v1/artists/36QJpDe2go2KgaRleHCDTp/albums',
764            $expected,
765            [],
766            $return
767        );
768
769        $response = $api->getArtistAlbums('spotify:artist:36QJpDe2go2KgaRleHCDTp', $options);
770
771        $this->assertObjectHasAttribute('items', $response);
772    }
773
774    public function testGetArtistTopTracks()
775    {
776        $options = ['country' => 'SE'];
777        $expected = ['country' => 'SE'];
778
779        $return = ['body' => get_fixture('artist-top-tracks')];
780        $api = $this->setupApi(
781            'GET',
782            '/v1/artists/36QJpDe2go2KgaRleHCDTp/top-tracks',
783            $expected,
784            [],
785            $return
786        );
787
788        $response = $api->getArtistTopTracks('spotify:artist:36QJpDe2go2KgaRleHCDTp', $options);
789
790        $this->assertObjectHasAttribute('tracks', $response);
791    }
792
793    public function testGetAudioFeatures()
794    {
795        $tracks = [
796            '0eGsygTp906u18L0Oimnem',
797            'spotify:track:1lDWb6b6ieDQ2xT7ewTC3G',
798        ];
799
800        $expected = [
801            'ids' => '0eGsygTp906u18L0Oimnem,1lDWb6b6ieDQ2xT7ewTC3G',
802        ];
803
804        $return = ['body' => get_fixture('audio-features')];
805        $api = $this->setupApi(
806            'GET',
807            '/v1/audio-features',
808            $expected,
809            [],
810            $return
811        );
812
813        $response = $api->getAudioFeatures($tracks);
814
815        $this->assertObjectHasAttribute('audio_features', $response);
816    }
817
818    public function testGetAudioAnalysis()
819    {
820        $return = ['body' => get_fixture('audio-analysis')];
821        $api = $this->setupApi(
822            'GET',
823            '/v1/audio-analysis/0eGsygTp906u18L0Oimnem',
824            [],
825            [],
826            $return
827        );
828
829        $response = $api->getAudioAnalysis('spotify:track:0eGsygTp906u18L0Oimnem');
830
831        $this->assertObjectHasAttribute('audio_analysis', $response);
832    }
833
834    public function testGetCategoriesList()
835    {
836        $options = [
837            'country' => 'SE',
838            'limit' => 10,
839        ];
840
841        $expected = [
842            'country' => 'SE',
843            'limit' => 10,
844        ];
845
846        $return = ['body' => get_fixture('categories-list')];
847        $api = $this->setupApi(
848            'GET',
849            '/v1/browse/categories',
850            $expected,
851            [],
852            $return
853        );
854
855        $response = $api->getCategoriesList($options);
856
857        $this->assertObjectHasAttribute('categories', $response);
858    }
859
860    public function testGetCategory()
861    {
862        $options = [
863            'country' => 'SE',
864            'locale' => 'sv-SE',
865        ];
866
867        $return = ['body' => get_fixture('category')];
868        $api = $this->setupApi(
869            'GET',
870            '/v1/browse/categories/party',
871            $options,
872            [],
873            $return
874        );
875
876        $response = $api->getCategory('party', $options);
877
878        $this->assertObjectHasAttribute('id', $response);
879    }
880
881    public function testGetCategoryPlaylists()
882    {
883        $options = [
884            'country' => 'SE',
885            'limit' => 10,
886        ];
887
888        $expected = [
889            'country' => 'SE',
890            'limit' => 10,
891        ];
892
893        $return = ['body' => get_fixture('category-playlists')];
894        $api = $this->setupApi(
895            'GET',
896            '/v1/browse/categories/party/playlists',
897            $expected,
898            [],
899            $return
900        );
901
902        $response = $api->getCategoryPlaylists('party', $options);
903
904        $this->assertObjectHasAttribute('playlists', $response);
905    }
906
907    public function testGetEpisode()
908    {
909        $options = ['market' => 'SE'];
910        $expected = ['market' => 'SE'];
911
912        $return = ['body' => get_fixture('episode')];
913        $api = $this->setupApi(
914            'GET',
915            '/v1/episodes/38bS44xjbVVZ3No3ByF1dJ',
916            $expected,
917            [],
918            $return
919        );
920
921        $response = $api->getEpisode('spotify:episode:38bS44xjbVVZ3No3ByF1dJ', $options);
922
923        $this->assertObjectHasAttribute('id', $response);
924    }
925
926    public function testGetEpisodes()
927    {
928        $episodes = [
929            '0eGsygTp906u18L0Oimnem',
930            'spotify:episode:1lDWb6b6ieDQ2xT7ewTC3G',
931        ];
932
933        $options = [
934            'market' => 'SE',
935        ];
936
937        $expected = [
938            'ids' => '0eGsygTp906u18L0Oimnem,1lDWb6b6ieDQ2xT7ewTC3G',
939            'market' => 'SE',
940        ];
941
942        $return = ['body' => get_fixture('episodes')];
943        $api = $this->setupApi(
944            'GET',
945            '/v1/episodes/',
946            $expected,
947            [],
948            $return
949        );
950
951        $response = $api->getEpisodes($episodes, $options);
952
953        $this->assertObjectHasAttribute('episodes', $response);
954    }
955
956    public function testGetFeaturedPlaylists()
957    {
958        $options = [
959            'country' => 'SE',
960            'limit' => 10,
961        ];
962
963        $expected = [
964            'country' => 'SE',
965            'limit' => 10,
966        ];
967
968        $return = ['body' => get_fixture('featured-playlists')];
969        $api = $this->setupApi(
970            'GET',
971            '/v1/browse/featured-playlists',
972            $expected,
973            [],
974            $return
975        );
976
977        $response = $api->getFeaturedPlaylists($options);
978
979        $this->assertObjectHasAttribute('playlists', $response);
980    }
981
982    public function testGetGenreSeeds()
983    {
984        $return = ['body' => get_fixture('available-genre-seeds')];
985        $api = $this->setupApi(
986            'GET',
987            '/v1/recommendations/available-genre-seeds',
988            [],
989            [],
990            $return
991        );
992
993        $response = $api->getGenreSeeds();
994
995        $this->assertObjectHasAttribute('genres', $response);
996    }
997
998    public function testGetLastResponse()
999    {
1000        $return = ['body' => get_fixture('track')];
1001        $api = $this->setupApi(
1002            'GET',
1003            '/v1/tracks/7EjyzZcbLxW7PaaLua9Ksb',
1004            [],
1005            [],
1006            $return
1007        );
1008
1009        $api->getTrack('7EjyzZcbLxW7PaaLua9Ksb');
1010
1011        $response = $api->getLastResponse();
1012
1013        $this->assertArrayHasKey('body', $response);
1014    }
1015
1016    public function testGetMyCurrentTrack()
1017    {
1018        $options = [
1019            'market' => 'SE',
1020            'additional_types' => ['track', 'episode'],
1021        ];
1022
1023        $expected = [
1024            'market' => 'SE',
1025            'additional_types' => 'track,episode',
1026        ];
1027
1028        $return = ['body' => get_fixture('user-current-track')];
1029        $api = $this->setupApi(
1030            'GET',
1031            '/v1/me/player/currently-playing',
1032            $expected,
1033            [],
1034            $return
1035        );
1036
1037        $response = $api->getMyCurrentTrack($options);
1038
1039        $this->assertObjectHasAttribute('item', $response);
1040    }
1041
1042    public function testGetMyDevices()
1043    {
1044        $return = ['body' => get_fixture('user-devices')];
1045        $api = $this->setupApi(
1046            'GET',
1047            '/v1/me/player/devices',
1048            [],
1049            [],
1050            $return
1051        );
1052
1053        $response = $api->getMyDevices();
1054
1055        $this->assertObjectHasAttribute('devices', $response);
1056    }
1057
1058    public function testGetMyCurrentPlaybackInfo()
1059    {
1060        $options = [
1061            'market' => 'SE',
1062            'additional_types' => ['track', 'episode'],
1063        ];
1064
1065        $expected = [
1066            'market' => 'SE',
1067            'additional_types' => 'track,episode',
1068        ];
1069
1070        $return = ['body' => get_fixture('user-current-playback-info')];
1071        $api = $this->setupApi(
1072            'GET',
1073            '/v1/me/player',
1074            $expected,
1075            [],
1076            $return
1077        );
1078
1079        $response = $api->getMyCurrentPlaybackInfo($options);
1080
1081        $this->assertObjectHasAttribute('item', $response);
1082    }
1083
1084    public function testGetMyPlaylists()
1085    {
1086        $options = ['limit' => 10];
1087        $expected = ['limit' => 10];
1088
1089        $return = ['body' => get_fixture('my-playlists')];
1090        $api = $this->setupApi(
1091            'GET',
1092            '/v1/me/playlists',
1093            $expected,
1094            [],
1095            $return
1096        );
1097
1098        $response = $api->getMyPlaylists($options);
1099
1100        $this->assertObjectHasAttribute('items', $response);
1101    }
1102
1103    public function testGetMyRecentTracks()
1104    {
1105        $options = ['limit' => '2'];
1106        $expected = ['limit' => '2'];
1107
1108        $return = ['body' => get_fixture('recently-played')];
1109        $api = $this->setupApi(
1110            'GET',
1111            '/v1/me/player/recently-played',
1112            $expected,
1113            [],
1114            $return
1115        );
1116
1117        $response = $api->getMyRecentTracks($options);
1118
1119        $this->assertObjectHasAttribute('items', $response);
1120    }
1121
1122    public function testGetMySavedAlbums()
1123    {
1124        $options = [
1125            'limit' => 10,
1126            'market' => 'SE',
1127        ];
1128
1129        $expected = [
1130            'limit' => 10,
1131            'market' => 'SE',
1132        ];
1133
1134        $return = ['body' => get_fixture('user-albums')];
1135        $api = $this->setupApi(
1136            'GET',
1137            '/v1/me/albums',
1138            $expected,
1139            [],
1140            $return
1141        );
1142
1143        $response = $api->getMySavedAlbums($options);
1144
1145        $this->assertObjectHasAttribute('items', $response);
1146    }
1147
1148    public function testGetMySavedShows()
1149    {
1150        $options = ['limit' => 10];
1151        $expected = ['limit' => 10];
1152
1153        $return = ['body' => get_fixture('user-shows')];
1154        $api = $this->setupApi(
1155            'GET',
1156            '/v1/me/shows',
1157            $expected,
1158            [],
1159            $return
1160        );
1161
1162        $response = $api->getMySavedShows($options);
1163
1164        $this->assertObjectHasAttribute('items', $response);
1165    }
1166
1167    public function testGetMySavedTracks()
1168    {
1169        $options = [
1170            'limit' => 10,
1171            'market' => 'SE',
1172        ];
1173
1174        $expected = [
1175            'limit' => 10,
1176            'market' => 'SE',
1177        ];
1178
1179        $return = ['body' => get_fixture('user-tracks')];
1180        $api = $this->setupApi(
1181            'GET',
1182            '/v1/me/tracks',
1183            $expected,
1184            [],
1185            $return
1186        );
1187
1188        $response = $api->getMySavedTracks($options);
1189
1190        $this->assertObjectHasAttribute('items', $response);
1191    }
1192
1193    public function testGetMyTop()
1194    {
1195        $options = [
1196            'limit' => 10,
1197            'time_range' => 'long_term',
1198        ];
1199
1200        $expected = [
1201            'limit' => 10,
1202            'time_range' => 'long_term',
1203        ];
1204
1205        $return = ['body' => get_fixture('top-artists-and-tracks')];
1206        $api = $this->setupApi(
1207            'GET',
1208            '/v1/me/top/artists',
1209            $expected,
1210            [],
1211            $return
1212        );
1213
1214        $response = $api->getMyTop('artists', $options);
1215
1216        $this->assertObjectHasAttribute('items', $response);
1217    }
1218
1219    public function testGetNewReleases()
1220    {
1221        $options = [
1222            'country' => 'SE',
1223            'limit' => 10,
1224        ];
1225
1226        $expected = [
1227            'country' => 'SE',
1228            'limit' => 10,
1229        ];
1230
1231        $return = ['body' => get_fixture('albums')];
1232        $api = $this->setupApi(
1233            'GET',
1234            '/v1/browse/new-releases',
1235            $expected,
1236            [],
1237            $return
1238        );
1239
1240        $response = $api->getNewReleases($options);
1241
1242        $this->assertObjectHasAttribute('albums', $response);
1243    }
1244
1245    public function testGetRecommendations()
1246    {
1247        $options = [
1248            'limit' => 10,
1249            'seed_tracks' => ['0eGsygTp906u18L0Oimnem', '1lDWb6b6ieDQ2xT7ewTC3G'],
1250        ];
1251
1252        $expected = [
1253            'limit' => 10,
1254            'seed_tracks' => '0eGsygTp906u18L0Oimnem,1lDWb6b6ieDQ2xT7ewTC3G',
1255        ];
1256
1257        $return = ['body' => get_fixture('recommendations')];
1258        $api = $this->setupApi(
1259            'GET',
1260            '/v1/recommendations',
1261            $expected,
1262            [],
1263            $return
1264        );
1265
1266        $response = $api->getRecommendations($options);
1267
1268        $this->assertObjectHasAttribute('seeds', $response);
1269    }
1270
1271    public function testGetReturnType()
1272    {
1273        $stub = $this->getMockBuilder('Request')
1274                ->setMethods(['getReturnType'])
1275                ->getMock();
1276
1277        $stub->expects($this->once())
1278                ->method('getReturnType')
1279                ->willReturn(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC);
1280
1281        $api = new SpotifyWebAPI\SpotifyWebAPI([], null, $stub);
1282
1283        $this->assertEquals(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC, $api->getReturnType());
1284    }
1285
1286    public function testGetRequest()
1287    {
1288        $api = new SpotifyWebAPI\SpotifyWebAPI();
1289
1290        $this->assertInstanceOf(SpotifyWebAPI\Request::class, $api->getRequest());
1291    }
1292
1293    public function testGetShow()
1294    {
1295        $options = ['market' => 'SE'];
1296        $expected = ['market' => 'SE'];
1297
1298        $return = ['body' => get_fixture('show')];
1299        $api = $this->setupApi(
1300            'GET',
1301            '/v1/shows/38bS44xjbVVZ3No3ByF1dJ',
1302            $expected,
1303            [],
1304            $return
1305        );
1306
1307        $response = $api->getShow('spotify:show:38bS44xjbVVZ3No3ByF1dJ', $options);
1308
1309        $this->assertObjectHasAttribute('id', $response);
1310    }
1311
1312    public function testGetShowEpisodes()
1313    {
1314        $options = [
1315            'limit' => 10,
1316            'market' => 'SE',
1317        ];
1318
1319        $expected = [
1320            'limit' => 10,
1321            'market' => 'SE',
1322        ];
1323
1324        $return = ['body' => get_fixture('show-episodes')];
1325        $api = $this->setupApi(
1326            'GET',
1327            '/v1/shows/38bS44xjbVVZ3No3ByF1dJ/episodes',
1328            $expected,
1329            [],
1330            $return
1331        );
1332
1333        $response = $api->getShowEpisodes('spotify:show:38bS44xjbVVZ3No3ByF1dJ', $options);
1334
1335        $this->assertObjectHasAttribute('items', $response);
1336    }
1337
1338    public function testGetShows()
1339    {
1340        $shows = [
1341            '5CfCWKI5pZ28U0uOzXkDHe',
1342            'spotify:show:5as3aKmN2k11yfDDDSrvaZ',
1343        ];
1344
1345        $options = [
1346            'market' => 'SE',
1347        ];
1348
1349        $expected = [
1350            'ids' => '5CfCWKI5pZ28U0uOzXkDHe,5as3aKmN2k11yfDDDSrvaZ',
1351            'market' => 'SE',
1352        ];
1353
1354        $return = ['body' => get_fixture('shows')];
1355        $api = $this->setupApi(
1356            'GET',
1357            '/v1/shows/',
1358            $expected,
1359            [],
1360            $return
1361        );
1362
1363        $response = $api->getShows($shows, $options);
1364
1365        $this->assertObjectHasAttribute('shows', $response);
1366    }
1367
1368    public function testGetTrack()
1369    {
1370        $options = ['market' => 'SE'];
1371        $expected = ['market' => 'SE'];
1372
1373        $return = ['body' => get_fixture('track')];
1374        $api = $this->setupApi(
1375            'GET',
1376            '/v1/tracks/0eGsygTp906u18L0Oimnem',
1377            $expected,
1378            [],
1379            $return
1380        );
1381
1382        $response = $api->getTrack('spotify:track:0eGsygTp906u18L0Oimnem', $options);
1383
1384        $this->assertObjectHasAttribute('id', $response);
1385    }
1386
1387    public function testGetTracks()
1388    {
1389        $tracks = [
1390            '0eGsygTp906u18L0Oimnem',
1391            'spotify:track:1lDWb6b6ieDQ2xT7ewTC3G',
1392        ];
1393
1394        $options = [
1395            'market' => 'SE',
1396        ];
1397
1398        $expected = [
1399            'ids' => '0eGsygTp906u18L0Oimnem,1lDWb6b6ieDQ2xT7ewTC3G',
1400            'market' => 'SE',
1401        ];
1402
1403        $return = ['body' => get_fixture('tracks')];
1404        $api = $this->setupApi(
1405            'GET',
1406            '/v1/tracks/',
1407            $expected,
1408            [],
1409            $return
1410        );
1411
1412        $response = $api->getTracks($tracks, $options);
1413
1414        $this->assertObjectHasAttribute('tracks', $response);
1415    }
1416
1417    public function testGetUser()
1418    {
1419        $return = ['body' => get_fixture('user')];
1420        $api = $this->setupApi(
1421            'GET',
1422            '/v1/users/mcgurk',
1423            [],
1424            [],
1425            $return
1426        );
1427
1428        $response = $api->getUser('spotify:user:mcgurk');
1429
1430        $this->assertObjectHasAttribute('id', $response);
1431    }
1432
1433    public function testGetUserFollowedArtists()
1434    {
1435        $options = [
1436            'limit' => 10,
1437        ];
1438
1439        $expected = [
1440            'limit' => 10,
1441            'type' => 'artist',
1442        ];
1443
1444        $return = ['body' => get_fixture('user-followed-artists')];
1445        $api = $this->setupApi(
1446            'GET',
1447            '/v1/me/following',
1448            $expected,
1449            [],
1450            $return
1451        );
1452
1453        $response = $api->getUserFollowedArtists($options);
1454
1455        $this->assertObjectHasAttribute('artists', $response);
1456    }
1457
1458    public function testGetPlaylist()
1459    {
1460        $options = [
1461            'fields' => ['id', 'uri'],
1462            'market' => 'SE',
1463        ];
1464
1465        $expected = [
1466            'fields' => 'id,uri',
1467            'market' => 'SE',
1468        ];
1469
1470        $return = ['body' => get_fixture('user-playlist')];
1471        $api = $this->setupApi(
1472            'GET',
1473            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9',
1474            $expected,
1475            [],
1476            $return
1477        );
1478
1479        $response = $api->getPlaylist(
1480            'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
1481            $options
1482        );
1483
1484        $this->assertObjectHasAttribute('id', $response);
1485    }
1486
1487    public function testGetUserPlaylists()
1488    {
1489        $options = ['limit' => 10];
1490        $expected = ['limit' => 10];
1491
1492        $return = ['body' => get_fixture('user-playlists')];
1493        $api = $this->setupApi(
1494            'GET',
1495            '/v1/users/mcgurk/playlists',
1496            $expected,
1497            [],
1498            $return
1499        );
1500
1501        $response = $api->getUserPlaylists('spotify:user:mcgurk', $options);
1502
1503        $this->assertObjectHasAttribute('items', $response);
1504    }
1505
1506    public function testGetPlaylistTracks()
1507    {
1508        $options = [
1509            'fields' => ['id', 'uri'],
1510            'limit' => 10,
1511            'market' => 'SE',
1512        ];
1513
1514        $expected = [
1515            'fields' => 'id,uri',
1516            'limit' => 10,
1517            'market' => 'SE',
1518        ];
1519
1520        $return = ['body' => get_fixture('user-playlist-tracks')];
1521        $api = $this->setupApi(
1522            'GET',
1523            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
1524            $expected,
1525            [],
1526            $return
1527        );
1528
1529        $response = $api->getPlaylistTracks(
1530            'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
1531            $options
1532        );
1533
1534        $this->assertObjectHasAttribute('items', $response);
1535    }
1536
1537    public function testMe()
1538    {
1539        $return = ['body' => get_fixture('user')];
1540        $api = $this->setupApi(
1541            'GET',
1542            '/v1/me',
1543            [],
1544            [],
1545            $return
1546        );
1547
1548        $response = $api->me();
1549
1550        $this->assertObjectHasAttribute('id', $response);
1551    }
1552
1553    public function testMyAlbumsContains()
1554    {
1555        $albums = [
1556            '1oR3KrPIp4CbagPa3PhtPp',
1557            '6lPb7Eoon6QPbscWbMsk6a',
1558            'spotify:album:1oR3KrPIp4CbagPa3PhtPp',
1559        ];
1560
1561        $expected = [
1562            'ids' => '1oR3KrPIp4CbagPa3PhtPp,6lPb7Eoon6QPbscWbMsk6a,1oR3KrPIp4CbagPa3PhtPp',
1563        ];
1564
1565        $return = ['body' => get_fixture('user-albums-contains')];
1566        $api = $this->setupApi(
1567            'GET',
1568            '/v1/me/albums/contains',
1569            $expected,
1570            [],
1571            $return
1572        );
1573
1574        $response = $api->myAlbumsContains($albums);
1575
1576        $this->assertTrue($response[0]);
1577    }
1578
1579    public function testMyShowsContains()
1580    {
1581        $shows = [
1582            '5AvwZVawapvyhJUIx71pdJ',
1583            '2C6ups0LMt1G8n81XLlkbsPo',
1584            'spotify:show:2C5AvwZVawapvyhJUIx71pdJ',
1585        ];
1586
1587        $expected = [
1588            'ids' => '5AvwZVawapvyhJUIx71pdJ,2C6ups0LMt1G8n81XLlkbsPo,2C5AvwZVawapvyhJUIx71pdJ',
1589        ];
1590
1591        $return = ['body' => get_fixture('user-shows-contains')];
1592        $api = $this->setupApi(
1593            'GET',
1594            '/v1/me/shows/contains',
1595            $expected,
1596            [],
1597            $return
1598        );
1599
1600        $response = $api->myShowsContains($shows);
1601
1602        $this->assertTrue($response[0]);
1603    }
1604
1605    public function testMyTracksContains()
1606    {
1607        $tracks = [
1608            '1id6H6vcwSB9GGv9NXh5cl',
1609            '3mqRLlD9j92BBv1ueFhJ1l',
1610            'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
1611        ];
1612
1613        $expected = [
1614            'ids' => '1id6H6vcwSB9GGv9NXh5cl,3mqRLlD9j92BBv1ueFhJ1l,1id6H6vcwSB9GGv9NXh5cl',
1615        ];
1616
1617        $return = ['body' => get_fixture('user-tracks-contains')];
1618        $api = $this->setupApi(
1619            'GET',
1620            '/v1/me/tracks/contains',
1621            $expected,
1622            [],
1623            $return
1624        );
1625
1626        $response = $api->myTracksContains($tracks);
1627
1628        $this->assertTrue($response[0]);
1629    }
1630
1631    public function testNext()
1632    {
1633        $return = ['status' => 204];
1634        $api = $this->setupApi(
1635            'POST',
1636            '/v1/me/player/next?device_id=abc123',
1637            [],
1638            [],
1639            $return
1640        );
1641
1642        $this->assertTrue(
1643            $api->next('abc123')
1644        );
1645    }
1646
1647    public function testPause()
1648    {
1649        $return = ['status' => 204];
1650        $api = $this->setupApi(
1651            'PUT',
1652            '/v1/me/player/pause?device_id=abc123',
1653            [],
1654            [],
1655            $return
1656        );
1657
1658        $this->assertTrue(
1659            $api->pause('abc123')
1660        );
1661    }
1662
1663    public function testPlay()
1664    {
1665        $options = [
1666            'context_uri' => 'spotify:album:1oR3KrPIp4CbagPa3PhtPp',
1667        ];
1668
1669        $expected = json_encode($options);
1670
1671        $headers = ['Content-Type' => 'application/json'];
1672        $return = ['status' => 204];
1673        $api = $this->setupApi(
1674            'PUT',
1675            '/v1/me/player/play?device_id=abc123',
1676            $expected,
1677            $headers,
1678            $return
1679        );
1680
1681        $this->assertTrue(
1682            $api->play('abc123', $options)
1683        );
1684    }
1685
1686    public function testPrevious()
1687    {
1688        $return = ['status' => 204];
1689        $api = $this->setupApi(
1690            'POST',
1691            '/v1/me/player/previous?device_id=abc123',
1692            [],
1693            [],
1694            $return
1695        );
1696
1697        $this->assertTrue(
1698            $api->previous('abc123')
1699        );
1700    }
1701
1702    public function testQueueId()
1703    {
1704        $return = ['status' => 204];
1705        $api = $this->setupApi(
1706            'POST',
1707            '/v1/me/player/queue?uri=spotify:track:6ek0XS2AUbzrHS0B5wPNcU&device_id=abc123',
1708            [],
1709            [],
1710            $return
1711        );
1712
1713        $this->assertTrue(
1714            $api->queue('6ek0XS2AUbzrHS0B5wPNcU', 'abc123')
1715        );
1716    }
1717
1718    public function testQueueUri()
1719    {
1720        $return = ['status' => 204];
1721        $api = $this->setupApi(
1722            'POST',
1723            '/v1/me/player/queue?uri=spotify:episode:0Q86acNRm6V9GYx55SXKwf&device_id=abc123',
1724            [],
1725            [],
1726            $return
1727        );
1728
1729        $this->assertTrue(
1730            $api->queue('spotify:episode:0Q86acNRm6V9GYx55SXKwf', 'abc123')
1731        );
1732    }
1733
1734    public function testReorderPlaylistTracks()
1735    {
1736        $options = [
1737            'insert_before' => 20,
1738            'range_length' => 5,
1739            'range_start' => 0,
1740        ];
1741
1742        $expected = json_encode([
1743            'insert_before' => 20,
1744            'range_length' => 5,
1745            'range_start' => 0,
1746        ]);
1747
1748        $headers = ['Content-Type' => 'application/json'];
1749        $return = ['body' => get_fixture('snapshot-id')];
1750        $api = $this->setupApi(
1751            'PUT',
1752            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
1753            $expected,
1754            $headers,
1755            $return
1756        );
1757
1758        $this->assertNotFalse(
1759            $api->reorderPlaylistTracks(
1760                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
1761                $options
1762            )
1763        );
1764    }
1765
1766    public function testRepeat()
1767    {
1768        $return = ['status' => 204];
1769        $api = $this->setupApi(
1770            'PUT',
1771            '/v1/me/player/repeat?state=track',
1772            [],
1773            [],
1774            $return
1775        );
1776
1777        $this->assertTrue(
1778            $api->repeat([
1779                'state' => 'track',
1780            ])
1781        );
1782    }
1783
1784    public function testReplacePlaylistTracks()
1785    {
1786        $tracks = [
1787            '1id6H6vcwSB9GGv9NXh5cl',
1788            'spotify:track:3mqRLlD9j92BBv1ueFhJ1l',
1789        ];
1790
1791        $expected = json_encode([
1792            'uris' => [
1793                'spotify:track:1id6H6vcwSB9GGv9NXh5cl',
1794                'spotify:track:3mqRLlD9j92BBv1ueFhJ1l',
1795            ],
1796        ]);
1797
1798        $headers = ['Content-Type' => 'application/json'];
1799        $return = ['status' => 201];
1800        $api = $this->setupApi(
1801            'PUT',
1802            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/tracks',
1803            $expected,
1804            $headers,
1805            $return
1806        );
1807
1808        $this->assertTrue(
1809            $api->replacePlaylistTracks(
1810                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
1811                $tracks
1812            )
1813        );
1814    }
1815
1816    public function testSearch()
1817    {
1818        $types = [
1819            'album',
1820            'artist',
1821        ];
1822
1823        $options = [
1824            'limit' => 10,
1825        ];
1826
1827        $expected = [
1828            'limit' => 10,
1829            'q' => 'blur',
1830            'type' => 'album,artist',
1831        ];
1832
1833        $return = ['body' => get_fixture('search-album')];
1834        $api = $this->setupApi(
1835            'GET',
1836            '/v1/search',
1837            $expected,
1838            [],
1839            $return
1840        );
1841
1842        $response = $api->search(
1843            'blur',
1844            $types,
1845            $options
1846        );
1847
1848        $this->assertObjectHasAttribute('albums', $response);
1849    }
1850
1851    public function testSeek()
1852    {
1853        $return = ['status' => 204];
1854        $api = $this->setupApi(
1855            'PUT',
1856            '/v1/me/player/seek?position_ms=5000',
1857            [],
1858            [],
1859            $return
1860        );
1861
1862        $this->assertTrue(
1863            $api->seek([
1864                'position_ms' => 5000,
1865            ])
1866        );
1867    }
1868
1869    public function testSetReasonOnSpotifyWebAPIException()
1870    {
1871        $expectedReason = 'NO_ACTIVE_DEVICE';
1872        $exception = new \SpotifyWebAPI\SpotifyWebAPIException();
1873        $exception->setReason($expectedReason);
1874
1875        $this->assertEquals($expectedReason, $exception->getReason());
1876    }
1877
1878    public function testSetReturnType()
1879    {
1880        $stub = $this->getMockBuilder('Request')
1881                ->setMethods(['setReturnType'])
1882                ->getMock();
1883
1884        $stub->expects($this->once())
1885                ->method('setReturnType')
1886                ->willReturn(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC);
1887
1888        $api = new SpotifyWebAPI\SpotifyWebAPI([], null, $stub);
1889        $api->setReturnType(SpotifyWebAPI\SpotifyWebAPI::RETURN_ASSOC);
1890    }
1891
1892    public function testShuffle()
1893    {
1894        $return = ['status' => 204];
1895        $api = $this->setupApi(
1896            'PUT',
1897            '/v1/me/player/shuffle?state=false',
1898            [],
1899            [],
1900            $return
1901        );
1902
1903        $this->assertTrue(
1904            $api->shuffle([
1905                'state' => false,
1906            ])
1907        );
1908    }
1909
1910    public function testUnfollowArtistsOrUsers()
1911    {
1912        $options = [
1913            'ids' => [
1914                '74ASZWbe4lXaubB36ztrGX',
1915                '36QJpDe2go2KgaRleHCDTp',
1916            ],
1917        ];
1918
1919        $expected = json_encode($options);
1920
1921        $headers = ['Content-Type' => 'application/json'];
1922        $return = ['status' => 204];
1923        $api = $this->setupApi(
1924            'DELETE',
1925            '/v1/me/following?type=artist',
1926            $expected,
1927            $headers,
1928            $return
1929        );
1930
1931        $this->assertTrue(
1932            $api->unFollowArtistsOrUsers(
1933                'artist',
1934                ['74ASZWbe4lXaubB36ztrGX', 'spotify:artist:36QJpDe2go2KgaRleHCDTp']
1935            )
1936        );
1937    }
1938
1939    public function testUnfollowPlaylistForCurrentUser()
1940    {
1941        $return = ['status' => 200];
1942        $api = $this->setupApi(
1943            'DELETE',
1944            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/followers',
1945            [],
1946            [],
1947            $return
1948        );
1949
1950        $this->assertTrue(
1951            $api->unfollowPlaylistForCurrentUser(
1952                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9'
1953            )
1954        );
1955    }
1956
1957    public function testUpdatePlaylist()
1958    {
1959        $options = [
1960            'name' => 'New playlist name',
1961            'public' => false,
1962        ];
1963
1964        $expected = json_encode($options);
1965
1966        $headers = ['Content-Type' => 'application/json'];
1967        $return = ['status' => 200];
1968        $api = $this->setupApi(
1969            'PUT',
1970            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9',
1971            $expected,
1972            $headers,
1973            $return
1974        );
1975
1976        $this->assertTrue(
1977            $api->updatePlaylist(
1978                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
1979                $options
1980            )
1981        );
1982    }
1983
1984    public function testUpdatePlaylistImage()
1985    {
1986        $imageData = 'dGVzdA==';
1987
1988        $return = ['status' => 202];
1989        $api = $this->setupApi(
1990            'PUT',
1991            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/images',
1992            $imageData,
1993            [],
1994            $return
1995        );
1996
1997        $this->assertTrue(
1998            $api->updatePlaylistImage(
1999                'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
2000                $imageData
2001            )
2002        );
2003    }
2004
2005    public function testUsersFollowPlaylist()
2006    {
2007        $options = [
2008            'ids' => [
2009                'possan',
2010                'spotify:user:elogain',
2011            ],
2012        ];
2013
2014        $expected = [
2015            'ids' => 'possan,elogain',
2016        ];
2017
2018        $return = ['body' => get_fixture('users-follows-playlist')];
2019        $api = $this->setupApi(
2020            'GET',
2021            '/v1/playlists/0UZ0Ll4HJHR7yvURYbHJe9/followers/contains',
2022            $expected,
2023            [],
2024            $return
2025        );
2026
2027        $response = $api->usersFollowPlaylist(
2028            'spotify:playlist:0UZ0Ll4HJHR7yvURYbHJe9',
2029            $options
2030        );
2031
2032        $this->assertTrue($response[0]);
2033    }
2034}
2035