koel/tests/Integration/Services/LastfmServiceTest.php
2024-10-24 17:45:45 +07:00

243 lines
7.3 KiB
PHP

<?php
namespace Tests\Integration\Services;
use App\Http\Integrations\Lastfm\Requests\GetAlbumInfoRequest;
use App\Http\Integrations\Lastfm\Requests\GetArtistInfoRequest;
use App\Http\Integrations\Lastfm\Requests\ScrobbleRequest;
use App\Http\Integrations\Lastfm\Requests\ToggleLoveTrackRequest;
use App\Http\Integrations\Lastfm\Requests\UpdateNowPlayingRequest;
use App\Models\Album;
use App\Models\Artist;
use App\Models\Song;
use App\Services\LastfmService;
use Illuminate\Support\Facades\File;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Saloon\Http\Faking\MockResponse;
use Saloon\Laravel\Saloon;
use Tests\TestCase;
use function Tests\create_user;
use function Tests\test_path;
class LastfmServiceTest extends TestCase
{
private LastfmService $service;
public function setUp(): void
{
parent::setUp();
config([
'koel.lastfm.key' => 'key',
'koel.lastfm.secret' => 'secret',
]);
$this->service = app(LastfmService::class);
}
#[Test]
public function getArtistInformation(): void
{
/** @var Artist $artist */
$artist = Artist::factory()->make(['name' => 'Kamelot']);
Saloon::fake([
GetArtistInfoRequest::class => MockResponse::make(body: File::get(test_path('blobs/lastfm/artist.json'))),
]);
$info = $this->service->getArtistInformation($artist);
Saloon::assertSent(static function (GetArtistInfoRequest $request): bool {
self::assertSame([
'method' => 'artist.getInfo',
'artist' => 'Kamelot',
'autocorrect' => 1,
'format' => 'json',
], $request->query()->all());
return true;
});
self::assertEquals([
'url' => 'https://www.last.fm/music/Kamelot',
'image' => null,
'bio' => [
'summary' => 'Quisque ut nisi.',
'full' => 'Quisque ut nisi. Vestibulum ullamcorper mauris at ligula.',
],
], $info->toArray());
}
#[Test]
public function getArtistInformationForNonExistentArtist(): void
{
/** @var Artist $artist */
$artist = Artist::factory()->make(['name' => 'bar']);
Saloon::fake([
GetArtistInfoRequest::class => MockResponse::make(
body: File::get(test_path('blobs/lastfm/artist-notfound.json'))
),
]);
self::assertNull($this->service->getArtistInformation($artist));
}
#[Test]
public function getAlbumInformation(): void
{
/** @var Album $album */
$album = Album::factory()->for(Artist::factory()->create(['name' => 'Kamelot']))->create(['name' => 'Epica']);
Saloon::fake([
GetAlbumInfoRequest::class => MockResponse::make(body: File::get(test_path('blobs/lastfm/album.json'))),
]);
$info = $this->service->getAlbumInformation($album);
Saloon::assertSent(static function (GetAlbumInfoRequest $request): bool {
self::assertSame([
'method' => 'album.getInfo',
'artist' => 'Kamelot',
'album' => 'Epica',
'autocorrect' => 1,
'format' => 'json',
], $request->query()->all());
return true;
});
self::assertEquals([
'url' => 'https://www.last.fm/music/Kamelot/Epica',
'cover' => null,
'tracks' => [
[
'title' => 'Track 1',
'url' => 'https://foo/track1',
'length' => 100,
],
[
'title' => 'Track 2',
'url' => 'https://foo/track2',
'length' => 150,
],
],
'wiki' => [
'summary' => 'Quisque ut nisi.',
'full' => 'Quisque ut nisi. Vestibulum ullamcorper mauris at ligula.',
],
], $info->toArray());
}
#[Test]
public function getAlbumInformationForNonExistentAlbum(): void
{
/** @var Album $album */
$album = Album::factory()->for(Artist::factory()->create(['name' => 'Kamelot']))->create(['name' => 'Foo']);
Saloon::fake([
GetAlbumInfoRequest::class => MockResponse::make(
body: File::get(test_path('blobs/lastfm/album-notfound.json'))
),
]);
self::assertNull($this->service->getAlbumInformation($album));
}
#[Test]
public function scrobble(): void
{
$user = create_user([
'preferences' => [
'lastfm_session_key' => 'my_key',
],
]);
/** @var Song $song */
$song = Song::factory()->create();
Saloon::fake([ScrobbleRequest::class => MockResponse::make()]);
$this->service->scrobble($song, $user, 100);
Saloon::assertSent(static function (ScrobbleRequest $request) use ($song): bool {
self::assertSame([
'method' => 'track.scrobble',
'artist' => $song->artist->name,
'track' => $song->title,
'timestamp' => 100,
'sk' => 'my_key',
'album' => $song->album->name,
], $request->body()->all());
return true;
});
}
/** @return array<mixed> */
public static function provideToggleLoveTrackData(): array
{
return [[true, 'track.love'], [false, 'track.unlove']];
}
#[DataProvider('provideToggleLoveTrackData')]
#[Test]
public function toggleLoveTrack(bool $love, string $method): void
{
$user = create_user([
'preferences' => [
'lastfm_session_key' => 'my_key',
],
]);
/** @var Song $song */
$song = Song::factory()->create();
Saloon::fake([ToggleLoveTrackRequest::class => MockResponse::make()]);
$this->service->toggleLoveTrack($song, $user, $love);
Saloon::assertSent(static function (ToggleLoveTrackRequest $request) use ($song, $love): bool {
self::assertSame([
'method' => $love ? 'track.love' : 'track.unlove',
'sk' => 'my_key',
'artist' => $song->artist->name,
'track' => $song->title,
], $request->body()->all());
return true;
});
}
#[Test]
public function updateNowPlaying(): void
{
$user = create_user([
'preferences' => [
'lastfm_session_key' => 'my_key',
],
]);
/** @var Song $song */
$song = Song::factory()->for(Artist::factory()->create(['name' => 'foo']))->create(['title' => 'bar']);
Saloon::fake([UpdateNowPlayingRequest::class => MockResponse::make()]);
$this->service->updateNowPlaying($song, $user);
Saloon::assertSent(static function (UpdateNowPlayingRequest $request) use ($song): bool {
self::assertSame([
'method' => 'track.updateNowPlaying',
'artist' => $song->artist->name,
'track' => $song->title,
'duration' => $song->length,
'sk' => 'my_key',
'album' => $song->album->name,
], $request->body()->all());
return true;
});
}
}