diff --git a/src/Expectation.php b/src/Expectation.php index aaa9b83e..1bc20abd 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -833,4 +833,19 @@ final class Expectation return $this; } + + /** + * Asserts that the given expectation target to have the given attribute. + * + * @param class-string $attribute + */ + public function toHaveAttribute(string $attribute): ArchExpectation + { + return Targeted::make( + $this, + fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) !== [], + "to have attribute '{$attribute}'", + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), + ); + } } diff --git a/src/Expectations/OppositeExpectation.php b/src/Expectations/OppositeExpectation.php index e857009d..4953c1af 100644 --- a/src/Expectations/OppositeExpectation.php +++ b/src/Expectations/OppositeExpectation.php @@ -378,6 +378,21 @@ final class OppositeExpectation ); } + /** + * Asserts that the given expectation target not to have the given attribute. + * + * @param class-string $attribute + */ + public function toHaveAttribute(string $attribute): ArchExpectation + { + return Targeted::make( + $this->original, + fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) === [], + "to not have attribute '{$attribute}'", + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')) + ); + } + /** * Handle dynamic method calls into the original expectation. * diff --git a/tests/Features/Expect/toHaveAttribute.php b/tests/Features/Expect/toHaveAttribute.php new file mode 100644 index 00000000..6de6be72 --- /dev/null +++ b/tests/Features/Expect/toHaveAttribute.php @@ -0,0 +1,18 @@ +expect('Tests\\Fixtures\\Arch\\ToHaveAttribute\\HaveAttribute') + ->toHaveAttribute('Tests\\Fixtures\\Arch\\ToHaveAttribute\\Attributes\\AsAttribute'); + +test('opposite class has attribute') + ->throws(ArchExpectationFailedException::class) + ->expect('Tests\\Fixtures\\Arch\\ToHaveAttribute\\HaveAttribute') + ->not + ->toHaveAttribute('Tests\\Fixtures\\Arch\\ToHaveAttribute\\Attributes\\AsAttribute'); + +test('class not has attribute') + ->expect('Tests\\Fixtures\\Arch\\ToHaveAttribute\\NotHaveAttribute') + ->not + ->toHaveAttribute('Tests\\Fixtures\\Arch\\ToHaveAttribute\\Attributes\\AsAttribute'); diff --git a/tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php b/tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php new file mode 100644 index 00000000..d77a5bfe --- /dev/null +++ b/tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php @@ -0,0 +1,13 @@ +