feat(test|api): add PlaylistSong tests

This commit is contained in:
Phan An 2022-07-27 10:49:33 +02:00
parent b3ee1ff528
commit 334c53727e
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
34 changed files with 224 additions and 95 deletions

View file

@ -43,6 +43,8 @@ class PlaylistSongController extends Controller
abort_if($playlist->is_smart, Response::HTTP_FORBIDDEN);
$this->playlistService->addSongsToPlaylist($playlist, $request->songs);
return response()->noContent();
}
public function remove(Playlist $playlist, RemoveSongsFromPlaylistRequest $request)
@ -52,5 +54,7 @@ class PlaylistSongController extends Controller
abort_if($playlist->is_smart, Response::HTTP_FORBIDDEN);
$this->playlistService->removeSongsFromPlaylist($playlist, $request->songs);
return response()->noContent();
}
}

View file

@ -34,7 +34,6 @@ class Playlist extends Model
protected $guarded = ['id'];
protected $casts = [
'user_id' => 'int',
'rules' => SmartPlaylistRulesCast::class,
];

View file

@ -37,7 +37,6 @@ class User extends Authenticatable
protected $appends = ['avatar'];
protected $casts = [
'id' => 'int',
'is_admin' => 'bool',
'preferences' => UserPreferencesCast::class,
];

View file

@ -9,6 +9,6 @@ class PlaylistPolicy
{
public function owner(User $user, Playlist $playlist): bool
{
return $user->id === $playlist->user_id;
return $playlist->user->is($user);
}
}

View file

@ -13,6 +13,6 @@ class UserPolicy
public function destroy(User $currentUser, User $userToDestroy): bool
{
return $currentUser->is_admin && $currentUser->id !== $userToDestroy->id;
return $currentUser->is_admin && $currentUser->isNot($userToDestroy);
}
}

View file

@ -8,30 +8,28 @@ use Throwable;
final class SmartPlaylistRuleGroup implements Arrayable
{
public ?int $id;
/** @var Collection|array<SmartPlaylistRule> */
public Collection $rules;
private function __construct(public ?int $id, public Collection $rules)
{
}
public static function tryCreate(array $jsonArray): ?self
{
try {
return self::create($jsonArray);
} catch (Throwable $exception) {
} catch (Throwable) {
return null;
}
}
public static function create(array $jsonArray): self
{
$group = new self();
$group->id = $jsonArray['id'] ?? null;
$id = $jsonArray['id'] ?? null;
$group->rules = collect(array_map(static function (array $rawRuleConfig) {
$rules = collect(array_map(static function (array $rawRuleConfig) {
return SmartPlaylistRule::create($rawRuleConfig);
}, $jsonArray['rules']));
return $group;
return new self($id, $rules);
}
/** @return array<mixed> */

View file

@ -33,7 +33,7 @@ class AlbumCoverTest extends TestCase
return $album->id === 9999;
}), 'Foo', 'jpeg');
$response = $this->putAsUser('api/album/' . $album->id . '/cover', [
$response = $this->putAs('api/album/' . $album->id . '/cover', [
'cover' => 'data:image/jpeg;base64,Rm9v',
], User::factory()->admin()->create());
@ -49,7 +49,7 @@ class AlbumCoverTest extends TestCase
->shouldReceive('writeAlbumCover')
->never();
$this->putAsUser('api/album/' . $album->id . '/cover', [
$this->putAs('api/album/' . $album->id . '/cover', [
'cover' => 'data:image/jpeg;base64,Rm9v',
], User::factory()->create())
->assertStatus(403);

View file

@ -37,7 +37,7 @@ class AlbumThumbnailTest extends TestCase
}))
->andReturn($thumbnailUrl);
$response = $this->getAsUser("api/album/{$createdAlbum->id}/thumbnail");
$response = $this->getAs("api/album/{$createdAlbum->id}/thumbnail");
$response->assertJson(['thumbnailUrl' => $thumbnailUrl]);
}
}

View file

