ldc-arcadia-api/tests/Integration/Infra/Adapters/Repositories/ApiClientRepositoryTest.php

231 lines
7.8 KiB
PHP
Raw Normal View History

<?php
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;
use Application\Security\Models\ValueObjects\ClientSecret;
use Application\Security\Models\ValueObjects\Entities\ClientId;
use DateTimeImmutable;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Infra\Adapters\Repositories\ApiClientRepository;
use Infra\Database\Models\ApiClient;
use Ramsey\Uuid\Uuid;
use Shared\Pagination;
use Tests\TestCase;
uses(TestCase::class, RefreshDatabase::class);
covers(ApiClientRepository::class);
beforeEach(function (): void {
ApiClient::query()->delete();
});
describe('ApiClientRepository Integration Tests', function (): void {
it('persists a new client into database', function (): void {
// GIVEN
$repository = new ApiClientRepository();
$clientId = new ClientId(Uuid::uuid7());
$identifier = new ClientIdentifier('arcadia_id_' . str_repeat('a', 32));
$secret = new ClientSecret('arcadia_sec_' . str_repeat('b', 86));
$client = Client::hydrate(
id: $clientId,
name: new ClientName('New API Client'),
identifier: $identifier,
secret: $secret,
isActive: true,
updatedAt: new DateTimeImmutable(),
);
// WHEN
$repository->persist($client);
// THEN
$found = $repository->find($clientId);
expect($found)->not->toBeNull()
->and($found->id->value)->toBe($clientId->value)
->and($found->name->value)->toBe('New API Client')
->and($found->identifier->value)->toBe($identifier->value)
->and($found->secret->value)->toBe($secret->value)
->and($found->isActive)->toBeTrue();
});
it('updates an existing client in database on persist', function (): void {
// GIVEN
$repository = new ApiClientRepository();
$rawId = Uuid::uuid7()->toString();
$identifier = 'arcadia_id_' . str_repeat('a', 32);
$oldSecret = 'arcadia_sec_' . str_repeat('1', 86);
$newSecret = 'arcadia_sec_' . str_repeat('2', 86);
ApiClient::factory()->create([
'id' => $rawId,
'name' => 'Initial Client',
'slug' => 'initial-client',
'identifier' => $identifier,
'secret' => $oldSecret,
'is_active' => true,
]);
$clientId = new ClientId(Uuid::fromString($rawId));
$client = Client::hydrate(
id: $clientId,
name: new ClientName('Initial Client'),
identifier: new ClientIdentifier($identifier),
secret: new ClientSecret($oldSecret),
isActive: true,
updatedAt: new DateTimeImmutable(),
);
$client->regenerateSecret(new ClientSecret($newSecret));
// WHEN
$repository->persist($client);
// THEN
$found = $repository->find($clientId);
expect($found)->not->toBeNull()
->and($found->secret->value)->toBe($newSecret);
});
it('finds a client by its ClientId', function (): void {
// GIVEN
$repository = new ApiClientRepository();
$rawId = Uuid::uuid7()->toString();
$identifier = 'arcadia_id_' . str_repeat('a', 32);
$secret = 'arcadia_sec_' . str_repeat('b', 86);
ApiClient::factory()->create([
'id' => $rawId,
'name' => 'Existing Client',
'slug' => 'existing-client',
'identifier' => $identifier,
'secret' => $secret,
'is_active' => true,
]);
$clientId = new ClientId(Uuid::fromString($rawId));
// WHEN
$client = $repository->find($clientId);
// THEN
expect($client)->not->toBeNull()
->and($client->id->value)->toBe($rawId)
->and($client->name->value)->toBe('Existing Client')
->and($client->identifier->value)->toBe($identifier);
});
it('finds a client by its ClientIdentifier', function (): void {
// GIVEN
$repository = new ApiClientRepository();
$rawId = Uuid::uuid7()->toString();
$identifier = 'arcadia_id_' . str_repeat('a', 32);
$secret = 'arcadia_sec_' . str_repeat('b', 86);
ApiClient::factory()->create([
'id' => $rawId,
'name' => 'Searchable Client',
'slug' => 'searchable-client',
'identifier' => $identifier,
'secret' => $secret,
'is_active' => true,
]);
$clientIdentifier = new ClientIdentifier($identifier);
// WHEN
$client = $repository->findByIdentifier($clientIdentifier);
// THEN
expect($client)->not->toBeNull()
->and($client->identifier->value)->toBe($identifier)
->and($client->name->value)->toBe('Searchable Client');
});
it('deletes an existing client from database', function (): void {
// GIVEN
/** @var \Tests\TestCase $this */
$repository = new ApiClientRepository();
$rawId = Uuid::uuid7()->toString();
$identifier = 'arcadia_id_' . str_repeat('a', 32);
$secret = 'arcadia_sec_' . str_repeat('b', 86);
ApiClient::factory()->create([
'id' => $rawId,
'name' => 'Client to Delete',
'slug' => 'client-to-delete',
'identifier' => $identifier,
'secret' => $secret,
'is_active' => true,
]);
$client = Client::hydrate(
id: new ClientId(Uuid::fromString($rawId)),
name: new ClientName('Client to Delete'),
identifier: new ClientIdentifier($identifier),
secret: new ClientSecret($secret),
isActive: true,
updatedAt: new DateTimeImmutable(),
);
// WHEN
$repository->delete($client);
// THEN
$this->assertDatabaseMissing('api_clients', [
'id' => $rawId,
]);
});
it('is idempotent 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,
updatedAt: new DateTimeImmutable(),
);
// WHEN
$repository->delete($client);
// THEN
expect($repository->find($client->id))->toBeNull();
});
it('finds all clients with pagination', function (): void {
// GIVEN
$repository = new ApiClientRepository();
for ($i = 1; $i <= 5; $i++) {
ApiClient::factory()->create([
'id' => Uuid::uuid7()->toString(),
'name' => "Client $i",
'slug' => "client-$i",
'identifier' => 'arcadia_id_' . str_pad((string) $i, 32, '0', STR_PAD_LEFT),
'secret' => 'arcadia_sec_' . str_pad((string) $i, 86, '0', STR_PAD_LEFT),
'is_active' => true,
]);
}
$pagination = Pagination::ofPage(pageNumber: 1, pageSize: 2);
// WHEN
$paginated = $repository->findAll($pagination);
// THEN
expect($paginated->getTotal())->toBe(5)
->and(count($paginated->getItems()))->toBe(2)
->and($paginated->getPagination()->pageNumber())->toBe(1);
});
});