From 579b9753187ed0486966453fa2266dc9d1468725 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Thu, 15 Sep 2022 23:55:54 +0100 Subject: [PATCH] Fixes `--filter` --- bin/pest | 1 - composer.json | 3 + .../Runner/Filter/NameFilterIterator.php | 177 ++++++++++++++++++ src/Concerns/Testable.php | 4 +- 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 overrides/Runner/Filter/NameFilterIterator.php diff --git a/bin/pest b/bin/pest index 438a88a9..2071865c 100755 --- a/bin/pest +++ b/bin/pest @@ -46,7 +46,6 @@ use Symfony\Component\Console\Output\OutputInterface; $args = $_SERVER['argv']; - // Let's remove any arguments that PHPUnit does not understand if ($argv->hasParameterOption('--test-directory')) { foreach ($args as $key => $value) { if (strpos($value, '--test-directory') !== false) { diff --git a/composer.json b/composer.json index 714ad404..948acc3d 100644 --- a/composer.json +++ b/composer.json @@ -27,10 +27,13 @@ "Pest\\": "src/" }, "exclude-from-classmap": [ + "../phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php", + "vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php", "../phpunit/src/Runner/TestSuiteLoader.php", "vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php" ], "files": [ + "overrides/Runner/Filter/NameFilterIterator.php", "overrides/Runner/TestSuiteLoader.php", "src/Functions.php", "src/Pest.php" diff --git a/overrides/Runner/Filter/NameFilterIterator.php b/overrides/Runner/Filter/NameFilterIterator.php new file mode 100644 index 00000000..69909b51 --- /dev/null +++ b/overrides/Runner/Filter/NameFilterIterator.php @@ -0,0 +1,177 @@ +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * 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 OWNER 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. + */ + +namespace PHPUnit\Runner\Filter; + +use function end; + +use Exception; + +use function implode; + +use Pest\Contracts\HasPrintableTestCaseName; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; + +use function preg_match; + +use RecursiveFilterIterator; +use RecursiveIterator; + +use function sprintf; +use function str_replace; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NameFilterIterator extends RecursiveFilterIterator +{ + private ?string $filter = null; + private ?int $filterMin = null; + private ?int $filterMax = null; + + /** + * @throws Exception + */ + public function __construct(RecursiveIterator $iterator, string $filter) + { + parent::__construct($iterator); + + $this->setFilter($filter); + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + $tmp = $this->describe($test); + + if ($tmp[0] !== '') { + $name = implode('::', $tmp); + } else { + $name = $tmp[1]; + } + + $accepted = @preg_match($this->filter, $name, $matches); + + if ($accepted && isset($this->filterMax)) { + $set = end($matches); + $accepted = $set >= $this->filterMin && $set <= $this->filterMax; + } + + return (bool) $accepted; + } + + /** + * @throws Exception + */ + private function setFilter(string $filter): void + { + 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( + '%s.*with data set #(\d+)$', + $matches[1] + ); + + $this->filterMin = (int) $matches[2]; + $this->filterMax = (int) $matches[3]; + } else { + $filter = sprintf( + '%s.*with data set #%s$', + $matches[1], + $matches[2] + ); + } + } // Handles: + // * testDetermineJsonError@JSON_ERROR_NONE + // * testDetermineJsonError@JSON.* + elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { + $filter = sprintf( + '%s.*with data set "%s"$', + $matches[1], + $matches[2] + ); + } + + // Escape delimiters in regular expression. Do NOT use preg_quote, + // to keep magic characters. + $filter = sprintf( + '/%s/i', + str_replace( + '/', + '\\/', + $filter + ) + ); + } + + $this->filter = $filter; + } + + /** + * @psalm-return array{0: string, 1: string} + */ + private function describe(Test $test): array + { + if ($test instanceof HasPrintableTestCaseName) { + return [ + $test::getPrintableTestCaseName(), + $test::getPrintableTestCaseMethodName(), + ]; + } + + if ($test instanceof TestCase) { + return [$test::class, $test->nameWithDataSet()]; + } + + if ($test instanceof SelfDescribing) { + return ['', $test->toString()]; + } + + return ['', $test::class]; + } +} diff --git a/src/Concerns/Testable.php b/src/Concerns/Testable.php index 879b53f1..858c2876 100644 --- a/src/Concerns/Testable.php +++ b/src/Concerns/Testable.php @@ -68,7 +68,9 @@ trait Testable $test = TestSuite::getInstance()->tests->get(self::$__filename); if ($test->hasMethod($name)) { - $this->__test = $test->getMethod($name)->getClosure($this); + $method = $test->getMethod($name); + self::$__description = $method->description; + $this->__test = $method->getClosure($this); } }