From df7b6c8454cbd286ac5bf3dd7352e776e2645a47 Mon Sep 17 00:00:00 2001 From: SimonBroekaert Date: Fri, 22 Aug 2025 02:14:30 +0200 Subject: [PATCH 1/2] feat: add toBeCasedCorrectly arch test assertion --- src/Expectation.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Expectation.php b/src/Expectation.php index 50729d7a..3a5cc94e 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -18,6 +18,7 @@ use Pest\Arch\Expectations\ToOnlyUse; use Pest\Arch\Expectations\ToUse; use Pest\Arch\Expectations\ToUseNothing; use Pest\Arch\PendingArchExpectation; +use Pest\Arch\Support\Composer; use Pest\Arch\Support\FileLineFinder; use Pest\Concerns\Extendable; use Pest\Concerns\Pipeable; @@ -669,6 +670,41 @@ final class Expectation throw InvalidExpectation::fromMethods(['toHavePrivateMethods']); } + /** + * Asserts that the given expectation target is cased correctly. + */ + public function toBeCasedCorrectly(): ArchExpectation + { + return Targeted::make( + $this, + function (ObjectDescription $object): bool { + if (! isset($object->reflectionClass)) { + return false; + } + + $realPath = realpath($object->path); + + foreach (Composer::userNamespaces() as $directory => $namespace) { + if (str_starts_with($realPath, $directory)) { + $relativePath = substr($realPath, strlen($directory) + 1); + $relativePath = explode('.', $relativePath)[0]; + $classFromPath = $namespace . '\\' . str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath); + + if ($classFromPath === $object->reflectionClass->getName()) { + return true; + } + + return false; + } + } + + return false; + }, + "to be cased correctly", + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), + ); + } + /** * Asserts that the given expectation target is enum. */ From 1675dd1d4193b9aa5210d07ac73efeefae0ca5f6 Mon Sep 17 00:00:00 2001 From: SimonBroekaert Date: Tue, 17 Feb 2026 19:03:46 +0100 Subject: [PATCH 2/2] chore: add tests for toBeCasedCorrectly() arch test --- tests/Features/Expect/toBeCasedCorrectly.php | 12 ++++++++++++ .../CorrectCasing/CorrectCasing.php | 5 +++++ .../IncorrectCasing/incorrectCasing.php | 5 +++++ .../incorrectDirectoryCasing/CorrectCasing.php | 5 +++++ 4 files changed, 27 insertions(+) create mode 100644 tests/Features/Expect/toBeCasedCorrectly.php create mode 100644 tests/Fixtures/Arch/ToBeCasedCorrectly/CorrectCasing/CorrectCasing.php create mode 100644 tests/Fixtures/Arch/ToBeCasedCorrectly/IncorrectCasing/incorrectCasing.php create mode 100644 tests/Fixtures/Arch/ToBeCasedCorrectly/incorrectDirectoryCasing/CorrectCasing.php diff --git a/tests/Features/Expect/toBeCasedCorrectly.php b/tests/Features/Expect/toBeCasedCorrectly.php new file mode 100644 index 00000000..6a8432d2 --- /dev/null +++ b/tests/Features/Expect/toBeCasedCorrectly.php @@ -0,0 +1,12 @@ +expect('Tests\Fixtures\Arch\ToBeCasedCorrectly\CorrectCasing') + ->toBeCasedCorrectly(); + +test('failure') + ->expect('Tests\Fixtures\Arch\ToBeCasedCorrectly\IncorrectCasing') + ->toBeCasedCorrectly() + ->throws(ArchExpectationFailedException::class); diff --git a/tests/Fixtures/Arch/ToBeCasedCorrectly/CorrectCasing/CorrectCasing.php b/tests/Fixtures/Arch/ToBeCasedCorrectly/CorrectCasing/CorrectCasing.php new file mode 100644 index 00000000..8418d969 --- /dev/null +++ b/tests/Fixtures/Arch/ToBeCasedCorrectly/CorrectCasing/CorrectCasing.php @@ -0,0 +1,5 @@ +