chore: coding style changes

This commit is contained in:
nuno maduro
2026-08-07 14:52:56 +01:00
parent eb88513baf
commit 42d9b777bf
221 changed files with 139 additions and 3086 deletions
-1
View File
@@ -111,7 +111,6 @@ $bootPest = (static function (): void {
exit; exit;
} }
// It must be a 1 byte string to ensure filesize() is equal to the number of tests executed
$exitCode = $application->runTest(realpath(trim($testPath))); $exitCode = $application->runTest(realpath(trim($testPath)));
fwrite($statusFile, (string) $exitCode); fwrite($statusFile, (string) $exitCode);
+1 -1
View File
@@ -62,7 +62,7 @@
"pestphp/pest-dev-tools": "^5.0.0", "pestphp/pest-dev-tools": "^5.0.0",
"pestphp/pest-plugin-browser": "^5.0.0", "pestphp/pest-plugin-browser": "^5.0.0",
"pestphp/pest-plugin-phpstan": "^5.0.0", "pestphp/pest-plugin-phpstan": "^5.0.0",
"pestphp/pest-plugin-rector": "^5.0.2", "pestphp/pest-plugin-rector": "^5.0.3",
"pestphp/pest-plugin-type-coverage": "^5.0.2", "pestphp/pest-plugin-type-coverage": "^5.0.2",
"psy/psysh": "^0.12.24" "psy/psysh": "^0.12.24"
}, },
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
+13 -51
View File
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -86,7 +54,7 @@ final class JunitXmlLogger
{ {
private readonly Printer $printer; private readonly Printer $printer;
private readonly Converter $converter; // pest-added private readonly Converter $converter;
private DOMDocument $document; private DOMDocument $document;
@@ -144,8 +112,7 @@ final class JunitXmlLogger
public function __construct(Printer $printer, Facade $facade) public function __construct(Printer $printer, Facade $facade)
{ {
$this->printer = $printer; $this->printer = $printer;
$this->converter = new Converter(Container::getInstance()->get(TestSuite::class)->rootPath); // pest-added $this->converter = new Converter(Container::getInstance()->get(TestSuite::class)->rootPath);
$this->registerSubscribers($facade); $this->registerSubscribers($facade);
$this->createDocument(); $this->createDocument();
} }
@@ -160,10 +127,9 @@ final class JunitXmlLogger
public function testSuiteStarted(Started $event): void public function testSuiteStarted(Started $event): void
{ {
$testSuite = $this->document->createElement('testsuite'); $testSuite = $this->document->createElement('testsuite');
$testSuite->setAttribute('name', $this->converter->getTestSuiteName($event->testSuite())); // pest-changed $testSuite->setAttribute('name', $this->converter->getTestSuiteName($event->testSuite()));
if ($event->testSuite()->isForTestClass()) { if ($event->testSuite()->isForTestClass()) {
$testSuite->setAttribute('file', $this->converter->getTestSuiteLocation($event->testSuite()) ?? ''); // pest-changed $testSuite->setAttribute('file', $this->converter->getTestSuiteLocation($event->testSuite()) ?? '');
} }
if ($this->testSuiteLevel > 0) { if ($this->testSuiteLevel > 0) {
@@ -380,12 +346,11 @@ final class JunitXmlLogger
assert($this->currentTestCase !== null); assert($this->currentTestCase !== null);
$buffer = $this->converter->getTestCaseMethodName($event->test()); // pest-changed $buffer = $this->converter->getTestCaseMethodName($event->test());
$throwable = $event->throwable(); $throwable = $event->throwable();
$buffer .= trim( $buffer .= trim(
$this->converter->getExceptionMessage($throwable).PHP_EOL. // pest-changed $this->converter->getExceptionMessage($throwable).PHP_EOL.
$this->converter->getExceptionDetails($throwable), // pest-changed $this->converter->getExceptionDetails($throwable),
); );
$fault = $this->document->createElement( $fault = $this->document->createElement(
@@ -485,18 +450,15 @@ final class JunitXmlLogger
$testCase = $this->document->createElement('testcase'); $testCase = $this->document->createElement('testcase');
$test = $event->test(); $test = $event->test();
$file = $this->converter->getTestCaseLocation($test); // pest-added $file = $this->converter->getTestCaseLocation($test);
$testCase->setAttribute('name', $this->converter->getTestCaseMethodName($test));
$testCase->setAttribute('name', $this->converter->getTestCaseMethodName($test)); // pest-changed $testCase->setAttribute('file', $file);
$testCase->setAttribute('file', $file); // pest-changed
if ($test->isTestMethod()) { if ($test->isTestMethod()) {
assert($test instanceof TestMethod); assert($test instanceof TestMethod);
// $testCase->setAttribute('line', (string) $test->line()); // pest-removed $className = $this->converter->getTrimmedTestClassName($test);
$className = $this->converter->getTrimmedTestClassName($test); // pest-added $testCase->setAttribute('class', $className);
$testCase->setAttribute('class', $className); // pest-changed $testCase->setAttribute('classname', str_replace('\\', '.', $className));
$testCase->setAttribute('classname', str_replace('\\', '.', $className)); // pest-changed
} }
$this->currentTestCase = $testCase; $this->currentTestCase = $testCase;
@@ -1,29 +1,5 @@
<?php <?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2011 Brian Scaturro
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
declare(strict_types=1); declare(strict_types=1);
namespace ParaTest\WrapperRunner; namespace ParaTest\WrapperRunner;
@@ -34,10 +10,6 @@ use function preg_match;
/** /**
* @internal * @internal
*
* This file is overridden so the "T" progress character — emitted by Pest for
* "todo" tests — is routed to the progress file next to the regular characters,
* instead of being treated as unexpected output.
*/ */
final readonly class ProgressPrinterOutput implements Printer final readonly class ProgressPrinterOutput implements Printer
{ {
@@ -48,7 +20,6 @@ final readonly class ProgressPrinterOutput implements Printer
public function print(string $buffer): void public function print(string $buffer): void
{ {
// Skip anything in \PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter::printProgress except $progress
if ( if (
$buffer === "\n" $buffer === "\n"
|| preg_match('/^ +$/', $buffer) === 1 || preg_match('/^ +$/', $buffer) === 1
+1 -38
View File
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -129,9 +97,6 @@ abstract class NameFilterIterator extends RecursiveFilterIterator
$dataSetMaximum = null; $dataSetMaximum = null;
if (@preg_match($filter, '') === false) { if (@preg_match($filter, '') === false) {
// Handles:
// * testAssertEqualsSucceeds#4
// * testAssertEqualsSucceeds#4-8
if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) {
if (isset($matches[3]) && $matches[2] < $matches[3]) { if (isset($matches[3]) && $matches[2] < $matches[3]) {
$filter = sprintf( $filter = sprintf(
@@ -148,7 +113,7 @@ abstract class NameFilterIterator extends RecursiveFilterIterator
$matches[2], $matches[2],
); );
} }
} // Handles: }
// * testDetermineJsonError@JSON_ERROR_NONE // * testDetermineJsonError@JSON_ERROR_NONE
// * testDetermineJsonError@JSON.* // * testDetermineJsonError@JSON.*
elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) {
@@ -159,8 +124,6 @@ abstract class NameFilterIterator extends RecursiveFilterIterator
); );
} }
// Escape delimiters in regular expression. Do NOT use preg_quote,
// to keep magic characters.
$filter = sprintf( $filter = sprintf(
'/%s/i', '/%s/i',
str_replace( str_replace(
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -196,9 +164,6 @@ final class DefaultResultCache implements ResultCache
); );
} }
/**
* Returns the cache version.
*/
private function cacheVersion(): string private function cacheVersion(): string
{ {
return 'pest_'.version(); return 'pest_'.version();
-32
View File
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
namespace PHPUnit\Runner; namespace PHPUnit\Runner;
-70
View File
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -256,13 +224,6 @@ final class TestSuiteSorter
return $tests; return $tests;
} }
/**
* Comparator callback function to sort tests for "reach failure as fast as possible".
*
* 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT
* 2. when tests are equally defective, sort the fastest to the front
* 3. do not reorder successful tests
*/
private function cmpDefectPriorityAndTime(Test $a, Test $b): int private function cmpDefectPriorityAndTime(Test $a, Test $b): int
{ {
assert($a instanceof Reorderable); assert($a instanceof Reorderable);
@@ -272,7 +233,6 @@ final class TestSuiteSorter
$priorityB = $this->defectSortOrder[$b->sortId()] ?? 0; $priorityB = $this->defectSortOrder[$b->sortId()] ?? 0;
if ($priorityA !== $priorityB) { if ($priorityA !== $priorityB) {
// Sort defect weight descending
return $priorityB <=> $priorityA; return $priorityB <=> $priorityA;
} }
@@ -280,13 +240,9 @@ final class TestSuiteSorter
return $this->cmpDuration($a, $b); return $this->cmpDuration($a, $b);
} }
// do not change execution order
return 0; return 0;
} }
/**
* Compares test duration for sorting tests by duration ascending.
*/
private function cmpDuration(Test $a, Test $b): int private function cmpDuration(Test $a, Test $b): int
{ {
if (! ($a instanceof Reorderable && $b instanceof Reorderable)) { if (! ($a instanceof Reorderable && $b instanceof Reorderable)) {
@@ -296,9 +252,6 @@ final class TestSuiteSorter
return $this->cache->time(ResultCacheId::fromReorderable($a)) <=> $this->cache->time(ResultCacheId::fromReorderable($b)); return $this->cache->time(ResultCacheId::fromReorderable($a)) <=> $this->cache->time(ResultCacheId::fromReorderable($b));
} }
/**
* Compares test size for sorting tests small->medium->large->unknown.
*/
private function cmpSize(Test $a, Test $b): int private function cmpSize(Test $a, Test $b): int
{ {
$sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite) $sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite)
@@ -312,30 +265,11 @@ final class TestSuiteSorter
} }
/** /**
* Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible.
* The algorithm will leave the tests in original running order when it can.
* For more details see the documentation for test dependencies.
*
* Short description of algorithm:
* 1. Pick the next Test from remaining tests to be checked for dependencies.
* 2. If the test has no dependencies: mark done, start again from the top
* 3. If the test has dependencies but none left to do: mark done, start again from the top
* 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution.
*
* @param array<TestCase> $tests * @param array<TestCase> $tests
* @return array<TestCase> * @return array<TestCase>
*/ */
private function resolveDependencies(array $tests): array private function resolveDependencies(array $tests): array
{ {
// Pest: Fast-path. If no test in this suite declares dependencies, the
// original O(N^2) algorithm is wasted work — it would splice each test
// one-by-one back into the same order. The check deliberately walks
// TestCase instances directly instead of calling TestSuite::requires(),
// because the latter lazily builds TestSuite::provides() via
// ExecutionOrderDependency::mergeUnique, which is O(N^2) in the total
// number of tests. With thousands of tests that single call alone can
// burn several seconds before the sort even begins. Reading the
// cached TestCase::$dependencies property stays O(N) and costs nothing
// when no test uses `->depends()` / PHPUnit `@depends`. // when no test uses `->depends()` / PHPUnit `@depends`.
if (! $this->anyTestHasDependencies($tests)) { if (! $this->anyTestHasDependencies($tests)) {
return $tests; return $tests;
@@ -361,10 +295,6 @@ final class TestSuiteSorter
/** /**
* Cheaply determines whether any test in the tree declares @depends. * Cheaply determines whether any test in the tree declares @depends.
* *
* Walks `TestSuite` containers recursively and inspects each `TestCase`
* directly so it never triggers `TestSuite::provides()`, which is O(N^2)
* in the total number of aggregated tests.
*
* @param iterable<Test> $tests * @param iterable<Test> $tests
*/ */
private function anyTestHasDependencies(iterable $tests): bool private function anyTestHasDependencies(iterable $tests): bool
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
@@ -51,10 +19,6 @@ use ReflectionClass;
/** /**
* @internal This class is not covered by the backward compatibility promise for PHPUnit * @internal This class is not covered by the backward compatibility promise for PHPUnit
*
* This file is overridden so PHPUnit's progress output emits a "T" before the
* regular "S" for "todo" tests — Pest's parallel result printer consumes the
* "T" and swallows the "S" that follows it.
*/ */
final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber
{ {
@@ -67,9 +31,6 @@ final readonly class TestSkippedSubscriber extends Subscriber implements Skipped
$this->printer()->testSkipped(); $this->printer()->testSkipped();
} }
/**
* Prints a "T" to the standard PHPUnit output to indicate a todo item.
*/
private function printTodoItem(): void private function printTodoItem(): void
{ {
$mirror = new ReflectionClass($this->printer()); $mirror = new ReflectionClass($this->printer());
@@ -1,37 +1,5 @@
<?php <?php
/*
* BSD 3-Clause License
*
* Copyright (c) 2001-2023, Sebastian Bergmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
declare(strict_types=1); declare(strict_types=1);
/* /*
* This file is part of PHPUnit. * This file is part of PHPUnit.
+4 -1
View File
@@ -1,5 +1,8 @@
{ {
"exclude": [ "exclude": [
"tests/Fixtures/Suites" "tests/Fixtures/Suites"
] ],
"rules": {
"Pint/phpdoc_type_annotations_only": true
}
} }
-6
View File
@@ -38,13 +38,7 @@ return RectorConfig::configure()
RemoveReturnTagIncompatibleWithNativeTypeRector::class => [ RemoveReturnTagIncompatibleWithNativeTypeRector::class => [
__DIR__.'/src/Expectations/HigherOrderExpectation.php', __DIR__.'/src/Expectations/HigherOrderExpectation.php',
], ],
// Merges unrelated expectations into a single `toMatchArray()`, turning
// `toContain()` into exact matches, dropping `->not`, and mistaking a
// `toBeTrue()` failure message for an expected value. Unsafe here.
UseToMatchArrayRector::class, UseToMatchArrayRector::class,
// Test fixtures rely on "unused" constructors, params and properties
// (resolved via the container or read through reflection), so the
// dead-code and return-type rules below must not touch the test suite.
RemoveEmptyClassMethodRector::class => [ RemoveEmptyClassMethodRector::class => [
__DIR__.'/tests', __DIR__.'/tests',
], ],
-13
View File
@@ -13,15 +13,11 @@ use Pest\Expectation;
abstract class AbstractPreset // @pest-arch-ignore-line abstract class AbstractPreset // @pest-arch-ignore-line
{ {
/** /**
* The expectations.
*
* @var array<int, Expectation<mixed>|ArchExpectation> * @var array<int, Expectation<mixed>|ArchExpectation>
*/ */
protected array $expectations = []; protected array $expectations = [];
/** /**
* Creates a new preset instance.
*
* @param array<int, string> $userNamespaces * @param array<int, string> $userNamespaces
*/ */
public function __construct( public function __construct(
@@ -31,15 +27,11 @@ abstract class AbstractPreset // @pest-arch-ignore-line
} }
/** /**
* Executes the arch preset.
*
* @internal * @internal
*/ */
abstract public function execute(): void; abstract public function execute(): void;
/** /**
* Ignores the given "targets" or "dependencies".
*
* @param array<int, string>|string $targetsOrDependencies * @param array<int, string>|string $targetsOrDependencies
*/ */
final public function ignoring(array|string $targetsOrDependencies): void final public function ignoring(array|string $targetsOrDependencies): void
@@ -51,8 +43,6 @@ abstract class AbstractPreset // @pest-arch-ignore-line
} }
/** /**
* Runs the given callback for each namespace.
*
* @param callable(Expectation<string>): ArchExpectation ...$callbacks * @param callable(Expectation<string>): ArchExpectation ...$callbacks
*/ */
final public function eachUserNamespace(callable ...$callbacks): void final public function eachUserNamespace(callable ...$callbacks): void
@@ -64,9 +54,6 @@ abstract class AbstractPreset // @pest-arch-ignore-line
} }
} }
/**
* Flushes the expectations.
*/
final public function flush(): void final public function flush(): void
{ {
$this->expectations = []; $this->expectations = [];
-8
View File
@@ -14,8 +14,6 @@ use Pest\Expectation;
final class Custom extends AbstractPreset final class Custom extends AbstractPreset
{ {
/** /**
* Creates a new preset instance.
*
* @param array<int, string> $userNamespaces * @param array<int, string> $userNamespaces
* @param Closure(array<int, string>): array<Expectation<mixed>|ArchExpectation> $execute * @param Closure(array<int, string>): array<Expectation<mixed>|ArchExpectation> $execute
*/ */
@@ -27,17 +25,11 @@ final class Custom extends AbstractPreset
parent::__construct($userNamespaces); parent::__construct($userNamespaces);
} }
/**
* Returns the name of the preset.
*/
public function name(): string public function name(): string
{ {
return $this->name; return $this->name;
} }
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->expectations = ($this->execute)($this->userNamespaces); $this->expectations = ($this->execute)($this->userNamespaces);
-3
View File
@@ -11,9 +11,6 @@ use Throwable;
*/ */
final class Laravel extends AbstractPreset final class Laravel extends AbstractPreset
{ {
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->expectations[] = expect('App\Traits') $this->expectations[] = expect('App\Traits')
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\ArchPresets;
*/ */
final class Php extends AbstractPreset final class Php extends AbstractPreset
{ {
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->expectations[] = expect([ $this->expectations[] = expect([
-3
View File
@@ -12,9 +12,6 @@ use Pest\Expectation;
*/ */
final class Relaxed extends AbstractPreset final class Relaxed extends AbstractPreset
{ {
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->eachUserNamespace( $this->eachUserNamespace(
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\ArchPresets;
*/ */
final class Security extends AbstractPreset final class Security extends AbstractPreset
{ {
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->expectations[] = expect([ $this->expectations[] = expect([
-3
View File
@@ -12,9 +12,6 @@ use Pest\Expectation;
*/ */
final class Strict extends AbstractPreset final class Strict extends AbstractPreset
{ {
/**
* Executes the arch preset.
*/
public function execute(): void public function execute(): void
{ {
$this->eachUserNamespace( $this->eachUserNamespace(
-5
View File
@@ -13,8 +13,6 @@ use PHPUnit\Util\ExcludeList;
final class BootExcludeList implements Bootstrapper final class BootExcludeList implements Bootstrapper
{ {
/** /**
* The directories to exclude.
*
* @var array<int, non-empty-string> * @var array<int, non-empty-string>
*/ */
private const array EXCLUDE_LIST = [ private const array EXCLUDE_LIST = [
@@ -25,9 +23,6 @@ final class BootExcludeList implements Bootstrapper
'stubs', 'stubs',
]; ];
/**
* Boots the "exclude list" for PHPUnit to ignore Pest files.
*/
public function boot(): void public function boot(): void
{ {
$baseDirectory = dirname(__DIR__, 2); $baseDirectory = dirname(__DIR__, 2);
-8
View File
@@ -21,8 +21,6 @@ use function Pest\testDirectory;
final class BootFiles implements Bootstrapper final class BootFiles implements Bootstrapper
{ {
/** /**
* The structure of the tests directory.
*
* @var array<int, string> * @var array<int, string>
*/ */
private const array STRUCTURE = [ private const array STRUCTURE = [
@@ -33,9 +31,6 @@ final class BootFiles implements Bootstrapper
'Pest.php', 'Pest.php',
]; ];
/**
* Boots the structure of the tests directory.
*/
public function boot(): void public function boot(): void
{ {
$rootPath = TestSuite::getInstance()->rootPath; $rootPath = TestSuite::getInstance()->rootPath;
@@ -67,9 +62,6 @@ final class BootFiles implements Bootstrapper
$this->bootDatasets($testsPath); $this->bootDatasets($testsPath);
} }
/**
* Loads, if possible, the given file.
*/
private function load(string $filename): void private function load(string $filename): void
{ {
if (! Str::endsWith($filename, '.php')) { if (! Str::endsWith($filename, '.php')) {
+1 -7
View File
@@ -14,18 +14,12 @@ use Symfony\Component\Console\Output\OutputInterface;
*/ */
final readonly class BootKernelDump implements Bootstrapper final readonly class BootKernelDump implements Bootstrapper
{ {
/**
* Creates a new Boot Kernel Dump instance.
*/
public function __construct( public function __construct(
private OutputInterface $output, private OutputInterface $output,
) { ) {
// ... //
} }
/**
* Boots the kernel dump.
*/
public function boot(): void public function boot(): void
{ {
Container::getInstance()->add(KernelDump::class, $kernelDump = new KernelDump( Container::getInstance()->add(KernelDump::class, $kernelDump = new KernelDump(
-5
View File
@@ -13,8 +13,6 @@ use Pest\Exceptions\ShouldNotHappen;
final class BootOverrides implements Bootstrapper final class BootOverrides implements Bootstrapper
{ {
/** /**
* The list of files to be overridden.
*
* @var array<int, string> * @var array<int, string>
*/ */
public const array FILES = [ public const array FILES = [
@@ -30,9 +28,6 @@ final class BootOverrides implements Bootstrapper
'Logging/JUnit/JunitXmlLogger.php', 'Logging/JUnit/JunitXmlLogger.php',
]; ];
/**
* Boots the list of files to be overridden.
*/
public function boot(): void public function boot(): void
{ {
foreach (self::FILES as $file) { foreach (self::FILES as $file) {
-8
View File
@@ -16,8 +16,6 @@ use PHPUnit\Event\Subscriber;
final readonly class BootSubscribers implements Bootstrapper final readonly class BootSubscribers implements Bootstrapper
{ {
/** /**
* The list of Subscribers.
*
* @var array<int, class-string<Subscriber>> * @var array<int, class-string<Subscriber>>
*/ */
private const array SUBSCRIBERS = [ private const array SUBSCRIBERS = [
@@ -44,16 +42,10 @@ final readonly class BootSubscribers implements Bootstrapper
Subscribers\EnsureTiaAssertionsAreRecordedOnFinished::class, Subscribers\EnsureTiaAssertionsAreRecordedOnFinished::class,
]; ];
/**
* Creates a new instance of the Boot Subscribers.
*/
public function __construct( public function __construct(
private Container $container, private Container $container,
) {} ) {}
/**
* Boots the list of Subscribers.
*/
public function boot(): void public function boot(): void
{ {
foreach (self::SUBSCRIBERS as $subscriber) { foreach (self::SUBSCRIBERS as $subscriber) {
+1 -7
View File
@@ -13,18 +13,12 @@ use Symfony\Component\Console\Output\OutputInterface;
*/ */
final readonly class BootView implements Bootstrapper final readonly class BootView implements Bootstrapper
{ {
/**
* Creates a new instance of the Boot View.
*/
public function __construct( public function __construct(
private OutputInterface $output private OutputInterface $output
) { ) {
// .. //
} }
/**
* Boots the view renderer.
*/
public function boot(): void public function boot(): void
{ {
View::renderUsing($this->output); View::renderUsing($this->output);
-12
View File
@@ -16,22 +16,13 @@ use function Termwind\renderUsing;
*/ */
final class Events final class Events
{ {
/**
* Sets the output.
*/
private static ?OutputInterface $output = null; private static ?OutputInterface $output = null;
/**
* Sets the output.
*/
public static function setOutput(OutputInterface $output): void public static function setOutput(OutputInterface $output): void
{ {
self::$output = $output; self::$output = $output;
} }
/**
* Fires before the test method description is printed.
*/
public static function beforeTestMethodDescription(TestResult $result, string $description): string public static function beforeTestMethodDescription(TestResult $result, string $description): string
{ {
if (($context = $result->context) === []) { if (($context = $result->context) === []) {
@@ -73,9 +64,6 @@ final class Events
return $description; return $description;
} }
/**
* Fires after the test method description is printed.
*/
public static function afterTestMethodDescription(TestResult $result): void public static function afterTestMethodDescription(TestResult $result): void
{ {
if (($context = $result->context) === []) { if (($context = $result->context) === []) {
-2
View File
@@ -14,8 +14,6 @@ trait Expectable
/** /**
* @template TValue * @template TValue
* *
* Creates a new Expectation.
*
* @param TValue $value * @param TValue $value
* @return Expectation<TValue> * @return Expectation<TValue>
*/ */
-7
View File
@@ -14,15 +14,11 @@ use Closure;
trait Extendable trait Extendable
{ {
/** /**
* The list of extends.
*
* @var array<string, Closure> * @var array<string, Closure>
*/ */
private static array $extends = []; private static array $extends = [];
/** /**
* Register a new extend.
*
* @param-closure-this T $extend * @param-closure-this T $extend
*/ */
public function extend(string $name, Closure $extend): void public function extend(string $name, Closure $extend): void
@@ -30,9 +26,6 @@ trait Extendable
static::$extends[$name] = $extend; static::$extends[$name] = $extend;
} }
/**
* Checks if given extend name is registered.
*/
public static function hasExtend(string $name): bool public static function hasExtend(string $name): bool
{ {
return array_key_exists($name, static::$extends); return array_key_exists($name, static::$extends);
-12
View File
@@ -9,33 +9,21 @@ namespace Pest\Concerns\Logging;
*/ */
trait WritesToConsole trait WritesToConsole
{ {
/**
* Writes the given success message to the console.
*/
private function writeSuccess(string $message): void private function writeSuccess(string $message): void
{ {
$this->writePestTestOutput($message, 'fg-green, bold', '✓'); $this->writePestTestOutput($message, 'fg-green, bold', '✓');
} }
/**
* Writes the given error message to the console.
*/
private function writeError(string $message): void private function writeError(string $message): void
{ {
$this->writePestTestOutput($message, 'fg-red, bold', ''); $this->writePestTestOutput($message, 'fg-red, bold', '');
} }
/**
* Writes the given warning message to the console.
*/
private function writeWarning(string $message): void private function writeWarning(string $message): void
{ {
$this->writePestTestOutput($message, 'fg-yellow, bold', '-'); $this->writePestTestOutput($message, 'fg-yellow, bold', '-');
} }
/**
* Writes the give message to the console.
*/
private function writePestTestOutput(string $message, string $color, string $symbol): void private function writePestTestOutput(string $message, string $color, string $symbol): void
{ {
$this->writeWithColor($color, "$symbol ", false); $this->writeWithColor($color, "$symbol ", false);
-11
View File
@@ -12,30 +12,21 @@ use Closure;
trait Pipeable trait Pipeable
{ {
/** /**
* The list of pipes.
*
* @var array<string, array<Closure(Closure, mixed ...$arguments): void>> * @var array<string, array<Closure(Closure, mixed ...$arguments): void>>
*/ */
private static array $pipes = []; private static array $pipes = [];
/** /**
* The list of interceptors.
*
* @var array<string, array<Closure(Closure, mixed ...$arguments): void>> * @var array<string, array<Closure(Closure, mixed ...$arguments): void>>
*/ */
private static array $interceptors = []; private static array $interceptors = [];
/**
* Register a pipe to be applied before an expectation is checked.
*/
public function pipe(string $name, Closure $pipe): void public function pipe(string $name, Closure $pipe): void
{ {
self::$pipes[$name][] = $pipe; self::$pipes[$name][] = $pipe;
} }
/** /**
* Register an interceptor that should replace an existing expectation.
*
* @param string|Closure(mixed $value, mixed ...$arguments):bool $filter * @param string|Closure(mixed $value, mixed ...$arguments):bool $filter
*/ */
public function intercept(string $name, string|Closure $filter, Closure $handler): void public function intercept(string $name, string|Closure $filter, Closure $handler): void
@@ -60,8 +51,6 @@ trait Pipeable
} }
/** /**
* Get the list of pipes by the given name.
*
* @return array<int, Closure> * @return array<int, Closure>
*/ */
private function pipes(string $name, object $context, string $scope): array private function pipes(string $name, object $context, string $scope): array
-2
View File
@@ -11,8 +11,6 @@ trait Retrievable
{ {
/** /**
* @template TRetrievableValue * @template TRetrievableValue
*
* Safely retrieve the value at the given key from an object or array.
* @template TRetrievableValue * @template TRetrievableValue
* *
* @param array<string, TRetrievableValue>|object $value * @param array<string, TRetrievableValue>|object $value
-114
View File
@@ -37,105 +37,53 @@ use Throwable;
*/ */
trait Testable trait Testable
{ {
/**
* The test's description.
*/
private string $__description; private string $__description;
/**
* The test's latest description.
*/
private static string $__latestDescription; private static string $__latestDescription;
/**
* The test's assignees.
*/
private static array $__latestAssignees = []; private static array $__latestAssignees = [];
/**
* The test's notes.
*/
private static array $__latestNotes = []; private static array $__latestNotes = [];
/** /**
* The test's issues.
*
* @var array<int, int> * @var array<int, int>
*/ */
private static array $__latestIssues = []; private static array $__latestIssues = [];
/** /**
* The test's PRs.
*
* @var array<int, int> * @var array<int, int>
*/ */
private static array $__latestPrs = []; private static array $__latestPrs = [];
/** /**
* The test's describing, if any.
*
* @var array<int, string> * @var array<int, string>
*/ */
public array $__describing = []; public array $__describing = [];
/**
* Whether the test has ran or not.
*/
public bool $__ran = false; public bool $__ran = false;
/**
* The active replay mode for this test, set in `setUp()` and checked
* in `__runTest()` / `tearDown()` to skip the body and after-each.
*/
private ReplayType $__replay = ReplayType::None; private ReplayType $__replay = ReplayType::None;
/**
* The cached assertion count to replay, captured when entering replay mode.
*/
private int $__replayAssertions = 0; private int $__replayAssertions = 0;
/**
* The test's test closure.
*/
private Closure $__test; private Closure $__test;
/**
* The test's before each closure.
*/
private ?Closure $__beforeEach = null; private ?Closure $__beforeEach = null;
/**
* The test's after each closure.
*/
private ?Closure $__afterEach = null; private ?Closure $__afterEach = null;
/**
* The test's before all closure.
*/
private static ?Closure $__beforeAll = null; private static ?Closure $__beforeAll = null;
/**
* The test's after all closure.
*/
private static ?Closure $__afterAll = null; private static ?Closure $__afterAll = null;
/**
* The list of snapshot changes, if any.
*/
private array $__snapshotChanges = []; private array $__snapshotChanges = [];
/**
* Resets the test case static properties.
*/
public static function flush(): void public static function flush(): void
{ {
self::$__beforeAll = null; self::$__beforeAll = null;
self::$__afterAll = null; self::$__afterAll = null;
} }
/**
* Adds a new "note" to the Test Case.
*/
public function note(array|string $note): self public function note(array|string $note): self
{ {
$note = is_array($note) ? $note : [$note]; $note = is_array($note) ? $note : [$note];
@@ -145,9 +93,6 @@ trait Testable
return $this; return $this;
} }
/**
* Adds a new "setUpBeforeClass" to the Test Case.
*/
public function __addBeforeAll(?Closure $hook): void public function __addBeforeAll(?Closure $hook): void
{ {
if (! $hook instanceof Closure) { if (! $hook instanceof Closure) {
@@ -159,9 +104,6 @@ trait Testable
: $hook; : $hook;
} }
/**
* Adds a new "tearDownAfterClass" to the Test Case.
*/
public function __addAfterAll(?Closure $hook): void public function __addAfterAll(?Closure $hook): void
{ {
if (! $hook instanceof Closure) { if (! $hook instanceof Closure) {
@@ -173,25 +115,16 @@ trait Testable
: $hook; : $hook;
} }
/**
* Adds a new "setUp" to the Test Case.
*/
public function __addBeforeEach(?Closure $hook): void public function __addBeforeEach(?Closure $hook): void
{ {
$this->__addHook('__beforeEach', $hook); $this->__addHook('__beforeEach', $hook);
} }
/**
* Adds a new "tearDown" to the Test Case.
*/
public function __addAfterEach(?Closure $hook): void public function __addAfterEach(?Closure $hook): void
{ {
$this->__addHook('__afterEach', $hook); $this->__addHook('__afterEach', $hook);
} }
/**
* Adds a new "hook" to the Test Case.
*/
private function __addHook(string $property, ?Closure $hook): void private function __addHook(string $property, ?Closure $hook): void
{ {
if (! $hook instanceof Closure) { if (! $hook instanceof Closure) {
@@ -203,9 +136,6 @@ trait Testable
: $hook; : $hook;
} }
/**
* This method is called before the first test of this Test Case is run.
*/
public static function setUpBeforeClass(): void public static function setUpBeforeClass(): void
{ {
parent::setUpBeforeClass(); parent::setUpBeforeClass();
@@ -223,9 +153,6 @@ trait Testable
} }
} }
/**
* This method is called after the last test of this Test Case is run.
*/
public static function tearDownAfterClass(): void public static function tearDownAfterClass(): void
{ {
$afterAll = TestSuite::getInstance()->afterAll->get(self::$__filename); $afterAll = TestSuite::getInstance()->afterAll->get(self::$__filename);
@@ -239,9 +166,6 @@ trait Testable
parent::tearDownAfterClass(); parent::tearDownAfterClass();
} }
/**
* Gets executed before the Test Case.
*/
protected function setUp(...$arguments): void protected function setUp(...$arguments): void
{ {
TestSuite::getInstance()->test = $this; TestSuite::getInstance()->test = $this;
@@ -325,12 +249,8 @@ trait Testable
$this->__ran = true; $this->__ran = true;
} }
/**
* Initialize test case properties from TestSuite.
*/
public function __initializeTestCase(): void public function __initializeTestCase(): void
{ {
// Return if the test case has already been initialized
if (isset($this->__test)) { if (isset($this->__test)) {
return; return;
} }
@@ -352,9 +272,6 @@ trait Testable
} }
} }
/**
* Gets executed after the Test Case.
*/
protected function tearDown(...$arguments): void protected function tearDown(...$arguments): void
{ {
if ($this->__replay !== ReplayType::None) { if ($this->__replay !== ReplayType::None) {
@@ -382,8 +299,6 @@ trait Testable
} }
/** /**
* Executes the Test Case current test.
*
* @throws Throwable * @throws Throwable
*/ */
private function __runTest(Closure $closure, ...$args): mixed private function __runTest(Closure $closure, ...$args): mixed
@@ -454,9 +369,6 @@ trait Testable
throw $lastException; throw $lastException;
} }
/**
* Determines if the given exception matches PHPUnit's expected exception.
*/
private function __isExpectedException(Throwable $e): bool private function __isExpectedException(Throwable $e): bool
{ {
$expectation = Closure::bind(fn () => $this->exceptionExpectation, $this, TestCase::class)(); $expectation = Closure::bind(fn () => $this->exceptionExpectation, $this, TestCase::class)();
@@ -491,8 +403,6 @@ trait Testable
} }
/** /**
* Resolve the passed arguments. Any Closures will be bound to the testcase and resolved.
*
* @throws Throwable * @throws Throwable
*/ */
private function __resolveTestArguments(array $arguments): array private function __resolveTestArguments(array $arguments): array
@@ -500,10 +410,6 @@ trait Testable
$method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name()); $method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());
if ($method->repetitions > 1) { if ($method->repetitions > 1) {
// If the test is repeated, the first argument is the iteration number
// we need to move it to the end of the arguments list
// so that the datasets are the first n arguments
// and the iteration number is the last argument
$firstArgument = array_shift($arguments); $firstArgument = array_shift($arguments);
$arguments[] = $firstArgument; $arguments[] = $firstArgument;
} }
@@ -552,8 +458,6 @@ trait Testable
} }
/** /**
* Ensures dataset items count matches underlying test case required parameters
*
* @throws ReflectionException * @throws ReflectionException
* @throws DatasetArgumentsMismatch * @throws DatasetArgumentsMismatch
*/ */
@@ -593,9 +497,6 @@ trait Testable
return ExceptionTrace::ensure(fn (): mixed => call_user_func_array(Closure::bind($closure, $this, $this::class), $arguments)); return ExceptionTrace::ensure(fn (): mixed => call_user_func_array(Closure::bind($closure, $this, $this::class), $arguments));
} }
/**
* Uses the given preset on the test.
*/
public function preset(): Preset public function preset(): Preset
{ {
return new Preset; return new Preset;
@@ -611,33 +512,21 @@ trait Testable
$this->markTestIncomplete(implode('. ', $this->__snapshotChanges)); $this->markTestIncomplete(implode('. ', $this->__snapshotChanges));
} }
/**
* The printable test case name.
*/
public static function getPrintableTestCaseName(): string public static function getPrintableTestCaseName(): string
{ {
return preg_replace('/P\\\/', '', self::class, 1); return preg_replace('/P\\\/', '', self::class, 1);
} }
/**
* The printable test case method name.
*/
public function getPrintableTestCaseMethodName(): string public function getPrintableTestCaseMethodName(): string
{ {
return $this->__description; return $this->__description;
} }
/**
* The latest printable test case method name.
*/
public static function getLatestPrintableTestCaseMethodName(): string public static function getLatestPrintableTestCaseMethodName(): string
{ {
return self::$__latestDescription ?? ''; return self::$__latestDescription ?? '';
} }
/**
* The printable test case method context.
*/
public static function getPrintableContext(): array public static function getPrintableContext(): array
{ {
return [ return [
@@ -648,9 +537,6 @@ trait Testable
]; ];
} }
/**
* Opens a shell for the test case.
*/
public function shell(): void public function shell(): void
{ {
Shell::open(); Shell::open();
-47
View File
@@ -14,31 +14,19 @@ use Pest\PendingCalls\UsesCall;
*/ */
final readonly class Configuration final readonly class Configuration
{ {
/**
* The filename of the configuration.
*/
private string $filename; private string $filename;
/**
* Creates a new configuration instance.
*/
public function __construct( public function __construct(
string $filename, string $filename,
) { ) {
$this->filename = str_ends_with($filename, DIRECTORY_SEPARATOR.'Pest.php') ? dirname($filename) : $filename; $this->filename = str_ends_with($filename, DIRECTORY_SEPARATOR.'Pest.php') ? dirname($filename) : $filename;
} }
/**
* Use the given classes and traits in the given targets.
*/
public function in(string ...$targets): UsesCall public function in(string ...$targets): UsesCall
{ {
return new UsesCall($this->filename, [])->in(...$targets); return new UsesCall($this->filename, [])->in(...$targets);
} }
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function extend(string ...$classAndTraits): UsesCall public function extend(string ...$classAndTraits): UsesCall
{ {
return new UsesCall( return new UsesCall(
@@ -47,97 +35,62 @@ final readonly class Configuration
); );
} }
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function extends(string ...$classAndTraits): UsesCall public function extends(string ...$classAndTraits): UsesCall
{ {
return $this->extend(...$classAndTraits); return $this->extend(...$classAndTraits);
} }
/**
* Depending on where is called, it will add the given groups globally or locally.
*/
public function group(string ...$groups): UsesCall public function group(string ...$groups): UsesCall
{ {
return new UsesCall($this->filename, [])->group(...$groups); return new UsesCall($this->filename, [])->group(...$groups);
} }
/**
* Marks all tests in the current file to be run exclusively.
*/
public function only(): void public function only(): void
{ {
new BeforeEachCall(TestSuite::getInstance(), $this->filename)->only(); new BeforeEachCall(TestSuite::getInstance(), $this->filename)->only();
} }
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function use(string ...$classAndTraits): UsesCall public function use(string ...$classAndTraits): UsesCall
{ {
return $this->extend(...$classAndTraits); return $this->extend(...$classAndTraits);
} }
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function uses(string ...$classAndTraits): UsesCall public function uses(string ...$classAndTraits): UsesCall
{ {
return $this->extends(...$classAndTraits); return $this->extends(...$classAndTraits);
} }
/**
* Gets the printer configuration.
*/
public function printer(): Configuration\Printer public function printer(): Configuration\Printer
{ {
return new Configuration\Printer; return new Configuration\Printer;
} }
/**
* Gets the presets configuration.
*/
public function presets(): Configuration\Presets public function presets(): Configuration\Presets
{ {
return new Configuration\Presets; return new Configuration\Presets;
} }
/**
* Gets the project configuration.
*/
public function project(): Configuration\Project public function project(): Configuration\Project
{ {
return Configuration\Project::getInstance(); return Configuration\Project::getInstance();
} }
/**
* Gets the browser configuration.
*/
public function browser(): Browser\Configuration public function browser(): Browser\Configuration
{ {
return new Browser\Configuration; return new Browser\Configuration;
} }
/**
* Gets the evals configuration.
*/
public function evals(): Evals\Configuration // @phpstan-ignore-line public function evals(): Evals\Configuration // @phpstan-ignore-line
{ {
return new Evals\Configuration; // @phpstan-ignore-line return new Evals\Configuration; // @phpstan-ignore-line
} }
/**
* Gets the TIA (Test Impact Analysis) configuration.
*/
public function tia(): Plugins\Tia\Configuration public function tia(): Plugins\Tia\Configuration
{ {
return new Plugins\Tia\Configuration; return new Plugins\Tia\Configuration;
} }
/** /**
* Proxies calls to the uses method.
*
* @param array<array-key, mixed> $arguments * @param array<array-key, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): mixed public function __call(string $name, array $arguments): mixed
-3
View File
@@ -9,9 +9,6 @@ use Pest\Preset;
final class Presets final class Presets
{ {
/**
* Creates a custom preset instance, and adds it to the list of presets.
*/
public function custom(string $name, Closure $execute): void public function custom(string $name, Closure $execute): void
{ {
Preset::custom($name, $execute); Preset::custom($name, $execute);
-3
View File
@@ -11,9 +11,6 @@ use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
*/ */
final readonly class Printer final readonly class Printer
{ {
/**
* Sets the theme to compact.
*/
public function compact(): self public function compact(): self
{ {
DefaultPrinter::compact(true); DefaultPrinter::compact(true);
-28
View File
@@ -10,42 +10,27 @@ namespace Pest\Configuration;
final class Project final class Project
{ {
/** /**
* The assignees link.
*
* @internal * @internal
*/ */
public string $assignees = ''; public string $assignees = '';
/** /**
* The issues link.
*
* @internal * @internal
*/ */
public string $issues = ''; public string $issues = '';
/** /**
* The PRs link.
*
* @internal * @internal
*/ */
public string $prs = ''; public string $prs = '';
/**
* The singleton instance.
*/
private static ?self $instance = null; private static ?self $instance = null;
/**
* Creates a new instance of the project.
*/
public static function getInstance(): self public static function getInstance(): self
{ {
return self::$instance ??= new self; return self::$instance ??= new self;
} }
/**
* Sets the test project to GitHub.
*/
public function github(string $project): self public function github(string $project): self
{ {
$this->issues = "https://github.com/{$project}/issues/%s"; $this->issues = "https://github.com/{$project}/issues/%s";
@@ -56,12 +41,8 @@ final class Project
return $this; return $this;
} }
/**
* Sets the test project to GitLab.
*/
public function gitlab(string $project, string $hostname = 'gitlab.com'): self public function gitlab(string $project, string $hostname = 'gitlab.com'): self
{ {
// Simple way to ensure only the host is used
$hostname = parse_url($hostname, PHP_URL_HOST) ?? $hostname; $hostname = parse_url($hostname, PHP_URL_HOST) ?? $hostname;
$this->issues = "https://{$hostname}/{$project}/-/work_items/%s"; $this->issues = "https://{$hostname}/{$project}/-/work_items/%s";
@@ -72,9 +53,6 @@ final class Project
return $this; return $this;
} }
/**
* Sets the test project to Bitbucket.
*/
public function bitbucket(string $project): self public function bitbucket(string $project): self
{ {
$this->issues = "https://bitbucket.org/{$project}/issues/%s"; $this->issues = "https://bitbucket.org/{$project}/issues/%s";
@@ -85,9 +63,6 @@ final class Project
return $this; return $this;
} }
/**
* Sets the test project to Jira.
*/
public function jira(string $namespace, string $project): self public function jira(string $namespace, string $project): self
{ {
$this->issues = "https://{$namespace}.atlassian.net/browse/{$project}-%s"; $this->issues = "https://{$namespace}.atlassian.net/browse/{$project}-%s";
@@ -97,9 +72,6 @@ final class Project
return $this; return $this;
} }
/**
* Sets the test project to custom.
*/
public function custom(string $issues, string $prs, string $assignees): self public function custom(string $issues, string $prs, string $assignees): self
{ {
$this->issues = $issues; $this->issues = $issues;
+1 -9
View File
@@ -12,8 +12,6 @@ use Symfony\Component\Console\Output\OutputInterface;
final readonly class Help final readonly class Help
{ {
/** /**
* The Command messages.
*
* @var array<int, string> * @var array<int, string>
*/ */
private const array HELP_MESSAGES = [ private const array HELP_MESSAGES = [
@@ -24,17 +22,11 @@ final readonly class Help
' <info>--group=<fg=cyan><name></></info> Only runs tests from the specified group(s)', ' <info>--group=<fg=cyan><name></></info> Only runs tests from the specified group(s)',
]; ];
/**
* Creates a new Console Command instance.
*/
public function __construct(private OutputInterface $output) public function __construct(private OutputInterface $output)
{ {
// .. //
} }
/**
* Executes the Console Command.
*/
public function __invoke(): void public function __invoke(): void
{ {
foreach (self::HELP_MESSAGES as $message) { foreach (self::HELP_MESSAGES as $message) {
+1 -9
View File
@@ -18,8 +18,6 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
final readonly class Thanks final readonly class Thanks
{ {
/** /**
* The support options.
*
* @var array<string, string> * @var array<string, string>
*/ */
private const array FUNDING_MESSAGES = [ private const array FUNDING_MESSAGES = [
@@ -33,19 +31,13 @@ final readonly class Thanks
'Sponsor' => 'https://github.com/sponsors/nunomaduro', 'Sponsor' => 'https://github.com/sponsors/nunomaduro',
]; ];
/**
* Creates a new Console Command instance.
*/
public function __construct( public function __construct(
private InputInterface $input, private InputInterface $input,
private OutputInterface $output private OutputInterface $output
) { ) {
// .. //
} }
/**
* Executes the Console Command.
*/
public function __invoke(): void public function __invoke(): void
{ {
$bootstrapper = new BootView($this->output); $bootstrapper = new BootView($this->output);
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts;
*/ */
interface Bootstrapper interface Bootstrapper
{ {
/**
* Boots the bootstrapper.
*/
public function boot(): void; public function boot(): void;
} }
+1 -1
View File
@@ -11,5 +11,5 @@ use NunoMaduro\Collision\Contracts\Adapters\Phpunit\HasPrintableTestCaseName as
*/ */
interface HasPrintableTestCaseName extends BaseHasPrintableTestCaseName interface HasPrintableTestCaseName extends BaseHasPrintableTestCaseName
{ {
// .. //
} }
-6
View File
@@ -11,13 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface;
*/ */
interface Panicable interface Panicable
{ {
/**
* Renders the panic on the given output.
*/
public function render(OutputInterface $output): void; public function render(OutputInterface $output): void;
/**
* The exit code to be used.
*/
public function exitCode(): int; public function exitCode(): int;
} }
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/ */
interface AddsOutput interface AddsOutput
{ {
/**
* Adds output after the Test Suite execution.
*/
public function addOutput(int $exitCode): int; public function addOutput(int $exitCode): int;
} }
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/ */
interface Bootable interface Bootable
{ {
/**
* Boots the plugin.
*/
public function boot(): void; public function boot(): void;
} }
@@ -10,8 +10,6 @@ namespace Pest\Contracts\Plugins;
interface HandlesArguments interface HandlesArguments
{ {
/** /**
* Adds arguments before the Test Suite execution.
*
* @param array<int, string> $arguments * @param array<int, string> $arguments
* @return array<int, string> * @return array<int, string>
*/ */
@@ -10,8 +10,6 @@ namespace Pest\Contracts\Plugins;
interface HandlesOriginalArguments interface HandlesOriginalArguments
{ {
/** /**
* Adds original arguments before the Test Suite execution.
*
* @param array<int, string> $arguments * @param array<int, string> $arguments
*/ */
public function handleOriginalArguments(array $arguments): void; public function handleOriginalArguments(array $arguments): void;
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/ */
interface Terminable interface Terminable
{ {
/**
* Terminates the plugin.
*/
public function terminate(): void; public function terminate(): void;
} }
-3
View File
@@ -6,8 +6,5 @@ namespace Pest\Contracts;
interface TestCaseFilter interface TestCaseFilter
{ {
/**
* Whether the test case is accepted.
*/
public function accept(string $testCaseFilename): bool; public function accept(string $testCaseFilename): bool;
} }
-3
View File
@@ -8,8 +8,5 @@ use Pest\Factories\TestCaseMethodFactory;
interface TestCaseMethodFilter interface TestCaseMethodFilter
{ {
/**
* Whether the test case method is accepted.
*/
public function accept(TestCaseMethodFactory $factory): bool; public function accept(TestCaseMethodFactory $factory): bool;
} }
-2
View File
@@ -12,8 +12,6 @@ use Pest\Factories\Attribute;
final class Attributes final class Attributes
{ {
/** /**
* Evaluates the given attributes and returns the code.
*
* @param iterable<int, Attribute> $attributes * @param iterable<int, Attribute> $attributes
*/ */
public static function code(iterable $attributes): string public static function code(iterable $attributes): string
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class AfterAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class AfterAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct(sprintf('The afterAll already exists in the filename [%s].', $filename)); parent::__construct(sprintf('The afterAll already exists in the filename [%s].', $filename));
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class AfterAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class AfterAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct(sprintf('The afterAll method can not be used within describe functions. Filename [%s].', $filename)); parent::__construct(sprintf('The afterAll method can not be used within describe functions. Filename [%s].', $filename));
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class AfterBeforeTestFunction extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class AfterBeforeTestFunction extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct('After method cannot be used with before the [test|it] functions in the filename ['.$filename.'].'); parent::__construct('After method cannot be used with before the [test|it] functions in the filename ['.$filename.'].');
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class BeforeAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class BeforeAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct(sprintf('The beforeAll already exists in the filename [%s].', $filename)); parent::__construct(sprintf('The beforeAll already exists in the filename [%s].', $filename));
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class BeforeAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class BeforeAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct(sprintf('The beforeAll method can not be used within describe functions. Filename [%s].', $filename)); parent::__construct(sprintf('The beforeAll method can not be used within describe functions. Filename [%s].', $filename));
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class DatasetAlreadyExists extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class DatasetAlreadyExists extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $name, string $scope) public function __construct(string $name, string $scope)
{ {
parent::__construct(sprintf('A dataset with the name [%s] already exists in scope [%s].', $name, $scope)); parent::__construct(sprintf('A dataset with the name [%s] already exists in scope [%s].', $name, $scope));
@@ -16,6 +16,4 @@ final class DatasetArgumentsMismatch extends Exception
parent::__construct(sprintf('Test expects %d arguments but dataset only provides %d', $requiredCount, $suppliedCount)); parent::__construct(sprintf('Test expects %d arguments but dataset only provides %d', $requiredCount, $suppliedCount));
} }
} }
//
} }
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class DatasetDoesNotExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class DatasetDoesNotExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $name) public function __construct(string $name)
{ {
parent::__construct(sprintf("A dataset with the name [%s] does not exist. You can create it using `dataset('%s', ['a', 'b']);`.", $name, $name)); parent::__construct(sprintf("A dataset with the name [%s] does not exist. You can create it using `dataset('%s', ['a', 'b']);`.", $name, $name));
-2
View File
@@ -15,8 +15,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
final class DatasetMissing extends BadFunctionCallException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class DatasetMissing extends BadFunctionCallException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/** /**
* Creates a new Exception instance.
*
* @param array<string, string> $arguments * @param array<string, string> $arguments
*/ */
public function __construct(string $file, string $name, array $arguments) public function __construct(string $file, string $name, array $arguments)
-3
View File
@@ -11,9 +11,6 @@ use Exception;
*/ */
final class ExpectationNotFound extends Exception final class ExpectationNotFound extends Exception
{ {
/**
* Creates a new ExpectationNotFound instance from the given name.
*/
public static function fromName(string $name): ExpectationNotFound public static function fromName(string $name): ExpectationNotFound
{ {
return new self("Expectation [$name] does not exist."); return new self("Expectation [$name] does not exist.");
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class FileOrFolderNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class FileOrFolderNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $filename) public function __construct(string $filename)
{ {
parent::__construct(sprintf('The file or folder with the name [%s] could not be found.', $filename)); parent::__construct(sprintf('The file or folder with the name [%s] could not be found.', $filename));
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $message) public function __construct(string $message)
{ {
parent::__construct($message, 1); parent::__construct($message, 1);
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class InvalidOption extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class InvalidOption extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $message) public function __construct(string $message)
{ {
parent::__construct($message, 1); parent::__construct($message, 1);
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class InvalidPestCommand extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class InvalidPestCommand extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct() public function __construct()
{ {
parent::__construct('Please run [./vendor/bin/pest] instead.'); parent::__construct('Please run [./vendor/bin/pest] instead.');
-6
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class InvalidTestClassName extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class InvalidTestClassName extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance for the given class name.
*/
public static function fromClassName(string $filename, string $className): self public static function fromClassName(string $filename, string $className): self
{ {
return new self(sprintf( return new self(sprintf(
@@ -26,9 +23,6 @@ final class InvalidTestClassName extends InvalidArgumentException implements Exc
)); ));
} }
/**
* Creates a new Exception instance for the given namespace.
*/
public static function fromNamespace(string $filename, string $namespace, string $part): self public static function fromNamespace(string $filename, string $namespace, string $part): self
{ {
return new self(sprintf( return new self(sprintf(
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class MissingDependency extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class MissingDependency extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $feature, string $dependency) public function __construct(string $feature, string $dependency)
{ {
parent::__construct(sprintf('The feature [%s] requires [%s].', $feature, $dependency)); parent::__construct(sprintf('The feature [%s] requires [%s].', $feature, $dependency));
-6
View File
@@ -16,9 +16,6 @@ use Symfony\Component\Console\Output\OutputInterface;
*/ */
final class NoDirtyTestsFound extends InvalidArgumentException implements ExceptionInterface, Panicable, RenderlessEditor, RenderlessTrace final class NoDirtyTestsFound extends InvalidArgumentException implements ExceptionInterface, Panicable, RenderlessEditor, RenderlessTrace
{ {
/**
* Renders the panic on the given output.
*/
public function render(OutputInterface $output): void public function render(OutputInterface $output): void
{ {
$output->writeln([ $output->writeln([
@@ -28,9 +25,6 @@ final class NoDirtyTestsFound extends InvalidArgumentException implements Except
]); ]);
} }
/**
* The exit code to be used.
*/
public function exitCode(): int public function exitCode(): int
{ {
return 0; return 0;
-6
View File
@@ -12,9 +12,6 @@ use RuntimeException;
*/ */
final class ShouldNotHappen extends RuntimeException final class ShouldNotHappen extends RuntimeException
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(Exception $exception) public function __construct(Exception $exception)
{ {
$message = $exception->getMessage(); $message = $exception->getMessage();
@@ -29,9 +26,6 @@ EOF
, $message, phpversion(), PHP_OS), 1, $exception); , $message, phpversion(), PHP_OS), 1, $exception);
} }
/**
* Creates a new instance of should not happen without a specific exception.
*/
public static function fromMessage(string $message): ShouldNotHappen public static function fromMessage(string $message): ShouldNotHappen
{ {
return new ShouldNotHappen(new Exception($message)); return new ShouldNotHappen(new Exception($message));
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class TestAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class TestAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $fileName, string $description) public function __construct(string $fileName, string $description)
{ {
parent::__construct(sprintf('A test with the description [%s] already exists in the filename [%s].', $description, $fileName)); parent::__construct(sprintf('A test with the description [%s] already exists in the filename [%s].', $description, $fileName));
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class TestCaseAlreadyInUse extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class TestCaseAlreadyInUse extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $inUse, string $newOne, string $folder) public function __construct(string $inUse, string $newOne, string $folder)
{ {
parent::__construct(sprintf( parent::__construct(sprintf(
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class TestCaseClassOrTraitNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class TestCaseClassOrTraitNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $testCaseClass) public function __construct(string $testCaseClass)
{ {
parent::__construct(sprintf('The class [%s] was not found.', $testCaseClass)); parent::__construct(sprintf('The class [%s] was not found.', $testCaseClass));
@@ -15,9 +15,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class TestClosureMustNotBeStatic extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class TestClosureMustNotBeStatic extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(TestCaseMethodFactory $method) public function __construct(TestCaseMethodFactory $method)
{ {
parent::__construct( parent::__construct(
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/ */
final class TestDescriptionMissing extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace final class TestDescriptionMissing extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{ {
/**
* Creates a new Exception instance.
*/
public function __construct(string $fileName) public function __construct(string $fileName)
{ {
parent::__construct(sprintf('Test description is missing in the filename [%s].', $fileName)); parent::__construct(sprintf('Test description is missing in the filename [%s].', $fileName));
+1 -198
View File
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Pest; namespace Pest;
use Attribute;
use BadMethodCallException; use BadMethodCallException;
use Closure; use Closure;
use InvalidArgumentException; use InvalidArgumentException;
@@ -60,19 +59,15 @@ final class Expectation
use Retrievable; use Retrievable;
/** /**
* Creates a new expectation.
*
* @param TValue $value * @param TValue $value
*/ */
public function __construct( public function __construct(
public mixed $value public mixed $value
) { ) {
// .. //
} }
/** /**
* Creates a new expectation.
*
* @template TAndValue * @template TAndValue
* *
* @param TAndValue $value * @param TAndValue $value
@@ -84,8 +79,6 @@ final class Expectation
} }
/** /**
* Creates a new expectation with the decoded JSON value.
*
* @return self<array<int|string, mixed>|bool> * @return self<array<int|string, mixed>|bool>
*/ */
public function json(): Expectation public function json(): Expectation
@@ -103,8 +96,6 @@ final class Expectation
} }
/** /**
* Dump the expectation value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function dump(mixed ...$arguments): self public function dump(mixed ...$arguments): self
@@ -118,9 +109,6 @@ final class Expectation
return $this; return $this;
} }
/**
* Dump the expectation value and end the script.
*/
public function dd(mixed ...$arguments): never public function dd(mixed ...$arguments): never
{ {
if (function_exists('dd')) { if (function_exists('dd')) {
@@ -141,8 +129,6 @@ final class Expectation
} }
/** /**
* Dump the expectation value when the result of the condition is truthy.
*
* @param (Closure(TValue): bool)|bool $condition * @param (Closure(TValue): bool)|bool $condition
* @return self<TValue> * @return self<TValue>
*/ */
@@ -158,8 +144,6 @@ final class Expectation
} }
/** /**
* Dump the expectation value when the result of the condition is falsy.
*
* @param (Closure(TValue): bool)|bool $condition * @param (Closure(TValue): bool)|bool $condition
* @return self<TValue> * @return self<TValue>
*/ */
@@ -175,8 +159,6 @@ final class Expectation
} }
/** /**
* Send the expectation value to Ray along with all given arguments.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function ray(mixed ...$arguments): self public function ray(mixed ...$arguments): self
@@ -189,8 +171,6 @@ final class Expectation
} }
/** /**
* Creates the opposite expectation for the value.
*
* @return OppositeExpectation<TValue> * @return OppositeExpectation<TValue>
*/ */
public function not(): OppositeExpectation public function not(): OppositeExpectation
@@ -199,8 +179,6 @@ final class Expectation
} }
/** /**
* Creates an expectation on each item of the iterable "value".
*
* @return EachExpectation<TValue> * @return EachExpectation<TValue>
*/ */
public function each(?callable $callback = null): EachExpectation public function each(?callable $callback = null): EachExpectation
@@ -219,8 +197,6 @@ final class Expectation
} }
/** /**
* Allows you to specify a sequential set of expectations for each item in a iterable "value".
*
* @template TSequenceValue * @template TSequenceValue
* *
* @param (callable(self<TValue>, self<string|int>): void)|TSequenceValue ...$callbacks * @param (callable(self<TValue>, self<string|int>): void)|TSequenceValue ...$callbacks
@@ -258,8 +234,6 @@ final class Expectation
} }
/** /**
* If the subject matches one of the given "expressions", the expression callback will run.
*
* @template TMatchSubject of array-key * @template TMatchSubject of array-key
* *
* @param (callable(): TMatchSubject)|TMatchSubject $subject * @param (callable(): TMatchSubject)|TMatchSubject $subject
@@ -298,8 +272,6 @@ final class Expectation
} }
/** /**
* Apply the callback if the given "condition" is falsy.
*
* @param (callable(): bool)|bool $condition * @param (callable(): bool)|bool $condition
* @param callable(Expectation<TValue>): mixed $callback * @param callable(Expectation<TValue>): mixed $callback
* @return self<TValue> * @return self<TValue>
@@ -314,8 +286,6 @@ final class Expectation
} }
/** /**
* Apply the callback if the given "condition" is truthy.
*
* @param (callable(): bool)|bool $condition * @param (callable(): bool)|bool $condition
* @param callable(self<TValue>): mixed $callback * @param callable(self<TValue>): mixed $callback
* @return self<TValue> * @return self<TValue>
@@ -334,8 +304,6 @@ final class Expectation
} }
/** /**
* Dynamically calls methods on the class or creates a new higher order expectation.
*
* @param array<int, mixed> $parameters * @param array<int, mixed> $parameters
* @return Expectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue> * @return Expectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue>
*/ */
@@ -379,8 +347,6 @@ final class Expectation
} }
/** /**
* Creates a new expectation closure from the given name.
*
* @throws ExpectationNotFound * @throws ExpectationNotFound
*/ */
private function getExpectationClosure(string $name): Closure private function getExpectationClosure(string $name): Closure
@@ -402,8 +368,6 @@ final class Expectation
} }
/** /**
* Dynamically calls methods on the class without any arguments or creates a new higher order expectation.
*
* @return Expectation<TValue>|OppositeExpectation<TValue>|EachExpectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue|null>|TValue * @return Expectation<TValue>|OppositeExpectation<TValue>|EachExpectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue|null>|TValue
*/ */
public function __get(string $name): mixed public function __get(string $name): mixed
@@ -422,9 +386,6 @@ final class Expectation
return $this->{$name}(); return $this->{$name}();
} }
/**
* Checks if the given expectation method exists.
*/
public static function hasMethod(string $name): bool public static function hasMethod(string $name): bool
{ {
return method_exists(self::class, $name) return method_exists(self::class, $name)
@@ -432,17 +393,12 @@ final class Expectation
|| self::hasExtend($name); || self::hasExtend($name);
} }
/**
* Matches any value.
*/
public function any(): Any public function any(): Any
{ {
return new Any; return new Any;
} }
/** /**
* Asserts that the given expectation target use the given dependencies.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toUse(array|string $targets): ArchExpectation public function toUse(array|string $targets): ArchExpectation
@@ -450,9 +406,6 @@ final class Expectation
return ToUse::make($this, $targets); return ToUse::make($this, $targets);
} }
/**
* Asserts that the given expectation target does have the given permissions
*/
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -463,9 +416,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to have line count less than the given number.
*/
public function toHaveLineCountLessThan(int $lines): ArchExpectation public function toHaveLineCountLessThan(int $lines): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -476,9 +426,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target have all methods documented.
*/
public function toHaveMethodsDocumented(): ArchExpectation public function toHaveMethodsDocumented(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -495,9 +442,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target have all properties documented.
*/
public function toHavePropertiesDocumented(): ArchExpectation public function toHavePropertiesDocumented(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -515,9 +459,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target use the "declare(strict_types=1)" declaration.
*/
public function toUseStrictTypes(): ArchExpectation public function toUseStrictTypes(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -528,9 +469,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target uses strict equality.
*/
public function toUseStrictEquality(): ArchExpectation public function toUseStrictEquality(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -541,9 +479,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target is final.
*/
public function toBeFinal(): ArchExpectation public function toBeFinal(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -554,9 +489,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target is readonly.
*/
public function toBeReadonly(): ArchExpectation public function toBeReadonly(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -567,9 +499,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target is trait.
*/
public function toBeTrait(): ArchExpectation public function toBeTrait(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -580,17 +509,11 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation targets are traits.
*/
public function toBeTraits(): ArchExpectation public function toBeTraits(): ArchExpectation
{ {
return $this->toBeTrait(); return $this->toBeTrait();
} }
/**
* Asserts that the given expectation target is abstract.
*/
public function toBeAbstract(): ArchExpectation public function toBeAbstract(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -602,8 +525,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation target has a specific method.
*
* @param array<int, string>|string $method * @param array<int, string>|string $method
*/ */
public function toHaveMethod(array|string $method): ArchExpectation public function toHaveMethod(array|string $method): ArchExpectation
@@ -619,8 +540,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation target has a specific methods.
*
* @param array<int, string> $methods * @param array<int, string> $methods
*/ */
public function toHaveMethods(array $methods): ArchExpectation public function toHaveMethods(array $methods): ArchExpectation
@@ -628,57 +547,36 @@ final class Expectation
return $this->toHaveMethod($methods); return $this->toHaveMethod($methods);
} }
/**
* Not supported.
*/
public function toHavePublicMethodsBesides(): void public function toHavePublicMethodsBesides(): void
{ {
throw InvalidExpectation::fromMethods(['toHavePublicMethodsBesides']); throw InvalidExpectation::fromMethods(['toHavePublicMethodsBesides']);
} }
/**
* Not supported.
*/
public function toHavePublicMethods(): void public function toHavePublicMethods(): void
{ {
throw InvalidExpectation::fromMethods(['toHavePublicMethods']); throw InvalidExpectation::fromMethods(['toHavePublicMethods']);
} }
/**
* Not supported.
*/
public function toHaveProtectedMethodsBesides(): void public function toHaveProtectedMethodsBesides(): void
{ {
throw InvalidExpectation::fromMethods(['toHaveProtectedMethodsBesides']); throw InvalidExpectation::fromMethods(['toHaveProtectedMethodsBesides']);
} }
/**
* Not supported.
*/
public function toHaveProtectedMethods(): void public function toHaveProtectedMethods(): void
{ {
throw InvalidExpectation::fromMethods(['toHaveProtectedMethods']); throw InvalidExpectation::fromMethods(['toHaveProtectedMethods']);
} }
/**
* Not supported.
*/
public function toHavePrivateMethodsBesides(): void public function toHavePrivateMethodsBesides(): void
{ {
throw InvalidExpectation::fromMethods(['toHavePrivateMethodsBesides']); throw InvalidExpectation::fromMethods(['toHavePrivateMethodsBesides']);
} }
/**
* Not supported.
*/
public function toHavePrivateMethods(): void public function toHavePrivateMethods(): void
{ {
throw InvalidExpectation::fromMethods(['toHavePrivateMethods']); throw InvalidExpectation::fromMethods(['toHavePrivateMethods']);
} }
/**
* Asserts that the given expectation target is cased correctly.
*/
public function toBeCasedCorrectly(): ArchExpectation public function toBeCasedCorrectly(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -711,9 +609,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target is enum.
*/
public function toBeEnum(): ArchExpectation public function toBeEnum(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -724,17 +619,11 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation targets are enums.
*/
public function toBeEnums(): ArchExpectation public function toBeEnums(): ArchExpectation
{ {
return $this->toBeEnum(); return $this->toBeEnum();
} }
/**
* Asserts that the given expectation target is a class.
*/
public function toBeClass(): ArchExpectation public function toBeClass(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -745,17 +634,11 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation targets are classes.
*/
public function toBeClasses(): ArchExpectation public function toBeClasses(): ArchExpectation
{ {
return $this->toBeClass(); return $this->toBeClass();
} }
/**
* Asserts that the given expectation target is interface.
*/
public function toBeInterface(): ArchExpectation public function toBeInterface(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -766,17 +649,11 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation targets are interfaces.
*/
public function toBeInterfaces(): ArchExpectation public function toBeInterfaces(): ArchExpectation
{ {
return $this->toBeInterface(); return $this->toBeInterface();
} }
/**
* Asserts that the given expectation target to be subclass of the given class.
*/
public function toExtend(string $class): ArchExpectation public function toExtend(string $class): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -787,9 +664,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to be have a parent class.
*/
public function toExtendNothing(): ArchExpectation public function toExtendNothing(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -800,17 +674,12 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to use the given trait.
*/
public function toUseTrait(string $trait): ArchExpectation public function toUseTrait(string $trait): ArchExpectation
{ {
return $this->toUseTraits($trait); return $this->toUseTraits($trait);
} }
/** /**
* Asserts that the given expectation target to use the given traits.
*
* @param array<int, string>|string $traits * @param array<int, string>|string $traits
*/ */
public function toUseTraits(array|string $traits): ArchExpectation public function toUseTraits(array|string $traits): ArchExpectation
@@ -852,9 +721,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to not implement any interfaces.
*/
public function toImplementNothing(): ArchExpectation public function toImplementNothing(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -866,8 +732,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation target to only implement the given interfaces.
*
* @param array<int, string>|string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toOnlyImplement(array|string $interfaces): ArchExpectation public function toOnlyImplement(array|string $interfaces): ArchExpectation
@@ -884,9 +748,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to have the given prefix.
*/
public function toHavePrefix(string $prefix): ArchExpectation public function toHavePrefix(string $prefix): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -897,9 +758,6 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target to have the given suffix.
*/
public function toHaveSuffix(string $suffix): ArchExpectation public function toHaveSuffix(string $suffix): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -911,8 +769,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation target to implement the given interfaces.
*
* @param array<int, string>|string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toImplement(array|string $interfaces): ArchExpectation public function toImplement(array|string $interfaces): ArchExpectation
@@ -928,8 +784,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation target "only" use on the given dependencies.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toOnlyUse(array|string $targets): ArchExpectation public function toOnlyUse(array|string $targets): ArchExpectation
@@ -937,33 +791,22 @@ final class Expectation
return ToOnlyUse::make($this, $targets); return ToOnlyUse::make($this, $targets);
} }
/**
* Asserts that the given expectation target does not use any dependencies.
*/
public function toUseNothing(): ArchExpectation public function toUseNothing(): ArchExpectation
{ {
return ToUseNothing::make($this); return ToUseNothing::make($this);
} }
/**
* Asserts that the source code of the given expectation target does not include suspicious characters.
*/
public function toHaveSuspiciousCharacters(): ArchExpectation public function toHaveSuspiciousCharacters(): ArchExpectation
{ {
throw InvalidExpectation::fromMethods(['toHaveSuspiciousCharacters']); throw InvalidExpectation::fromMethods(['toHaveSuspiciousCharacters']);
} }
/**
* Not supported.
*/
public function toBeUsed(): void public function toBeUsed(): void
{ {
throw InvalidExpectation::fromMethods(['toBeUsed']); throw InvalidExpectation::fromMethods(['toBeUsed']);
} }
/** /**
* Asserts that the given expectation dependency is used by the given targets.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toBeUsedIn(array|string $targets): ArchExpectation public function toBeUsedIn(array|string $targets): ArchExpectation
@@ -972,8 +815,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation dependency is "only" used by the given targets.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toOnlyBeUsedIn(array|string $targets): ArchExpectation public function toOnlyBeUsedIn(array|string $targets): ArchExpectation
@@ -981,17 +822,11 @@ final class Expectation
return ToOnlyBeUsedIn::make($this, $targets); return ToOnlyBeUsedIn::make($this, $targets);
} }
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsedInNothing(): ArchExpectation public function toBeUsedInNothing(): ArchExpectation
{ {
return ToBeUsedInNothing::make($this); return ToBeUsedInNothing::make($this);
} }
/**
* Asserts that the given expectation dependency is an invokable class.
*/
public function toBeInvokable(): ArchExpectation public function toBeInvokable(): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -1003,8 +838,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation is iterable and contains snake_case keys.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveSnakeCaseKeys(string $message = ''): self public function toHaveSnakeCaseKeys(string $message = ''): self
@@ -1027,8 +860,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation is iterable and contains kebab-case keys.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveKebabCaseKeys(string $message = ''): self public function toHaveKebabCaseKeys(string $message = ''): self
@@ -1051,8 +882,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation is iterable and contains camelCase keys.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveCamelCaseKeys(string $message = ''): self public function toHaveCamelCaseKeys(string $message = ''): self
@@ -1075,8 +904,6 @@ final class Expectation
} }
/** /**
* Asserts that the given expectation is iterable and contains StudlyCase keys.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveStudlyCaseKeys(string $message = ''): self public function toHaveStudlyCaseKeys(string $message = ''): self
@@ -1098,9 +925,6 @@ final class Expectation
return $this; return $this;
} }
/**
* Asserts that the given expectation target to have the given attribute.
*/
public function toHaveAttribute(string $attribute): ArchExpectation public function toHaveAttribute(string $attribute): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -1111,25 +935,16 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target has a constructor method.
*/
public function toHaveConstructor(): ArchExpectation public function toHaveConstructor(): ArchExpectation
{ {
return $this->toHaveMethod('__construct'); return $this->toHaveMethod('__construct');
} }
/**
* Asserts that the given expectation target has a destructor method.
*/
public function toHaveDestructor(): ArchExpectation public function toHaveDestructor(): ArchExpectation
{ {
return $this->toHaveMethod('__destruct'); return $this->toHaveMethod('__destruct');
} }
/**
* Asserts that the given expectation target is a backed enum of given type.
*/
private function toBeBackedEnum(string $backingType): ArchExpectation private function toBeBackedEnum(string $backingType): ArchExpectation
{ {
return Targeted::make( return Targeted::make(
@@ -1143,33 +958,21 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation targets are string backed enums.
*/
public function toBeStringBackedEnums(): ArchExpectation public function toBeStringBackedEnums(): ArchExpectation
{ {
return $this->toBeStringBackedEnum(); return $this->toBeStringBackedEnum();
} }
/**
* Asserts that the given expectation targets are int backed enums.
*/
public function toBeIntBackedEnums(): ArchExpectation public function toBeIntBackedEnums(): ArchExpectation
{ {
return $this->toBeIntBackedEnum(); return $this->toBeIntBackedEnum();
} }
/**
* Asserts that the given expectation target is a string backed enum.
*/
public function toBeStringBackedEnum(): ArchExpectation public function toBeStringBackedEnum(): ArchExpectation
{ {
return $this->toBeBackedEnum('string'); return $this->toBeBackedEnum('string');
} }
/**
* Asserts that the given expectation target is an int backed enum.
*/
public function toBeIntBackedEnum(): ArchExpectation public function toBeIntBackedEnum(): ArchExpectation
{ {
return $this->toBeBackedEnum('int'); return $this->toBeBackedEnum('int');
-13
View File
@@ -17,21 +17,14 @@ use function expect;
*/ */
final class EachExpectation final class EachExpectation
{ {
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false; private bool $opposite = false;
/** /**
* Creates an expectation on each item of the iterable "value".
*
* @param Expectation<TValue> $original * @param Expectation<TValue> $original
*/ */
public function __construct(private readonly Expectation $original) {} public function __construct(private readonly Expectation $original) {}
/** /**
* Creates a new expectation.
*
* @template TAndValue * @template TAndValue
* *
* @param TAndValue $value * @param TAndValue $value
@@ -43,8 +36,6 @@ final class EachExpectation
} }
/** /**
* Creates the opposite expectation for the value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function not(): self public function not(): self
@@ -55,8 +46,6 @@ final class EachExpectation
} }
/** /**
* Dynamically calls methods on the class with the given arguments on each item.
*
* @param array<int|string, mixed> $arguments * @param array<int|string, mixed> $arguments
* @return self<TValue> * @return self<TValue>
*/ */
@@ -73,8 +62,6 @@ final class EachExpectation
} }
/** /**
* Dynamically calls methods on the class without any arguments on each item.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function __get(string $name): self public function __get(string $name): self
@@ -25,19 +25,11 @@ final class HigherOrderExpectation
*/ */
private Expectation|EachExpectation $expectation; private Expectation|EachExpectation $expectation;
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false; private bool $opposite = false;
/**
* Indicates if the expectation should reset the value.
*/
private bool $shouldReset = false; private bool $shouldReset = false;
/** /**
* Creates a new higher order expectation.
*
* @param Expectation<TOriginalValue> $original * @param Expectation<TOriginalValue> $original
* @param TValue $value * @param TValue $value
*/ */
@@ -47,8 +39,6 @@ final class HigherOrderExpectation
} }
/** /**
* Creates the opposite expectation for the value.
*
* @return self<TOriginalValue, TValue> * @return self<TOriginalValue, TValue>
*/ */
public function not(): self public function not(): self
@@ -59,8 +49,6 @@ final class HigherOrderExpectation
} }
/** /**
* Creates a new Expectation.
*
* @template TExpectValue * @template TExpectValue
* *
* @param TExpectValue $value * @param TExpectValue $value
@@ -72,8 +60,6 @@ final class HigherOrderExpectation
} }
/** /**
* Creates a new expectation.
*
* @template TExpectValue * @template TExpectValue
* *
* @param TExpectValue $value * @param TExpectValue $value
@@ -85,9 +71,6 @@ final class HigherOrderExpectation
} }
/** /**
* Scope an expectation callback to the current value in
* the HigherOrderExpectation chain.
*
* @param Closure(Expectation<TValue>): void $expectation * @param Closure(Expectation<TValue>): void $expectation
* @return HigherOrderExpectation<TOriginalValue, TOriginalValue> * @return HigherOrderExpectation<TOriginalValue, TOriginalValue>
*/ */
@@ -99,8 +82,6 @@ final class HigherOrderExpectation
} }
/** /**
* Creates a new expectation with the decoded JSON value.
*
* @return self<TOriginalValue, array<string|int, mixed>|bool> * @return self<TOriginalValue, array<string|int, mixed>|bool>
*/ */
public function json(): self public function json(): self
@@ -109,8 +90,6 @@ final class HigherOrderExpectation
} }
/** /**
* Dynamically calls methods on the class with the given arguments.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
* @return self<TOriginalValue, mixed> * @return self<TOriginalValue, mixed>
*/ */
@@ -125,8 +104,6 @@ final class HigherOrderExpectation
} }
/** /**
* Accesses properties in the value or in the expectation.
*
* @return self<TOriginalValue, mixed> * @return self<TOriginalValue, mixed>
*/ */
public function __get(string $name): self public function __get(string $name): self
@@ -145,9 +122,6 @@ final class HigherOrderExpectation
return $this->performAssertion($name, []); return $this->performAssertion($name, []);
} }
/**
* Determines if the original expectation has the given method name.
*/
private function expectationHasMethod(string $name): bool private function expectationHasMethod(string $name): bool
{ {
if (method_exists($this->original, $name)) { if (method_exists($this->original, $name)) {
@@ -161,8 +135,6 @@ final class HigherOrderExpectation
} }
/** /**
* Retrieve the applicable value based on the current reset condition.
*
* @return TOriginalValue|TValue * @return TOriginalValue|TValue
*/ */
private function getValue(): mixed private function getValue(): mixed
@@ -171,8 +143,6 @@ final class HigherOrderExpectation
} }
/** /**
* Performs the given assertion with the current expectation.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
* @return self<TOriginalValue, TValue> * @return self<TOriginalValue, TValue>
*/ */
-152
View File
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Pest\Expectations; namespace Pest\Expectations;
use Attribute;
use Pest\Arch\Contracts\ArchExpectation; use Pest\Arch\Contracts\ArchExpectation;
use Pest\Arch\Expectations\Targeted; use Pest\Arch\Expectations\Targeted;
use Pest\Arch\Expectations\ToBeUsedIn; use Pest\Arch\Expectations\ToBeUsedIn;
@@ -38,15 +37,11 @@ use stdClass;
final readonly class OppositeExpectation final readonly class OppositeExpectation
{ {
/** /**
* Creates a new opposite expectation.
*
* @param Expectation<TValue> $original * @param Expectation<TValue> $original
*/ */
public function __construct(private Expectation $original) {} public function __construct(private Expectation $original) {}
/** /**
* Asserts that the value array not has the provided $keys.
*
* @param array<int, int|string|array<int-string, mixed>> $keys * @param array<int, int|string|array<int-string, mixed>> $keys
* @return Expectation<TValue> * @return Expectation<TValue>
*/ */
@@ -70,8 +65,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation target does not use any of the given dependencies.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toUse(array|string $targets): ArchExpectation public function toUse(array|string $targets): ArchExpectation
@@ -84,9 +77,6 @@ final readonly class OppositeExpectation
), is_string($targets) ? [$targets] : $targets)); ), is_string($targets) ? [$targets] : $targets));
} }
/**
* Asserts that the given expectation target does not have the given permissions
*/
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -100,17 +90,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Not supported.
*/
public function toHaveLineCountLessThan(): ArchExpectation public function toHaveLineCountLessThan(): ArchExpectation
{ {
throw InvalidExpectation::fromMethods(['not', 'toHaveLineCountLessThan']); throw InvalidExpectation::fromMethods(['not', 'toHaveLineCountLessThan']);
} }
/**
* Not supported.
*/
public function toHaveMethodsDocumented(): ArchExpectation public function toHaveMethodsDocumented(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -130,9 +114,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Not supported.
*/
public function toHavePropertiesDocumented(): ArchExpectation public function toHavePropertiesDocumented(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -153,9 +134,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target does not use the "declare(strict_types=1)" declaration.
*/
public function toUseStrictTypes(): ArchExpectation public function toUseStrictTypes(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -169,9 +147,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target does not use the strict equality operator.
*/
public function toUseStrictEquality(): ArchExpectation public function toUseStrictEquality(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -185,9 +160,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target is not final.
*/
public function toBeFinal(): ArchExpectation public function toBeFinal(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -201,9 +173,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target is not readonly.
*/
public function toBeReadonly(): ArchExpectation public function toBeReadonly(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -217,9 +186,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target is not trait.
*/
public function toBeTrait(): ArchExpectation public function toBeTrait(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -233,17 +199,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation targets are not traits.
*/
public function toBeTraits(): ArchExpectation public function toBeTraits(): ArchExpectation
{ {
return $this->toBeTrait(); return $this->toBeTrait();
} }
/**
* Asserts that the given expectation target is not abstract.
*/
public function toBeAbstract(): ArchExpectation public function toBeAbstract(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -258,8 +218,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation target does not have a specific method.
*
* @param array<int, string>|string $method * @param array<int, string>|string $method
*/ */
public function toHaveMethod(array|string $method): ArchExpectation public function toHaveMethod(array|string $method): ArchExpectation
@@ -280,9 +238,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target does not have suspicious characters.
*/
public function toHaveSuspiciousCharacters(): ArchExpectation public function toHaveSuspiciousCharacters(): ArchExpectation
{ {
if (! class_exists(Spoofchecker::class)) { if (! class_exists(Spoofchecker::class)) {
@@ -303,8 +258,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation target does not have the given methods.
*
* @param array<int, string> $methods * @param array<int, string> $methods
*/ */
public function toHaveMethods(array $methods): ArchExpectation public function toHaveMethods(array $methods): ArchExpectation
@@ -313,8 +266,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation target not to have the public methods besides the given methods.
*
* @param array<int, string>|string $methods * @param array<int, string>|string $methods
*/ */
public function toHavePublicMethodsBesides(array|string $methods): ArchExpectation public function toHavePublicMethodsBesides(array|string $methods): ArchExpectation
@@ -350,17 +301,12 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target not to have the public methods.
*/
public function toHavePublicMethods(): ArchExpectation public function toHavePublicMethods(): ArchExpectation
{ {
return $this->toHavePublicMethodsBesides([]); return $this->toHavePublicMethodsBesides([]);
} }
/** /**
* Asserts that the given expectation target not to have the protected methods besides the given methods.
*
* @param array<int, string>|string $methods * @param array<int, string>|string $methods
*/ */
public function toHaveProtectedMethodsBesides(array|string $methods): ArchExpectation public function toHaveProtectedMethodsBesides(array|string $methods): ArchExpectation
@@ -396,17 +342,12 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target not to have the protected methods.
*/
public function toHaveProtectedMethods(): ArchExpectation public function toHaveProtectedMethods(): ArchExpectation
{ {
return $this->toHaveProtectedMethodsBesides([]); return $this->toHaveProtectedMethodsBesides([]);
} }
/** /**
* Asserts that the given expectation target not to have the private methods besides the given methods.
*
* @param array<int, string>|string $methods * @param array<int, string>|string $methods
*/ */
public function toHavePrivateMethodsBesides(array|string $methods): ArchExpectation public function toHavePrivateMethodsBesides(array|string $methods): ArchExpectation
@@ -442,17 +383,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target not to have the private methods.
*/
public function toHavePrivateMethods(): ArchExpectation public function toHavePrivateMethods(): ArchExpectation
{ {
return $this->toHavePrivateMethodsBesides([]); return $this->toHavePrivateMethodsBesides([]);
} }
/**
* Asserts that the given expectation target is not enum.
*/
public function toBeEnum(): ArchExpectation public function toBeEnum(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -466,17 +401,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation targets are not enums.
*/
public function toBeEnums(): ArchExpectation public function toBeEnums(): ArchExpectation
{ {
return $this->toBeEnum(); return $this->toBeEnum();
} }
/**
* Asserts that the given expectation targets is not class.
*/
public function toBeClass(): ArchExpectation public function toBeClass(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -490,17 +419,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation targets are not classes.
*/
public function toBeClasses(): ArchExpectation public function toBeClasses(): ArchExpectation
{ {
return $this->toBeClass(); return $this->toBeClass();
} }
/**
* Asserts that the given expectation target is not interface.
*/
public function toBeInterface(): ArchExpectation public function toBeInterface(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -514,17 +437,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation targets are not interfaces.
*/
public function toBeInterfaces(): ArchExpectation public function toBeInterfaces(): ArchExpectation
{ {
return $this->toBeInterface(); return $this->toBeInterface();
} }
/**
* Asserts that the given expectation target to be not subclass of the given class.
*/
public function toExtend(string $class): ArchExpectation public function toExtend(string $class): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -538,9 +455,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target to be not have any parent class.
*/
public function toExtendNothing(): ArchExpectation public function toExtendNothing(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -554,17 +468,12 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target not to use the given trait.
*/
public function toUseTrait(string $trait): ArchExpectation public function toUseTrait(string $trait): ArchExpectation
{ {
return $this->toUseTraits($trait); return $this->toUseTraits($trait);
} }
/** /**
* Asserts that the given expectation target not to use the given traits.
*
* @param array<int, string>|string $traits * @param array<int, string>|string $traits
*/ */
public function toUseTraits(array|string $traits): ArchExpectation public function toUseTraits(array|string $traits): ArchExpectation
@@ -583,8 +492,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation target not to implement the given interfaces.
*
* @param array<int, string>|string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toImplement(array|string $interfaces): ArchExpectation public function toImplement(array|string $interfaces): ArchExpectation
@@ -602,9 +509,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target to not implement any interfaces.
*/
public function toImplementNothing(): ArchExpectation public function toImplementNothing(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -618,17 +522,11 @@ final readonly class OppositeExpectation
); );
} }
/**
* Not supported.
*/
public function toOnlyImplement(): void public function toOnlyImplement(): void
{ {
throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']); throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']);
} }
/**
* Asserts that the given expectation target to not have the given prefix.
*/
public function toHavePrefix(string $prefix): ArchExpectation public function toHavePrefix(string $prefix): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -642,9 +540,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target to not have the given suffix.
*/
public function toHaveSuffix(string $suffix): ArchExpectation public function toHaveSuffix(string $suffix): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -658,25 +553,16 @@ final readonly class OppositeExpectation
); );
} }
/**
* Not supported.
*/
public function toOnlyUse(): void public function toOnlyUse(): void
{ {
throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']); throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']);
} }
/**
* Not supported.
*/
public function toUseNothing(): void public function toUseNothing(): void
{ {
throw InvalidExpectation::fromMethods(['not', 'toUseNothing']); throw InvalidExpectation::fromMethods(['not', 'toUseNothing']);
} }
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsed(): ArchExpectation public function toBeUsed(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -686,8 +572,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Asserts that the given expectation dependency is not used by any of the given targets.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
public function toBeUsedIn(array|string $targets): ArchExpectation public function toBeUsedIn(array|string $targets): ArchExpectation
@@ -705,17 +589,11 @@ final readonly class OppositeExpectation
throw InvalidExpectation::fromMethods(['not', 'toOnlyBeUsedIn']); throw InvalidExpectation::fromMethods(['not', 'toOnlyBeUsedIn']);
} }
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsedInNothing(): void public function toBeUsedInNothing(): void
{ {
throw InvalidExpectation::fromMethods(['not', 'toBeUsedInNothing']); throw InvalidExpectation::fromMethods(['not', 'toBeUsedInNothing']);
} }
/**
* Asserts that the given expectation dependency is not an invokable class.
*/
public function toBeInvokable(): ArchExpectation public function toBeInvokable(): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -729,9 +607,6 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target not to have the given attribute.
*/
public function toHaveAttribute(string $attribute): ArchExpectation public function toHaveAttribute(string $attribute): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -746,8 +621,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Handle dynamic method calls into the original expectation.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
* @return Expectation<TValue>|Expectation<mixed>|never * @return Expectation<TValue>|Expectation<mixed>|never
*/ */
@@ -768,8 +641,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Handle dynamic properties gets into the original expectation.
*
* @return Expectation<TValue>|Expectation<mixed>|never * @return Expectation<TValue>|Expectation<mixed>|never
*/ */
public function __get(string $name): Expectation public function __get(string $name): Expectation
@@ -788,8 +659,6 @@ final readonly class OppositeExpectation
} }
/** /**
* Creates a new expectation failed exception with a nice readable message.
*
* @param array<int, mixed>|string $arguments * @param array<int, mixed>|string $arguments
*/ */
public function throwExpectationFailedException(string $name, array|string $arguments = []): never public function throwExpectationFailedException(string $name, array|string $arguments = []): never
@@ -806,25 +675,16 @@ final readonly class OppositeExpectation
)); ));
} }
/**
* Asserts that the given expectation target does not have a constructor method.
*/
public function toHaveConstructor(): ArchExpectation public function toHaveConstructor(): ArchExpectation
{ {
return $this->toHaveMethod('__construct'); return $this->toHaveMethod('__construct');
} }
/**
* Asserts that the given expectation target does not have a destructor method.
*/
public function toHaveDestructor(): ArchExpectation public function toHaveDestructor(): ArchExpectation
{ {
return $this->toHaveMethod('__destruct'); return $this->toHaveMethod('__destruct');
} }
/**
* Asserts that the given expectation target is not a backed enum of given type.
*/
private function toBeBackedEnum(string $backingType): ArchExpectation private function toBeBackedEnum(string $backingType): ArchExpectation
{ {
/** @var Expectation<array<int, string>|string> $original */ /** @var Expectation<array<int, string>|string> $original */
@@ -841,33 +701,21 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation targets are not string backed enums.
*/
public function toBeStringBackedEnums(): ArchExpectation public function toBeStringBackedEnums(): ArchExpectation
{ {
return $this->toBeStringBackedEnum(); return $this->toBeStringBackedEnum();
} }
/**
* Asserts that the given expectation targets are not int backed enums.
*/
public function toBeIntBackedEnums(): ArchExpectation public function toBeIntBackedEnums(): ArchExpectation
{ {
return $this->toBeIntBackedEnum(); return $this->toBeIntBackedEnum();
} }
/**
* Asserts that the given expectation target is not a string backed enum.
*/
public function toBeStringBackedEnum(): ArchExpectation public function toBeStringBackedEnum(): ArchExpectation
{ {
return $this->toBeBackedEnum('string'); return $this->toBeBackedEnum('string');
} }
/**
* Asserts that the given expectation target is not an int backed enum.
*/
public function toBeIntBackedEnum(): ArchExpectation public function toBeIntBackedEnum(): ArchExpectation
{ {
return $this->toBeBackedEnum('int'); return $this->toBeBackedEnum('int');
@@ -8,24 +8,12 @@ use Pest\Support\HigherOrderMessageCollection;
trait HigherOrderable trait HigherOrderable
{ {
/**
* The higher order messages that are chainable.
*/
public HigherOrderMessageCollection $chains; public HigherOrderMessageCollection $chains;
/**
* The higher order messages that are "factory" proxyable.
*/
public HigherOrderMessageCollection $factoryProxies; public HigherOrderMessageCollection $factoryProxies;
/**
* The higher order messages that are proxyable.
*/
public HigherOrderMessageCollection $proxies; public HigherOrderMessageCollection $proxies;
/**
* Boot the higher order properties.
*/
private function bootHigherOrderable(): void private function bootHigherOrderable(): void
{ {
$this->chains = new HigherOrderMessageCollection; $this->chains = new HigherOrderMessageCollection;
-29
View File
@@ -30,29 +30,21 @@ final class TestCaseFactory
use HigherOrderable; use HigherOrderable;
/** /**
* The list of attributes.
*
* @var array<int, Attribute> * @var array<int, Attribute>
*/ */
public array $attributes = []; public array $attributes = [];
/** /**
* The FQN of the Test Case class.
*
* @var class-string * @var class-string
*/ */
public string $class = TestCase::class; public string $class = TestCase::class;
/** /**
* The list of class methods.
*
* @var array<string, TestCaseMethodFactory> * @var array<string, TestCaseMethodFactory>
*/ */
public array $methods = []; public array $methods = [];
/** /**
* The list of class traits.
*
* @var array <int, class-string> * @var array <int, class-string>
*/ */
public array $traits = [ public array $traits = [
@@ -60,14 +52,8 @@ final class TestCaseFactory
Concerns\Expectable::class, Concerns\Expectable::class,
]; ];
/**
* The namespace for the test case, overrides the path-based namespace when set.
*/
public ?string $namespace = null; public ?string $namespace = null;
/**
* Creates a new Factory instance.
*/
public function __construct( public function __construct(
public string $filename public string $filename
) { ) {
@@ -84,14 +70,11 @@ final class TestCaseFactory
} }
/** /**
* Creates a Test Case class using a runtime evaluate.
*
* @param array<string, TestCaseMethodFactory> $methods * @param array<string, TestCaseMethodFactory> $methods
*/ */
public function evaluate(string $filename, array $methods): void public function evaluate(string $filename, array $methods): void
{ {
if ('\\' === DIRECTORY_SEPARATOR) { if ('\\' === DIRECTORY_SEPARATOR) {
// In case Windows, strtolower drive name, like in UsesCall.
$filename = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', static fn (array $match): string => strtolower($match['drive']), $filename); $filename = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\)~i', static fn (array $match): string => strtolower($match['drive']), $filename);
} }
@@ -114,11 +97,8 @@ final class TestCaseFactory
$relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath); $relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath);
// Strip out any %-encoded octets.
$relativePath = (string) preg_replace('|%[a-fA-F0-9][a-fA-F0-9]|', '', $relativePath); $relativePath = (string) preg_replace('|%[a-fA-F0-9][a-fA-F0-9]|', '', $relativePath);
// Remove escaped quote sequences (maintain namespace)
$relativePath = str_replace(array_map(fn (string $quote): string => sprintf('\\%s', $quote), ['\'', '"']), '', $relativePath); $relativePath = str_replace(array_map(fn (string $quote): string => sprintf('\\%s', $quote), ['\'', '"']), '', $relativePath);
// Limit to Unicode letters and numbers.
$relativePath = (string) preg_replace('/[^\p{L}\p{N}\\\\]/u', '', $relativePath); $relativePath = (string) preg_replace('/[^\p{L}\p{N}\\\\]/u', '', $relativePath);
$classFQN = 'P\\'.$relativePath; $classFQN = 'P\\'.$relativePath;
@@ -197,9 +177,6 @@ final class TestCaseFactory
} }
} }
/**
* Adds the given Method to the Test Case.
*/
public function addMethod(TestCaseMethodFactory $method): void public function addMethod(TestCaseMethodFactory $method): void
{ {
if ($method->description === null) { if ($method->description === null) {
@@ -233,9 +210,6 @@ final class TestCaseFactory
$this->methods[$method->description] = $method; $this->methods[$method->description] = $method;
} }
/**
* Checks if a test case has a method.
*/
public function hasMethod(string $methodName): bool public function hasMethod(string $methodName): bool
{ {
foreach ($this->methods as $method) { foreach ($this->methods as $method) {
@@ -251,9 +225,6 @@ final class TestCaseFactory
return false; return false;
} }
/**
* Gets a Method by the given name.
*/
public function getMethod(string $methodName): TestCaseMethodFactory public function getMethod(string $methodName): TestCaseMethodFactory
{ {
foreach ($this->methods as $method) { foreach ($this->methods as $method) {
-51
View File
@@ -27,84 +27,54 @@ final class TestCaseMethodFactory
use HigherOrderable; use HigherOrderable;
/** /**
* The list of attributes.
*
* @var array<int, Attribute> * @var array<int, Attribute>
*/ */
public array $attributes = []; public array $attributes = [];
/** /**
* The test's describing, if any.
*
* @var array<int, Description> * @var array<int, Description>
*/ */
public array $describing = []; public array $describing = [];
/**
* The test's description, if any.
*/
public ?string $description = null; public ?string $description = null;
/**
* The test's number of repetitions.
*/
public int $repetitions = 1; public int $repetitions = 1;
/**
* The test's number of flaky retry tries.
*/
public ?int $flakyTries = null; public ?int $flakyTries = null;
/**
* Determines if the test is a "todo".
*/
public bool $todo = false; public bool $todo = false;
/** /**
* The associated issue numbers.
*
* @var array<int, int> * @var array<int, int>
*/ */
public array $issues = []; public array $issues = [];
/** /**
* The test assignees.
*
* @var array<int, string> * @var array<int, string>
*/ */
public array $assignees = []; public array $assignees = [];
/** /**
* The associated PRs numbers.
*
* @var array<int, int> * @var array<int, int>
*/ */
public array $prs = []; public array $prs = [];
/** /**
* The test's notes.
*
* @var array<int, string> * @var array<int, string>
*/ */
public array $notes = []; public array $notes = [];
/** /**
* The test's datasets.
*
* @var array<Closure|iterable<int|string, mixed>|string> * @var array<Closure|iterable<int|string, mixed>|string>
*/ */
public array $datasets = []; public array $datasets = [];
/** /**
* The test's dependencies.
*
* @var array<int, string> * @var array<int, string>
*/ */
public array $depends = []; public array $depends = [];
/** /**
* The test's groups.
*
* @var array<int, string> * @var array<int, string>
*/ */
public array $groups = []; public array $groups = [];
@@ -114,9 +84,6 @@ final class TestCaseMethodFactory
*/ */
public bool $__ran = false; public bool $__ran = false;
/**
* Creates a new test case method factory instance.
*/
public function __construct( public function __construct(
public string $filename, public string $filename,
public ?Closure $closure, public ?Closure $closure,
@@ -128,9 +95,6 @@ final class TestCaseMethodFactory
$this->bootHigherOrderable(); $this->bootHigherOrderable();
} }
/**
* Sets the test's hooks, and runs any proxy to the test case.
*/
public function setUp(TestCase $concrete): void public function setUp(TestCase $concrete): void
{ {
$concrete::flush(); // @phpstan-ignore-line $concrete::flush(); // @phpstan-ignore-line
@@ -146,17 +110,11 @@ final class TestCaseMethodFactory
$this->factoryProxies->proxy($concrete); $this->factoryProxies->proxy($concrete);
} }
/**
* Flushes the test case.
*/
public function tearDown(TestCase $concrete): void public function tearDown(TestCase $concrete): void
{ {
$concrete::flush(); // @phpstan-ignore-line $concrete::flush(); // @phpstan-ignore-line
} }
/**
* Creates the test's closure.
*/
public function getClosure(): Closure public function getClosure(): Closure
{ {
$closure = $this->closure; $closure = $this->closure;
@@ -178,17 +136,11 @@ final class TestCaseMethodFactory
}; };
} }
/**
* Determine if the test case will receive argument input from Pest, or not.
*/
public function receivesArguments(): bool public function receivesArguments(): bool
{ {
return $this->datasets !== [] || $this->depends !== [] || $this->repetitions > 1; return $this->datasets !== [] || $this->depends !== [] || $this->repetitions > 1;
} }
/**
* Creates a PHPUnit method as a string ready for evaluation.
*/
public function buildForEvaluation(): string public function buildForEvaluation(): string
{ {
if ($this->description === null) { if ($this->description === null) {
@@ -248,9 +200,6 @@ final class TestCaseMethodFactory
PHP; PHP;
} }
/**
* Creates a PHPUnit Data Provider as a string ready for evaluation.
*/
private function buildDatasetForEvaluation(string $methodName, string $dataProviderName): string private function buildDatasetForEvaluation(string $methodName, string $dataProviderName): string
{ {
$datasets = $this->datasets; $datasets = $this->datasets;
-45
View File
@@ -27,8 +27,6 @@ use PHPUnit\Framework\TestCase;
if (! function_exists('expect')) { if (! function_exists('expect')) {
/** /**
* Creates a new expectation.
*
* @template TValue * @template TValue
* *
* @param TValue|null $value * @param TValue|null $value
@@ -41,9 +39,6 @@ if (! function_exists('expect')) {
} }
if (! function_exists('beforeAll')) { if (! function_exists('beforeAll')) {
/**
* Runs the given closure before all tests in the current file.
*/
function beforeAll(Closure $closure): void function beforeAll(Closure $closure): void
{ {
if (DescribeCall::describing() !== []) { if (DescribeCall::describing() !== []) {
@@ -58,8 +53,6 @@ if (! function_exists('beforeAll')) {
if (! function_exists('beforeEach')) { if (! function_exists('beforeEach')) {
/** /**
* Runs the given closure before each test in the current file.
*
* @param-closure-this TestCall $closure * @param-closure-this TestCall $closure
*/ */
function beforeEach(?Closure $closure = null): BeforeEachCall function beforeEach(?Closure $closure = null): BeforeEachCall
@@ -72,8 +65,6 @@ if (! function_exists('beforeEach')) {
if (! function_exists('dataset')) { if (! function_exists('dataset')) {
/** /**
* Registers the given dataset.
*
* @param Closure|iterable<int|string, mixed> $dataset * @param Closure|iterable<int|string, mixed> $dataset
*/ */
function dataset(string $name, Closure|iterable $dataset): void function dataset(string $name, Closure|iterable $dataset): void
@@ -85,11 +76,6 @@ if (! function_exists('dataset')) {
} }
if (! function_exists('describe')) { if (! function_exists('describe')) {
/**
* Adds the given closure as a group of tests. The first argument
* is the group description; the second argument is a closure
* that contains the group tests.
*/
function describe(string $description, Closure $tests): DescribeCall function describe(string $description, Closure $tests): DescribeCall
{ {
$filename = Backtrace::testFile(); $filename = Backtrace::testFile();
@@ -100,9 +86,6 @@ if (! function_exists('describe')) {
if (! function_exists('uses')) { if (! function_exists('uses')) {
/** /**
* The uses function binds the given
* arguments to test closures.
*
* @param class-string ...$classAndTraits * @param class-string ...$classAndTraits
*/ */
function uses(string ...$classAndTraits): UsesCall function uses(string ...$classAndTraits): UsesCall
@@ -114,9 +97,6 @@ if (! function_exists('uses')) {
} }
if (! function_exists('pest')) { if (! function_exists('pest')) {
/**
* Creates a new Pest configuration instance.
*/
function pest(): Configuration function pest(): Configuration
{ {
return new Configuration(Backtrace::testFile()); return new Configuration(Backtrace::testFile());
@@ -125,10 +105,6 @@ if (! function_exists('pest')) {
if (! function_exists('test')) { if (! function_exists('test')) {
/** /**
* Adds the given closure as a test. The first argument
* is the test description; the second argument is
* a closure that contains the test expectations.
*
* @param-closure-this TestCall $closure * @param-closure-this TestCall $closure
* *
* @return ($description is string ? TestCall : HigherOrderTapProxy|TestCall) * @return ($description is string ? TestCall : HigherOrderTapProxy|TestCall)
@@ -147,10 +123,6 @@ if (! function_exists('test')) {
if (! function_exists('it')) { if (! function_exists('it')) {
/** /**
* Adds the given closure as a test. The first argument
* is the test description; the second argument is
* a closure that contains the test expectations.
*
* @param-closure-this TestCall $closure * @param-closure-this TestCall $closure
*/ */
function it(string $description, ?Closure $closure = null): TestCall function it(string $description, ?Closure $closure = null): TestCall
@@ -162,9 +134,6 @@ if (! function_exists('it')) {
} }
if (! function_exists('todo')) { if (! function_exists('todo')) {
/**
* Creates a new test that is marked as "todo".
*/
function todo(string $description): TestCall function todo(string $description): TestCall
{ {
return test($description)->todo(); return test($description)->todo();
@@ -173,8 +142,6 @@ if (! function_exists('todo')) {
if (! function_exists('afterEach')) { if (! function_exists('afterEach')) {
/** /**
* Runs the given closure after each test in the current file.
*
* @param-closure-this TestCall $closure * @param-closure-this TestCall $closure
*/ */
function afterEach(?Closure $closure = null): AfterEachCall function afterEach(?Closure $closure = null): AfterEachCall
@@ -186,9 +153,6 @@ if (! function_exists('afterEach')) {
} }
if (! function_exists('afterAll')) { if (! function_exists('afterAll')) {
/**
* Runs the given closure after all tests in the current file.
*/
function afterAll(Closure $closure): void function afterAll(Closure $closure): void
{ {
if (DescribeCall::describing() !== []) { if (DescribeCall::describing() !== []) {
@@ -203,8 +167,6 @@ if (! function_exists('afterAll')) {
if (! function_exists('covers')) { if (! function_exists('covers')) {
/** /**
* Specifies which classes, or functions, a test case covers.
*
* @param array<int, string>|string $classesOrFunctions * @param array<int, string>|string $classesOrFunctions
*/ */
function covers(array|string ...$classesOrFunctions): void function covers(array|string ...$classesOrFunctions): void
@@ -232,8 +194,6 @@ if (! function_exists('covers')) {
if (! function_exists('mutates')) { if (! function_exists('mutates')) {
/** /**
* Specifies which classes, enums, or traits a test case mutates.
*
* @param array<int, string>|string $targets * @param array<int, string>|string $targets
*/ */
function mutates(array|string ...$targets): void function mutates(array|string ...$targets): void
@@ -266,9 +226,6 @@ if (! function_exists('mutates')) {
} }
if (! function_exists('fixture')) { if (! function_exists('fixture')) {
/**
* Returns the absolute path to a fixture file.
*/
function fixture(string $file): string function fixture(string $file): string
{ {
$file = implode(DIRECTORY_SEPARATOR, [ $file = implode(DIRECTORY_SEPARATOR, [
@@ -292,8 +249,6 @@ if (! function_exists('fixture')) {
if (! function_exists('visit')) { if (! function_exists('visit')) {
/** /**
* Browse to the given URL.
*
* @template TUrl of array<int, string>|string * @template TUrl of array<int, string>|string
* *
* @param TUrl $url * @param TUrl $url
-23
View File
@@ -29,14 +29,9 @@ use Whoops\Exception\Inspector;
*/ */
final class Kernel final class Kernel
{ {
/**
* Either the kernel is terminated or not.
*/
private bool $terminated = false; private bool $terminated = false;
/** /**
* The Kernel bootstrappers.
*
* @var array<int, class-string> * @var array<int, class-string>
*/ */
private const array BOOTSTRAPPERS = [ private const array BOOTSTRAPPERS = [
@@ -51,10 +46,6 @@ final class Kernel
]; ];
/** /**
* The Kernel restarters — resolved and invoked from `bin/pest`
* before any other Pest class is touched, so the list is exposed
* on the Kernel rather than driven from `bin/pest` directly.
*
* @var array<int, class-string<Contracts\Restarter>> * @var array<int, class-string<Contracts\Restarter>>
*/ */
public const array RESTARTERS = [ public const array RESTARTERS = [
@@ -62,14 +53,8 @@ final class Kernel
Restarters\PcovRestarter::class, Restarters\PcovRestarter::class,
]; ];
/**
* Creates a new Kernel instance.
*/
public function __construct(private readonly Application $application, private readonly OutputInterface $output) {} public function __construct(private readonly Application $application, private readonly OutputInterface $output) {}
/**
* Boots the Kernel.
*/
public static function boot(TestSuite $testSuite, InputInterface $input, OutputInterface $output): self public static function boot(TestSuite $testSuite, InputInterface $input, OutputInterface $output): self
{ {
$container = Container::getInstance(); $container = Container::getInstance();
@@ -102,8 +87,6 @@ final class Kernel
} }
/** /**
* Runs the application, and returns the exit code.
*
* @param array<int, string> $originalArguments * @param array<int, string> $originalArguments
* @param array<int, string> $arguments * @param array<int, string> $arguments
*/ */
@@ -135,9 +118,6 @@ final class Kernel
return $result; return $result;
} }
/**
* Terminate the Kernel.
*/
public function terminate(): void public function terminate(): void
{ {
if ($this->terminated) { if ($this->terminated) {
@@ -155,9 +135,6 @@ final class Kernel
CallsTerminable::execute(); CallsTerminable::execute();
} }
/**
* Shutdowns unexpectedly the Kernel.
*/
public function shutdown(): void public function shutdown(): void
{ {
$this->terminate(); $this->terminate();
+1 -25
View File
@@ -10,23 +10,14 @@ use Symfony\Component\Console\Output\OutputInterface;
final class KernelDump final class KernelDump
{ {
/**
* The output buffer, if any.
*/
private string $buffer = ''; private string $buffer = '';
/**
* Creates a new Kernel Dump instance.
*/
public function __construct( public function __construct(
private readonly OutputInterface $output, private readonly OutputInterface $output,
) { ) {
// ... //
} }
/**
* Enable the output buffering.
*/
public function enable(): void public function enable(): void
{ {
if (class_exists(Execution::class) && Execution::running()) { if (class_exists(Execution::class) && Execution::running()) {
@@ -40,9 +31,6 @@ final class KernelDump
}); });
} }
/**
* Disable the output buffering.
*/
public function disable(): void public function disable(): void
{ {
@ob_clean(); @ob_clean();
@@ -52,17 +40,11 @@ final class KernelDump
} }
} }
/**
* Terminate the output buffering.
*/
public function terminate(): void public function terminate(): void
{ {
$this->disable(); $this->disable();
} }
/**
* Flushes the buffer.
*/
private function flush(): void private function flush(): void
{ {
View::renderUsing($this->output); View::renderUsing($this->output);
@@ -103,17 +85,11 @@ final class KernelDump
$this->buffer = ''; $this->buffer = '';
} }
/**
* Checks if the given output contains an opening headline.
*/
private function isOpeningHeadline(string $output): bool private function isOpeningHeadline(string $output): bool
{ {
return str_contains($output, 'by Sebastian Bergmann and contributors.'); return str_contains($output, 'by Sebastian Bergmann and contributors.');
} }
/**
* Checks if the given output contains an opening headline.
*/
private function isInternalError(string $output): bool private function isInternalError(string $output): bool
{ {
return str_contains($output, 'An error occurred inside PHPUnit.'); return str_contains($output, 'An error occurred inside PHPUnit.');
-57
View File
@@ -25,28 +25,16 @@ use PHPUnit\TestRunner\TestResult\TestResult as PhpUnitTestResult;
*/ */
final readonly class Converter final readonly class Converter
{ {
/**
* The prefix for the test suite name.
*/
private const string PREFIX = 'P\\'; private const string PREFIX = 'P\\';
/**
* The state generator.
*/
private StateGenerator $stateGenerator; private StateGenerator $stateGenerator;
/**
* Creates a new instance of the Converter.
*/
public function __construct( public function __construct(
private string $rootPath, private string $rootPath,
) { ) {
$this->stateGenerator = new StateGenerator; $this->stateGenerator = new StateGenerator;
} }
/**
* Gets the test case method name.
*/
public function getTestCaseMethodName(Test $test): string public function getTestCaseMethodName(Test $test): string
{ {
if (! $test instanceof TestMethod) { if (! $test instanceof TestMethod) {
@@ -56,9 +44,6 @@ final readonly class Converter
return $test->testDox()->prettifiedMethodName(); return $test->testDox()->prettifiedMethodName();
} }
/**
* Gets the test case location.
*/
public function getTestCaseLocation(Test $test): string public function getTestCaseLocation(Test $test): string
{ {
if (! $test instanceof TestMethod) { if (! $test instanceof TestMethod) {
@@ -68,15 +53,11 @@ final readonly class Converter
$path = $test->testDox()->prettifiedClassName(); $path = $test->testDox()->prettifiedClassName();
$relativePath = $this->toRelativePath($path); $relativePath = $this->toRelativePath($path);
// TODO: Get the description without the dataset.
$description = $test->testDox()->prettifiedMethodName(); $description = $test->testDox()->prettifiedMethodName();
return "$relativePath::$description"; return "$relativePath::$description";
} }
/**
* Gets the exception message.
*/
public function getExceptionMessage(Throwable $throwable): string public function getExceptionMessage(Throwable $throwable): string
{ {
if (is_a($throwable->className(), FrameworkException::class, true)) { if (is_a($throwable->className(), FrameworkException::class, true)) {
@@ -93,9 +74,6 @@ final readonly class Converter
return $buffer; return $buffer;
} }
/**
* Gets the exception details.
*/
public function getExceptionDetails(Throwable $throwable): string public function getExceptionDetails(Throwable $throwable): string
{ {
$buffer = $this->getStackTrace($throwable); $buffer = $this->getStackTrace($throwable);
@@ -113,26 +91,19 @@ final readonly class Converter
return $buffer; return $buffer;
} }
/**
* Gets the stack trace.
*/
public function getStackTrace(Throwable $throwable): string public function getStackTrace(Throwable $throwable): string
{ {
$stackTrace = $throwable->stackTrace(); $stackTrace = $throwable->stackTrace();
// Split stacktrace per frame.
$frames = explode("\n", $stackTrace); $frames = explode("\n", $stackTrace);
// Remove empty lines
$frames = array_filter($frames); $frames = array_filter($frames);
// clean the paths of each frame.
$frames = array_map( $frames = array_map(
$this->toRelativePath(...), $this->toRelativePath(...),
$frames $frames
); );
// Format stacktrace as `at <path>`
$frames = array_map( $frames = array_map(
fn (string $frame): string => "at $frame", fn (string $frame): string => "at $frame",
$frames $frames
@@ -141,9 +112,6 @@ final readonly class Converter
return implode("\n", $frames); return implode("\n", $frames);
} }
/**
* Gets the test suite name.
*/
public function getTestSuiteName(TestSuite $testSuite): string public function getTestSuiteName(TestSuite $testSuite): string
{ {
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) { if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
@@ -162,17 +130,11 @@ final readonly class Converter
return Str::after($name, self::PREFIX); return Str::after($name, self::PREFIX);
} }
/**
* Gets the trimmed test class name.
*/
public function getTrimmedTestClassName(TestMethod $test): string public function getTrimmedTestClassName(TestMethod $test): string
{ {
return Str::after($test->className(), self::PREFIX); return Str::after($test->className(), self::PREFIX);
} }
/**
* Gets the test suite location.
*/
public function getTestSuiteLocation(TestSuite $testSuite): ?string public function getTestSuiteLocation(TestSuite $testSuite): ?string
{ {
$firstTest = $this->getFirstTest($testSuite); $firstTest = $this->getFirstTest($testSuite);
@@ -191,22 +153,15 @@ final readonly class Converter
return $classRelativePath; return $classRelativePath;
} }
/**
* Gets the prettified test method name without dataset-related suffix.
*/
private function getTestMethodNameWithoutDatasetSuffix(TestMethod $testMethod): string private function getTestMethodNameWithoutDatasetSuffix(TestMethod $testMethod): string
{ {
return Str::beforeLast($testMethod->testDox()->prettifiedMethodName(), ' with data set '); return Str::beforeLast($testMethod->testDox()->prettifiedMethodName(), ' with data set ');
} }
/**
* Gets the first test from the test suite.
*/
private function getFirstTest(TestSuite $testSuite): ?TestMethod private function getFirstTest(TestSuite $testSuite): ?TestMethod
{ {
$tests = $testSuite->tests()->asArray(); $tests = $testSuite->tests()->asArray();
// TODO: figure out how to get the file path without a test being there.
if ($tests === []) { if ($tests === []) {
return null; return null;
} }
@@ -219,26 +174,16 @@ final readonly class Converter
return $firstTest; return $firstTest;
} }
/**
* Gets the test suite size.
*/
public function getTestSuiteSize(TestSuite $testSuite): int public function getTestSuiteSize(TestSuite $testSuite): int
{ {
return $testSuite->count(); return $testSuite->count();
} }
/**
* Transforms the given path in relative path.
*/
private function toRelativePath(string $path): string private function toRelativePath(string $path): string
{ {
// Remove cwd from the path.
return str_replace("$this->rootPath".DIRECTORY_SEPARATOR, '', $path); return str_replace("$this->rootPath".DIRECTORY_SEPARATOR, '', $path);
} }
/**
* Get the test result.
*/
public function getStateFromResult(PhpUnitTestResult $result): State public function getStateFromResult(PhpUnitTestResult $result): State
{ {
$events = [ $events = [
@@ -253,11 +198,9 @@ final readonly class Converter
foreach ($events as $event) { foreach ($events as $event) {
if ($event instanceof AfterLastTestMethodErrored) { if ($event instanceof AfterLastTestMethodErrored) {
// PHPUnit's collector does not count these towards `numberOfTestsRun`...
continue; continue;
} }
if ($event instanceof AfterLastTestMethodFailed) { if ($event instanceof AfterLastTestMethodFailed) {
// PHPUnit's collector does not count these towards `numberOfTestsRun`...
continue; continue;
} }
if ($event instanceof BeforeFirstTestMethodErrored || $event instanceof BeforeFirstTestMethodFailed) { if ($event instanceof BeforeFirstTestMethodErrored || $event instanceof BeforeFirstTestMethodFailed) {
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\Logging\TeamCity;
*/ */
final class ServiceMessage final class ServiceMessage
{ {
/**
* The flow ID.
*/
private static ?int $flowId = null; private static ?int $flowId = null;
/** /**
@@ -11,14 +11,8 @@ use Pest\Logging\TeamCity\TeamCityLogger;
*/ */
abstract class Subscriber // @pest-arch-ignore-line abstract class Subscriber // @pest-arch-ignore-line
{ {
/**
* Creates a new Subscriber instance.
*/
public function __construct(private readonly TeamCityLogger $logger) {} public function __construct(private readonly TeamCityLogger $logger) {}
/**
* Creates a new TeamCityLogger instance.
*/
final protected function logger(): TeamCityLogger // @pest-arch-ignore-line final protected function logger(): TeamCityLogger // @pest-arch-ignore-line
{ {
return $this->logger; return $this->logger;
@@ -15,7 +15,7 @@ final class TestSkippedSubscriber extends Subscriber implements SkippedSubscribe
public function notify(Skipped $event): void public function notify(Skipped $event): void
{ {
if ($event->message() === '__TODO__') { if ($event->message() === '__TODO__') {
return; // "todo" tests are reported in the summary, not as ignored tests... return;
} }
$this->logger()->testSkipped($event); $this->logger()->testSkipped($event);
-18
View File
@@ -43,14 +43,8 @@ use Symfony\Component\Console\Output\OutputInterface;
*/ */
final class TeamCityLogger final class TeamCityLogger
{ {
/**
* The current time.
*/
private ?HRTime $time = null; private ?HRTime $time = null;
/**
* Indicates if the summary test count has been printed.
*/
private bool $isSummaryTestCountPrinted = false; private bool $isSummaryTestCountPrinted = false;
/** /**
@@ -129,10 +123,6 @@ final class TeamCityLogger
}); });
} }
/**
* This will trigger in the following scenarios
* - When an exception is thrown
*/
public function testErrored(Errored $event): void public function testErrored(Errored $event): void
{ {
$this->whenFirstEventForTest($event->test(), function () use ($event): void { $this->whenFirstEventForTest($event->test(), function () use ($event): void {
@@ -150,10 +140,6 @@ final class TeamCityLogger
}); });
} }
/**
* This will trigger in the following scenarios
* - When an assertion fails
*/
public function testFailed(Failed $event): void public function testFailed(Failed $event): void
{ {
$this->whenFirstEventForTest($event->test(), function () use ($event): void { $this->whenFirstEventForTest($event->test(), function () use ($event): void {
@@ -182,10 +168,6 @@ final class TeamCityLogger
}); });
} }
/**
* This will trigger in the following scenarios
* - When no assertions in a test
*/
public function testConsideredRisky(ConsideredRisky $event): void public function testConsideredRisky(ConsideredRisky $event): void
{ {
$this->whenFirstEventForTest($event->test(), function () use ($event): void { $this->whenFirstEventForTest($event->test(), function () use ($event): void {
+1 -169
View File
@@ -38,27 +38,18 @@ use Traversable;
*/ */
final class Expectation final class Expectation
{ {
/**
* The exporter instance, if any.
*/
private ?Exporter $exporter = null; private ?Exporter $exporter = null;
/** /**
* Creates a new expectation.
*
* @param TValue $value * @param TValue $value
*/ */
public function __construct( public function __construct(
public mixed $value public mixed $value
) { ) {
// .. //
} }
/** /**
* Asserts that two variables have the same type and
* value. Used on objects, it asserts that two
* variables reference the same object.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBe(mixed $expected, string $message = ''): self public function toBe(mixed $expected, string $message = ''): self
@@ -69,8 +60,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is empty.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeEmpty(string $message = ''): self public function toBeEmpty(string $message = ''): self
@@ -81,8 +70,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is true.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeTrue(string $message = ''): self public function toBeTrue(string $message = ''): self
@@ -93,8 +80,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is truthy.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeTruthy(string $message = ''): self public function toBeTruthy(string $message = ''): self
@@ -105,8 +90,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is false.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeFalse(string $message = ''): self public function toBeFalse(string $message = ''): self
@@ -117,8 +100,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is falsy.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeFalsy(string $message = ''): self public function toBeFalsy(string $message = ''): self
@@ -129,8 +110,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is greater than $expected.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeGreaterThan(int|float|string|DateTimeInterface $expected, string $message = ''): self public function toBeGreaterThan(int|float|string|DateTimeInterface $expected, string $message = ''): self
@@ -141,8 +120,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is greater than or equal to $expected.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeGreaterThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self public function toBeGreaterThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self
@@ -153,8 +130,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is less than or equal to $expected.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeLessThan(int|float|string|DateTimeInterface $expected, string $message = ''): self public function toBeLessThan(int|float|string|DateTimeInterface $expected, string $message = ''): self
@@ -165,8 +140,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is less than $expected.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeLessThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self public function toBeLessThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self
@@ -177,8 +150,6 @@ final class Expectation
} }
/** /**
* Asserts that $needle is an element of the value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toContain(mixed ...$needles): self public function toContain(mixed ...$needles): self
@@ -198,8 +169,6 @@ final class Expectation
} }
/** /**
* Asserts that $needle equal an element of the value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toContainEqual(mixed ...$needles): self public function toContainEqual(mixed ...$needles): self
@@ -216,8 +185,6 @@ final class Expectation
} }
/** /**
* Asserts that the value starts with $expected.
*
* @param non-empty-string $expected * @param non-empty-string $expected
* @return self<TValue> * @return self<TValue>
*/ */
@@ -233,8 +200,6 @@ final class Expectation
} }
/** /**
* Asserts that the value ends with $expected.
*
* @param non-empty-string $expected * @param non-empty-string $expected
* @return self<TValue> * @return self<TValue>
*/ */
@@ -250,8 +215,6 @@ final class Expectation
} }
/** /**
* Asserts that $number matches value's Length.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveLength(int $number, string $message = ''): self public function toHaveLength(int $number, string $message = ''): self
@@ -278,8 +241,6 @@ final class Expectation
} }
/** /**
* Asserts that $count matches the number of elements of the value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveCount(int $count, string $message = ''): self public function toHaveCount(int $count, string $message = ''): self
@@ -294,8 +255,6 @@ final class Expectation
} }
/** /**
* Asserts that the size of the value and $expected are the same.
*
* @param Countable|iterable<mixed> $expected * @param Countable|iterable<mixed> $expected
* @return self<TValue> * @return self<TValue>
*/ */
@@ -311,8 +270,6 @@ final class Expectation
} }
/** /**
* Asserts that the value contains the property $name.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveProperty(string $name, mixed $value = new Any, string $message = ''): self public function toHaveProperty(string $name, mixed $value = new Any, string $message = ''): self
@@ -331,8 +288,6 @@ final class Expectation
} }
/** /**
* Asserts that the value contains the provided properties $names.
*
* @param iterable<string, mixed>|iterable<int, string> $names * @param iterable<string, mixed>|iterable<int, string> $names
* @return self<TValue> * @return self<TValue>
*/ */
@@ -346,8 +301,6 @@ final class Expectation
} }
/** /**
* Asserts that two variables have the same value.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toEqual(mixed $expected, string $message = ''): self public function toEqual(mixed $expected, string $message = ''): self
@@ -358,14 +311,6 @@ final class Expectation
} }
/** /**
* Asserts that two variables have the same value.
* The contents of $expected and the $this->value are
* canonicalized before they are compared. For instance, when the two
* variables $expected and $this->value are arrays, then these arrays
* are sorted before they are compared. When $expected and $this->value
* are objects, each object is converted to an array containing all
* private, protected and public attributes.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toEqualCanonicalizing(mixed $expected, string $message = ''): self public function toEqualCanonicalizing(mixed $expected, string $message = ''): self
@@ -376,9 +321,6 @@ final class Expectation
} }
/** /**
* Asserts that the absolute difference between the value and $expected
* is lower than $delta.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toEqualWithDelta(mixed $expected, float $delta, string $message = ''): self public function toEqualWithDelta(mixed $expected, float $delta, string $message = ''): self
@@ -389,8 +331,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is one of the given values.
*
* @param iterable<int|string, mixed> $values * @param iterable<int|string, mixed> $values
* @return self<TValue> * @return self<TValue>
*/ */
@@ -402,8 +342,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is infinite.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeInfinite(string $message = ''): self public function toBeInfinite(string $message = ''): self
@@ -414,8 +352,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is an instance of $class.
*
* @param class-string $class * @param class-string $class
* @return self<TValue> * @return self<TValue>
*/ */
@@ -427,8 +363,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is an array.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeArray(string $message = ''): self public function toBeArray(string $message = ''): self
@@ -439,8 +373,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a list.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeList(string $message = ''): self public function toBeList(string $message = ''): self
@@ -451,8 +383,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type bool.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeBool(string $message = ''): self public function toBeBool(string $message = ''): self
@@ -463,8 +393,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type callable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeCallable(string $message = ''): self public function toBeCallable(string $message = ''): self
@@ -475,8 +403,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type float.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeFloat(string $message = ''): self public function toBeFloat(string $message = ''): self
@@ -487,8 +413,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type int.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeInt(string $message = ''): self public function toBeInt(string $message = ''): self
@@ -499,8 +423,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type iterable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeIterable(string $message = ''): self public function toBeIterable(string $message = ''): self
@@ -511,8 +433,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type numeric.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeNumeric(string $message = ''): self public function toBeNumeric(string $message = ''): self
@@ -523,8 +443,6 @@ final class Expectation
} }
/** /**
* Asserts that the value contains only digits.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeDigits(string $message = ''): self public function toBeDigits(string $message = ''): self
@@ -535,8 +453,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type object.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeObject(string $message = ''): self public function toBeObject(string $message = ''): self
@@ -547,8 +463,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type resource.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeResource(string $message = ''): self public function toBeResource(string $message = ''): self
@@ -559,8 +473,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type scalar.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeScalar(string $message = ''): self public function toBeScalar(string $message = ''): self
@@ -571,8 +483,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is of type string.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeString(string $message = ''): self public function toBeString(string $message = ''): self
@@ -583,8 +493,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a JSON string.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeJson(string $message = ''): self public function toBeJson(string $message = ''): self
@@ -597,8 +505,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is NAN.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeNan(string $message = ''): self public function toBeNan(string $message = ''): self
@@ -609,8 +515,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is null.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeNull(string $message = ''): self public function toBeNull(string $message = ''): self
@@ -621,8 +525,6 @@ final class Expectation
} }
/** /**
* Asserts that the value array has the provided $key.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toHaveKey(string|int $key, mixed $value = new Any, string $message = ''): self public function toHaveKey(string|int $key, mixed $value = new Any, string $message = ''): self
@@ -653,8 +555,6 @@ final class Expectation
} }
/** /**
* Asserts that the value array has the provided $keys.
*
* @param array<int, int|string|array<array-key, mixed>> $keys * @param array<int, int|string|array<array-key, mixed>> $keys
* @return self<TValue> * @return self<TValue>
*/ */
@@ -672,8 +572,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a directory.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeDirectory(string $message = ''): self public function toBeDirectory(string $message = ''): self
@@ -688,8 +586,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a directory and is readable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeReadableDirectory(string $message = ''): self public function toBeReadableDirectory(string $message = ''): self
@@ -704,8 +600,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a directory and is writable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeWritableDirectory(string $message = ''): self public function toBeWritableDirectory(string $message = ''): self
@@ -720,8 +614,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a file.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeFile(string $message = ''): self public function toBeFile(string $message = ''): self
@@ -736,8 +628,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a file and is readable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeReadableFile(string $message = ''): self public function toBeReadableFile(string $message = ''): self
@@ -752,8 +642,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a file and is writable.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeWritableFile(string $message = ''): self public function toBeWritableFile(string $message = ''): self
@@ -767,8 +655,6 @@ final class Expectation
} }
/** /**
* Asserts that the value array matches the given array subset.
*
* @param iterable<int|string, mixed> $array * @param iterable<int|string, mixed> $array
* @return self<TValue> * @return self<TValue>
*/ */
@@ -796,9 +682,6 @@ final class Expectation
} }
/** /**
* Asserts that the value object matches a subset
* of the properties of an given object.
*
* @param iterable<string, mixed> $object * @param iterable<string, mixed> $object
* @return self<TValue> * @return self<TValue>
*/ */
@@ -827,8 +710,6 @@ final class Expectation
} }
/** /**
* Asserts that the value "stringable" matches the given snapshot..
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toMatchSnapshot(string $message = ''): self public function toMatchSnapshot(string $message = ''): self
@@ -883,8 +764,6 @@ final class Expectation
} }
/** /**
* Asserts that the value matches a regular expression.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toMatch(string $expression, string $message = ''): self public function toMatch(string $expression, string $message = ''): self
@@ -898,8 +777,6 @@ final class Expectation
} }
/** /**
* Asserts that the value matches a constraint.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toMatchConstraint(Constraint $constraint, string $message = ''): self public function toMatchConstraint(Constraint $constraint, string $message = ''): self
@@ -925,8 +802,6 @@ final class Expectation
} }
/** /**
* Asserts that executing value throws an exception.
*
* @param (Closure(Throwable): mixed)|string $exception * @param (Closure(Throwable): mixed)|string $exception
* @return self<TValue> * @return self<TValue>
*/ */
@@ -994,9 +869,6 @@ final class Expectation
throw new ExpectationFailedException("Exception \"$exception\" not thrown."); throw new ExpectationFailedException("Exception \"$exception\" not thrown.");
} }
/**
* Exports the given value.
*/
private function export(mixed $value): string private function export(mixed $value): string
{ {
if (! $this->exporter instanceof Exporter) { if (! $this->exporter instanceof Exporter) {
@@ -1007,8 +879,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is uppercase.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeUppercase(string $message = ''): self public function toBeUppercase(string $message = ''): self
@@ -1019,8 +889,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is lowercase.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeLowercase(string $message = ''): self public function toBeLowercase(string $message = ''): self
@@ -1031,8 +899,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is alphanumeric.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeAlphaNumeric(string $message = ''): self public function toBeAlphaNumeric(string $message = ''): self
@@ -1043,8 +909,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is alpha.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeAlpha(string $message = ''): self public function toBeAlpha(string $message = ''): self
@@ -1055,8 +919,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is snake_case.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeSnakeCase(string $message = ''): self public function toBeSnakeCase(string $message = ''): self
@@ -1073,8 +935,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is kebab-case.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeKebabCase(string $message = ''): self public function toBeKebabCase(string $message = ''): self
@@ -1091,8 +951,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is camelCase.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeCamelCase(string $message = ''): self public function toBeCamelCase(string $message = ''): self
@@ -1109,8 +967,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is StudlyCase.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeStudlyCase(string $message = ''): self public function toBeStudlyCase(string $message = ''): self
@@ -1127,8 +983,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is UUID.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeUuid(string $message = ''): self public function toBeUuid(string $message = ''): self
@@ -1143,8 +997,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a ULID.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeUlid(string $message = ''): self public function toBeUlid(string $message = ''): self
@@ -1159,8 +1011,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is between 2 specified values
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeBetween(int|float|DateTimeInterface $lowestValue, int|float|DateTimeInterface $highestValue, string $message = ''): self public function toBeBetween(int|float|DateTimeInterface $lowestValue, int|float|DateTimeInterface $highestValue, string $message = ''): self
@@ -1172,8 +1022,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is an email address.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeEmail(string $message = ''): self public function toBeEmail(string $message = ''): self
@@ -1188,8 +1036,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a url
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeUrl(string $message = ''): self public function toBeUrl(string $message = ''): self
@@ -1204,8 +1050,6 @@ final class Expectation
} }
/** /**
* Asserts that the value can be converted to a slug
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeSlug(string $message = ''): self public function toBeSlug(string $message = ''): self
@@ -1221,8 +1065,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is an IP address.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeIpAddress(string $message = ''): self public function toBeIpAddress(string $message = ''): self
@@ -1237,8 +1079,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a MAC address.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeMacAddress(string $message = ''): self public function toBeMacAddress(string $message = ''): self
@@ -1253,8 +1093,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a hostname.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeHostname(string $message = ''): self public function toBeHostname(string $message = ''): self
@@ -1269,8 +1107,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a domain name.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeDomain(string $message = ''): self public function toBeDomain(string $message = ''): self
@@ -1288,8 +1124,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a base64-encoded string.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeBase64(string $message = ''): self public function toBeBase64(string $message = ''): self
@@ -1305,8 +1139,6 @@ final class Expectation
} }
/** /**
* Asserts that the value is a hexadecimal string.
*
* @return self<TValue> * @return self<TValue>
*/ */
public function toBeHexadecimal(string $message = ''): self public function toBeHexadecimal(string $message = ''): self
@@ -15,12 +15,6 @@ use PHPStan\Type\ObjectType;
use PHPStan\Type\Type; use PHPStan\Type\Type;
/** /**
* Prevents native declared properties of HigherOrderExpectation (like $original,
* $expectation, $opposite, $shouldReset) from being incorrectly resolved as
* higher-order value property accesses by downstream ExpressionTypeResolverExtensions.
*
* This extension must be registered BEFORE the pest-plugin-phpstan HigherOrderExpectationTypeExtension.
*
* @internal * @internal
*/ */
final readonly class HigherOrderExpectationTypeExtension implements ExpressionTypeResolverExtension final readonly class HigherOrderExpectationTypeExtension implements ExpressionTypeResolverExtension
+1 -10
View File
@@ -14,18 +14,12 @@ use Whoops\Exception\Inspector;
final readonly class Panic final readonly class Panic
{ {
/**
* Creates a new Panic instance.
*/
private function __construct( private function __construct(
private Throwable $throwable private Throwable $throwable
) { ) {
// ... //
} }
/**
* Creates a new Panic instance, and exits the application.
*/
public static function with(Throwable $throwable): never public static function with(Throwable $throwable): never
{ {
if ($throwable instanceof TestDescriptionMissing && ! is_null($previous = $throwable->getPrevious())) { if ($throwable instanceof TestDescriptionMissing && ! is_null($previous = $throwable->getPrevious())) {
@@ -39,9 +33,6 @@ final readonly class Panic
exit(1); exit(1);
} }
/**
* Handles the panic.
*/
private function handle(): void private function handle(): void
{ {
try { try {
-14
View File
@@ -20,19 +20,10 @@ final class AfterEachCall
{ {
use Describable; use Describable;
/**
* The "afterEach" closure.
*/
private readonly Closure $closure; private readonly Closure $closure;
/**
* The calls that should be proxied.
*/
private readonly HigherOrderMessageCollection $proxies; private readonly HigherOrderMessageCollection $proxies;
/**
* Creates a new Pending Call.
*/
public function __construct( public function __construct(
private readonly TestSuite $testSuite, private readonly TestSuite $testSuite,
private readonly string $filename, private readonly string $filename,
@@ -45,9 +36,6 @@ final class AfterEachCall
$this->describing = DescribeCall::describing(); $this->describing = DescribeCall::describing();
} }
/**
* Creates the Call.
*/
public function __destruct() public function __destruct()
{ {
$describing = $this->describing; $describing = $this->describing;
@@ -69,8 +57,6 @@ final class AfterEachCall
} }
/** /**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): self public function __call(string $name, array $arguments): self
-20
View File
@@ -23,24 +23,12 @@ final class BeforeEachCall
{ {
use Describable; use Describable;
/**
* Holds the before each closure.
*/
private readonly Closure $closure; private readonly Closure $closure;
/**
* The test call proxies.
*/
private readonly HigherOrderMessageCollection $testCallProxies; private readonly HigherOrderMessageCollection $testCallProxies;
/**
* The test case proxies.
*/
private readonly HigherOrderMessageCollection $testCaseProxies; private readonly HigherOrderMessageCollection $testCaseProxies;
/**
* Creates a new Pending Call.
*/
public function __construct( public function __construct(
public readonly TestSuite $testSuite, public readonly TestSuite $testSuite,
private readonly string $filename, private readonly string $filename,
@@ -54,9 +42,6 @@ final class BeforeEachCall
$this->describing = DescribeCall::describing(); $this->describing = DescribeCall::describing();
} }
/**
* Creates the Call.
*/
public function __destruct() public function __destruct()
{ {
$describing = $this->describing; $describing = $this->describing;
@@ -92,9 +77,6 @@ final class BeforeEachCall
); );
} }
/**
* Runs the given closure after the test.
*/
public function after(Closure $closure): self public function after(Closure $closure): self
{ {
if ($this->describing === []) { if ($this->describing === []) {
@@ -105,8 +87,6 @@ final class BeforeEachCall
} }
/** /**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): self public function __call(string $name, array $arguments): self
@@ -12,15 +12,11 @@ use Pest\Support\Description;
trait Describable trait Describable
{ {
/** /**
* Note: this is property is not used; however, it gets added automatically by rector php.
*
* @var array<int, Description> * @var array<int, Description>
*/ */
public array $__describing; public array $__describing;
/** /**
* The describing of the test case.
*
* @var array<int, Description> * @var array<int, Description>
*/ */
public array $describing = []; public array $describing = [];
+1 -19
View File
@@ -14,20 +14,12 @@ use Pest\TestSuite;
final class DescribeCall final class DescribeCall
{ {
/** /**
* The current describe call.
*
* @var array<int, Description> * @var array<int, Description>
*/ */
private static array $describing = []; private static array $describing = [];
/**
* The describe "before each" call.
*/
private ?BeforeEachCall $currentBeforeEachCall = null; private ?BeforeEachCall $currentBeforeEachCall = null;
/**
* Creates a new Pending Call.
*/
public function __construct( public function __construct(
public readonly TestSuite $testSuite, public readonly TestSuite $testSuite,
public readonly string $filename, public readonly string $filename,
@@ -38,8 +30,6 @@ final class DescribeCall
} }
/** /**
* What is the current describing.
*
* @return array<int, Description> * @return array<int, Description>
*/ */
public static function describing(): array public static function describing(): array
@@ -47,17 +37,11 @@ final class DescribeCall
return self::$describing; return self::$describing;
} }
/**
* Creates the Call.
*/
public function __destruct() public function __destruct()
{ {
// Ensure BeforeEachCall destructs before creating tests
// by moving to local scope and clearing the reference
$beforeEach = $this->currentBeforeEachCall; $beforeEach = $this->currentBeforeEachCall;
$this->currentBeforeEachCall = null; $this->currentBeforeEachCall = null;
unset($beforeEach); // Trigger destructor immediately unset($beforeEach);
self::$describing[] = $this->description; self::$describing[] = $this->description;
try { try {
@@ -68,8 +52,6 @@ final class DescribeCall
} }
/** /**
* Dynamically calls methods on each test call.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): self public function __call(string $name, array $arguments): self
-126
View File
@@ -38,25 +38,14 @@ final class TestCall // @phpstan-ignore-line
use Describable; use Describable;
/** /**
* The list of test case factory attributes.
*
* @var array<int, Attribute> * @var array<int, Attribute>
*/ */
private array $testCaseFactoryAttributes = []; private array $testCaseFactoryAttributes = [];
/**
* The Test Case Factory.
*/
public readonly TestCaseMethodFactory $testCaseMethod; public readonly TestCaseMethodFactory $testCaseMethod;
/**
* If test call is descriptionLess.
*/
private readonly bool $descriptionLess; private readonly bool $descriptionLess;
/**
* Creates a new Pending Call.
*/
public function __construct( public function __construct(
private readonly TestSuite $testSuite, private readonly TestSuite $testSuite,
private readonly string $filename, private readonly string $filename,
@@ -72,9 +61,6 @@ final class TestCall // @phpstan-ignore-line
$this->testSuite->beforeEach->get($this->filename)[0]($this); $this->testSuite->beforeEach->get($this->filename)[0]($this);
} }
/**
* Runs the given closure after the test.
*/
public function after(Closure $closure): self public function after(Closure $closure): self
{ {
if ($this->description === null) { if ($this->description === null) {
@@ -108,17 +94,11 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Asserts that the test fails with the given message.
*/
public function fails(?string $message = null): self public function fails(?string $message = null): self
{ {
return $this->throws(AssertionFailedError::class, $message); return $this->throws(AssertionFailedError::class, $message);
} }
/**
* Asserts that the test throws the given `$exceptionClass` when called.
*/
public function throws(string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self public function throws(string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self
{ {
if (is_int($exception)) { if (is_int($exception)) {
@@ -147,8 +127,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Asserts that the test throws the given `$exceptionClass` when called if the given condition is true.
*
* @param (callable(): bool)|bool $condition * @param (callable(): bool)|bool $condition
*/ */
public function throwsIf(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self public function throwsIf(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self
@@ -165,8 +143,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Asserts that the test throws the given `$exceptionClass` when called if the given condition is false.
*
* @param (callable(): bool)|bool $condition * @param (callable(): bool)|bool $condition
*/ */
public function throwsUnless(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self public function throwsUnless(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self
@@ -183,8 +159,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Runs the current test multiple times with each item of the given `iterable`.
*
* @param Closure|iterable<array-key, mixed>|string $data * @param Closure|iterable<array-key, mixed>|string $data
*/ */
public function with(Closure|iterable|string ...$data): self public function with(Closure|iterable|string ...$data): self
@@ -196,9 +170,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the test depends.
*/
public function depends(string ...$depends): self public function depends(string ...$depends): self
{ {
foreach ($depends as $depend) { foreach ($depends as $depend) {
@@ -208,9 +179,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the test group(s).
*/
public function group(string ...$groups): self public function group(string ...$groups): self
{ {
foreach ($groups as $group) { foreach ($groups as $group) {
@@ -223,9 +191,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Filters the test suite by "only" tests.
*/
public function only(): self public function only(): self
{ {
Only::enable($this, ...func_get_args()); Only::enable($this, ...func_get_args());
@@ -233,9 +198,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Skips the current test.
*/
public function skip(Closure|bool|string $conditionOrMessage = true, string $message = ''): self public function skip(Closure|bool|string $conditionOrMessage = true, string $message = ''): self
{ {
$condition = is_string($conditionOrMessage) $condition = is_string($conditionOrMessage)
@@ -260,9 +222,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Skips the current test on the given PHP version.
*/
public function skipOnPhp(string $version): self public function skipOnPhp(string $version): self
{ {
if (mb_strlen($version) < 2) { if (mb_strlen($version) < 2) {
@@ -275,7 +234,6 @@ final class TestCall // @phpstan-ignore-line
} elseif (str_starts_with($version, '>') || str_starts_with($version, '<')) { } elseif (str_starts_with($version, '>') || str_starts_with($version, '<')) {
$operator = $version[0]; $operator = $version[0];
$version = substr($version, 1); $version = substr($version, 1);
// ensure starts with number:
} elseif (is_numeric($version[0])) { } elseif (is_numeric($version[0])) {
$operator = '=='; $operator = '==';
} else { } else {
@@ -285,33 +243,21 @@ final class TestCall // @phpstan-ignore-line
return $this->skip(version_compare(PHP_VERSION, $version, $operator), sprintf('This test is skipped on PHP [%s%s].', $operator, $version)); return $this->skip(version_compare(PHP_VERSION, $version, $operator), sprintf('This test is skipped on PHP [%s%s].', $operator, $version));
} }
/**
* Skips the current test if the given test is running on Windows.
*/
public function skipOnWindows(): self public function skipOnWindows(): self
{ {
return $this->skipOnOs('Windows', 'This test is skipped on [Windows].'); return $this->skipOnOs('Windows', 'This test is skipped on [Windows].');
} }
/**
* Skips the current test if the given test is running on Mac OS.
*/
public function skipOnMac(): self public function skipOnMac(): self
{ {
return $this->skipOnOs('Darwin', 'This test is skipped on [Mac].'); return $this->skipOnOs('Darwin', 'This test is skipped on [Mac].');
} }
/**
* Skips the current test if the given test is running on Linux.
*/
public function skipOnLinux(): self public function skipOnLinux(): self
{ {
return $this->skipOnOs('Linux', 'This test is skipped on [Linux].'); return $this->skipOnOs('Linux', 'This test is skipped on [Linux].');
} }
/**
* Skips the current test if the given test is running on the given operating systems.
*/
private function skipOnOs(string $osFamily, string $message): self private function skipOnOs(string $osFamily, string $message): self
{ {
return $osFamily === PHP_OS_FAMILY return $osFamily === PHP_OS_FAMILY
@@ -319,9 +265,6 @@ final class TestCall // @phpstan-ignore-line
: $this; : $this;
} }
/**
* Weather the current test is running on a CI environment.
*/
private function runningOnCI(): bool private function runningOnCI(): bool
{ {
foreach ([ foreach ([
@@ -353,9 +296,6 @@ final class TestCall // @phpstan-ignore-line
return Environment::name() === Environment::CI; return Environment::name() === Environment::CI;
} }
/**
* Skips the current test when running on a CI environments.
*/
public function skipOnCI(): self public function skipOnCI(): self
{ {
if ($this->runningOnCI()) { if ($this->runningOnCI()) {
@@ -374,33 +314,21 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Skips the current test unless the given test is running on Windows.
*/
public function onlyOnWindows(): self public function onlyOnWindows(): self
{ {
return $this->skipOnMac()->skipOnLinux(); return $this->skipOnMac()->skipOnLinux();
} }
/**
* Skips the current test unless the given test is running on Mac.
*/
public function onlyOnMac(): self public function onlyOnMac(): self
{ {
return $this->skipOnWindows()->skipOnLinux(); return $this->skipOnWindows()->skipOnLinux();
} }
/**
* Skips the current test unless the given test is running on Linux.
*/
public function onlyOnLinux(): self public function onlyOnLinux(): self
{ {
return $this->skipOnWindows()->skipOnMac(); return $this->skipOnWindows()->skipOnMac();
} }
/**
* Repeats the current test the given number of times.
*/
public function repeat(int $times): self public function repeat(int $times): self
{ {
if ($times < 1) { if ($times < 1) {
@@ -412,9 +340,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Marks the test as flaky, retrying it up to the given number of times.
*/
public function flaky(int $tries = 3): self public function flaky(int $tries = 3): self
{ {
if ($tries < 1) { if ($tries < 1) {
@@ -426,9 +351,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Marks the test as "todo".
*/
public function todo(// @phpstan-ignore-line public function todo(// @phpstan-ignore-line
array|string|null $note = null, array|string|null $note = null,
array|string|null $assignee = null, array|string|null $assignee = null,
@@ -458,9 +380,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the test as "work in progress".
*/
public function wip(// @phpstan-ignore-line public function wip(// @phpstan-ignore-line
array|string|null $note = null, array|string|null $note = null,
array|string|null $assignee = null, array|string|null $assignee = null,
@@ -486,9 +405,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the test as "done".
*/
public function done(// @phpstan-ignore-line public function done(// @phpstan-ignore-line
array|string|null $note = null, array|string|null $note = null,
array|string|null $assignee = null, array|string|null $assignee = null,
@@ -515,8 +431,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Associates the test with the given issue(s).
*
* @param array<int, string|int>|string|int $number * @param array<int, string|int>|string|int $number
*/ */
public function issue(array|string|int $number): self public function issue(array|string|int $number): self
@@ -531,8 +445,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Associates the test with the given ticket(s). (Alias for `issue`)
*
* @param array<int, string|int>|string|int $number * @param array<int, string|int>|string|int $number
*/ */
public function ticket(array|string|int $number): self public function ticket(array|string|int $number): self
@@ -541,8 +453,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Sets the test assignee(s).
*
* @param array<int, string>|string $assignee * @param array<int, string>|string $assignee
*/ */
public function assignee(array|string $assignee): self public function assignee(array|string $assignee): self
@@ -555,8 +465,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Associates the test with the given pull request(s).
*
* @param array<int, string|int>|string|int $number * @param array<int, string|int>|string|int $number
*/ */
public function pr(array|string|int $number): self public function pr(array|string|int $number): self
@@ -571,8 +479,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Adds a note to the test.
*
* @param array<int, string>|string $note * @param array<int, string>|string $note
*/ */
public function note(array|string $note): self public function note(array|string $note): self
@@ -585,8 +491,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Sets the covered classes or methods.
*
* @param array<int, string>|string $classesOrFunctions * @param array<int, string>|string $classesOrFunctions
*/ */
public function covers(array|string ...$classesOrFunctions): self public function covers(array|string ...$classesOrFunctions): self
@@ -615,9 +519,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the covered classes.
*/
public function coversClass(string ...$classes): self public function coversClass(string ...$classes): self
{ {
foreach ($classes as $class) { foreach ($classes as $class) {
@@ -638,9 +539,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the covered classes.
*/
public function coversTrait(string ...$traits): self public function coversTrait(string ...$traits): self
{ {
foreach ($traits as $trait) { foreach ($traits as $trait) {
@@ -661,9 +559,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Sets the covered functions.
*/
public function coversFunction(string ...$functions): self public function coversFunction(string ...$functions): self
{ {
foreach ($functions as $function) { foreach ($functions as $function) {
@@ -677,9 +572,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Adds one or more references to the tested method or class. This helps
* to link test cases to the source code for easier navigation.
*
* @param array<class-string|string>|class-string ...$classes * @param array<class-string|string>|class-string ...$classes
*/ */
public function references(string|array ...$classes): self public function references(string|array ...$classes): self
@@ -690,9 +582,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Adds one or more references to the tested method or class. This helps
* to link test cases to the source code for easier navigation.
*
* @param array<class-string|string>|class-string ...$classes * @param array<class-string|string>|class-string ...$classes
*/ */
public function see(string|array ...$classes): self public function see(string|array ...$classes): self
@@ -700,11 +589,6 @@ final class TestCall // @phpstan-ignore-line
return $this->references(...$classes); return $this->references(...$classes);
} }
/**
* Informs the test runner that no expectations happen in this test,
* and its purpose is simply to check whether the given code can
* be executed without throwing exceptions.
*/
public function throwsNoExceptions(): self public function throwsNoExceptions(): self
{ {
$this->testCaseMethod->proxies->add(Backtrace::file(), Backtrace::line(), 'expectNotToPerformAssertions', []); $this->testCaseMethod->proxies->add(Backtrace::file(), Backtrace::line(), 'expectNotToPerformAssertions', []);
@@ -712,17 +596,12 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Saves the property accessors to be used on the target.
*/
public function __get(string $name): self public function __get(string $name): self
{ {
return $this->addChain(Backtrace::file(), Backtrace::line(), $name); return $this->addChain(Backtrace::file(), Backtrace::line(), $name);
} }
/** /**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): self public function __call(string $name, array $arguments): self
@@ -731,8 +610,6 @@ final class TestCall // @phpstan-ignore-line
} }
/** /**
* Add a chain to the test case factory. Omitting the arguments will treat it as a property accessor.
*
* @param array<int, mixed>|null $arguments * @param array<int, mixed>|null $arguments
*/ */
private function addChain(string $file, int $line, string $name, ?array $arguments = null): self private function addChain(string $file, int $line, string $name, ?array $arguments = null): self
@@ -758,9 +635,6 @@ final class TestCall // @phpstan-ignore-line
return $this; return $this;
} }
/**
* Creates the Call.
*/
public function __destruct() public function __destruct()
{ {
if ($this->description === null) { if ($this->description === null) {
-41
View File
@@ -14,36 +14,21 @@ use Pest\TestSuite;
final class UsesCall final class UsesCall
{ {
/** /**
* Contains a global before each hook closure to be executed.
*
* Array indices here matter. They are mapped as follows:
*
* - `0` => `beforeAll`
* - `1` => `beforeEach`
* - `2` => `afterEach`
* - `3` => `afterAll`
*
* @var array<int, Closure> * @var array<int, Closure>
*/ */
private array $hooks = []; private array $hooks = [];
/** /**
* Holds the targets of the uses.
*
* @var array<int, string> * @var array<int, string>
*/ */
private array $targets; private array $targets;
/** /**
* Holds the groups of the uses.
*
* @var array<int, string> * @var array<int, string>
*/ */
private array $groups = []; private array $groups = [];
/** /**
* Creates a new Pending Call.
*
* @param array<int, string> $classAndTraits * @param array<int, string> $classAndTraits
*/ */
public function __construct( public function __construct(
@@ -62,8 +47,6 @@ final class UsesCall
} }
/** /**
* Specifies the class or traits to use.
*
* @alias extend * @alias extend
*/ */
public function use(string ...$classAndTraits): self public function use(string ...$classAndTraits): self
@@ -71,9 +54,6 @@ final class UsesCall
return $this->extend(...$classAndTraits); return $this->extend(...$classAndTraits);
} }
/**
* Specifies the class or traits to use.
*/
public function extend(string ...$classAndTraits): self public function extend(string ...$classAndTraits): self
{ {
$this->classAndTraits = array_merge($this->classAndTraits, array_values($classAndTraits)); $this->classAndTraits = array_merge($this->classAndTraits, array_values($classAndTraits));
@@ -81,9 +61,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* The directories or file where the class or traits should be used.
*/
public function in(string ...$targets): self public function in(string ...$targets): self
{ {
$targets = array_map(function (string $path): string { $targets = array_map(function (string $path): string {
@@ -116,9 +93,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Sets the test group(s).
*/
public function group(string ...$groups): self public function group(string ...$groups): self
{ {
$this->groups = array_values($groups); $this->groups = array_values($groups);
@@ -126,9 +100,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Sets the global beforeAll test hook.
*/
public function beforeAll(Closure $hook): self public function beforeAll(Closure $hook): self
{ {
$this->hooks[0] = $hook; $this->hooks[0] = $hook;
@@ -136,9 +107,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Sets the global beforeEach test hook.
*/
public function beforeEach(Closure $hook): self public function beforeEach(Closure $hook): self
{ {
$this->hooks[1] = $hook; $this->hooks[1] = $hook;
@@ -146,9 +114,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Sets the global afterEach test hook.
*/
public function afterEach(Closure $hook): self public function afterEach(Closure $hook): self
{ {
$this->hooks[2] = $hook; $this->hooks[2] = $hook;
@@ -156,9 +121,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Sets the global afterAll test hook.
*/
public function afterAll(Closure $hook): self public function afterAll(Closure $hook): self
{ {
$this->hooks[3] = $hook; $this->hooks[3] = $hook;
@@ -166,9 +128,6 @@ final class UsesCall
return $this; return $this;
} }
/**
* Creates the Call.
*/
public function __destruct() public function __destruct()
{ {
TestSuite::getInstance()->tests->use( TestSuite::getInstance()->tests->use(
+1 -1
View File
@@ -6,7 +6,7 @@ namespace Pest;
function version(): string function version(): string
{ {
return '5.0.4'; return '5.0.5';
} }
function testDirectory(string $file = ''): string function testDirectory(string $file = ''): string
-4
View File
@@ -7,8 +7,6 @@ namespace Pest;
final class Plugin final class Plugin
{ {
/** /**
* The lazy callables to be executed once the test suite boots.
*
* @var array<int, callable> * @var array<int, callable>
* *
* @internal * @internal
@@ -16,8 +14,6 @@ final class Plugin
public static array $callables = []; public static array $callables = [];
/** /**
* Lazy loads an `uses` call on the context of plugins.
*
* @param class-string ...$traits * @param class-string ...$traits
*/ */
public static function uses(string ...$traits): void public static function uses(string ...$traits): void

Some files were not shown because too many files have changed in this diff Show More