82 lines
3.3 KiB
PHP
82 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
use App\Contracts\Action;
|
|
use App\Contracts\ActionInput;
|
|
use App\Contracts\Query;
|
|
use App\Contracts\QueryInput;
|
|
use Symfony\Component\Finder\Finder;
|
|
|
|
describe('application coding rules', function (): void {
|
|
arch('No Domain Entities are used in Controllers')
|
|
->expect('App\Http\Controllers')
|
|
->not->toUse('Domain\Entities');
|
|
|
|
arch('No Domain Entities are used in Policies')
|
|
->expect('App\Policies')
|
|
->not->toUse('Domain\Entities');
|
|
|
|
arch('App Repositories implement App\Contracts\Repository')
|
|
->expect('App\Repositories')
|
|
->toImplement('App\Contracts\Repository');
|
|
|
|
arch('App Directories implement App\Contracts\Directory')
|
|
->expect('App\Directories')
|
|
->toImplement('App\Contracts\Directory');
|
|
|
|
arch('App DTOs are final readonly classes')
|
|
->expect('App\Dto')
|
|
->classes()
|
|
->toBeFinal()
|
|
->toBeReadonly();
|
|
|
|
arch('App Actions implement App\Contracts\Action and Inputs implement ActionInput', function (): void {
|
|
$path = __DIR__ . '/../../app/Actions';
|
|
$files = (new Finder())->files()->in($path)->name('*.php');
|
|
|
|
foreach ($files as $file) {
|
|
$subPath = $file->getRelativePathname();
|
|
$className = 'App\\Actions\\' . str_replace(['/', '.php'], ['\\', ''], $subPath);
|
|
$reflection = new \ReflectionClass($className);
|
|
|
|
if (str_ends_with($className, 'Input')) {
|
|
expect($reflection->implementsInterface(ActionInput::class))
|
|
->toBeTrue("{$className} must implement App\Contracts\ActionInput");
|
|
} elseif (str_ends_with($className, 'Output')) {
|
|
if ($reflection->isEnum()) {
|
|
expect($reflection->isEnum())->toBeTrue();
|
|
} else {
|
|
expect($reflection->isFinal())
|
|
->toBeTrue("{$className} must be final");
|
|
expect($reflection->isReadOnly())
|
|
->toBeTrue("{$className} must be readonly");
|
|
}
|
|
} else {
|
|
expect($reflection->implementsInterface(Action::class))
|
|
->toBeTrue("{$className} must implement App\Contracts\Action");
|
|
}
|
|
}
|
|
});
|
|
|
|
arch('App Queries implement App\Contracts\Query and Inputs implement QueryInput', function (): void {
|
|
$path = __DIR__ . '/../../app/Queries';
|
|
$files = (new Finder())->files()->in($path)->name('*.php');
|
|
|
|
foreach ($files as $file) {
|
|
$subPath = $file->getRelativePathname();
|
|
$className = 'App\\Queries\\' . str_replace(['/', '.php'], ['\\', ''], $subPath);
|
|
$reflection = new \ReflectionClass($className);
|
|
|
|
if (str_ends_with($className, 'Input')) {
|
|
expect($reflection->implementsInterface(QueryInput::class))
|
|
->toBeTrue("{$className} must implement App\Contracts\QueryInput");
|
|
} elseif (str_ends_with($className, 'Output')) {
|
|
expect($reflection->isFinal() && $reflection->isReadOnly())
|
|
->toBeTrue("{$className} must be final readonly");
|
|
} else {
|
|
expect($reflection->implementsInterface(Query::class))
|
|
->toBeTrue("{$className} must implement App\Contracts\Query");
|
|
}
|
|
}
|
|
});
|
|
});
|