koel/tests/Feature/KoelPlus/SongTest.php
2024-10-24 17:45:45 +07:00

184 lines
5.9 KiB
PHP

<?php
namespace Tests\Feature\KoelPlus;
use App\Models\Song;
use Illuminate\Support\Collection;
use PHPUnit\Framework\Attributes\Test;
use Tests\PlusTestCase;
use function Tests\create_user;
class SongTest extends PlusTestCase
{
#[Test]
public function withOwnSongsOnlyOptionOn(): void
{
$user = create_user();
Song::factory(2)->public()->create();
/** @var Collection<array-key, Song> $ownSongs */
$ownSongs = Song::factory(3)->for($user, 'owner')->create();
$this->getAs('api/songs?own_songs_only=true', $user)
->assertSuccessful()
->assertJsonCount(3, 'data')
->assertJsonFragment(['id' => $ownSongs[0]->id])
->assertJsonFragment(['id' => $ownSongs[1]->id])
->assertJsonFragment(['id' => $ownSongs[2]->id]);
}
#[Test]
public function withOwnSongsOnlyOptionOffOrMissing(): void
{
$user = create_user();
Song::factory(2)->public()->create();
Song::factory(3)->for($user, 'owner')->create();
$this->getAs('api/songs?own_songs_only=false', $user)
->assertSuccessful()
->assertJsonCount(5, 'data');
$this->getAs('api/songs', $user)
->assertSuccessful()
->assertJsonCount(5, 'data');
}
#[Test]
public function showSongPolicy(): void
{
$user = create_user();
/** @var Song $publicSong */
$publicSong = Song::factory()->public()->create();
// We can access public songs.
$this->getAs("api/songs/$publicSong->id", $user)->assertSuccessful();
/** @var Song $ownPrivateSong */
$ownPrivateSong = Song::factory()->for($user, 'owner')->private()->create();
// We can access our own private songs.
$this->getAs('api/songs/' . $ownPrivateSong->id, $user)->assertSuccessful();
/** @var Song $externalUnownedSong */
$externalUnownedSong = Song::factory()->private()->create();
// But we can't access private songs that are not ours.
$this->getAs("api/songs/$externalUnownedSong->id", $user)->assertForbidden();
}
#[Test]
public function editSongsPolicy(): void
{
$currentUser = create_user();
$anotherUser = create_user();
/** @var Collection<Song> $externalUnownedSongs */
$externalUnownedSongs = Song::factory(3)->for($anotherUser, 'owner')->private()->create();
// We can't edit songs that are not ours.
$this->putAs('api/songs', [
'songs' => $externalUnownedSongs->pluck('id')->toArray(),
'data' => [
'title' => 'New Title',
],
], $currentUser)->assertForbidden();
// Even if some of the songs are owned by us, we still can't edit them.
$mixedSongs = $externalUnownedSongs->merge(Song::factory(2)->for($currentUser, 'owner')->create());
$this->putAs('api/songs', [
'songs' => $mixedSongs->pluck('id')->toArray(),
'data' => [
'title' => 'New Title',
],
], $currentUser)->assertForbidden();
// But we can edit our own songs.
$ownSongs = Song::factory(3)->for($currentUser, 'owner')->create();
$this->putAs('api/songs', [
'songs' => $ownSongs->pluck('id')->toArray(),
'data' => [
'title' => 'New Title',
],
], $currentUser)->assertSuccessful();
}
#[Test]
public function deleteSongsPolicy(): void
{
$currentUser = create_user();
$anotherUser = create_user();
/** @var Collection<Song> $externalUnownedSongs */
$externalUnownedSongs = Song::factory(3)->for($anotherUser, 'owner')->private()->create();
// We can't delete songs that are not ours.
$this->deleteAs('api/songs', ['songs' => $externalUnownedSongs->pluck('id')->toArray()], $currentUser)
->assertForbidden();
// Even if some of the songs are owned by us, we still can't delete them.
$mixedSongs = $externalUnownedSongs->merge(Song::factory(2)->for($currentUser, 'owner')->create());
$this->deleteAs('api/songs', ['songs' => $mixedSongs->pluck('id')->toArray()], $currentUser)
->assertForbidden();
// But we can delete our own songs.
$ownSongs = Song::factory(3)->for($currentUser, 'owner')->create();
$this->deleteAs('api/songs', ['songs' => $ownSongs->pluck('id')->toArray()], $currentUser)
->assertSuccessful();
}
#[Test]
public function publicizeSongs(): void
{
$user = create_user();
/** @var Song $songs */
$songs = Song::factory(3)->for($user, 'owner')->private()->create();
$this->putAs('api/songs/publicize', ['songs' => $songs->pluck('id')->toArray()], $user)
->assertSuccessful();
$songs->each(static function (Song $song): void {
$song->refresh();
self::assertTrue($song->is_public);
});
}
#[Test]
public function privatizeSongs(): void
{
$user = create_user();
/** @var Song $songs */
$songs = Song::factory(3)->for($user, 'owner')->public()->create();
$this->putAs('api/songs/privatize', ['songs' => $songs->pluck('id')->toArray()], $user)
->assertSuccessful();
$songs->each(static function (Song $song): void {
$song->refresh();
self::assertFalse($song->is_public);
});
}
#[Test]
public function publicizingOrPrivatizingSongsRequiresOwnership(): void
{
$songs = Song::factory(3)->public()->create();
$this->putAs('api/songs/privatize', ['songs' => $songs->pluck('id')->toArray()])
->assertForbidden();
$otherSongs = Song::factory(3)->private()->create();
$this->putAs('api/songs/publicize', ['songs' => $otherSongs->pluck('id')->toArray()])
->assertForbidden();
}
}