diff --git a/src/Expression/ForClasses/HaveCorrespondingUnit.php b/src/Expression/ForClasses/HaveCorrespondingUnit.php new file mode 100644 index 00000000..6ac84dfb --- /dev/null +++ b/src/Expression/ForClasses/HaveCorrespondingUnit.php @@ -0,0 +1,57 @@ +inferFqnFunction = $inferFqnFunction; + } + + public function describe(ClassDescription $theClass, string $because): Description + { + $correspondingFqn = $this->inferCorrespondingFqn($theClass); + + return new Description("should have a matching unit named: '$correspondingFqn'", $because); + } + + public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void + { + $correspondingFqn = $this->inferCorrespondingFqn($theClass); + + if ( + !trait_exists($correspondingFqn) + && !class_exists($correspondingFqn) + && !interface_exists($correspondingFqn) + ) { + $violations->add( + new Violation( + $theClass->getFQCN(), + $this->describe($theClass, $because)->toString() + ) + ); + } + } + + /** + * @return class-string + */ + public function inferCorrespondingFqn(ClassDescription $theClass): string + { + $inferFqn = $this->inferFqnFunction; + + return $inferFqn($theClass->getFQCN()); + } +} diff --git a/tests/Unit/Expressions/ForClasses/DummyClasses/Cat.php b/tests/Unit/Expressions/ForClasses/DummyClasses/Cat.php new file mode 100644 index 00000000..04a0856e --- /dev/null +++ b/tests/Unit/Expressions/ForClasses/DummyClasses/Cat.php @@ -0,0 +1,9 @@ +evaluate($classDescription, $violations, $because); + + self::assertEquals(0, $violations->count()); + } + + public function test_it_should_return_violation_error(): void + { + $class = Dog::class; + $classDescription = new ClassDescription( + FullyQualifiedClassName::fromString($class), + [], + [], + null, + false, + false, + false, + false, + false + ); + $constraint = new HaveCorrespondingUnit( + function ($fqn) { + return $fqn.'TestCase'; + } + ); + + $because = 'we want all our command handlers to have a test'; + $violations = new Violations(); + $constraint->evaluate($classDescription, $violations, $because); + + self::assertNotEquals(0, $violations->count()); + + $violationError = $constraint->describe($classDescription, $because)->toString(); + $this->assertEquals( + 'should have a matching unit named: ' + ."'Arkitect\Tests\Unit\Expressions\ForClasses\DummyClasses\DogTestCase' because $because", + $violationError + ); + } +}