Skip to content

Commit

Permalink
chore(phpat): test shared infrastructure architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
rgomezcasas committed Oct 3, 2023
1 parent 4ae23d9 commit ebdca74
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 43 deletions.
6 changes: 6 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ parameters:
- ./apps/backoffice/frontend/var
- ./apps/mooc/backend/var
- ./apps/mooc/frontend/var

services:
-
class: CodelyTv\Tests\Shared\SharedArchitectureTest
tags:
- phpat.test

-
class: CodelyTv\Tests\Mooc\MoocArchitectureTest
tags:
- phpat.test
9 changes: 0 additions & 9 deletions src/Shared/Domain/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@

use DateTimeImmutable;
use DateTimeInterface;
use ReflectionClass;
use RuntimeException;

use function Lambdish\Phunctional\filter;

final class Utils
Expand Down Expand Up @@ -81,13 +79,6 @@ public static function filesIn(string $path, string $fileType): array
);
}

public static function extractClassName(object $object): string
{
$reflect = new ReflectionClass($object);

return $reflect->getShortName();
}

public static function iterableToArray(iterable $iterable): array
{
if (is_array($iterable)) {
Expand Down
10 changes: 9 additions & 1 deletion src/Shared/Infrastructure/Symfony/ApiExceptionListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use CodelyTv\Shared\Domain\DomainError;
use CodelyTv\Shared\Domain\Utils;
use ReflectionClass;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Throwable;
Expand Down Expand Up @@ -35,6 +36,13 @@ private function exceptionCodeFor(Throwable $error): string

return $error instanceof $domainErrorClass
? $error->errorCode()
: Utils::toSnakeCase(Utils::extractClassName($error));
: Utils::toSnakeCase($this->extractClassName($error));
}

private function extractClassName(object $object): string
{
$reflect = new ReflectionClass($object);

return $reflect->getShortName();
}
}
56 changes: 56 additions & 0 deletions tests/Mooc/MoocArchitectureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace CodelyTv\Tests\Mooc;

use CodelyTv\Tests\Shared\Infrastructure\ArchitectureTest;
use PHPat\Selector\Selector;
use PHPat\Test\Builder\Rule;
use PHPat\Test\PHPat;

final class MoocArchitectureTest
{
public function test_mooc_domain_should_only_import_itself_and_shared(): Rule
{
return PHPat::rule()
->classes(Selector::inNamespace('/^CodelyTv\\\\Mooc\\\\.+\\\\Domain/', true))
->canOnlyDependOn()
->classes(...array_merge(ArchitectureTest::languageClasses(), [
// Itself
Selector::inNamespace('/^CodelyTv\\\\Mooc\\\\.+\\\\Domain/', true),
// Shared
Selector::inNamespace('CodelyTv\Shared\Domain'),
]))
->because('mooc domain can only import itself and shared domain');
}

public function test_mooc_application_should_only_import_itself_and_domain(): Rule
{
return PHPat::rule()
->classes(Selector::inNamespace('/^CodelyTv\\\\Mooc\\\\.+\\\\Application/', true))
->canOnlyDependOn()
->classes(...array_merge(ArchitectureTest::languageClasses(), [
// Itself
Selector::inNamespace('/^CodelyTv\\\\Mooc\\\\.+\\\\Application/', true),
Selector::inNamespace('/^CodelyTv\\\\Mooc\\\\.+\\\\Domain/', true),
// Shared
Selector::inNamespace('CodelyTv\Shared'),
]))
->because('mooc application can only import itself and shared');
}

public function test_mooc_infrastructure_should_not_import_other_contexts_beside_shared(): Rule
{
return PHPat::rule()
->classes(Selector::inNamespace('CodelyTv\Mooc'))
->shouldNotDependOn()
->classes(Selector::inNamespace('CodelyTv'))
->excluding(
// Itself
Selector::inNamespace('CodelyTv\Mooc'),
// Shared
Selector::inNamespace('CodelyTv\Shared'),
);
}
}
40 changes: 40 additions & 0 deletions tests/Shared/Infrastructure/ArchitectureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace CodelyTv\Tests\Shared\Infrastructure;

use ArrayIterator;
use BackedEnum;
use Countable;
use DateTimeImmutable;
use DateTimeInterface;
use DomainException;
use InvalidArgumentException;
use IteratorAggregate;
use PHPat\Selector\Selector;
use RuntimeException;
use Stringable;
use Throwable;
use Traversable;

final class ArchitectureTest
{
public static function languageClasses(): array
{
return [
Selector::classname(Throwable::class),
Selector::classname(InvalidArgumentException::class),
Selector::classname(RuntimeException::class),
Selector::classname(DateTimeImmutable::class),
Selector::classname(DateTimeInterface::class),
Selector::classname(DomainException::class),
Selector::classname(Stringable::class),
Selector::classname(BackedEnum::class),
Selector::classname(Countable::class),
Selector::classname(IteratorAggregate::class),
Selector::classname(Traversable::class),
Selector::classname(ArrayIterator::class),
];
}
}
35 changes: 2 additions & 33 deletions tests/Shared/SharedArchitectureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,13 @@

namespace CodelyTv\Tests\Shared;

use ArrayIterator;
use BackedEnum;
use CodelyTv\Backoffice\Auth\Application\Authenticate\AuthenticateUserCommand;
use CodelyTv\Tests\Shared\Infrastructure\ArchitectureTest;
use CodelyTv\Tests\Shared\Infrastructure\Doctrine\MySqlDatabaseCleaner;
use Countable;
use DateTimeImmutable;
use DateTimeInterface;
use DomainException;
use InvalidArgumentException;
use IteratorAggregate;
use PHPat\Selector\Selector;
use PHPat\Test\Builder\Rule;
use PHPat\Test\PHPat;
use Ramsey\Uuid\Uuid;
use ReflectionClass;
use RuntimeException;
use Stringable;
use Throwable;
use Traversable;

final class SharedArchitectureTest
{
Expand All @@ -31,7 +19,7 @@ public function test_shared_domain_should_not_import_from_outside(): Rule
return PHPat::rule()
->classes(Selector::inNamespace('CodelyTv\Shared\Domain'))
->canOnlyDependOn()
->classes(...array_merge($this->languageClasses(), [
->classes(...array_merge(ArchitectureTest::languageClasses(), [
// Itself
Selector::inNamespace('CodelyTv\Shared\Domain'),
// Dependencies treated as domain
Expand All @@ -54,23 +42,4 @@ public function test_shared_infrastructure_should_not_import_from_other_contexts
Selector::classname(AuthenticateUserCommand::class),
);
}

private function languageClasses(): array
{
return [
Selector::classname(Throwable::class),
Selector::classname(InvalidArgumentException::class),
Selector::classname(RuntimeException::class),
Selector::classname(DateTimeImmutable::class),
Selector::classname(DateTimeInterface::class),
Selector::classname(DomainException::class),
Selector::classname(Stringable::class),
Selector::classname(BackedEnum::class),
Selector::classname(Countable::class),
Selector::classname(IteratorAggregate::class),
Selector::classname(Traversable::class),
Selector::classname(ArrayIterator::class),
Selector::classname(ReflectionClass::class),
];
}
}

0 comments on commit ebdca74

Please sign in to comment.