feat: CreateMangaFromMangadex endpoint + tests, missing image saving

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-02-11 00:10:54 +01:00
parent ae0eac3197
commit 50080f9779
14 changed files with 387 additions and 29 deletions

View File

@@ -5,6 +5,7 @@ namespace App\Tests\Domain\Manga\Adapter;
use App\Domain\Manga\Domain\Contract\Provider\MangaProviderInterface;
use App\Domain\Manga\Domain\Model\Manga;
use App\Domain\Manga\Domain\Model\MangaCollection;
use App\Domain\Manga\Domain\Model\ValueObject\ExternalId;
class InMemoryMangaProvider implements MangaProviderInterface
{
@@ -31,4 +32,15 @@ class InMemoryMangaProvider implements MangaProviderInterface
return new MangaCollection($results);
}
public function findByExternalId(ExternalId $externalId): ?Manga
{
foreach ($this->mangas as $manga) {
if ($manga->getExternalId() && $manga->getExternalId()->getValue() === $externalId->getValue()) {
return $manga;
}
}
return null;
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace App\Tests\Domain\Manga\Adapter;
use App\Domain\Manga\Domain\Contract\Client\MangadexClientInterface;
class InMemoryMangadexClient implements MangadexClientInterface
{
private array $mangas = [];
private array $feeds = [];
private array $aggregates = [];
public function __construct(
array $mangas = [],
array $feeds = [],
array $aggregates = []
) {
$this->mangas = $mangas;
$this->feeds = $feeds;
$this->aggregates = $aggregates;
}
public function authenticate(): void
{
// No need to implement for tests
}
public function refreshToken(): void
{
// No need to implement for tests
}
public function searchManga(string $title): array
{
$results = [];
foreach ($this->mangas as $id => $manga) {
if (isset($manga['attributes']['title']['en']) &&
str_contains(
strtolower($manga['attributes']['title']['en']),
strtolower($title)
)
) {
$results[] = array_merge(['id' => $id], $manga);
}
}
return ['data' => $results];
}
public function getMangaRatings(array $mangaIds): array
{
$statistics = [];
foreach ($mangaIds as $id) {
$statistics[$id] = [
'rating' => ['average' => 4.5] // Default rating for tests
];
}
return ['statistics' => $statistics];
}
public function getMangaFeed(string $mangaId, int $offset = 0, int $limit = 500, string $order = 'asc'): array
{
if (!isset($this->feeds[$mangaId])) {
return [
'data' => [],
'total' => 0
];
}
$feed = $this->feeds[$mangaId];
if ($order === 'desc') {
$feed = array_reverse($feed);
}
return [
'data' => array_slice($feed, $offset, $limit),
'total' => count($feed)
];
}
public function getMangaAggregate(string $mangaId): array
{
if (!isset($this->aggregates[$mangaId])) {
return [
'result' => 'ok',
'volumes' => []
];
}
return [
'result' => 'ok',
'volumes' => $this->aggregates[$mangaId]
];
}
public function getManga(string $mangaId): array
{
if (!isset($this->mangas[$mangaId])) {
return ['data' => null];
}
return [
'result' => 'ok',
'data' => array_merge(['id' => $mangaId], $this->mangas[$mangaId])
];
}
public function addManga(string $id, array $data): void
{
$this->mangas[$id] = $data;
}
public function addFeed(string $mangaId, array $feed): void
{
$this->feeds[$mangaId] = $feed;
}
public function addAggregate(string $mangaId, array $aggregate): void
{
$this->aggregates[$mangaId] = $aggregate;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Tests\Domain\Manga\Application\CommandHandler;
use App\Domain\Manga\Application\Command\CreateMangaFromMangadex;
use App\Domain\Manga\Application\CommandHandler\CreateMangaFromMangadexHandler;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Manga\Domain\Model\Manga;
use App\Domain\Manga\Domain\Model\ValueObject\ExternalId;
use App\Domain\Manga\Domain\Model\ValueObject\MangaId;
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
use App\Tests\Domain\Manga\Adapter\InMemoryMangaProvider;
use App\Tests\Domain\Manga\Adapter\InMemoryMangaRepository;
use PHPUnit\Framework\TestCase;
class CreateMangaFromMangadexHandlerTest extends TestCase
{
private InMemoryMangaProvider $provider;
private InMemoryMangaRepository $repository;
private CreateMangaFromMangadexHandler $handler;
protected function setUp(): void
{
$this->provider = new InMemoryMangaProvider();
$this->repository = new InMemoryMangaRepository();
$this->handler = new CreateMangaFromMangadexHandler(
$this->provider,
$this->repository
);
}
public function testHandleSuccess(): void
{
// Arrange
$externalId = 'manga-123';
$manga = new Manga(
new MangaId('123'),
new MangaTitle('Test Manga'),
new MangaSlug('test-manga'),
'Description',
'Author',
2020,
['action'],
'ongoing',
new ExternalId($externalId),
'http://example.com/cover.jpg',
4.5
);
$this->provider = new InMemoryMangaProvider([$manga]);
$this->handler = new CreateMangaFromMangadexHandler(
$this->provider,
$this->repository
);
// Act
$command = new CreateMangaFromMangadex($externalId);
$this->handler->handle($command);
// Assert
$savedManga = $this->repository->findById('123');
$this->assertNotNull($savedManga);
$this->assertEquals($externalId, $savedManga->getExternalId()->getValue());
$this->assertEquals('Test Manga', $savedManga->getTitle()->getValue());
}
public function testHandleThrowsExceptionWhenMangaNotFound(): void
{
// Arrange
$command = new CreateMangaFromMangadex('non-existent-manga');
// Assert
$this->expectException(MangaNotFoundException::class);
$this->expectExceptionMessage('Manga not found on Mangadex');
// Act
$this->handler->handle($command);
}
}