ldc-arcadia-api/tests/Architecture/DomainTest.php

148 lines
4 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Architecture;
use Domain\Models\ValueObjects\Employees\EmployeeSortColumn;
use Domain\Models\ValueObjects\Inco\IncoSheetSortColumn;
use Domain\Models\ValueObjects\Inco\PortionType;
use Shared\DDD\Event\Event;
use Shared\DDD\Model\AggregateRoot;
use Shared\DDD\Model\Entity;
use Shared\DDD\Model\ReadModel;
use Shared\DDD\Port\Directory;
use Shared\DDD\Port\Repository;
describe('Domain Architecture Rules', function (): void {
arch('Domain Entities implement Shared\DDD\Model\Entity')
->expect('Domain\Models\Entities')
->toImplement(Entity::class);
arch('Domain Entities are final and readonly')
->expect('Domain\Models\Entities')
->toBeReadonly()
->toBeFinal();
arch('Domain Ports contain only interfaces')
->expect('Domain\Ports')
->classes()
->toBeInterface();
arch('Domain Port Directories extend Shared\DDD\Port\Directory')
->expect('Domain\Ports\Directories')
->toExtend(Directory::class);
arch('Domain Port Repositories extend Shared\DDD\Port\Repository')
->expect('Domain\Ports\Repositories')
->toExtend(Repository::class);
arch('Domain Value Objects are final and readonly')
->expect('Domain\Models\ValueObjects')
->classes()
->toBeReadonly()
->toBeFinal()
->ignoring([
EmployeeSortColumn::class,
IncoSheetSortColumn::class,
PortionType::class,
]);
arch('Domain Events implement Shared\DDD\Event\Event and are final and readonly')
->expect('Domain\Events')
->toImplement(Event::class)
->classes()
->toBeReadonly()
->toBeFinal();
arch('Domain Builders are final')
->expect('Domain\Builders')
->classes()
->toBeFinal();
arch('Domain Services are final and readonly')
->expect('Domain\Services')
->classes()
->toBeReadonly()
->toBeFinal();
arch('Domain exceptions extend native DomainException')
->expect('Domain\Exceptions')
->toExtend(\DomainException::class);
arch('Domain does not depend on Application, Presentation, Infra, or App')
->expect('Domain')
->not->toUse([
'Application',
'Presentation',
'Infra',
'Infrastructure',
'App',
]);
arch('Domain does not depend on Illuminate or Symfony frameworks')
->expect('Domain')
->not->toUse([
'Illuminate',
'Symfony',
]);
arch('Domain does not use Laravel helper functions')
->expect('Domain')
->not->toUse([
'abort',
'app',
'auth',
'asset',
'back',
'bcrypt',
'broadcast',
'cache',
'config',
'cookie',
'csrf_token',
'dd',
'dump',
'decrypt',
'dispatch',
'event',
'factory',
'logger',
'redirect',
'request',
'response',
'route',
'session',
'storage',
'url',
'throw_if',
'throw_unless',
'__',
'trans',
'trans_choice',
'view',
]);
arch('Domain layer uses strict types')
->expect('Domain')
->toUseStrictTypes();
});
describe('AggregateRoot & ReadModel Architecture Rules', function (): void {
arch('AggregateRoot implementations are final')
->expect(AggregateRoot::class)
->classes()
->toBeFinal();
arch('Domain AggregateRoot implementations are readonly')
->expect('Domain\Models\Entities')
->classes()
->toBeReadonly();
arch('ReadModel implementations are final and readonly')
->expect(ReadModel::class)
->classes()
->toBeFinal()
->toBeReadonly()
->ignoring(ReadModel::class);
});