Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Expression/ForClasses/IsA.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function __construct(string $allowedFqcn)

public function describe(ClassDescription $theClass, string $because = ''): Description
{
return new Description("should inherit from: $this->allowedFqcn", $because);
return new Description("{$theClass->getName()} should be a $this->allowedFqcn", $because);
}

public function evaluate(ClassDescription $theClass, Violations $violations, string $because = ''): void
Expand Down
44 changes: 44 additions & 0 deletions src/Expression/ForClasses/IsNotA.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Arkitect\Expression\ForClasses;

use Arkitect\Analyzer\ClassDescription;
use Arkitect\Expression\Description;
use Arkitect\Expression\Expression;
use Arkitect\Rules\Violation;
use Arkitect\Rules\ViolationMessage;
use Arkitect\Rules\Violations;

final class IsNotA implements Expression
{
/** @var class-string */
private string $disallowedFqcn;

/**
* @param class-string $disallowedFqcn
*/
public function __construct(string $disallowedFqcn)
{
$this->disallowedFqcn = $disallowedFqcn;
}

public function describe(ClassDescription $theClass, string $because = ''): Description
{
return new Description("{$theClass->getName()} should not be a $this->disallowedFqcn", $because);
}

public function evaluate(ClassDescription $theClass, Violations $violations, string $because = ''): void
{
if (is_a($theClass->getFQCN(), $this->disallowedFqcn, true)) {
$violation = Violation::create(
$theClass->getFQCN(),
ViolationMessage::selfExplanatory($this->describe($theClass, $because)),
$theClass->getFilePath()
);

$violations->add($violation);
}
}
}
22 changes: 11 additions & 11 deletions tests/Unit/Expressions/ForClasses/IsATest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
use Arkitect\Analyzer\ClassDescriptionBuilder;
use Arkitect\Expression\ForClasses\IsA;
use Arkitect\Rules\Violations;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Animal\Dog;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Fruit\Banana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Fruit\CavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Fruit\DwarfCavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Fruit\FruitInterface;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Animal\Dog;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Fruit\Banana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Fruit\CavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Fruit\DwarfCavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Fruit\FruitInterface;
use PHPUnit\Framework\TestCase;

final class IsATest extends TestCase
Expand Down Expand Up @@ -48,7 +48,7 @@ public function test_it_should_have_no_violation_when_it_extends(): void
self::assertEquals(0, $violations->count());
}

public function test_it_should_have_violation_if_it_doesnt_extend(): void
public function test_it_should_have_violation_when_it_doesnt_extend(): void
{
$interface = FruitInterface::class;
$isA = new IsA($interface);
Expand All @@ -62,12 +62,12 @@ public function test_it_should_have_violation_if_it_doesnt_extend(): void

self::assertEquals(1, $violations->count());
self::assertEquals(
"should inherit from: $interface",
"Dog should be a $interface",
$isA->describe($classDescription, '')->toString()
);
}

public function test_it_should_have_violation_if_it_doesnt_implement(): void
public function test_it_should_have_violation_when_it_doesnt_implement(): void
{
$class = Banana::class;
$isA = new IsA($class);
Expand All @@ -81,19 +81,19 @@ public function test_it_should_have_violation_if_it_doesnt_implement(): void

self::assertEquals(1, $violations->count());
self::assertEquals(
"should inherit from: $class",
"Dog should be a $class",
$isA->describe($classDescription, '')->toString()
);
}
}

namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Animal;
namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Animal;

final class Dog
{
}

namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsOneOfTest\Fruit;
namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsATest\Fruit;

interface FruitInterface
{
Expand Down
112 changes: 112 additions & 0 deletions tests/Unit/Expressions/ForClasses/IsNotATest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

namespace Arkitect\Tests\Unit\Expressions\ForClasses;

use Arkitect\Analyzer\ClassDescriptionBuilder;
use Arkitect\Expression\ForClasses\IsNotA;
use Arkitect\Rules\Violations;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Animal\Dog;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Fruit\Banana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Fruit\CavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Fruit\DwarfCavendishBanana;
use Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Fruit\FruitInterface;
use PHPUnit\Framework\TestCase;

final class IsNotATest extends TestCase
{
public function test_it_should_have_no_violation_when_it_doesnt_extend(): void
{
$interface = FruitInterface::class;
$isNotA = new IsNotA($interface);
$classDescription = (new ClassDescriptionBuilder())
->setFilePath('src/Foo.php')
->setClassName(Dog::class)
->build();

$violations = new Violations();
$isNotA->evaluate($classDescription, $violations, '');

self::assertEquals(0, $violations->count());
}

public function test_it_should_have_no_violation_when_it_doesnt_implement(): void
{
$class = Banana::class;
$isNotA = new IsNotA($class);
$classDescription = (new ClassDescriptionBuilder())
->setFilePath('src/Foo.php')
->setClassName(Dog::class)
->build();

$violations = new Violations();
$isNotA->evaluate($classDescription, $violations, '');

self::assertEquals(0, $violations->count());
}

public function test_it_should_have_violation_when_it_implements(): void
{
$interface = FruitInterface::class;
$isNotA = new IsNotA($interface);
$classDescription = (new ClassDescriptionBuilder())
->setFilePath('src/Foo.php')
->setClassName(CavendishBanana::class)
->addInterface($interface, 10)
->build();

$violations = new Violations();
$isNotA->evaluate($classDescription, $violations, '');

self::assertEquals(1, $violations->count());
self::assertEquals(
"CavendishBanana should not be a $interface",
$isNotA->describe($classDescription, '')->toString()
);
}

public function test_it_should_have_violation_when_it_extends(): void
{
$class = Banana::class;
$isNotA = new IsNotA($class);
$classDescription = (new ClassDescriptionBuilder())
->setFilePath('src/Foo.php')
->setClassName(DwarfCavendishBanana::class)
->addExtends($class, 10)
->build();

$violations = new Violations();
$isNotA->evaluate($classDescription, $violations, '');

self::assertEquals(1, $violations->count());
self::assertEquals(
"DwarfCavendishBanana should not be a $class",
$isNotA->describe($classDescription, '')->toString()
);
}
}

namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Animal;

final class Dog
{
}

namespace Arkitect\Tests\Unit\Expressions\ForClasses\IsNotA\Fruit;

interface FruitInterface
{
}

class Banana implements FruitInterface
{
}

class CavendishBanana extends Banana
{
}

final class DwarfCavendishBanana extends CavendishBanana
{
}