From 678898efe73b30d22fc1a245f199d88b9058a4a2 Mon Sep 17 00:00:00 2001 From: Thai Nguyen Hung Date: Thu, 24 Aug 2023 14:26:54 +0700 Subject: [PATCH] feat: `toHaveAttribute` expectation --- src/Expectation.php | 15 +++++++++++++++ src/Expectations/OppositeExpectation.php | 15 +++++++++++++++ tests/Features/Expect/toHaveAttribute.php | 18 ++++++++++++++++++ .../ToHaveAttribute/Attributes/AsAttribute.php | 13 +++++++++++++ .../HaveAttribute/HaveAttributeClass.php | 13 +++++++++++++ .../NotHaveAttribute/NotHaveAttributeClass.php | 10 ++++++++++ 6 files changed, 84 insertions(+) create mode 100644 tests/Features/Expect/toHaveAttribute.php create mode 100644 tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php create mode 100644 tests/Fixtures/Arch/ToHaveAttribute/HaveAttribute/HaveAttributeClass.php create mode 100644 tests/Fixtures/Arch/ToHaveAttribute/NotHaveAttribute/NotHaveAttributeClass.php 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 @@ +