From 4c88590b893337d2fabdf12a032f68cb8df1f288 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sat, 26 Jul 2025 07:47:00 -0600 Subject: [PATCH] feat: `not.toHaveSuspiciousCharacters` --- src/ArchPresets/Php.php | 7 +++++++ src/Expectation.php | 11 ++--------- src/Expectations/OppositeExpectation.php | 19 +++++++++++++++++++ tests/.snapshots/success.txt | 2 +- tests/Visual/Parallel.php | 2 +- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/ArchPresets/Php.php b/src/ArchPresets/Php.php index 22b409b6..b70a2a11 100644 --- a/src/ArchPresets/Php.php +++ b/src/ArchPresets/Php.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace Pest\ArchPresets; +use Pest\Arch\Contracts\ArchExpectation; +use Pest\Expectation; + /** * @internal */ @@ -89,5 +92,9 @@ final class Php extends AbstractPreset 'xdebug_var_dump', 'trap', ])->not->toBeUsed(); + + $this->eachUserNamespace( + fn (Expectation $namespace): ArchExpectation => $namespace->not->toHaveSuspiciousCharacters(), + ); } } diff --git a/src/Expectation.php b/src/Expectation.php index d885d0b1..5c8a076b 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -897,16 +897,9 @@ final class Expectation /** * Asserts that the source code of the given expectation target does not include suspicious characters. */ - public function toNotIncludeSuspiciousCharacters(): ArchExpectation + public function toHaveSuspiciousCharacters(): ArchExpectation { - $checker = new Spoofchecker(); - - return Targeted::make( - $this, - fn (ObjectDescription $object) => ! $checker->isSuspicious(file_get_contents($object->path)), - 'to not include suspicious characters', - FileLineFinder::where(fn (string $line) => $checker->isSuspicious($line)), - ); + throw InvalidExpectation::fromMethods(['toHaveSuspiciousCharacters']); } /** diff --git a/src/Expectations/OppositeExpectation.php b/src/Expectations/OppositeExpectation.php index d5c3f083..eec50c63 100644 --- a/src/Expectations/OppositeExpectation.php +++ b/src/Expectations/OppositeExpectation.php @@ -24,6 +24,7 @@ use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExpectationFailedException; use ReflectionMethod; use ReflectionProperty; +use Spoofchecker; use stdClass; /** @@ -278,6 +279,24 @@ final readonly class OppositeExpectation ); } + /** + * Asserts that the given expectation target does not have suspicious characters. + */ + public function toHaveSuspiciousCharacters(): ArchExpectation + { + $checker = new Spoofchecker; + + /** @var Expectation|string> $original */ + $original = $this->original; + + return Targeted::make( + $original, + fn (ObjectDescription $object): bool => ! $checker->isSuspicious((string) file_get_contents($object->path)), + 'to not include suspicious characters', + FileLineFinder::where(fn (string $line): bool => $checker->isSuspicious($line)), + ); + } + /** * Asserts that the given expectation target does not have the given methods. * diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 734f573b..2f4c6d14 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -1785,4 +1785,4 @@ ✓ pass with dataset with ('my-datas-set-value') ✓ within describe → pass with dataset with ('my-datas-set-value') - Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 35 skipped, 1189 passed (2815 assertions) \ No newline at end of file + Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 35 skipped, 1189 passed (2816 assertions) \ No newline at end of file diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index fb04f117..ebc5a1be 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -16,7 +16,7 @@ $run = function () { test('parallel', function () use ($run) { expect($run('--exclude-group=integration')) - ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 26 skipped, 1179 passed (2791 assertions)') + ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 26 skipped, 1179 passed (2792 assertions)') ->toContain('Parallel: 3 processes'); })->skipOnWindows();