diff --git a/src/Application/Security/Ports/Repositories/ClientRepository.php b/src/Application/Security/Ports/Repositories/ClientRepository.php index 2a6a4fa..863ebe9 100644 --- a/src/Application/Security/Ports/Repositories/ClientRepository.php +++ b/src/Application/Security/Ports/Repositories/ClientRepository.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Application\Security\Ports\Repositories; +use Application\Security\Exceptions\ClientNotFoundException; use Application\Security\Models\Entities\Client; use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; @@ -21,6 +22,9 @@ interface ClientRepository extends Repository public function persist(Client $client): void; + /** + * @throws ClientNotFoundException + */ public function delete(Client $client): void; public function existsByName(ClientName $name): bool; diff --git a/src/Infra/Adapters/Repositories/ApiClientRepository.php b/src/Infra/Adapters/Repositories/ApiClientRepository.php index ccff9d9..22c4c7f 100644 --- a/src/Infra/Adapters/Repositories/ApiClientRepository.php +++ b/src/Infra/Adapters/Repositories/ApiClientRepository.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Infra\Adapters\Repositories; +use Application\Security\Exceptions\ClientNotFoundException; use Application\Security\Models\Entities\Client; use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; @@ -113,7 +114,7 @@ final class ApiClientRepository implements ClientRepository { $deleted = ApiClient::query()->where('id', $client->id->value)->delete(); if ($deleted === 0) { - throw new \LogicException('Client not found'); + throw ClientNotFoundException::forClient($client->id->value); } } diff --git a/src/Infra/Adapters/Repositories/InMemoryClientRepository.php b/src/Infra/Adapters/Repositories/InMemoryClientRepository.php index db4beec..efc9d80 100644 --- a/src/Infra/Adapters/Repositories/InMemoryClientRepository.php +++ b/src/Infra/Adapters/Repositories/InMemoryClientRepository.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Infra\Adapters\Repositories; +use Application\Security\Exceptions\ClientNotFoundException; use Application\Security\Models\Entities\Client; use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; @@ -47,6 +48,10 @@ final class InMemoryClientRepository implements ClientRepository #[\Override] public function delete(Client $client): void { + if (! isset($this->clients[$client->id->value])) { + throw ClientNotFoundException::forClient($client->id->value); + } + unset($this->clients[$client->id->value]); } diff --git a/src/Shared/DDD/Port/Repository.php b/src/Shared/DDD/Port/Repository.php index 3b4a0b6..4b344ee 100644 --- a/src/Shared/DDD/Port/Repository.php +++ b/src/Shared/DDD/Port/Repository.php @@ -11,6 +11,8 @@ namespace Shared\DDD\Port; * @method TEntity|null find(TId $id) * @method void persist(TEntity $entity) * @method void delete(TEntity $entity) + * + * @throws \Shared\DDD\Exception\NotFoundException */ interface Repository { diff --git a/tests/Integration/Infra/Adapters/Repositories/ApiClientRepositoryTest.php b/tests/Integration/Infra/Adapters/Repositories/ApiClientRepositoryTest.php index d34f018..9b23e68 100644 --- a/tests/Integration/Infra/Adapters/Repositories/ApiClientRepositoryTest.php +++ b/tests/Integration/Infra/Adapters/Repositories/ApiClientRepositoryTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Tests\Integration\Infra\Adapters\Repositories; +use Application\Security\Exceptions\ClientNotFoundException; use Application\Security\Models\Entities\Client; use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; @@ -185,6 +186,24 @@ describe('ApiClientRepository Integration Tests', function (): void { ]); }); + it('throws ClientNotFoundException when deleting non-existent client', function (): void { + // GIVEN + $repository = new ApiClientRepository(); + $client = Client::hydrate( + id: new ClientId(Uuid::uuid7()), + name: new ClientName('Non Existent'), + identifier: new ClientIdentifier('arcadia_id_' . str_repeat('z', 32)), + secret: new ClientSecret('arcadia_sec_' . str_repeat('z', 86)), + isActive: true, + createdAt: new DateTimeImmutable(), + updatedAt: new DateTimeImmutable(), + ); + + // WHEN & THEN + expect(fn () => $repository->delete($client)) + ->toThrow(ClientNotFoundException::class); + }); + it('finds all clients with pagination', function (): void { // GIVEN $repository = new ApiClientRepository(); diff --git a/tests/Unit/Infra/Adapters/Repositories/InMemoryClientRepositoryTest.php b/tests/Unit/Infra/Adapters/Repositories/InMemoryClientRepositoryTest.php index fdbd53c..6836840 100644 --- a/tests/Unit/Infra/Adapters/Repositories/InMemoryClientRepositoryTest.php +++ b/tests/Unit/Infra/Adapters/Repositories/InMemoryClientRepositoryTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Tests\Unit\Infra\Adapters\Repositories; +use Application\Security\Exceptions\ClientNotFoundException; use Application\Security\Models\Entities\Client; use Application\Security\Models\ValueObjects\ClientIdentifier; use Application\Security\Models\ValueObjects\ClientName; @@ -63,6 +64,16 @@ describe('InMemoryClientRepository Unit Tests', function (): void { ->and($foundAfterDelete)->toBeNull(); }); + it('throws ClientNotFoundException when deleting non-existent client', function (): void { + // GIVEN + $repository = new InMemoryClientRepository(); + $client = createClient('arcadia_id_' . str_repeat('9', 32)); + + // WHEN & THEN + expect(fn () => $repository->delete($client)) + ->toThrow(ClientNotFoundException::class); + }); + it('finds all clients with pagination', function (): void { // GIVEN $repository = new InMemoryClientRepository();