@ -33,7 +33,7 @@ class ArtistImageTest extends TestCase
return $artist->id === 9999;
}), 'Foo', 'jpeg');
$this->putAsUser('api/artist/9999/image', [
$this->putAs('api/artist/9999/image', [
'image' => 'data:image/jpeg;base64,Rm9v',
], User::factory()->admin()->create())
->assertStatus(200);
@ -47,7 +47,7 @@ class ArtistImageTest extends TestCase
->shouldReceive('writeArtistImage')
->never();
$this->putAsUser('api/artist/9999/image', [
$this->putAs('api/artist/9999/image', [
'image' => 'data:image/jpeg;base64,Rm9v',
], User::factory()->create())
->assertStatus(403);

View file

@ -164,9 +164,7 @@ class DownloadTest extends TestCase
self::mock(InteractionRepository::class)
->shouldReceive('getUserFavorites')
->once()
->with(Mockery::on(static function (User $retrievedUser) use ($user): bool {
return $retrievedUser->id === $user->id;
}))
->with(Mockery::on(static fn (User $retrievedUser) => $retrievedUser->is($user)))
->andReturn($favorites);
$this->downloadService

View file

@ -26,7 +26,7 @@ class InteractionTest extends TestCase
/** @var Song $song */
$song = Song::orderBy('id')->first();
$this->postAsUser('api/interaction/play', ['song' => $song->id], $user);
$this->postAs('api/interaction/play', ['song' => $song->id], $user);
self::assertDatabaseHas('interactions', [
'user_id' => $user->id,
@ -35,7 +35,7 @@ class InteractionTest extends TestCase
]);
// Try again
$this->postAsUser('api/interaction/play', ['song' => $song->id], $user);
$this->postAs('api/interaction/play', ['song' => $song->id], $user);
self::assertDatabaseHas('interactions', [
'user_id' => $user->id,
@ -53,7 +53,7 @@ class InteractionTest extends TestCase
/** @var Song $song */
$song = Song::orderBy('id')->first();
$this->postAsUser('api/interaction/like', ['song' => $song->id], $user);
$this->postAs('api/interaction/like', ['song' => $song->id], $user);
self::assertDatabaseHas('interactions', [
'user_id' => $user->id,
@ -62,7 +62,7 @@ class InteractionTest extends TestCase
]);
// Try again
$this->postAsUser('api/interaction/like', ['song' => $song->id], $user);
$this->postAs('api/interaction/like', ['song' => $song->id], $user);
self::assertDatabaseHas('interactions', [
'user_id' => $user->id,
@ -82,7 +82,7 @@ class InteractionTest extends TestCase
$songs = Song::orderBy('id')->take(2)->get();
$songIds = array_pluck($songs->toArray(), 'id');
$this->postAsUser('api/interaction/batch/like', ['songs' => $songIds], $user);
$this->postAs('api/interaction/batch/like', ['songs' => $songIds], $user);
foreach ($songs as $song) {
self::assertDatabaseHas('interactions', [
@ -92,7 +92,7 @@ class InteractionTest extends TestCase
]);
}
$this->postAsUser('api/interaction/batch/unlike', ['songs' => $songIds], $user);
$this->postAs('api/interaction/batch/unlike', ['songs' => $songIds], $user);
foreach ($songs as $song) {
self::assertDatabaseHas('interactions', [

View file

@ -31,7 +31,7 @@ class LastfmTest extends TestCase
{
/** @var User $user */
$user = User::factory()->create();
$this->postAsUser('api/lastfm/session-key', ['key' => 'foo'], $user)
$this->postAs('api/lastfm/session-key', ['key' => 'foo'], $user)
->assertStatus(204);
self::assertEquals('foo', $user->refresh()->lastfm_session_key);
@ -120,7 +120,7 @@ class LastfmTest extends TestCase
/** @var User $user */
$user = User::factory()->create();
self::assertNotNull($user->lastfm_session_key);
$this->deleteAsUser('api/lastfm/disconnect', [], $user);
$this->deleteAs('api/lastfm/disconnect', [], $user);
$user->refresh();
self::assertNull($user->lastfm_session_key);

View file

@ -33,9 +33,7 @@ class PlaylistSongTest extends TestCase
$user = User::factory()->create();
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create([
'user_id' => $user->id,
]);
$playlist = Playlist::factory()->create([], $user);
/** @var array<Song>|Collection $songs */
$songs = Song::orderBy('id')->take(4)->get();
@ -46,7 +44,7 @@ class PlaylistSongTest extends TestCase
$path = $useDeprecatedRoute ? "api/playlist/$playlist->id/sync" : "api/playlist/$playlist->id/songs";
$this->putAsUser($path, [
$this->putAs($path, [
'songs' => $songs->pluck('id')->all(),
], $user)->assertOk();
@ -77,7 +75,7 @@ class PlaylistSongTest extends TestCase
$songs = Song::factory(2)->create();
$playlist->songs()->saveMany($songs);
$this->getAsUser("api/playlist/$playlist->id/songs", $user)
$this->getAs("api/playlist/$playlist->id/songs", $user)
->assertJson($songs->pluck('id')->all());
}
}

View file

@ -25,7 +25,7 @@ class PlaylistTest extends TestCase
/** @var array<Song>|Collection $songs */
$songs = Song::orderBy('id')->take(3)->get();
$response = $this->postAsUser('api/playlist', [
$response = $this->postAs('api/playlist', [
'name' => 'Foo Bar',
'songs' => $songs->pluck('id')->toArray(),
'rules' => [],
@ -52,7 +52,7 @@ class PlaylistTest extends TestCase
'value' => ['Bob Dylan'],
]);
$this->postAsUser('api/playlist', [
$this->postAs('api/playlist', [
'name' => 'Smart Foo Bar',
'rules' => [
[
@ -74,7 +74,7 @@ class PlaylistTest extends TestCase
public function testCreatingSmartPlaylistIgnoresSongs(): void
{
$this->postAsUser('api/playlist', [
$this->postAs('api/playlist', [
'name' => 'Smart Foo Bar',
'rules' => [
[
@ -100,7 +100,7 @@ class PlaylistTest extends TestCase
public function testCreatingPlaylistWithNonExistentSongsFails(): void
{
$response = $this->postAsUser('api/playlist', [
$response = $this->postAs('api/playlist', [
'name' => 'Foo Bar',
'rules' => [],
'songs' => ['foo'],
@ -120,7 +120,7 @@ class PlaylistTest extends TestCase
'name' => 'Foo',
]);
$this->putAsUser("api/playlist/$playlist->id", ['name' => 'Bar'], $user);
$this->putAs("api/playlist/$playlist->id", ['name' => 'Bar'], $user);
self::assertSame('Bar', $playlist->refresh()->name);
}
@ -132,7 +132,7 @@ class PlaylistTest extends TestCase
'name' => 'Foo',
]);
$response = $this->putAsUser("api/playlist/$playlist->id", ['name' => 'Qux']);
$response = $this->putAs("api/playlist/$playlist->id", ['name' => 'Qux']);
$response->assertStatus(403);
}
@ -146,7 +146,7 @@ class PlaylistTest extends TestCase
'user_id' => $user->id,
]);
$this->deleteAsUser("api/playlist/$playlist->id", [], $user);
$this->deleteAs("api/playlist/$playlist->id", [], $user);
self::assertDatabaseMissing('playlists', ['id' => $playlist->id]);
}
@ -155,7 +155,7 @@ class PlaylistTest extends TestCase
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create();
$this->deleteAsUser("api/playlist/$playlist->id")
$this->deleteAs("api/playlist/$playlist->id")
->assertStatus(403);
}
}

View file

@ -19,7 +19,7 @@ class ProfileTest extends TestCase
public function testUpdateProfileRequiresCurrentPassword(): void
{
$this->putAsUser('api/me', [
$this->putAs('api/me', [
'name' => 'Foo',
'email' => 'bar@baz.com',
], $this->user)
@ -28,7 +28,7 @@ class ProfileTest extends TestCase
public function testUpdateProfileWithoutNewPassword(): void
{
$this->putAsUser('api/me', [
$this->putAs('api/me', [
'name' => 'Foo',
'email' => 'bar@baz.com',
'current_password' => 'secret',
@ -43,7 +43,7 @@ class ProfileTest extends TestCase
public function testUpdateProfileWithNewPassword(): void
{
$this->putAsUser('api/me', [
$this->putAs('api/me', [
'name' => 'Foo',
'email' => 'bar@baz.com',
'new_password' => 'new-secret',

View file

@ -25,7 +25,7 @@ class ScrobbleTest extends TestCase
->with($song->album->artist->name, $song->title, $timestamp, $song->album->name, $user->lastfm_session_key)
->once();
$this->postAsUser("/api/$song->id/scrobble", ['timestamp' => $timestamp], $user)
$this->postAs("/api/$song->id/scrobble", ['timestamp' => $timestamp], $user)
->assertNoContent();
}
}

View file

@ -23,7 +23,7 @@ class SettingTest extends TestCase
{
$this->mediaSyncService->shouldReceive('sync')->once();
$this->putAsUser('/api/settings', ['media_path' => __DIR__], User::factory()->admin()->create())
$this->putAs('/api/settings', ['media_path' => __DIR__], User::factory()->admin()->create())
->assertSuccessful();
self::assertEquals(__DIR__, Setting::get('media_path'));
@ -31,7 +31,7 @@ class SettingTest extends TestCase
public function testNonAdminCannotSaveSettings(): void
{
$this->putAsUser('/api/settings', ['media_path' => __DIR__], User::factory()->create())
$this->putAs('/api/settings', ['media_path' => __DIR__], User::factory()->create())
->assertForbidden();
}
}

View file

@ -21,7 +21,7 @@ class SongTest extends TestCase
{
$song = Song::first();
$this->putAsUser('/api/songs', [
$this->putAs('/api/songs', [
'songs' => [$song->id],
'data' => [
'title' => 'Foo Bar',
@ -56,7 +56,7 @@ class SongTest extends TestCase
$song = Song::first();
$originalArtistId = $song->artist->id;
$this->putAsUser('/api/songs', [
$this->putAs('/api/songs', [
'songs' => [$song->id],
'data' => [
'title' => '',
@ -79,7 +79,7 @@ class SongTest extends TestCase
{
$songIds = Song::latest()->take(3)->pluck('id')->toArray();
$this->putAsUser('/api/songs', [
$this->putAs('/api/songs', [
'songs' => $songIds,
'data' => [
'title' => 'foo',
@ -109,7 +109,7 @@ class SongTest extends TestCase
$originalSongs = Song::latest()->take(3)->get();
$songIds = $originalSongs->pluck('id')->toArray();
$this->putAsUser('/api/songs', [
$this->putAs('/api/songs', [
'songs' => $songIds,
'data' => [
'title' => 'Foo Bar',
@ -143,7 +143,7 @@ class SongTest extends TestCase
{
$song = Song::first();
$this->putAsUser('/api/songs', [
$this->putAs('/api/songs', [
'songs' => [$song->id],
'data' => [
'title' => 'Foo Bar',

View file

@ -8,7 +8,7 @@ use Tests\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
private function jsonAsUser(?User $user, string $method, $uri, array $data = [], array $headers = []): TestResponse
private function jsonAs(?User $user, string $method, $uri, array $data = [], array $headers = []): TestResponse
{
/** @var User $user */
$user = $user ?: User::factory()->create();
@ -17,23 +17,23 @@ abstract class TestCase extends BaseTestCase
return parent::json($method, $uri, $data, $headers);
}
protected function getAsUser(string $url, ?User $user = null): TestResponse
protected function getAs(string $url, ?User $user = null): TestResponse
{
return $this->jsonAsUser($user, 'get', $url);
return $this->jsonAs($user, 'get', $url);
}
protected function deleteAsUser(string $url, array $data = [], ?User $user = null): TestResponse
protected function deleteAs(string $url, array $data = [], ?User $user = null): TestResponse
{
return $this->jsonAsUser($user, 'delete', $url, $data);
return $this->jsonAs($user, 'delete', $url, $data);
}
protected function postAsUser(string $url, array $data, ?User $user = null): TestResponse
protected function postAs(string $url, array $data, ?User $user = null): TestResponse
{
return $this->jsonAsUser($user, 'post', $url, $data);
return $this->jsonAs($user, 'post', $url, $data);
}
protected function putAsUser(string $url, array $data, ?User $user = null): TestResponse
protected function putAs(string $url, array $data, ?User $user = null): TestResponse
{
return $this->jsonAsUser($user, 'put', $url, $data);
return $this->jsonAs($user, 'put', $url, $data);
}
}

View file

@ -32,7 +32,7 @@ class UploadTest extends TestCase
->shouldReceive('handleUploadedFile')
->never();
$this->postAsUser('/api/upload', ['file' => $file], User::factory()->create())->assertStatus(403);
$this->postAs('/api/upload', ['file' => $file], User::factory()->create())->assertStatus(403);
}
/** @return array<mixed> */
@ -55,7 +55,7 @@ class UploadTest extends TestCase
->with($file)
->andThrow($exceptionClass);
$this->postAsUser('/api/upload', ['file' => $file], User::factory()->admin()->create())
$this->postAs('/api/upload', ['file' => $file], User::factory()->admin()->create())
->assertStatus($statusCode);
}
@ -71,7 +71,7 @@ class UploadTest extends TestCase
->with($file)
->andReturn($song);
$this->postAsUser('/api/upload', ['file' => $file], User::factory()->admin()->create())
$this->postAs('/api/upload', ['file' => $file], User::factory()->admin()->create())
->assertJsonStructure([
'song',
'album',

View file

@ -14,7 +14,7 @@ class UserTest extends TestCase
public function testNonAdminCannotCreateUser(): void
{
$this->postAsUser('api/user', [
$this->postAs('api/user', [
'name' => 'Foo',
'email' => 'bar@baz.com',
'password' => 'secret',
@ -24,7 +24,7 @@ class UserTest extends TestCase
public function testAdminCreatesUser(): void
{
$this->postAsUser('api/user', [
$this->postAs('api/user', [
'name' => 'Foo',
'email' => 'bar@baz.com',
'password' => 'secret',
@ -46,7 +46,7 @@ class UserTest extends TestCase
/** @var User $user */
$user = User::factory()->admin()->create(['password' => 'secret']);
$this->putAsUser("api/user/$user->id", [
$this->putAs("api/user/$user->id", [
'name' => 'Foo',
'email' => 'bar@baz.com',
'password' => 'new-secret',
@ -67,7 +67,7 @@ class UserTest extends TestCase
$user = User::factory()->create();
$admin = User::factory()->admin()->create();
$this->deleteAsUser("api/user/$user->id", [], $admin);
$this->deleteAs("api/user/$user->id", [], $admin);
self::assertDatabaseMissing('users', ['id' => $user->id]);
}
@ -77,7 +77,7 @@ class UserTest extends TestCase
$admin = User::factory()->admin()->create();
// A user can't delete himself
$this->deleteAsUser("api/user/$admin->id", [], $admin)
$this->deleteAs("api/user/$admin->id", [], $admin)
->assertStatus(403);
self::assertDatabaseHas('users', ['id' => $admin->id]);

View file

@ -57,7 +57,7 @@ class AlbumInformationTest extends TestCase
]
));
$this->getAsUser('api/albums/' . $album->id . '/information')
$this->getAs('api/albums/' . $album->id . '/information')
->assertJsonStructure(self::JSON_STRUCTURE);
}
@ -69,7 +69,7 @@ class AlbumInformationTest extends TestCase
/** @var Album $album */
$album = Album::factory()->create();
$this->getAsUser('api/albums/' . $album->id . '/information')
$this->getAs('api/albums/' . $album->id . '/information')
->assertJsonStructure(self::JSON_STRUCTURE);
}
}

View file

@ -12,11 +12,9 @@ class AlbumSongTest extends TestCase
/** @var Album $album */
$album = Album::factory()->create();
Song::factory(5)->create([
'album_id' => $album->id,
]);
Song::factory(5)->for($album)->create();
$this->getAsUser('api/albums/' . $album->id . '/songs')
$this->getAs('api/albums/' . $album->id . '/songs')
->assertJsonStructure(['*' => SongTest::JSON_STRUCTURE]);
}
}

View file

@ -42,7 +42,7 @@ class AlbumTest extends TestCase
{
Album::factory(10)->create();
$this->getAsUser('api/albums')
$this->getAs('api/albums')
->assertJsonStructure(self::JSON_COLLECTION_STRUCTURE);
}
@ -51,7 +51,7 @@ class AlbumTest extends TestCase
/** @var Album $album */
$album = Album::factory()->create();
$this->getAsUser('api/albums/' . $album->id)
$this->getAs('api/albums/' . $album->id)
->assertJsonStructure(self::JSON_STRUCTURE);
}
}

View file

@ -38,7 +38,7 @@ class ArtistInformationTest extends TestCase
],
));
$this->getAsUser('api/artists/' . $artist->id . '/information')
$this->getAs('api/artists/' . $artist->id . '/information')
->assertJsonStructure(self::JSON_STRUCTURE);
}
@ -50,7 +50,7 @@ class ArtistInformationTest extends TestCase
/** @var Artist $artist */
$artist = Artist::factory()->create();
$this->getAsUser('api/artists/' . $artist->id . '/information')
$this->getAs('api/artists/' . $artist->id . '/information')
->assertJsonStructure(self::JSON_STRUCTURE);
}
}

View file

@ -12,11 +12,9 @@ class ArtistSongTest extends TestCase
/** @var Artist $artist */
$artist = Artist::factory()->create();
Song::factory(5)->create([
'artist_id' => $artist->id,
]);
Song::factory(5)->for($artist)->create();
$this->getAsUser('api/artists/' . $artist->id . '/songs')
$this->getAs('api/artists/' . $artist->id . '/songs')
->assertJsonStructure(['*' => SongTest::JSON_STRUCTURE]);
}
}

View file

@ -41,7 +41,7 @@ class ArtistTest extends TestCase
{
Artist::factory(10)->create();
$this->getAsUser('api/artists')
$this->getAs('api/artists')
->assertJsonStructure(self::JSON_COLLECTION_STRUCTURE);
}
@ -50,7 +50,7 @@ class ArtistTest extends TestCase
/** @var Artist $artist */
$artist = Artist::factory()->create();
$this->getAsUser('api/artists/' . $artist->id)
$this->getAs('api/artists/' . $artist->id)
->assertJsonStructure(self::JSON_STRUCTURE);
}
}

View file

@ -6,7 +6,7 @@ class DataTest extends TestCase
{
public function testIndex(): void
{
$this->getAsUser('/api/data')->assertJsonStructure([
$this->getAs('/api/data')->assertJsonStructure([
'settings',
'playlists',
'current_user',

View file

@ -19,7 +19,7 @@ class ExcerptSearchTest extends TestCase
Album::factory()->create(['name' => 'Foo Number Five']);
Album::factory(4)->create();
$this->getAsUser('api/search?q=foo')
$this->getAs('api/search?q=foo')
->assertJsonStructure([
'songs' => ['*' => SongTest::JSON_STRUCTURE],
'artists' => ['*' => ArtistTest::JSON_STRUCTURE],

View file

@ -16,7 +16,7 @@ class FavoriteTest extends TestCase
'user_id' => $user->id,
]);
$this->getAsUser('api/favorites', $user)
$this->getAs('api/favorites', $user)
->assertJsonStructure(['*' => SongTest::JSON_STRUCTURE]);
}
}

View file

@ -12,11 +12,9 @@ class OverviewTest extends TestCase
/** @var User $user */
$user = User::factory()->create();
Interaction::factory(20)->create([
'user_id' => $user->id,
]);
Interaction::factory(20)->for($user)->create();
$this->getAsUser('api/overview', $user)
$this->getAs('api/overview', $user)
->assertJsonStructure([
'most_played_songs' => ['*' => SongTest::JSON_STRUCTURE],
'recently_played_songs' => ['*' => SongTest::JSON_STRUCTURE],

View file

@ -13,7 +13,7 @@ class PlayCountTest extends TestCase
'play_count' => 10,
]);
$response = $this->postAsUser('/api/interaction/play', [
$response = $this->postAs('/api/interaction/play', [
'song' => $interaction->song->id,
], $interaction->user);

View file

@ -0,0 +1,139 @@
<?php
namespace Tests\Feature\V6;
use App\Models\Playlist;
use App\Models\Song;
use App\Models\User;
use Illuminate\Http\Response;
class PlaylistSongTest extends TestCase
{
public function testGetNormalPlaylist(): void
{
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create();
$playlist->songs()->attach(Song::factory(5)->create());
$this->getAs('api/playlists/' . $playlist->id . '/songs', $playlist->user)
->assertJsonStructure(['*' => SongTest::JSON_STRUCTURE]);
}
public function testGetSmartPlaylist(): void
{
Song::factory()->create(['title' => 'A foo song']);
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create([
'rules' => [
[
'id' => 1658843809274,
'rules' => [
[
'id' => 1658843809274,
'model' => 'title',
'operator' => 'contains',
'value' => ['foo'],
],
],
],
],
]);
$this->getAs('api/playlists/' . $playlist->id . '/songs', $playlist->user)
->assertJsonStructure(['*' => SongTest::JSON_STRUCTURE]);
}
public function testNonOwnerCannotAccessPlaylist(): void
{
$user = User::factory()->create();
/** @var Playlist $playlist */
$playlist = Playlist::factory()->for($user)->create();
$playlist->songs()->attach(Song::factory(5)->create());
$this->getAs('api/playlists/' . $playlist->id . '/songs')
->assertStatus(Response::HTTP_FORBIDDEN);
}
public function testAddSongsToPlaylist(): void
{
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create();
$songs = Song::factory(2)->create();
$this->postAs('api/playlists/' . $playlist->id . '/songs', [
'songs' => $songs->map(static fn (Song $song) => $song->id)->all(),
], $playlist->user)
->assertNoContent();
self::assertEqualsCanonicalizing($songs->pluck('id')->all(), $playlist->songs->pluck('id')->all());
}
public function testRemoveSongsFromPlaylist(): void
{
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create();
$toRemainSongs = Song::factory(5)->create();
$toBeRemovedSongs = Song::factory(2)->create();
$playlist->songs()->attach($toRemainSongs->merge($toBeRemovedSongs));
self::assertCount(7, $playlist->songs);
$this->deleteAs('api/playlists/' . $playlist->id . '/songs', [
'songs' => $toBeRemovedSongs->map(static fn (Song $song) => $song->id)->all(),
], $playlist->user)
->assertNoContent();
$playlist->refresh();
self::assertEqualsCanonicalizing($toRemainSongs->pluck('id')->all(), $playlist->songs->pluck('id')->all());
}
public function testNonOwnerCannotModifyPlaylist(): void
{
$user = User::factory()->create();
/** @var Playlist $playlist */
$playlist = Playlist::factory()->for($user)->create();
/** @var Song $song */
$song = Song::factory()->create();
$this->postAs('api/playlists/' . $playlist->id . '/songs', ['songs' => [$song->id]])
->assertStatus(Response::HTTP_FORBIDDEN);
$this->deleteAs('api/playlists/' . $playlist->id . '/songs', ['songs' => [$song->id]])
->assertStatus(Response::HTTP_FORBIDDEN);
}
public function testSmartPlaylistContentCannotBeModified(): void
{
/** @var Playlist $playlist */
$playlist = Playlist::factory()->create([
'rules' => [
[
'id' => 1658843809274,
'rules' => [
[
'id' => 1658843809274,
'model' => 'title',
'operator' => 'contains',
'value' => ['foo'],
],
],
],
],
]);
$songs = Song::factory(2)->create()->map(static fn (Song $song) => $song->id)->all();
$this->postAs('api/playlists/' . $playlist->id . '/songs', ['songs' => $songs], $playlist->user)
->assertStatus(Response::HTTP_FORBIDDEN);
$this->deleteAs('api/playlists/' . $playlist->id . '/songs', ['songs' => $songs], $playlist->user)
->assertStatus(Response::HTTP_FORBIDDEN);
}
}

View file

@ -29,7 +29,7 @@ class YouTubeTest extends TestCase
}), 'foo')
->once();
$this->getAsUser("/api/youtube/search/song/{$song->id}?pageToken=foo")
$this->getAs("/api/youtube/search/song/{$song->id}?pageToken=foo")
->assertOk();
}
}