Skip to content

Commit

Permalink
Merge pull request #934 from hungthai1401/to_have_attribute_expectation
Browse files Browse the repository at this point in the history
[2.x] Add `toHaveAttribute` expectation
  • Loading branch information
nunomaduro authored Sep 3, 2023
2 parents 7dcd42d + e698995 commit 0fc232b
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/Expectation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Pest;

use Attribute;
use BadMethodCallException;
use Closure;
use InvalidArgumentException;
Expand Down Expand Up @@ -846,4 +847,19 @@ public function toHaveStudlyCaseKeys(string $message = ''): self

return $this;
}

/**
* Asserts that the given expectation target to have the given attribute.
*
* @param class-string<Attribute> $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')),
);
}
}
16 changes: 16 additions & 0 deletions src/Expectations/OppositeExpectation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Pest\Expectations;

use Attribute;
use Pest\Arch\Contracts\ArchExpectation;
use Pest\Arch\Expectations\Targeted;
use Pest\Arch\Expectations\ToBeUsedIn;
Expand Down Expand Up @@ -391,6 +392,21 @@ public function toBeInvokable(): ArchExpectation
);
}

/**
* Asserts that the given expectation target not to have the given attribute.
*
* @param class-string<Attribute> $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.
*
Expand Down
18 changes: 18 additions & 0 deletions tests/Features/Expect/toHaveAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use Pest\Arch\Exceptions\ArchExpectationFailedException;

test('class has attribute')
->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');
12 changes: 12 additions & 0 deletions tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures\Arch\ToHaveAttribute\Attributes;

use Attribute;

#[Attribute()]
class AsAttribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures\Arch\ToHaveAttribute\HaveAttribute;

use Tests\Fixtures\Arch\ToHaveAttribute\Attributes\AsAttribute;

#[AsAttribute]
class HaveAttributeClass
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures\Arch\ToHaveAttribute\NotHaveAttribute;

class NotHaveAttributeClass
{
}

0 comments on commit 0fc232b

Please sign in to comment.