ldc-arcadia-api/tests/Unit/Domain/Services/BrandResolverTest.php

110 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Domain\Services;
use Domain\Exceptions\BrandNotFoundException;
use Domain\Models\Entities\Brand;
use Domain\Models\ValueObjects\Brand\ArcadiaBrand;
use Domain\Models\ValueObjects\Brand\ArcadiaId;
use Domain\Models\ValueObjects\Brand\BrandCode;
use Domain\Models\ValueObjects\Brand\BrandId;
use Domain\Models\ValueObjects\Brand\BrandName;
use Domain\Services\BrandCodeGenerator;
use Domain\Services\BrandResolver;
use Infra\Adapters\Directories\InMemoryArcadiaBrandDirectory;
use Infra\Adapters\Repositories\InMemoryBrandRepository;
use Psr\Log\NullLogger;
use Ramsey\Uuid\Uuid;
covers(BrandResolver::class);
describe('BrandResolver Unit Tests', function (): void {
$arcadiaDirectory = new InMemoryArcadiaBrandDirectory();
$brandRepository = new InMemoryBrandRepository();
$codeGenerator = new BrandCodeGenerator();
$logger = new NullLogger();
beforeEach(function () use ($arcadiaDirectory, $brandRepository): void {
$arcadiaDirectory->clear();
$brandRepository->clear();
});
it('returns existing brand if already present in repository', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator, $logger): void {
// GIVEN
$existing = Brand::hydrate(
id: new BrandId(Uuid::uuid7()),
name: new BrandName('Le Gaulois'),
code: new BrandCode('LGL01'),
arcadiaId: new ArcadiaId(1),
);
$brandRepository->add($existing);
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $logger);
$arcadiaBrand = new ArcadiaBrand(new ArcadiaId(1), new BrandName('Le Gaulois'));
// WHEN
$resolved = $resolver->resolve($arcadiaBrand);
// THEN
expect($resolved)->toBe($existing);
});
it('generates, persists and logs a new brand if not in repository', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator, $logger): void {
// GIVEN
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $logger);
$arcadiaBrand = new ArcadiaBrand(new ArcadiaId(2), new BrandName('Maître CoQ'));
// WHEN
$resolved = $resolver->resolve($arcadiaBrand);
// THEN
expect($resolved->arcadiaId->value)->toBe(2)
->and($resolved->name->value)->toBe('Maître CoQ')
->and(str_starts_with($resolved->code->value, 'MCQ'))->toBeTrue();
expect($brandRepository->findByArcadiaId(new ArcadiaId(2)))->not->toBeNull();
});
it('resolves by ArcadiaId directly', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator, $logger): void {
// GIVEN
$arcadiaBrand = new ArcadiaBrand(new ArcadiaId(3), new BrandName('Loué'));
$arcadiaDirectory->add($arcadiaBrand);
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $logger);
// WHEN
$resolved = $resolver->resolveByArcadiaId(new ArcadiaId(3));
// THEN
expect($resolved->arcadiaId->value)->toBe(3)
->and($resolved->name->value)->toBe('Loué');
});
it('throws BrandNotFoundException when resolving by unknown ArcadiaId', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator, $logger): void {
// GIVEN
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $logger);
// WHEN & THEN
expect(fn () => $resolver->resolveByArcadiaId(new ArcadiaId(999)))
->toThrow(BrandNotFoundException::class, 'Arcadia brand with ID 999 not found.');
});
it('resolves all brands from Arcadia directory', function () use ($arcadiaDirectory, $brandRepository, $codeGenerator, $logger): void {
// GIVEN
$arcadiaDirectory->add(
new ArcadiaBrand(new ArcadiaId(1), new BrandName('Le Gaulois')),
new ArcadiaBrand(new ArcadiaId(2), new BrandName('Maître CoQ')),
);
$resolver = new BrandResolver($arcadiaDirectory, $brandRepository, $codeGenerator, $logger);
// WHEN
$resolvedList = $resolver->resolveAll();
// THEN
expect($resolvedList)->toHaveCount(2)
->and($brandRepository->findAll())->toHaveCount(2);
});
});