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;
}
// It must be a 1 byte string to ensure filesize() is equal to the number of tests executed
$exitCode = $application->runTest(realpath(trim($testPath)));
fwrite($statusFile, (string) $exitCode);
+1 -1
View File
@@ -62,7 +62,7 @@
"pestphp/pest-dev-tools": "^5.0.0",
"pestphp/pest-plugin-browser": "^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",
"psy/psysh": "^0.12.24"
},
@@ -1,37 +1,5 @@
<?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);
/*
+13 -51
View File
@@ -1,37 +1,5 @@
<?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);
/*
@@ -86,7 +54,7 @@ final class JunitXmlLogger
{
private readonly Printer $printer;
private readonly Converter $converter; // pest-added
private readonly Converter $converter;
private DOMDocument $document;
@@ -144,8 +112,7 @@ final class JunitXmlLogger
public function __construct(Printer $printer, Facade $facade)
{
$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->createDocument();
}
@@ -160,10 +127,9 @@ final class JunitXmlLogger
public function testSuiteStarted(Started $event): void
{
$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()) {
$testSuite->setAttribute('file', $this->converter->getTestSuiteLocation($event->testSuite()) ?? ''); // pest-changed
$testSuite->setAttribute('file', $this->converter->getTestSuiteLocation($event->testSuite()) ?? '');
}
if ($this->testSuiteLevel > 0) {
@@ -380,12 +346,11 @@ final class JunitXmlLogger
assert($this->currentTestCase !== null);
$buffer = $this->converter->getTestCaseMethodName($event->test()); // pest-changed
$buffer = $this->converter->getTestCaseMethodName($event->test());
$throwable = $event->throwable();
$buffer .= trim(
$this->converter->getExceptionMessage($throwable).PHP_EOL. // pest-changed
$this->converter->getExceptionDetails($throwable), // pest-changed
$this->converter->getExceptionMessage($throwable).PHP_EOL.
$this->converter->getExceptionDetails($throwable),
);
$fault = $this->document->createElement(
@@ -485,18 +450,15 @@ final class JunitXmlLogger
$testCase = $this->document->createElement('testcase');
$test = $event->test();
$file = $this->converter->getTestCaseLocation($test); // pest-added
$testCase->setAttribute('name', $this->converter->getTestCaseMethodName($test)); // pest-changed
$testCase->setAttribute('file', $file); // pest-changed
$file = $this->converter->getTestCaseLocation($test);
$testCase->setAttribute('name', $this->converter->getTestCaseMethodName($test));
$testCase->setAttribute('file', $file);
if ($test->isTestMethod()) {
assert($test instanceof TestMethod);
// $testCase->setAttribute('line', (string) $test->line()); // pest-removed
$className = $this->converter->getTrimmedTestClassName($test); // pest-added
$testCase->setAttribute('class', $className); // pest-changed
$testCase->setAttribute('classname', str_replace('\\', '.', $className)); // pest-changed
$className = $this->converter->getTrimmedTestClassName($test);
$testCase->setAttribute('class', $className);
$testCase->setAttribute('classname', str_replace('\\', '.', $className));
}
$this->currentTestCase = $testCase;
@@ -1,29 +1,5 @@
<?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);
namespace ParaTest\WrapperRunner;
@@ -34,10 +10,6 @@ use function preg_match;
/**
* @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
{
@@ -48,7 +20,6 @@ final readonly class ProgressPrinterOutput implements Printer
public function print(string $buffer): void
{
// Skip anything in \PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter::printProgress except $progress
if (
$buffer === "\n"
|| preg_match('/^ +$/', $buffer) === 1
+1 -38
View File
@@ -1,37 +1,5 @@
<?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);
/*
@@ -129,9 +97,6 @@ abstract class NameFilterIterator extends RecursiveFilterIterator
$dataSetMaximum = null;
if (@preg_match($filter, '') === false) {
// Handles:
// * testAssertEqualsSucceeds#4
// * testAssertEqualsSucceeds#4-8
if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) {
if (isset($matches[3]) && $matches[2] < $matches[3]) {
$filter = sprintf(
@@ -148,7 +113,7 @@ abstract class NameFilterIterator extends RecursiveFilterIterator
$matches[2],
);
}
} // Handles:
}
// * testDetermineJsonError@JSON_ERROR_NONE
// * testDetermineJsonError@JSON.*
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(
'/%s/i',
str_replace(
@@ -1,37 +1,5 @@
<?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);
/*
@@ -196,9 +164,6 @@ final class DefaultResultCache implements ResultCache
);
}
/**
* Returns the cache version.
*/
private function cacheVersion(): string
{
return 'pest_'.version();
-32
View File
@@ -1,37 +1,5 @@
<?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);
namespace PHPUnit\Runner;
-70
View File
@@ -1,37 +1,5 @@
<?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);
/*
@@ -256,13 +224,6 @@ final class TestSuiteSorter
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
{
assert($a instanceof Reorderable);
@@ -272,7 +233,6 @@ final class TestSuiteSorter
$priorityB = $this->defectSortOrder[$b->sortId()] ?? 0;
if ($priorityA !== $priorityB) {
// Sort defect weight descending
return $priorityB <=> $priorityA;
}
@@ -280,13 +240,9 @@ final class TestSuiteSorter
return $this->cmpDuration($a, $b);
}
// do not change execution order
return 0;
}
/**
* Compares test duration for sorting tests by duration ascending.
*/
private function cmpDuration(Test $a, Test $b): int
{
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));
}
/**
* Compares test size for sorting tests small->medium->large->unknown.
*/
private function cmpSize(Test $a, Test $b): int
{
$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
* @return array<TestCase>
*/
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`.
if (! $this->anyTestHasDependencies($tests)) {
return $tests;
@@ -361,10 +295,6 @@ final class TestSuiteSorter
/**
* 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
*/
private function anyTestHasDependencies(iterable $tests): bool
@@ -1,37 +1,5 @@
<?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);
/*
@@ -1,37 +1,5 @@
<?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);
/*
@@ -51,10 +19,6 @@ use ReflectionClass;
/**
* @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
{
@@ -67,9 +31,6 @@ final readonly class TestSkippedSubscriber extends Subscriber implements Skipped
$this->printer()->testSkipped();
}
/**
* Prints a "T" to the standard PHPUnit output to indicate a todo item.
*/
private function printTodoItem(): void
{
$mirror = new ReflectionClass($this->printer());
@@ -1,37 +1,5 @@
<?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);
/*
* This file is part of PHPUnit.
+4 -1
View File
@@ -1,5 +1,8 @@
{
"exclude": [
"tests/Fixtures/Suites"
]
],
"rules": {
"Pint/phpdoc_type_annotations_only": true
}
}
-6
View File
@@ -38,13 +38,7 @@ return RectorConfig::configure()
RemoveReturnTagIncompatibleWithNativeTypeRector::class => [
__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,
// 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 => [
__DIR__.'/tests',
],
-13
View File
@@ -13,15 +13,11 @@ use Pest\Expectation;
abstract class AbstractPreset // @pest-arch-ignore-line
{
/**
* The expectations.
*
* @var array<int, Expectation<mixed>|ArchExpectation>
*/
protected array $expectations = [];
/**
* Creates a new preset instance.
*
* @param array<int, string> $userNamespaces
*/
public function __construct(
@@ -31,15 +27,11 @@ abstract class AbstractPreset // @pest-arch-ignore-line
}
/**
* Executes the arch preset.
*
* @internal
*/
abstract public function execute(): void;
/**
* Ignores the given "targets" or "dependencies".
*
* @param array<int, string>|string $targetsOrDependencies
*/
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
*/
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
{
$this->expectations = [];
-8
View File
@@ -14,8 +14,6 @@ use Pest\Expectation;
final class Custom extends AbstractPreset
{
/**
* Creates a new preset instance.
*
* @param array<int, string> $userNamespaces
* @param Closure(array<int, string>): array<Expectation<mixed>|ArchExpectation> $execute
*/
@@ -27,17 +25,11 @@ final class Custom extends AbstractPreset
parent::__construct($userNamespaces);
}
/**
* Returns the name of the preset.
*/
public function name(): string
{
return $this->name;
}
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->expectations = ($this->execute)($this->userNamespaces);
-3
View File
@@ -11,9 +11,6 @@ use Throwable;
*/
final class Laravel extends AbstractPreset
{
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->expectations[] = expect('App\Traits')
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\ArchPresets;
*/
final class Php extends AbstractPreset
{
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->expectations[] = expect([
-3
View File
@@ -12,9 +12,6 @@ use Pest\Expectation;
*/
final class Relaxed extends AbstractPreset
{
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->eachUserNamespace(
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\ArchPresets;
*/
final class Security extends AbstractPreset
{
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->expectations[] = expect([
-3
View File
@@ -12,9 +12,6 @@ use Pest\Expectation;
*/
final class Strict extends AbstractPreset
{
/**
* Executes the arch preset.
*/
public function execute(): void
{
$this->eachUserNamespace(
-5
View File
@@ -13,8 +13,6 @@ use PHPUnit\Util\ExcludeList;
final class BootExcludeList implements Bootstrapper
{
/**
* The directories to exclude.
*
* @var array<int, non-empty-string>
*/
private const array EXCLUDE_LIST = [
@@ -25,9 +23,6 @@ final class BootExcludeList implements Bootstrapper
'stubs',
];
/**
* Boots the "exclude list" for PHPUnit to ignore Pest files.
*/
public function boot(): void
{
$baseDirectory = dirname(__DIR__, 2);
-8
View File
@@ -21,8 +21,6 @@ use function Pest\testDirectory;
final class BootFiles implements Bootstrapper
{
/**
* The structure of the tests directory.
*
* @var array<int, string>
*/
private const array STRUCTURE = [
@@ -33,9 +31,6 @@ final class BootFiles implements Bootstrapper
'Pest.php',
];
/**
* Boots the structure of the tests directory.
*/
public function boot(): void
{
$rootPath = TestSuite::getInstance()->rootPath;
@@ -67,9 +62,6 @@ final class BootFiles implements Bootstrapper
$this->bootDatasets($testsPath);
}
/**
* Loads, if possible, the given file.
*/
private function load(string $filename): void
{
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
{
/**
* Creates a new Boot Kernel Dump instance.
*/
public function __construct(
private OutputInterface $output,
) {
// ...
//
}
/**
* Boots the kernel dump.
*/
public function boot(): void
{
Container::getInstance()->add(KernelDump::class, $kernelDump = new KernelDump(
-5
View File
@@ -13,8 +13,6 @@ use Pest\Exceptions\ShouldNotHappen;
final class BootOverrides implements Bootstrapper
{
/**
* The list of files to be overridden.
*
* @var array<int, string>
*/
public const array FILES = [
@@ -30,9 +28,6 @@ final class BootOverrides implements Bootstrapper
'Logging/JUnit/JunitXmlLogger.php',
];
/**
* Boots the list of files to be overridden.
*/
public function boot(): void
{
foreach (self::FILES as $file) {
-8
View File
@@ -16,8 +16,6 @@ use PHPUnit\Event\Subscriber;
final readonly class BootSubscribers implements Bootstrapper
{
/**
* The list of Subscribers.
*
* @var array<int, class-string<Subscriber>>
*/
private const array SUBSCRIBERS = [
@@ -44,16 +42,10 @@ final readonly class BootSubscribers implements Bootstrapper
Subscribers\EnsureTiaAssertionsAreRecordedOnFinished::class,
];
/**
* Creates a new instance of the Boot Subscribers.
*/
public function __construct(
private Container $container,
) {}
/**
* Boots the list of Subscribers.
*/
public function boot(): void
{
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
{
/**
* Creates a new instance of the Boot View.
*/
public function __construct(
private OutputInterface $output
) {
// ..
//
}
/**
* Boots the view renderer.
*/
public function boot(): void
{
View::renderUsing($this->output);
-12
View File
@@ -16,22 +16,13 @@ use function Termwind\renderUsing;
*/
final class Events
{
/**
* Sets the output.
*/
private static ?OutputInterface $output = null;
/**
* Sets the output.
*/
public static function setOutput(OutputInterface $output): void
{
self::$output = $output;
}
/**
* Fires before the test method description is printed.
*/
public static function beforeTestMethodDescription(TestResult $result, string $description): string
{
if (($context = $result->context) === []) {
@@ -73,9 +64,6 @@ final class Events
return $description;
}
/**
* Fires after the test method description is printed.
*/
public static function afterTestMethodDescription(TestResult $result): void
{
if (($context = $result->context) === []) {
-2
View File
@@ -14,8 +14,6 @@ trait Expectable
/**
* @template TValue
*
* Creates a new Expectation.
*
* @param TValue $value
* @return Expectation<TValue>
*/
-7
View File
@@ -14,15 +14,11 @@ use Closure;
trait Extendable
{
/**
* The list of extends.
*
* @var array<string, Closure>
*/
private static array $extends = [];
/**
* Register a new extend.
*
* @param-closure-this T $extend
*/
public function extend(string $name, Closure $extend): void
@@ -30,9 +26,6 @@ trait Extendable
static::$extends[$name] = $extend;
}
/**
* Checks if given extend name is registered.
*/
public static function hasExtend(string $name): bool
{
return array_key_exists($name, static::$extends);
-12
View File
@@ -9,33 +9,21 @@ namespace Pest\Concerns\Logging;
*/
trait WritesToConsole
{
/**
* Writes the given success message to the console.
*/
private function writeSuccess(string $message): void
{
$this->writePestTestOutput($message, 'fg-green, bold', '✓');
}
/**
* Writes the given error message to the console.
*/
private function writeError(string $message): void
{
$this->writePestTestOutput($message, 'fg-red, bold', '');
}
/**
* Writes the given warning message to the console.
*/
private function writeWarning(string $message): void
{
$this->writePestTestOutput($message, 'fg-yellow, bold', '-');
}
/**
* Writes the give message to the console.
*/
private function writePestTestOutput(string $message, string $color, string $symbol): void
{
$this->writeWithColor($color, "$symbol ", false);
-11
View File
@@ -12,30 +12,21 @@ use Closure;
trait Pipeable
{
/**
* The list of pipes.
*
* @var array<string, array<Closure(Closure, mixed ...$arguments): void>>
*/
private static array $pipes = [];
/**
* The list of interceptors.
*
* @var array<string, array<Closure(Closure, mixed ...$arguments): void>>
*/
private static array $interceptors = [];
/**
* Register a pipe to be applied before an expectation is checked.
*/
public function pipe(string $name, Closure $pipe): void
{
self::$pipes[$name][] = $pipe;
}
/**
* Register an interceptor that should replace an existing expectation.
*
* @param string|Closure(mixed $value, mixed ...$arguments):bool $filter
*/
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>
*/
private function pipes(string $name, object $context, string $scope): array
-2
View File
@@ -11,8 +11,6 @@ trait Retrievable
{
/**
* @template TRetrievableValue
*
* Safely retrieve the value at the given key from an object or array.
* @template TRetrievableValue
*
* @param array<string, TRetrievableValue>|object $value
-114
View File
@@ -37,105 +37,53 @@ use Throwable;
*/
trait Testable
{
/**
* The test's description.
*/
private string $__description;
/**
* The test's latest description.
*/
private static string $__latestDescription;
/**
* The test's assignees.
*/
private static array $__latestAssignees = [];
/**
* The test's notes.
*/
private static array $__latestNotes = [];
/**
* The test's issues.
*
* @var array<int, int>
*/
private static array $__latestIssues = [];
/**
* The test's PRs.
*
* @var array<int, int>
*/
private static array $__latestPrs = [];
/**
* The test's describing, if any.
*
* @var array<int, string>
*/
public array $__describing = [];
/**
* Whether the test has ran or not.
*/
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;
/**
* The cached assertion count to replay, captured when entering replay mode.
*/
private int $__replayAssertions = 0;
/**
* The test's test closure.
*/
private Closure $__test;
/**
* The test's before each closure.
*/
private ?Closure $__beforeEach = null;
/**
* The test's after each closure.
*/
private ?Closure $__afterEach = null;
/**
* The test's before all closure.
*/
private static ?Closure $__beforeAll = null;
/**
* The test's after all closure.
*/
private static ?Closure $__afterAll = null;
/**
* The list of snapshot changes, if any.
*/
private array $__snapshotChanges = [];
/**
* Resets the test case static properties.
*/
public static function flush(): void
{
self::$__beforeAll = null;
self::$__afterAll = null;
}
/**
* Adds a new "note" to the Test Case.
*/
public function note(array|string $note): self
{
$note = is_array($note) ? $note : [$note];
@@ -145,9 +93,6 @@ trait Testable
return $this;
}
/**
* Adds a new "setUpBeforeClass" to the Test Case.
*/
public function __addBeforeAll(?Closure $hook): void
{
if (! $hook instanceof Closure) {
@@ -159,9 +104,6 @@ trait Testable
: $hook;
}
/**
* Adds a new "tearDownAfterClass" to the Test Case.
*/
public function __addAfterAll(?Closure $hook): void
{
if (! $hook instanceof Closure) {
@@ -173,25 +115,16 @@ trait Testable
: $hook;
}
/**
* Adds a new "setUp" to the Test Case.
*/
public function __addBeforeEach(?Closure $hook): void
{
$this->__addHook('__beforeEach', $hook);
}
/**
* Adds a new "tearDown" to the Test Case.
*/
public function __addAfterEach(?Closure $hook): void
{
$this->__addHook('__afterEach', $hook);
}
/**
* Adds a new "hook" to the Test Case.
*/
private function __addHook(string $property, ?Closure $hook): void
{
if (! $hook instanceof Closure) {
@@ -203,9 +136,6 @@ trait Testable
: $hook;
}
/**
* This method is called before the first test of this Test Case is run.
*/
public static function setUpBeforeClass(): void
{
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
{
$afterAll = TestSuite::getInstance()->afterAll->get(self::$__filename);
@@ -239,9 +166,6 @@ trait Testable
parent::tearDownAfterClass();
}
/**
* Gets executed before the Test Case.
*/
protected function setUp(...$arguments): void
{
TestSuite::getInstance()->test = $this;
@@ -325,12 +249,8 @@ trait Testable
$this->__ran = true;
}
/**
* Initialize test case properties from TestSuite.
*/
public function __initializeTestCase(): void
{
// Return if the test case has already been initialized
if (isset($this->__test)) {
return;
}
@@ -352,9 +272,6 @@ trait Testable
}
}
/**
* Gets executed after the Test Case.
*/
protected function tearDown(...$arguments): void
{
if ($this->__replay !== ReplayType::None) {
@@ -382,8 +299,6 @@ trait Testable
}
/**
* Executes the Test Case current test.
*
* @throws Throwable
*/
private function __runTest(Closure $closure, ...$args): mixed
@@ -454,9 +369,6 @@ trait Testable
throw $lastException;
}
/**
* Determines if the given exception matches PHPUnit's expected exception.
*/
private function __isExpectedException(Throwable $e): bool
{
$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
*/
private function __resolveTestArguments(array $arguments): array
@@ -500,10 +410,6 @@ trait Testable
$method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());
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);
$arguments[] = $firstArgument;
}
@@ -552,8 +458,6 @@ trait Testable
}
/**
* Ensures dataset items count matches underlying test case required parameters
*
* @throws ReflectionException
* @throws DatasetArgumentsMismatch
*/
@@ -593,9 +497,6 @@ trait Testable
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
{
return new Preset;
@@ -611,33 +512,21 @@ trait Testable
$this->markTestIncomplete(implode('. ', $this->__snapshotChanges));
}
/**
* The printable test case name.
*/
public static function getPrintableTestCaseName(): string
{
return preg_replace('/P\\\/', '', self::class, 1);
}
/**
* The printable test case method name.
*/
public function getPrintableTestCaseMethodName(): string
{
return $this->__description;
}
/**
* The latest printable test case method name.
*/
public static function getLatestPrintableTestCaseMethodName(): string
{
return self::$__latestDescription ?? '';
}
/**
* The printable test case method context.
*/
public static function getPrintableContext(): array
{
return [
@@ -648,9 +537,6 @@ trait Testable
];
}
/**
* Opens a shell for the test case.
*/
public function shell(): void
{
Shell::open();
-47
View File
@@ -14,31 +14,19 @@ use Pest\PendingCalls\UsesCall;
*/
final readonly class Configuration
{
/**
* The filename of the configuration.
*/
private string $filename;
/**
* Creates a new configuration instance.
*/
public function __construct(
string $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
{
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
{
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
{
return $this->extend(...$classAndTraits);
}
/**
* Depending on where is called, it will add the given groups globally or locally.
*/
public function group(string ...$groups): UsesCall
{
return new UsesCall($this->filename, [])->group(...$groups);
}
/**
* Marks all tests in the current file to be run exclusively.
*/
public function only(): void
{
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
{
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
{
return $this->extends(...$classAndTraits);
}
/**
* Gets the printer configuration.
*/
public function printer(): Configuration\Printer
{
return new Configuration\Printer;
}
/**
* Gets the presets configuration.
*/
public function presets(): Configuration\Presets
{
return new Configuration\Presets;
}
/**
* Gets the project configuration.
*/
public function project(): Configuration\Project
{
return Configuration\Project::getInstance();
}
/**
* Gets the browser configuration.
*/
public function browser(): Browser\Configuration
{
return new Browser\Configuration;
}
/**
* Gets the evals configuration.
*/
public function evals(): 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
{
return new Plugins\Tia\Configuration;
}
/**
* Proxies calls to the uses method.
*
* @param array<array-key, mixed> $arguments
*/
public function __call(string $name, array $arguments): mixed
-3
View File
@@ -9,9 +9,6 @@ use Pest\Preset;
final class Presets
{
/**
* Creates a custom preset instance, and adds it to the list of presets.
*/
public function custom(string $name, Closure $execute): void
{
Preset::custom($name, $execute);
-3
View File
@@ -11,9 +11,6 @@ use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
*/
final readonly class Printer
{
/**
* Sets the theme to compact.
*/
public function compact(): self
{
DefaultPrinter::compact(true);
-28
View File
@@ -10,42 +10,27 @@ namespace Pest\Configuration;
final class Project
{
/**
* The assignees link.
*
* @internal
*/
public string $assignees = '';
/**
* The issues link.
*
* @internal
*/
public string $issues = '';
/**
* The PRs link.
*
* @internal
*/
public string $prs = '';
/**
* The singleton instance.
*/
private static ?self $instance = null;
/**
* Creates a new instance of the project.
*/
public static function getInstance(): self
{
return self::$instance ??= new self;
}
/**
* Sets the test project to GitHub.
*/
public function github(string $project): self
{
$this->issues = "https://github.com/{$project}/issues/%s";
@@ -56,12 +41,8 @@ final class Project
return $this;
}
/**
* Sets the test project to GitLab.
*/
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;
$this->issues = "https://{$hostname}/{$project}/-/work_items/%s";
@@ -72,9 +53,6 @@ final class Project
return $this;
}
/**
* Sets the test project to Bitbucket.
*/
public function bitbucket(string $project): self
{
$this->issues = "https://bitbucket.org/{$project}/issues/%s";
@@ -85,9 +63,6 @@ final class Project
return $this;
}
/**
* Sets the test project to Jira.
*/
public function jira(string $namespace, string $project): self
{
$this->issues = "https://{$namespace}.atlassian.net/browse/{$project}-%s";
@@ -97,9 +72,6 @@ final class Project
return $this;
}
/**
* Sets the test project to custom.
*/
public function custom(string $issues, string $prs, string $assignees): self
{
$this->issues = $issues;
+1 -9
View File
@@ -12,8 +12,6 @@ use Symfony\Component\Console\Output\OutputInterface;
final readonly class Help
{
/**
* The Command messages.
*
* @var array<int, string>
*/
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)',
];
/**
* Creates a new Console Command instance.
*/
public function __construct(private OutputInterface $output)
{
// ..
//
}
/**
* Executes the Console Command.
*/
public function __invoke(): void
{
foreach (self::HELP_MESSAGES as $message) {
+1 -9
View File
@@ -18,8 +18,6 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
final readonly class Thanks
{
/**
* The support options.
*
* @var array<string, string>
*/
private const array FUNDING_MESSAGES = [
@@ -33,19 +31,13 @@ final readonly class Thanks
'Sponsor' => 'https://github.com/sponsors/nunomaduro',
];
/**
* Creates a new Console Command instance.
*/
public function __construct(
private InputInterface $input,
private OutputInterface $output
) {
// ..
//
}
/**
* Executes the Console Command.
*/
public function __invoke(): void
{
$bootstrapper = new BootView($this->output);
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts;
*/
interface Bootstrapper
{
/**
* Boots the bootstrapper.
*/
public function boot(): void;
}
+1 -1
View File
@@ -11,5 +11,5 @@ use NunoMaduro\Collision\Contracts\Adapters\Phpunit\HasPrintableTestCaseName as
*/
interface HasPrintableTestCaseName extends BaseHasPrintableTestCaseName
{
// ..
//
}
-6
View File
@@ -11,13 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
interface Panicable
{
/**
* Renders the panic on the given output.
*/
public function render(OutputInterface $output): void;
/**
* The exit code to be used.
*/
public function exitCode(): int;
}
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/
interface AddsOutput
{
/**
* Adds output after the Test Suite execution.
*/
public function addOutput(int $exitCode): int;
}
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/
interface Bootable
{
/**
* Boots the plugin.
*/
public function boot(): void;
}
@@ -10,8 +10,6 @@ namespace Pest\Contracts\Plugins;
interface HandlesArguments
{
/**
* Adds arguments before the Test Suite execution.
*
* @param array<int, string> $arguments
* @return array<int, string>
*/
@@ -10,8 +10,6 @@ namespace Pest\Contracts\Plugins;
interface HandlesOriginalArguments
{
/**
* Adds original arguments before the Test Suite execution.
*
* @param array<int, string> $arguments
*/
public function handleOriginalArguments(array $arguments): void;
-3
View File
@@ -9,8 +9,5 @@ namespace Pest\Contracts\Plugins;
*/
interface Terminable
{
/**
* Terminates the plugin.
*/
public function terminate(): void;
}
-3
View File
@@ -6,8 +6,5 @@ namespace Pest\Contracts;
interface TestCaseFilter
{
/**
* Whether the test case is accepted.
*/
public function accept(string $testCaseFilename): bool;
}
-3
View File
@@ -8,8 +8,5 @@ use Pest\Factories\TestCaseMethodFactory;
interface TestCaseMethodFilter
{
/**
* Whether the test case method is accepted.
*/
public function accept(TestCaseMethodFactory $factory): bool;
}
-2
View File
@@ -12,8 +12,6 @@ use Pest\Factories\Attribute;
final class Attributes
{
/**
* Evaluates the given attributes and returns the code.
*
* @param iterable<int, Attribute> $attributes
*/
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $name, string $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));
}
}
//
}
-3
View File
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/
final class DatasetDoesNotExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{
/**
* Creates a new Exception instance.
*/
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));
-2
View File
@@ -15,8 +15,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
final class DatasetMissing extends BadFunctionCallException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{
/**
* Creates a new Exception instance.
*
* @param array<string, string> $arguments
*/
public function __construct(string $file, string $name, array $arguments)
-3
View File
@@ -11,9 +11,6 @@ use Exception;
*/
final class ExpectationNotFound extends Exception
{
/**
* Creates a new ExpectationNotFound instance from the given name.
*/
public static function fromName(string $name): ExpectationNotFound
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $message)
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $message)
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct()
{
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
{
/**
* Creates a new Exception instance for the given class name.
*/
public static function fromClassName(string $filename, string $className): self
{
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
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $feature, string $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
{
/**
* Renders the panic on the given output.
*/
public function render(OutputInterface $output): void
{
$output->writeln([
@@ -28,9 +25,6 @@ final class NoDirtyTestsFound extends InvalidArgumentException implements Except
]);
}
/**
* The exit code to be used.
*/
public function exitCode(): int
{
return 0;
-6
View File
@@ -12,9 +12,6 @@ use RuntimeException;
*/
final class ShouldNotHappen extends RuntimeException
{
/**
* Creates a new Exception instance.
*/
public function __construct(Exception $exception)
{
$message = $exception->getMessage();
@@ -29,9 +26,6 @@ EOF
, $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
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $fileName, string $description)
{
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
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $inUse, string $newOne, string $folder)
{
parent::__construct(sprintf(
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/
final class TestCaseClassOrTraitNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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
{
/**
* Creates a new Exception instance.
*/
public function __construct(TestCaseMethodFactory $method)
{
parent::__construct(
@@ -14,9 +14,6 @@ use Symfony\Component\Console\Exception\ExceptionInterface;
*/
final class TestDescriptionMissing extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace
{
/**
* Creates a new Exception instance.
*/
public function __construct(string $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;
use Attribute;
use BadMethodCallException;
use Closure;
use InvalidArgumentException;
@@ -60,19 +59,15 @@ final class Expectation
use Retrievable;
/**
* Creates a new expectation.
*
* @param TValue $value
*/
public function __construct(
public mixed $value
) {
// ..
//
}
/**
* Creates a new expectation.
*
* @template TAndValue
*
* @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>
*/
public function json(): Expectation
@@ -103,8 +96,6 @@ final class Expectation
}
/**
* Dump the expectation value.
*
* @return self<TValue>
*/
public function dump(mixed ...$arguments): self
@@ -118,9 +109,6 @@ final class Expectation
return $this;
}
/**
* Dump the expectation value and end the script.
*/
public function dd(mixed ...$arguments): never
{
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
* @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
* @return self<TValue>
*/
@@ -175,8 +159,6 @@ final class Expectation
}
/**
* Send the expectation value to Ray along with all given arguments.
*
* @return self<TValue>
*/
public function ray(mixed ...$arguments): self
@@ -189,8 +171,6 @@ final class Expectation
}
/**
* Creates the opposite expectation for the value.
*
* @return OppositeExpectation<TValue>
*/
public function not(): OppositeExpectation
@@ -199,8 +179,6 @@ final class Expectation
}
/**
* Creates an expectation on each item of the iterable "value".
*
* @return EachExpectation<TValue>
*/
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
*
* @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
*
* @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(Expectation<TValue>): mixed $callback
* @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(self<TValue>): mixed $callback
* @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
* @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
*/
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
*/
public function __get(string $name): mixed
@@ -422,9 +386,6 @@ final class Expectation
return $this->{$name}();
}
/**
* Checks if the given expectation method exists.
*/
public static function hasMethod(string $name): bool
{
return method_exists(self::class, $name)
@@ -432,17 +393,12 @@ final class Expectation
|| self::hasExtend($name);
}
/**
* Matches any value.
*/
public function any(): Any
{
return new Any;
}
/**
* Asserts that the given expectation target use the given dependencies.
*
* @param array<int, string>|string $targets
*/
public function toUse(array|string $targets): ArchExpectation
@@ -450,9 +406,6 @@ final class Expectation
return ToUse::make($this, $targets);
}
/**
* Asserts that the given expectation target does have the given permissions
*/
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
{
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
{
return Targeted::make(
@@ -476,9 +426,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target have all methods documented.
*/
public function toHaveMethodsDocumented(): ArchExpectation
{
return Targeted::make(
@@ -495,9 +442,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target have all properties documented.
*/
public function toHavePropertiesDocumented(): ArchExpectation
{
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
{
return Targeted::make(
@@ -528,9 +469,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target uses strict equality.
*/
public function toUseStrictEquality(): ArchExpectation
{
return Targeted::make(
@@ -541,9 +479,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target is final.
*/
public function toBeFinal(): ArchExpectation
{
return Targeted::make(
@@ -554,9 +489,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target is readonly.
*/
public function toBeReadonly(): ArchExpectation
{
return Targeted::make(
@@ -567,9 +499,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target is trait.
*/
public function toBeTrait(): ArchExpectation
{
return Targeted::make(
@@ -580,17 +509,11 @@ final class Expectation
);
}
/**
* Asserts that the given expectation targets are traits.
*/
public function toBeTraits(): ArchExpectation
{
return $this->toBeTrait();
}
/**
* Asserts that the given expectation target is abstract.
*/
public function toBeAbstract(): ArchExpectation
{
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
*/
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
*/
public function toHaveMethods(array $methods): ArchExpectation
@@ -628,57 +547,36 @@ final class Expectation
return $this->toHaveMethod($methods);
}
/**
* Not supported.
*/
public function toHavePublicMethodsBesides(): void
{
throw InvalidExpectation::fromMethods(['toHavePublicMethodsBesides']);
}
/**
* Not supported.
*/
public function toHavePublicMethods(): void
{
throw InvalidExpectation::fromMethods(['toHavePublicMethods']);
}
/**
* Not supported.
*/
public function toHaveProtectedMethodsBesides(): void
{
throw InvalidExpectation::fromMethods(['toHaveProtectedMethodsBesides']);
}
/**
* Not supported.
*/
public function toHaveProtectedMethods(): void
{
throw InvalidExpectation::fromMethods(['toHaveProtectedMethods']);
}
/**
* Not supported.
*/
public function toHavePrivateMethodsBesides(): void
{
throw InvalidExpectation::fromMethods(['toHavePrivateMethodsBesides']);
}
/**
* Not supported.
*/
public function toHavePrivateMethods(): void
{
throw InvalidExpectation::fromMethods(['toHavePrivateMethods']);
}
/**
* Asserts that the given expectation target is cased correctly.
*/
public function toBeCasedCorrectly(): ArchExpectation
{
return Targeted::make(
@@ -711,9 +609,6 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target is enum.
*/
public function toBeEnum(): ArchExpectation
{
return Targeted::make(
@@ -724,17 +619,11 @@ final class Expectation
);
}
/**
* Asserts that the given expectation targets are enums.
*/
public function toBeEnums(): ArchExpectation
{
return $this->toBeEnum();
}
/**
* Asserts that the given expectation target is a class.
*/
public function toBeClass(): ArchExpectation
{
return Targeted::make(
@@ -745,17 +634,11 @@ final class Expectation
);
}
/**
* Asserts that the given expectation targets are classes.
*/
public function toBeClasses(): ArchExpectation
{
return $this->toBeClass();
}
/**
* Asserts that the given expectation target is interface.
*/
public function toBeInterface(): ArchExpectation
{
return Targeted::make(
@@ -766,17 +649,11 @@ final class Expectation
);
}
/**
* Asserts that the given expectation targets are interfaces.
*/
public function toBeInterfaces(): ArchExpectation
{
return $this->toBeInterface();
}
/**
* Asserts that the given expectation target to be subclass of the given class.
*/
public function toExtend(string $class): ArchExpectation
{
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
{
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
{
return $this->toUseTraits($trait);
}
/**
* Asserts that the given expectation target to use the given traits.
*
* @param array<int, string>|string $traits
*/
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
{
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
*/
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
{
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
{
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
*/
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
*/
public function toOnlyUse(array|string $targets): ArchExpectation
@@ -937,33 +791,22 @@ final class Expectation
return ToOnlyUse::make($this, $targets);
}
/**
* Asserts that the given expectation target does not use any dependencies.
*/
public function toUseNothing(): ArchExpectation
{
return ToUseNothing::make($this);
}
/**
* Asserts that the source code of the given expectation target does not include suspicious characters.
*/
public function toHaveSuspiciousCharacters(): ArchExpectation
{
throw InvalidExpectation::fromMethods(['toHaveSuspiciousCharacters']);
}
/**
* Not supported.
*/
public function toBeUsed(): void
{
throw InvalidExpectation::fromMethods(['toBeUsed']);
}
/**
* Asserts that the given expectation dependency is used by the given targets.
*
* @param array<int, string>|string $targets
*/
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
*/
public function toOnlyBeUsedIn(array|string $targets): ArchExpectation
@@ -981,17 +822,11 @@ final class Expectation
return ToOnlyBeUsedIn::make($this, $targets);
}
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsedInNothing(): ArchExpectation
{
return ToBeUsedInNothing::make($this);
}
/**
* Asserts that the given expectation dependency is an invokable class.
*/
public function toBeInvokable(): ArchExpectation
{
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>
*/
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>
*/
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>
*/
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>
*/
public function toHaveStudlyCaseKeys(string $message = ''): self
@@ -1098,9 +925,6 @@ final class Expectation
return $this;
}
/**
* Asserts that the given expectation target to have the given attribute.
*/
public function toHaveAttribute(string $attribute): ArchExpectation
{
return Targeted::make(
@@ -1111,25 +935,16 @@ final class Expectation
);
}
/**
* Asserts that the given expectation target has a constructor method.
*/
public function toHaveConstructor(): ArchExpectation
{
return $this->toHaveMethod('__construct');
}
/**
* Asserts that the given expectation target has a destructor method.
*/
public function toHaveDestructor(): ArchExpectation
{
return $this->toHaveMethod('__destruct');
}
/**
* Asserts that the given expectation target is a backed enum of given type.
*/
private function toBeBackedEnum(string $backingType): ArchExpectation
{
return Targeted::make(
@@ -1143,33 +958,21 @@ final class Expectation
);
}
/**
* Asserts that the given expectation targets are string backed enums.
*/
public function toBeStringBackedEnums(): ArchExpectation
{
return $this->toBeStringBackedEnum();
}
/**
* Asserts that the given expectation targets are int backed enums.
*/
public function toBeIntBackedEnums(): ArchExpectation
{
return $this->toBeIntBackedEnum();
}
/**
* Asserts that the given expectation target is a string backed enum.
*/
public function toBeStringBackedEnum(): ArchExpectation
{
return $this->toBeBackedEnum('string');
}
/**
* Asserts that the given expectation target is an int backed enum.
*/
public function toBeIntBackedEnum(): ArchExpectation
{
return $this->toBeBackedEnum('int');
-13
View File
@@ -17,21 +17,14 @@ use function expect;
*/
final class EachExpectation
{
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false;
/**
* Creates an expectation on each item of the iterable "value".
*
* @param Expectation<TValue> $original
*/
public function __construct(private readonly Expectation $original) {}
/**
* Creates a new expectation.
*
* @template TAndValue
*
* @param TAndValue $value
@@ -43,8 +36,6 @@ final class EachExpectation
}
/**
* Creates the opposite expectation for the value.
*
* @return self<TValue>
*/
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
* @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>
*/
public function __get(string $name): self
@@ -25,19 +25,11 @@ final class HigherOrderExpectation
*/
private Expectation|EachExpectation $expectation;
/**
* Indicates if the expectation is the opposite.
*/
private bool $opposite = false;
/**
* Indicates if the expectation should reset the value.
*/
private bool $shouldReset = false;
/**
* Creates a new higher order expectation.
*
* @param Expectation<TOriginalValue> $original
* @param TValue $value
*/
@@ -47,8 +39,6 @@ final class HigherOrderExpectation
}
/**
* Creates the opposite expectation for the value.
*
* @return self<TOriginalValue, TValue>
*/
public function not(): self
@@ -59,8 +49,6 @@ final class HigherOrderExpectation
}
/**
* Creates a new Expectation.
*
* @template TExpectValue
*
* @param TExpectValue $value
@@ -72,8 +60,6 @@ final class HigherOrderExpectation
}
/**
* Creates a new expectation.
*
* @template TExpectValue
*
* @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
* @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>
*/
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
* @return self<TOriginalValue, mixed>
*/
@@ -125,8 +104,6 @@ final class HigherOrderExpectation
}
/**
* Accesses properties in the value or in the expectation.
*
* @return self<TOriginalValue, mixed>
*/
public function __get(string $name): self
@@ -145,9 +122,6 @@ final class HigherOrderExpectation
return $this->performAssertion($name, []);
}
/**
* Determines if the original expectation has the given method name.
*/
private function expectationHasMethod(string $name): bool
{
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
*/
private function getValue(): mixed
@@ -171,8 +143,6 @@ final class HigherOrderExpectation
}
/**
* Performs the given assertion with the current expectation.
*
* @param array<int, mixed> $arguments
* @return self<TOriginalValue, TValue>
*/
-152
View File
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Pest\Expectations;
use Attribute;
use Pest\Arch\Contracts\ArchExpectation;
use Pest\Arch\Expectations\Targeted;
use Pest\Arch\Expectations\ToBeUsedIn;
@@ -38,15 +37,11 @@ use stdClass;
final readonly class OppositeExpectation
{
/**
* Creates a new opposite expectation.
*
* @param Expectation<TValue> $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
* @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
*/
public function toUse(array|string $targets): ArchExpectation
@@ -84,9 +77,6 @@ final readonly class OppositeExpectation
), is_string($targets) ? [$targets] : $targets));
}
/**
* Asserts that the given expectation target does not have the given permissions
*/
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
@@ -100,17 +90,11 @@ final readonly class OppositeExpectation
);
}
/**
* Not supported.
*/
public function toHaveLineCountLessThan(): ArchExpectation
{
throw InvalidExpectation::fromMethods(['not', 'toHaveLineCountLessThan']);
}
/**
* Not supported.
*/
public function toHaveMethodsDocumented(): ArchExpectation
{
/** @var Expectation<array<int, string>|string> $original */
@@ -130,9 +114,6 @@ final readonly class OppositeExpectation
);
}
/**
* Not supported.
*/
public function toHavePropertiesDocumented(): ArchExpectation
{
/** @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
{
/** @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
{
/** @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
{
/** @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
{
/** @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
{
/** @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
{
return $this->toBeTrait();
}
/**
* Asserts that the given expectation target is not abstract.
*/
public function toBeAbstract(): ArchExpectation
{
/** @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
*/
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
{
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
*/
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
*/
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
{
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
*/
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
{
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
*/
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
{
return $this->toHavePrivateMethodsBesides([]);
}
/**
* Asserts that the given expectation target is not enum.
*/
public function toBeEnum(): ArchExpectation
{
/** @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
{
return $this->toBeEnum();
}
/**
* Asserts that the given expectation targets is not class.
*/
public function toBeClass(): ArchExpectation
{
/** @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
{
return $this->toBeClass();
}
/**
* Asserts that the given expectation target is not interface.
*/
public function toBeInterface(): ArchExpectation
{
/** @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
{
return $this->toBeInterface();
}
/**
* Asserts that the given expectation target to be not subclass of the given class.
*/
public function toExtend(string $class): ArchExpectation
{
/** @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
{
/** @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
{
return $this->toUseTraits($trait);
}
/**
* Asserts that the given expectation target not to use the given traits.
*
* @param array<int, string>|string $traits
*/
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
*/
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
{
/** @var Expectation<array<int, string>|string> $original */
@@ -618,17 +522,11 @@ final readonly class OppositeExpectation
);
}
/**
* Not supported.
*/
public function toOnlyImplement(): void
{
throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']);
}
/**
* Asserts that the given expectation target to not have the given prefix.
*/
public function toHavePrefix(string $prefix): ArchExpectation
{
/** @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
{
/** @var Expectation<array<int, string>|string> $original */
@@ -658,25 +553,16 @@ final readonly class OppositeExpectation
);
}
/**
* Not supported.
*/
public function toOnlyUse(): void
{
throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']);
}
/**
* Not supported.
*/
public function toUseNothing(): void
{
throw InvalidExpectation::fromMethods(['not', 'toUseNothing']);
}
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsed(): ArchExpectation
{
/** @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
*/
public function toBeUsedIn(array|string $targets): ArchExpectation
@@ -705,17 +589,11 @@ final readonly class OppositeExpectation
throw InvalidExpectation::fromMethods(['not', 'toOnlyBeUsedIn']);
}
/**
* Asserts that the given expectation dependency is not used.
*/
public function toBeUsedInNothing(): void
{
throw InvalidExpectation::fromMethods(['not', 'toBeUsedInNothing']);
}
/**
* Asserts that the given expectation dependency is not an invokable class.
*/
public function toBeInvokable(): ArchExpectation
{
/** @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
{
/** @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
* @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
*/
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
*/
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
{
return $this->toHaveMethod('__construct');
}
/**
* Asserts that the given expectation target does not have a destructor method.
*/
public function toHaveDestructor(): ArchExpectation
{
return $this->toHaveMethod('__destruct');
}
/**
* Asserts that the given expectation target is not a backed enum of given type.
*/
private function toBeBackedEnum(string $backingType): ArchExpectation
{
/** @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
{
return $this->toBeStringBackedEnum();
}
/**
* Asserts that the given expectation targets are not int backed enums.
*/
public function toBeIntBackedEnums(): ArchExpectation
{
return $this->toBeIntBackedEnum();
}
/**
* Asserts that the given expectation target is not a string backed enum.
*/
public function toBeStringBackedEnum(): ArchExpectation
{
return $this->toBeBackedEnum('string');
}
/**
* Asserts that the given expectation target is not an int backed enum.
*/
public function toBeIntBackedEnum(): ArchExpectation
{
return $this->toBeBackedEnum('int');
@@ -8,24 +8,12 @@ use Pest\Support\HigherOrderMessageCollection;
trait HigherOrderable
{
/**
* The higher order messages that are chainable.
*/
public HigherOrderMessageCollection $chains;
/**
* The higher order messages that are "factory" proxyable.
*/
public HigherOrderMessageCollection $factoryProxies;
/**
* The higher order messages that are proxyable.
*/
public HigherOrderMessageCollection $proxies;
/**
* Boot the higher order properties.
*/
private function bootHigherOrderable(): void
{
$this->chains = new HigherOrderMessageCollection;
-29
View File
@@ -30,29 +30,21 @@ final class TestCaseFactory
use HigherOrderable;
/**
* The list of attributes.
*
* @var array<int, Attribute>
*/
public array $attributes = [];
/**
* The FQN of the Test Case class.
*
* @var class-string
*/
public string $class = TestCase::class;
/**
* The list of class methods.
*
* @var array<string, TestCaseMethodFactory>
*/
public array $methods = [];
/**
* The list of class traits.
*
* @var array <int, class-string>
*/
public array $traits = [
@@ -60,14 +52,8 @@ final class TestCaseFactory
Concerns\Expectable::class,
];
/**
* The namespace for the test case, overrides the path-based namespace when set.
*/
public ?string $namespace = null;
/**
* Creates a new Factory instance.
*/
public function __construct(
public string $filename
) {
@@ -84,14 +70,11 @@ final class TestCaseFactory
}
/**
* Creates a Test Case class using a runtime evaluate.
*
* @param array<string, TestCaseMethodFactory> $methods
*/
public function evaluate(string $filename, array $methods): void
{
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);
}
@@ -114,11 +97,8 @@ final class TestCaseFactory
$relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath);
// Strip out any %-encoded octets.
$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);
// Limit to Unicode letters and numbers.
$relativePath = (string) preg_replace('/[^\p{L}\p{N}\\\\]/u', '', $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
{
if ($method->description === null) {
@@ -233,9 +210,6 @@ final class TestCaseFactory
$this->methods[$method->description] = $method;
}
/**
* Checks if a test case has a method.
*/
public function hasMethod(string $methodName): bool
{
foreach ($this->methods as $method) {
@@ -251,9 +225,6 @@ final class TestCaseFactory
return false;
}
/**
* Gets a Method by the given name.
*/
public function getMethod(string $methodName): TestCaseMethodFactory
{
foreach ($this->methods as $method) {
-51
View File
@@ -27,84 +27,54 @@ final class TestCaseMethodFactory
use HigherOrderable;
/**
* The list of attributes.
*
* @var array<int, Attribute>
*/
public array $attributes = [];
/**
* The test's describing, if any.
*
* @var array<int, Description>
*/
public array $describing = [];
/**
* The test's description, if any.
*/
public ?string $description = null;
/**
* The test's number of repetitions.
*/
public int $repetitions = 1;
/**
* The test's number of flaky retry tries.
*/
public ?int $flakyTries = null;
/**
* Determines if the test is a "todo".
*/
public bool $todo = false;
/**
* The associated issue numbers.
*
* @var array<int, int>
*/
public array $issues = [];
/**
* The test assignees.
*
* @var array<int, string>
*/
public array $assignees = [];
/**
* The associated PRs numbers.
*
* @var array<int, int>
*/
public array $prs = [];
/**
* The test's notes.
*
* @var array<int, string>
*/
public array $notes = [];
/**
* The test's datasets.
*
* @var array<Closure|iterable<int|string, mixed>|string>
*/
public array $datasets = [];
/**
* The test's dependencies.
*
* @var array<int, string>
*/
public array $depends = [];
/**
* The test's groups.
*
* @var array<int, string>
*/
public array $groups = [];
@@ -114,9 +84,6 @@ final class TestCaseMethodFactory
*/
public bool $__ran = false;
/**
* Creates a new test case method factory instance.
*/
public function __construct(
public string $filename,
public ?Closure $closure,
@@ -128,9 +95,6 @@ final class TestCaseMethodFactory
$this->bootHigherOrderable();
}
/**
* Sets the test's hooks, and runs any proxy to the test case.
*/
public function setUp(TestCase $concrete): void
{
$concrete::flush(); // @phpstan-ignore-line
@@ -146,17 +110,11 @@ final class TestCaseMethodFactory
$this->factoryProxies->proxy($concrete);
}
/**
* Flushes the test case.
*/
public function tearDown(TestCase $concrete): void
{
$concrete::flush(); // @phpstan-ignore-line
}
/**
* Creates the test's closure.
*/
public function getClosure(): 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
{
return $this->datasets !== [] || $this->depends !== [] || $this->repetitions > 1;
}
/**
* Creates a PHPUnit method as a string ready for evaluation.
*/
public function buildForEvaluation(): string
{
if ($this->description === null) {
@@ -248,9 +200,6 @@ final class TestCaseMethodFactory
PHP;
}
/**
* Creates a PHPUnit Data Provider as a string ready for evaluation.
*/
private function buildDatasetForEvaluation(string $methodName, string $dataProviderName): string
{
$datasets = $this->datasets;
-45
View File
@@ -27,8 +27,6 @@ use PHPUnit\Framework\TestCase;
if (! function_exists('expect')) {
/**
* Creates a new expectation.
*
* @template TValue
*
* @param TValue|null $value
@@ -41,9 +39,6 @@ if (! function_exists('expect')) {
}
if (! function_exists('beforeAll')) {
/**
* Runs the given closure before all tests in the current file.
*/
function beforeAll(Closure $closure): void
{
if (DescribeCall::describing() !== []) {
@@ -58,8 +53,6 @@ if (! function_exists('beforeAll')) {
if (! function_exists('beforeEach')) {
/**
* Runs the given closure before each test in the current file.
*
* @param-closure-this TestCall $closure
*/
function beforeEach(?Closure $closure = null): BeforeEachCall
@@ -72,8 +65,6 @@ if (! function_exists('beforeEach')) {
if (! function_exists('dataset')) {
/**
* Registers the given dataset.
*
* @param Closure|iterable<int|string, mixed> $dataset
*/
function dataset(string $name, Closure|iterable $dataset): void
@@ -85,11 +76,6 @@ if (! function_exists('dataset')) {
}
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
{
$filename = Backtrace::testFile();
@@ -100,9 +86,6 @@ if (! function_exists('describe')) {
if (! function_exists('uses')) {
/**
* The uses function binds the given
* arguments to test closures.
*
* @param class-string ...$classAndTraits
*/
function uses(string ...$classAndTraits): UsesCall
@@ -114,9 +97,6 @@ if (! function_exists('uses')) {
}
if (! function_exists('pest')) {
/**
* Creates a new Pest configuration instance.
*/
function pest(): Configuration
{
return new Configuration(Backtrace::testFile());
@@ -125,10 +105,6 @@ if (! function_exists('pest')) {
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
*
* @return ($description is string ? TestCall : HigherOrderTapProxy|TestCall)
@@ -147,10 +123,6 @@ if (! function_exists('test')) {
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
*/
function it(string $description, ?Closure $closure = null): TestCall
@@ -162,9 +134,6 @@ if (! function_exists('it')) {
}
if (! function_exists('todo')) {
/**
* Creates a new test that is marked as "todo".
*/
function todo(string $description): TestCall
{
return test($description)->todo();
@@ -173,8 +142,6 @@ if (! function_exists('todo')) {
if (! function_exists('afterEach')) {
/**
* Runs the given closure after each test in the current file.
*
* @param-closure-this TestCall $closure
*/
function afterEach(?Closure $closure = null): AfterEachCall
@@ -186,9 +153,6 @@ if (! function_exists('afterEach')) {
}
if (! function_exists('afterAll')) {
/**
* Runs the given closure after all tests in the current file.
*/
function afterAll(Closure $closure): void
{
if (DescribeCall::describing() !== []) {
@@ -203,8 +167,6 @@ if (! function_exists('afterAll')) {
if (! function_exists('covers')) {
/**
* Specifies which classes, or functions, a test case covers.
*
* @param array<int, string>|string $classesOrFunctions
*/
function covers(array|string ...$classesOrFunctions): void
@@ -232,8 +194,6 @@ if (! function_exists('covers')) {
if (! function_exists('mutates')) {
/**
* Specifies which classes, enums, or traits a test case mutates.
*
* @param array<int, string>|string $targets
*/
function mutates(array|string ...$targets): void
@@ -266,9 +226,6 @@ if (! function_exists('mutates')) {
}
if (! function_exists('fixture')) {
/**
* Returns the absolute path to a fixture file.
*/
function fixture(string $file): string
{
$file = implode(DIRECTORY_SEPARATOR, [
@@ -292,8 +249,6 @@ if (! function_exists('fixture')) {
if (! function_exists('visit')) {
/**
* Browse to the given URL.
*
* @template TUrl of array<int, string>|string
*
* @param TUrl $url
-23
View File
@@ -29,14 +29,9 @@ use Whoops\Exception\Inspector;
*/
final class Kernel
{
/**
* Either the kernel is terminated or not.
*/
private bool $terminated = false;
/**
* The Kernel bootstrappers.
*
* @var array<int, class-string>
*/
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>>
*/
public const array RESTARTERS = [
@@ -62,14 +53,8 @@ final class Kernel
Restarters\PcovRestarter::class,
];
/**
* Creates a new Kernel instance.
*/
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
{
$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> $arguments
*/
@@ -135,9 +118,6 @@ final class Kernel
return $result;
}
/**
* Terminate the Kernel.
*/
public function terminate(): void
{
if ($this->terminated) {
@@ -155,9 +135,6 @@ final class Kernel
CallsTerminable::execute();
}
/**
* Shutdowns unexpectedly the Kernel.
*/
public function shutdown(): void
{
$this->terminate();
+1 -25
View File
@@ -10,23 +10,14 @@ use Symfony\Component\Console\Output\OutputInterface;
final class KernelDump
{
/**
* The output buffer, if any.
*/
private string $buffer = '';
/**
* Creates a new Kernel Dump instance.
*/
public function __construct(
private readonly OutputInterface $output,
) {
// ...
//
}
/**
* Enable the output buffering.
*/
public function enable(): void
{
if (class_exists(Execution::class) && Execution::running()) {
@@ -40,9 +31,6 @@ final class KernelDump
});
}
/**
* Disable the output buffering.
*/
public function disable(): void
{
@ob_clean();
@@ -52,17 +40,11 @@ final class KernelDump
}
}
/**
* Terminate the output buffering.
*/
public function terminate(): void
{
$this->disable();
}
/**
* Flushes the buffer.
*/
private function flush(): void
{
View::renderUsing($this->output);
@@ -103,17 +85,11 @@ final class KernelDump
$this->buffer = '';
}
/**
* Checks if the given output contains an opening headline.
*/
private function isOpeningHeadline(string $output): bool
{
return str_contains($output, 'by Sebastian Bergmann and contributors.');
}
/**
* Checks if the given output contains an opening headline.
*/
private function isInternalError(string $output): bool
{
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
{
/**
* The prefix for the test suite name.
*/
private const string PREFIX = 'P\\';
/**
* The state generator.
*/
private StateGenerator $stateGenerator;
/**
* Creates a new instance of the Converter.
*/
public function __construct(
private string $rootPath,
) {
$this->stateGenerator = new StateGenerator;
}
/**
* Gets the test case method name.
*/
public function getTestCaseMethodName(Test $test): string
{
if (! $test instanceof TestMethod) {
@@ -56,9 +44,6 @@ final readonly class Converter
return $test->testDox()->prettifiedMethodName();
}
/**
* Gets the test case location.
*/
public function getTestCaseLocation(Test $test): string
{
if (! $test instanceof TestMethod) {
@@ -68,15 +53,11 @@ final readonly class Converter
$path = $test->testDox()->prettifiedClassName();
$relativePath = $this->toRelativePath($path);
// TODO: Get the description without the dataset.
$description = $test->testDox()->prettifiedMethodName();
return "$relativePath::$description";
}
/**
* Gets the exception message.
*/
public function getExceptionMessage(Throwable $throwable): string
{
if (is_a($throwable->className(), FrameworkException::class, true)) {
@@ -93,9 +74,6 @@ final readonly class Converter
return $buffer;
}
/**
* Gets the exception details.
*/
public function getExceptionDetails(Throwable $throwable): string
{
$buffer = $this->getStackTrace($throwable);
@@ -113,26 +91,19 @@ final readonly class Converter
return $buffer;
}
/**
* Gets the stack trace.
*/
public function getStackTrace(Throwable $throwable): string
{
$stackTrace = $throwable->stackTrace();
// Split stacktrace per frame.
$frames = explode("\n", $stackTrace);
// Remove empty lines
$frames = array_filter($frames);
// clean the paths of each frame.
$frames = array_map(
$this->toRelativePath(...),
$frames
);
// Format stacktrace as `at <path>`
$frames = array_map(
fn (string $frame): string => "at $frame",
$frames
@@ -141,9 +112,6 @@ final readonly class Converter
return implode("\n", $frames);
}
/**
* Gets the test suite name.
*/
public function getTestSuiteName(TestSuite $testSuite): string
{
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
@@ -162,17 +130,11 @@ final readonly class Converter
return Str::after($name, self::PREFIX);
}
/**
* Gets the trimmed test class name.
*/
public function getTrimmedTestClassName(TestMethod $test): string
{
return Str::after($test->className(), self::PREFIX);
}
/**
* Gets the test suite location.
*/
public function getTestSuiteLocation(TestSuite $testSuite): ?string
{
$firstTest = $this->getFirstTest($testSuite);
@@ -191,22 +153,15 @@ final readonly class Converter
return $classRelativePath;
}
/**
* Gets the prettified test method name without dataset-related suffix.
*/
private function getTestMethodNameWithoutDatasetSuffix(TestMethod $testMethod): string
{
return Str::beforeLast($testMethod->testDox()->prettifiedMethodName(), ' with data set ');
}
/**
* Gets the first test from the test suite.
*/
private function getFirstTest(TestSuite $testSuite): ?TestMethod
{
$tests = $testSuite->tests()->asArray();
// TODO: figure out how to get the file path without a test being there.
if ($tests === []) {
return null;
}
@@ -219,26 +174,16 @@ final readonly class Converter
return $firstTest;
}
/**
* Gets the test suite size.
*/
public function getTestSuiteSize(TestSuite $testSuite): int
{
return $testSuite->count();
}
/**
* Transforms the given path in relative path.
*/
private function toRelativePath(string $path): string
{
// Remove cwd from the path.
return str_replace("$this->rootPath".DIRECTORY_SEPARATOR, '', $path);
}
/**
* Get the test result.
*/
public function getStateFromResult(PhpUnitTestResult $result): State
{
$events = [
@@ -253,11 +198,9 @@ final readonly class Converter
foreach ($events as $event) {
if ($event instanceof AfterLastTestMethodErrored) {
// PHPUnit's collector does not count these towards `numberOfTestsRun`...
continue;
}
if ($event instanceof AfterLastTestMethodFailed) {
// PHPUnit's collector does not count these towards `numberOfTestsRun`...
continue;
}
if ($event instanceof BeforeFirstTestMethodErrored || $event instanceof BeforeFirstTestMethodFailed) {
-3
View File
@@ -9,9 +9,6 @@ namespace Pest\Logging\TeamCity;
*/
final class ServiceMessage
{
/**
* The flow ID.
*/
private static ?int $flowId = null;
/**
@@ -11,14 +11,8 @@ use Pest\Logging\TeamCity\TeamCityLogger;
*/
abstract class Subscriber // @pest-arch-ignore-line
{
/**
* Creates a new Subscriber instance.
*/
public function __construct(private readonly TeamCityLogger $logger) {}
/**
* Creates a new TeamCityLogger instance.
*/
final protected function logger(): TeamCityLogger // @pest-arch-ignore-line
{
return $this->logger;
@@ -15,7 +15,7 @@ final class TestSkippedSubscriber extends Subscriber implements SkippedSubscribe
public function notify(Skipped $event): void
{
if ($event->message() === '__TODO__') {
return; // "todo" tests are reported in the summary, not as ignored tests...
return;
}
$this->logger()->testSkipped($event);
-18
View File
@@ -43,14 +43,8 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
final class TeamCityLogger
{
/**
* The current time.
*/
private ?HRTime $time = null;
/**
* Indicates if the summary test count has been printed.
*/
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
{
$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
{
$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
{
$this->whenFirstEventForTest($event->test(), function () use ($event): void {
+1 -169
View File
@@ -38,27 +38,18 @@ use Traversable;
*/
final class Expectation
{
/**
* The exporter instance, if any.
*/
private ?Exporter $exporter = null;
/**
* Creates a new expectation.
*
* @param TValue $value
*/
public function __construct(
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>
*/
public function toBe(mixed $expected, string $message = ''): self
@@ -69,8 +60,6 @@ final class Expectation
}
/**
* Asserts that the value is empty.
*
* @return self<TValue>
*/
public function toBeEmpty(string $message = ''): self
@@ -81,8 +70,6 @@ final class Expectation
}
/**
* Asserts that the value is true.
*
* @return self<TValue>
*/
public function toBeTrue(string $message = ''): self
@@ -93,8 +80,6 @@ final class Expectation
}
/**
* Asserts that the value is truthy.
*
* @return self<TValue>
*/
public function toBeTruthy(string $message = ''): self
@@ -105,8 +90,6 @@ final class Expectation
}
/**
* Asserts that the value is false.
*
* @return self<TValue>
*/
public function toBeFalse(string $message = ''): self
@@ -117,8 +100,6 @@ final class Expectation
}
/**
* Asserts that the value is falsy.
*
* @return self<TValue>
*/
public function toBeFalsy(string $message = ''): self
@@ -129,8 +110,6 @@ final class Expectation
}
/**
* Asserts that the value is greater than $expected.
*
* @return self<TValue>
*/
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>
*/
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>
*/
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>
*/
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>
*/
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>
*/
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
* @return self<TValue>
*/
@@ -233,8 +200,6 @@ final class Expectation
}
/**
* Asserts that the value ends with $expected.
*
* @param non-empty-string $expected
* @return self<TValue>
*/
@@ -250,8 +215,6 @@ final class Expectation
}
/**
* Asserts that $number matches value's Length.
*
* @return self<TValue>
*/
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>
*/
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
* @return self<TValue>
*/
@@ -311,8 +270,6 @@ final class Expectation
}
/**
* Asserts that the value contains the property $name.
*
* @return self<TValue>
*/
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
* @return self<TValue>
*/
@@ -346,8 +301,6 @@ final class Expectation
}
/**
* Asserts that two variables have the same value.
*
* @return self<TValue>
*/
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>
*/
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>
*/
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
* @return self<TValue>
*/
@@ -402,8 +342,6 @@ final class Expectation
}
/**
* Asserts that the value is infinite.
*
* @return self<TValue>
*/
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
* @return self<TValue>
*/
@@ -427,8 +363,6 @@ final class Expectation
}
/**
* Asserts that the value is an array.
*
* @return self<TValue>
*/
public function toBeArray(string $message = ''): self
@@ -439,8 +373,6 @@ final class Expectation
}
/**
* Asserts that the value is a list.
*
* @return self<TValue>
*/
public function toBeList(string $message = ''): self
@@ -451,8 +383,6 @@ final class Expectation
}
/**
* Asserts that the value is of type bool.
*
* @return self<TValue>
*/
public function toBeBool(string $message = ''): self
@@ -463,8 +393,6 @@ final class Expectation
}
/**
* Asserts that the value is of type callable.
*
* @return self<TValue>
*/
public function toBeCallable(string $message = ''): self
@@ -475,8 +403,6 @@ final class Expectation
}
/**
* Asserts that the value is of type float.
*
* @return self<TValue>
*/
public function toBeFloat(string $message = ''): self
@@ -487,8 +413,6 @@ final class Expectation
}
/**
* Asserts that the value is of type int.
*
* @return self<TValue>
*/
public function toBeInt(string $message = ''): self
@@ -499,8 +423,6 @@ final class Expectation
}
/**
* Asserts that the value is of type iterable.
*
* @return self<TValue>
*/
public function toBeIterable(string $message = ''): self
@@ -511,8 +433,6 @@ final class Expectation
}
/**
* Asserts that the value is of type numeric.
*
* @return self<TValue>
*/
public function toBeNumeric(string $message = ''): self
@@ -523,8 +443,6 @@ final class Expectation
}
/**
* Asserts that the value contains only digits.
*
* @return self<TValue>
*/
public function toBeDigits(string $message = ''): self
@@ -535,8 +453,6 @@ final class Expectation
}
/**
* Asserts that the value is of type object.
*
* @return self<TValue>
*/
public function toBeObject(string $message = ''): self
@@ -547,8 +463,6 @@ final class Expectation
}
/**
* Asserts that the value is of type resource.
*
* @return self<TValue>
*/
public function toBeResource(string $message = ''): self
@@ -559,8 +473,6 @@ final class Expectation
}
/**
* Asserts that the value is of type scalar.
*
* @return self<TValue>
*/
public function toBeScalar(string $message = ''): self
@@ -571,8 +483,6 @@ final class Expectation
}
/**
* Asserts that the value is of type string.
*
* @return self<TValue>
*/
public function toBeString(string $message = ''): self
@@ -583,8 +493,6 @@ final class Expectation
}
/**
* Asserts that the value is a JSON string.
*
* @return self<TValue>
*/
public function toBeJson(string $message = ''): self
@@ -597,8 +505,6 @@ final class Expectation
}
/**
* Asserts that the value is NAN.
*
* @return self<TValue>
*/
public function toBeNan(string $message = ''): self
@@ -609,8 +515,6 @@ final class Expectation
}
/**
* Asserts that the value is null.
*
* @return self<TValue>
*/
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>
*/
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
* @return self<TValue>
*/
@@ -672,8 +572,6 @@ final class Expectation
}
/**
* Asserts that the value is a directory.
*
* @return self<TValue>
*/
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>
*/
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>
*/
public function toBeWritableDirectory(string $message = ''): self
@@ -720,8 +614,6 @@ final class Expectation
}
/**
* Asserts that the value is a file.
*
* @return self<TValue>
*/
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>
*/
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>
*/
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
* @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
* @return self<TValue>
*/
@@ -827,8 +710,6 @@ final class Expectation
}
/**
* Asserts that the value "stringable" matches the given snapshot..
*
* @return self<TValue>
*/
public function toMatchSnapshot(string $message = ''): self
@@ -883,8 +764,6 @@ final class Expectation
}
/**
* Asserts that the value matches a regular expression.
*
* @return self<TValue>
*/
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>
*/
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
* @return self<TValue>
*/
@@ -994,9 +869,6 @@ final class Expectation
throw new ExpectationFailedException("Exception \"$exception\" not thrown.");
}
/**
* Exports the given value.
*/
private function export(mixed $value): string
{
if (! $this->exporter instanceof Exporter) {
@@ -1007,8 +879,6 @@ final class Expectation
}
/**
* Asserts that the value is uppercase.
*
* @return self<TValue>
*/
public function toBeUppercase(string $message = ''): self
@@ -1019,8 +889,6 @@ final class Expectation
}
/**
* Asserts that the value is lowercase.
*
* @return self<TValue>
*/
public function toBeLowercase(string $message = ''): self
@@ -1031,8 +899,6 @@ final class Expectation
}
/**
* Asserts that the value is alphanumeric.
*
* @return self<TValue>
*/
public function toBeAlphaNumeric(string $message = ''): self
@@ -1043,8 +909,6 @@ final class Expectation
}
/**
* Asserts that the value is alpha.
*
* @return self<TValue>
*/
public function toBeAlpha(string $message = ''): self
@@ -1055,8 +919,6 @@ final class Expectation
}
/**
* Asserts that the value is snake_case.
*
* @return self<TValue>
*/
public function toBeSnakeCase(string $message = ''): self
@@ -1073,8 +935,6 @@ final class Expectation
}
/**
* Asserts that the value is kebab-case.
*
* @return self<TValue>
*/
public function toBeKebabCase(string $message = ''): self
@@ -1091,8 +951,6 @@ final class Expectation
}
/**
* Asserts that the value is camelCase.
*
* @return self<TValue>
*/
public function toBeCamelCase(string $message = ''): self
@@ -1109,8 +967,6 @@ final class Expectation
}
/**
* Asserts that the value is StudlyCase.
*
* @return self<TValue>
*/
public function toBeStudlyCase(string $message = ''): self
@@ -1127,8 +983,6 @@ final class Expectation
}
/**
* Asserts that the value is UUID.
*
* @return self<TValue>
*/
public function toBeUuid(string $message = ''): self
@@ -1143,8 +997,6 @@ final class Expectation
}
/**
* Asserts that the value is a ULID.
*
* @return self<TValue>
*/
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>
*/
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>
*/
public function toBeEmail(string $message = ''): self
@@ -1188,8 +1036,6 @@ final class Expectation
}
/**
* Asserts that the value is a url
*
* @return self<TValue>
*/
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>
*/
public function toBeSlug(string $message = ''): self
@@ -1221,8 +1065,6 @@ final class Expectation
}
/**
* Asserts that the value is an IP address.
*
* @return self<TValue>
*/
public function toBeIpAddress(string $message = ''): self
@@ -1237,8 +1079,6 @@ final class Expectation
}
/**
* Asserts that the value is a MAC address.
*
* @return self<TValue>
*/
public function toBeMacAddress(string $message = ''): self
@@ -1253,8 +1093,6 @@ final class Expectation
}
/**
* Asserts that the value is a hostname.
*
* @return self<TValue>
*/
public function toBeHostname(string $message = ''): self
@@ -1269,8 +1107,6 @@ final class Expectation
}
/**
* Asserts that the value is a domain name.
*
* @return self<TValue>
*/
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>
*/
public function toBeBase64(string $message = ''): self
@@ -1305,8 +1139,6 @@ final class Expectation
}
/**
* Asserts that the value is a hexadecimal string.
*
* @return self<TValue>
*/
public function toBeHexadecimal(string $message = ''): self
@@ -15,12 +15,6 @@ use PHPStan\Type\ObjectType;
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
*/
final readonly class HigherOrderExpectationTypeExtension implements ExpressionTypeResolverExtension
+1 -10
View File
@@ -14,18 +14,12 @@ use Whoops\Exception\Inspector;
final readonly class Panic
{
/**
* Creates a new Panic instance.
*/
private function __construct(
private Throwable $throwable
) {
// ...
//
}
/**
* Creates a new Panic instance, and exits the application.
*/
public static function with(Throwable $throwable): never
{
if ($throwable instanceof TestDescriptionMissing && ! is_null($previous = $throwable->getPrevious())) {
@@ -39,9 +33,6 @@ final readonly class Panic
exit(1);
}
/**
* Handles the panic.
*/
private function handle(): void
{
try {
-14
View File
@@ -20,19 +20,10 @@ final class AfterEachCall
{
use Describable;
/**
* The "afterEach" closure.
*/
private readonly Closure $closure;
/**
* The calls that should be proxied.
*/
private readonly HigherOrderMessageCollection $proxies;
/**
* Creates a new Pending Call.
*/
public function __construct(
private readonly TestSuite $testSuite,
private readonly string $filename,
@@ -45,9 +36,6 @@ final class AfterEachCall
$this->describing = DescribeCall::describing();
}
/**
* Creates the Call.
*/
public function __destruct()
{
$describing = $this->describing;
@@ -69,8 +57,6 @@ final class AfterEachCall
}
/**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): self
-20
View File
@@ -23,24 +23,12 @@ final class BeforeEachCall
{
use Describable;
/**
* Holds the before each closure.
*/
private readonly Closure $closure;
/**
* The test call proxies.
*/
private readonly HigherOrderMessageCollection $testCallProxies;
/**
* The test case proxies.
*/
private readonly HigherOrderMessageCollection $testCaseProxies;
/**
* Creates a new Pending Call.
*/
public function __construct(
public readonly TestSuite $testSuite,
private readonly string $filename,
@@ -54,9 +42,6 @@ final class BeforeEachCall
$this->describing = DescribeCall::describing();
}
/**
* Creates the Call.
*/
public function __destruct()
{
$describing = $this->describing;
@@ -92,9 +77,6 @@ final class BeforeEachCall
);
}
/**
* Runs the given closure after the test.
*/
public function after(Closure $closure): self
{
if ($this->describing === []) {
@@ -105,8 +87,6 @@ final class BeforeEachCall
}
/**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): self
@@ -12,15 +12,11 @@ use Pest\Support\Description;
trait Describable
{
/**
* Note: this is property is not used; however, it gets added automatically by rector php.
*
* @var array<int, Description>
*/
public array $__describing;
/**
* The describing of the test case.
*
* @var array<int, Description>
*/
public array $describing = [];
+1 -19
View File
@@ -14,20 +14,12 @@ use Pest\TestSuite;
final class DescribeCall
{
/**
* The current describe call.
*
* @var array<int, Description>
*/
private static array $describing = [];
/**
* The describe "before each" call.
*/
private ?BeforeEachCall $currentBeforeEachCall = null;
/**
* Creates a new Pending Call.
*/
public function __construct(
public readonly TestSuite $testSuite,
public readonly string $filename,
@@ -38,8 +30,6 @@ final class DescribeCall
}
/**
* What is the current describing.
*
* @return array<int, Description>
*/
public static function describing(): array
@@ -47,17 +37,11 @@ final class DescribeCall
return self::$describing;
}
/**
* Creates the Call.
*/
public function __destruct()
{
// Ensure BeforeEachCall destructs before creating tests
// by moving to local scope and clearing the reference
$beforeEach = $this->currentBeforeEachCall;
$this->currentBeforeEachCall = null;
unset($beforeEach); // Trigger destructor immediately
unset($beforeEach);
self::$describing[] = $this->description;
try {
@@ -68,8 +52,6 @@ final class DescribeCall
}
/**
* Dynamically calls methods on each test call.
*
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): self
-126
View File
@@ -38,25 +38,14 @@ final class TestCall // @phpstan-ignore-line
use Describable;
/**
* The list of test case factory attributes.
*
* @var array<int, Attribute>
*/
private array $testCaseFactoryAttributes = [];
/**
* The Test Case Factory.
*/
public readonly TestCaseMethodFactory $testCaseMethod;
/**
* If test call is descriptionLess.
*/
private readonly bool $descriptionLess;
/**
* Creates a new Pending Call.
*/
public function __construct(
private readonly TestSuite $testSuite,
private readonly string $filename,
@@ -72,9 +61,6 @@ final class TestCall // @phpstan-ignore-line
$this->testSuite->beforeEach->get($this->filename)[0]($this);
}
/**
* Runs the given closure after the test.
*/
public function after(Closure $closure): self
{
if ($this->description === null) {
@@ -108,17 +94,11 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Asserts that the test fails with the given message.
*/
public function fails(?string $message = null): self
{
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
{
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
*/
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
*/
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
*/
public function with(Closure|iterable|string ...$data): self
@@ -196,9 +170,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the test depends.
*/
public function depends(string ...$depends): self
{
foreach ($depends as $depend) {
@@ -208,9 +179,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the test group(s).
*/
public function group(string ...$groups): self
{
foreach ($groups as $group) {
@@ -223,9 +191,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Filters the test suite by "only" tests.
*/
public function only(): self
{
Only::enable($this, ...func_get_args());
@@ -233,9 +198,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Skips the current test.
*/
public function skip(Closure|bool|string $conditionOrMessage = true, string $message = ''): self
{
$condition = is_string($conditionOrMessage)
@@ -260,9 +222,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Skips the current test on the given PHP version.
*/
public function skipOnPhp(string $version): self
{
if (mb_strlen($version) < 2) {
@@ -275,7 +234,6 @@ final class TestCall // @phpstan-ignore-line
} elseif (str_starts_with($version, '>') || str_starts_with($version, '<')) {
$operator = $version[0];
$version = substr($version, 1);
// ensure starts with number:
} elseif (is_numeric($version[0])) {
$operator = '==';
} 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));
}
/**
* Skips the current test if the given test is running on Windows.
*/
public function skipOnWindows(): self
{
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
{
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
{
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
{
return $osFamily === PHP_OS_FAMILY
@@ -319,9 +265,6 @@ final class TestCall // @phpstan-ignore-line
: $this;
}
/**
* Weather the current test is running on a CI environment.
*/
private function runningOnCI(): bool
{
foreach ([
@@ -353,9 +296,6 @@ final class TestCall // @phpstan-ignore-line
return Environment::name() === Environment::CI;
}
/**
* Skips the current test when running on a CI environments.
*/
public function skipOnCI(): self
{
if ($this->runningOnCI()) {
@@ -374,33 +314,21 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Skips the current test unless the given test is running on Windows.
*/
public function onlyOnWindows(): self
{
return $this->skipOnMac()->skipOnLinux();
}
/**
* Skips the current test unless the given test is running on Mac.
*/
public function onlyOnMac(): self
{
return $this->skipOnWindows()->skipOnLinux();
}
/**
* Skips the current test unless the given test is running on Linux.
*/
public function onlyOnLinux(): self
{
return $this->skipOnWindows()->skipOnMac();
}
/**
* Repeats the current test the given number of times.
*/
public function repeat(int $times): self
{
if ($times < 1) {
@@ -412,9 +340,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Marks the test as flaky, retrying it up to the given number of times.
*/
public function flaky(int $tries = 3): self
{
if ($tries < 1) {
@@ -426,9 +351,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Marks the test as "todo".
*/
public function todo(// @phpstan-ignore-line
array|string|null $note = null,
array|string|null $assignee = null,
@@ -458,9 +380,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the test as "work in progress".
*/
public function wip(// @phpstan-ignore-line
array|string|null $note = null,
array|string|null $assignee = null,
@@ -486,9 +405,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the test as "done".
*/
public function done(// @phpstan-ignore-line
array|string|null $note = 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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
public function covers(array|string ...$classesOrFunctions): self
@@ -615,9 +519,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the covered classes.
*/
public function coversClass(string ...$classes): self
{
foreach ($classes as $class) {
@@ -638,9 +539,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the covered classes.
*/
public function coversTrait(string ...$traits): self
{
foreach ($traits as $trait) {
@@ -661,9 +559,6 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Sets the covered functions.
*/
public function coversFunction(string ...$functions): self
{
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
*/
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
*/
public function see(string|array ...$classes): self
@@ -700,11 +589,6 @@ final class TestCall // @phpstan-ignore-line
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
{
$this->testCaseMethod->proxies->add(Backtrace::file(), Backtrace::line(), 'expectNotToPerformAssertions', []);
@@ -712,17 +596,12 @@ final class TestCall // @phpstan-ignore-line
return $this;
}
/**
* Saves the property accessors to be used on the target.
*/
public function __get(string $name): self
{
return $this->addChain(Backtrace::file(), Backtrace::line(), $name);
}
/**
* Saves the calls to be used on the target.
*
* @param array<int, mixed> $arguments
*/
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
*/
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;
}
/**
* Creates the Call.
*/
public function __destruct()
{
if ($this->description === null) {
-41
View File
@@ -14,36 +14,21 @@ use Pest\TestSuite;
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>
*/
private array $hooks = [];
/**
* Holds the targets of the uses.
*
* @var array<int, string>
*/
private array $targets;
/**
* Holds the groups of the uses.
*
* @var array<int, string>
*/
private array $groups = [];
/**
* Creates a new Pending Call.
*
* @param array<int, string> $classAndTraits
*/
public function __construct(
@@ -62,8 +47,6 @@ final class UsesCall
}
/**
* Specifies the class or traits to use.
*
* @alias extend
*/
public function use(string ...$classAndTraits): self
@@ -71,9 +54,6 @@ final class UsesCall
return $this->extend(...$classAndTraits);
}
/**
* Specifies the class or traits to use.
*/
public function extend(string ...$classAndTraits): self
{
$this->classAndTraits = array_merge($this->classAndTraits, array_values($classAndTraits));
@@ -81,9 +61,6 @@ final class UsesCall
return $this;
}
/**
* The directories or file where the class or traits should be used.
*/
public function in(string ...$targets): self
{
$targets = array_map(function (string $path): string {
@@ -116,9 +93,6 @@ final class UsesCall
return $this;
}
/**
* Sets the test group(s).
*/
public function group(string ...$groups): self
{
$this->groups = array_values($groups);
@@ -126,9 +100,6 @@ final class UsesCall
return $this;
}
/**
* Sets the global beforeAll test hook.
*/
public function beforeAll(Closure $hook): self
{
$this->hooks[0] = $hook;
@@ -136,9 +107,6 @@ final class UsesCall
return $this;
}
/**
* Sets the global beforeEach test hook.
*/
public function beforeEach(Closure $hook): self
{
$this->hooks[1] = $hook;
@@ -146,9 +114,6 @@ final class UsesCall
return $this;
}
/**
* Sets the global afterEach test hook.
*/
public function afterEach(Closure $hook): self
{
$this->hooks[2] = $hook;
@@ -156,9 +121,6 @@ final class UsesCall
return $this;
}
/**
* Sets the global afterAll test hook.
*/
public function afterAll(Closure $hook): self
{
$this->hooks[3] = $hook;
@@ -166,9 +128,6 @@ final class UsesCall
return $this;
}
/**
* Creates the Call.
*/
public function __destruct()
{
TestSuite::getInstance()->tests->use(
+1 -1
View File
@@ -6,7 +6,7 @@ namespace Pest;
function version(): string
{
return '5.0.4';
return '5.0.5';
}
function testDirectory(string $file = ''): string
-4
View File
@@ -7,8 +7,6 @@ namespace Pest;
final class Plugin
{
/**
* The lazy callables to be executed once the test suite boots.
*
* @var array<int, callable>
*
* @internal
@@ -16,8 +14,6 @@ final class Plugin
public static array $callables = [];
/**
* Lazy loads an `uses` call on the context of plugins.
*
* @param class-string ...$traits
*/
public static function uses(string ...$traits): void

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