diff --git a/CHANGELOG.md b/CHANGELOG.md index c8972013..811f5e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased +## [v2.1.0 (2023-03-21)](https://github.com/pestphp/pest/compare/v2.0.2...v2.1.0) + +### Added +- `only` test case method ([bcd1503](https://github.com/pestphp/pest/commit/bcd1503cade938853a55c1283b02b6b820ea0b69)) + +### Fixed +- Issues with different characters on test names ([715](https://github.com/pestphp/pest/pull/715)) + ## [v2.0.2 (2023-03-20)](https://github.com/pestphp/pest/compare/v2.0.1...v2.0.2) ### Fixed diff --git a/composer.json b/composer.json index bbc508f0..3685d4df 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "require": { "php": "^8.1.0", "brianium/paratest": "^7.1.2", - "nunomaduro/collision": "^7.2.0", + "nunomaduro/collision": "^7.3.1", "nunomaduro/termwind": "^1.15.1", "pestphp/pest-plugin": "^2.0.0", "pestphp/pest-plugin-arch": "^2.0.1", @@ -92,6 +92,7 @@ "Pest\\Plugins\\Environment", "Pest\\Plugins\\Help", "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", "Pest\\Plugins\\Printer", "Pest\\Plugins\\ProcessIsolation", "Pest\\Plugins\\Profile", diff --git a/overrides/TextUI/TestSuiteFilterProcessor.php b/overrides/TextUI/TestSuiteFilterProcessor.php new file mode 100644 index 00000000..31ce5fe6 --- /dev/null +++ b/overrides/TextUI/TestSuiteFilterProcessor.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PHPUnit\TextUI; + +use function array_map; +use Pest\Plugins\Only; +use PHPUnit\Event; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\FilterNotConfiguredException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFilterProcessor +{ + private Factory $filterFactory; + + public function __construct(Factory $factory = new Factory) + { + $this->filterFactory = $factory; + } + + /** + * @throws Event\RuntimeException + * @throws FilterNotConfiguredException + */ + public function process(Configuration $configuration, TestSuite $suite): void + { + if (! $configuration->hasFilter() && + ! $configuration->hasGroups() && + ! $configuration->hasExcludeGroups() && + ! $configuration->hasTestsCovering() && + ! $configuration->hasTestsUsing() && + ! Only::isEnabled() + ) { + return; + } + + if ($configuration->hasExcludeGroups()) { + $this->filterFactory->addExcludeGroupFilter( + $configuration->excludeGroups() + ); + } + + if (Only::isEnabled()) { + $this->filterFactory->addIncludeGroupFilter(['__pest_only']); + } elseif ($configuration->hasGroups()) { + $this->filterFactory->addIncludeGroupFilter( + $configuration->groups() + ); + } + + if ($configuration->hasTestsCovering()) { + $this->filterFactory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_covers_'.$name, + $configuration->testsCovering() + ) + ); + } + + if ($configuration->hasTestsUsing()) { + $this->filterFactory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_uses_'.$name, + $configuration->testsUsing() + ) + ); + } + + if ($configuration->hasFilter()) { + $this->filterFactory->addNameFilter( + $configuration->filter() + ); + } + + $suite->injectFilter($this->filterFactory); + + Event\Facade::emitter()->testSuiteFiltered( + Event\TestSuite\TestSuiteBuilder::from($suite) + ); + } +} diff --git a/src/Bootstrappers/BootOverrides.php b/src/Bootstrappers/BootOverrides.php index d25f935d..e1489d7c 100644 --- a/src/Bootstrappers/BootOverrides.php +++ b/src/Bootstrappers/BootOverrides.php @@ -23,6 +23,7 @@ final class BootOverrides implements Bootstrapper 'Runner/TestSuiteLoader.php', 'TextUI/Command/WarmCodeCoverageCacheCommand.php', 'TextUI/Output/Default/ProgressPrinter/TestSkippedSubscriber.php', + 'TextUI/TestSuiteFilterProcessor.php', ]; /** diff --git a/src/Expectation.php b/src/Expectation.php index 07b0d5d5..537883bb 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -64,7 +64,7 @@ final class Expectation */ public function and(mixed $value): Expectation { - return $value instanceof static ? $value : new self($value); + return $value instanceof self ? $value : new self($value); } /** diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index c793ef17..8b237ec7 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -10,6 +10,7 @@ use Pest\Factories\Covers\CoversClass; use Pest\Factories\Covers\CoversFunction; use Pest\Factories\Covers\CoversNothing; use Pest\Factories\TestCaseMethodFactory; +use Pest\Plugins\Only; use Pest\Support\Backtrace; use Pest\Support\Exporter; use Pest\Support\HigherOrderCallables; @@ -134,6 +135,16 @@ final class TestCall return $this; } + /** + * Filters the test suite by "only" tests. + */ + public function only(): self + { + Only::enable($this); + + return $this; + } + /** * Skips the current test. */ diff --git a/src/Pest.php b/src/Pest.php index d0fa2ff3..32978f6e 100644 --- a/src/Pest.php +++ b/src/Pest.php @@ -6,7 +6,7 @@ namespace Pest; function version(): string { - return '2.0.2'; + return '2.1.0'; } function testDirectory(string $file = ''): string diff --git a/src/Plugins/Only.php b/src/Plugins/Only.php new file mode 100644 index 00000000..aa4556b8 --- /dev/null +++ b/src/Plugins/Only.php @@ -0,0 +1,61 @@ +group('__pest_only'); + + $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock'; + + if (! file_exists($lockFile)) { + touch($lockFile); + } + } + + /** + * Checks if "only" mode is enabled. + */ + public static function isEnabled(): bool + { + $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock'; + + return file_exists($lockFile); + } +} diff --git a/src/Support/Arr.php b/src/Support/Arr.php index bd80ae56..aed6c5a7 100644 --- a/src/Support/Arr.php +++ b/src/Support/Arr.php @@ -73,7 +73,7 @@ final class Arr foreach ($array as $key => $value) { if (is_array($value) && $value !== []) { - $results = array_merge($results, static::dot($value, $prepend.$key.'.')); + $results = array_merge($results, self::dot($value, $prepend.$key.'.')); } else { $results[$prepend.$value] = $value; } diff --git a/src/Support/Reflection.php b/src/Support/Reflection.php index 14edd7ad..18a71aa6 100644 --- a/src/Support/Reflection.php +++ b/src/Support/Reflection.php @@ -42,7 +42,7 @@ final class Reflection } if (is_callable($method)) { - return static::bindCallable($method, $args); + return self::bindCallable($method, $args); } throw $exception; @@ -72,7 +72,7 @@ final class Reflection return $test instanceof \PHPUnit\Framework\TestCase ? Closure::fromCallable($callable)->bindTo($test)(...$test->providedData()) - : static::bindCallable($callable); + : self::bindCallable($callable); } /** diff --git a/src/Support/Str.php b/src/Support/Str.php index 9ed75c1f..21ee5c5b 100644 --- a/src/Support/Str.php +++ b/src/Support/Str.php @@ -61,7 +61,8 @@ final class Str { $code = self::PREFIX.str_replace(' ', '_', $code); - return (string) preg_replace('/[^A-Z_a-z0-9]/', '_', $code); + // sticks to PHP8.2 function naming rules https://www.php.net/manual/en/functions.user-defined.php + return (string) preg_replace('/[^a-zA-Z0-9_\x80-\xff]/', '_', $code); } /** diff --git a/tests/.snapshots/help-command.txt b/tests/.snapshots/help-command.txt index aa7cf29f..2ebc633d 100644 --- a/tests/.snapshots/help-command.txt +++ b/tests/.snapshots/help-command.txt @@ -1,5 +1,5 @@ - Pest Testing Framework 2.0.2. + Pest Testing Framework 2.1.0. USAGE: pest [options] diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index ad025028..2db57d3f 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -914,6 +914,52 @@ ✓ it may start with P with ('P\PPPackages\Foo', 'PPPackages\Foo') ✓ it may start with P with ('PPPackages\Foo', 'PPPackages\Foo') #1 ✓ it may start with P with ('PPPackages\Foo', 'PPPackages\Foo') #2 + ✓ ふ+が+ + ✓ ほげ + ✓ 卜竹弓一十山 + ✓ アゴデヸ + ✓ !p8VrB + ✓ &xe6VeKWF#n4 + ✓ %%HurHUnw7zM! + ✓ rundeliekend + ✓ g%%c!Jt9$fy#Kf + ✓ NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX + ✓ ÀĤ{¼÷ + ✓ ìèéàòç + ✓ زهراء المعادي + ✓ الجبيهه + ✓ الظهران + ✓ Каролин + ✓ অ্যান্টার্কটিকা + ✓ Frýdek-Místek" + ✓ Allingåbro& + ✓ Κεντροαφρικανική Δημοκρατία + ✓ آذربایجان غربی + ✓ זימבבואה + ✓ Belišće + ✓ Գվատեմալա + ✓ パプアニューギニア + ✓ 富山県 + ✓ Қарағанды + ✓ Қостанай + ✓ 안양시 동안구 + ✓ Itālija + ✓ Honningsvåg + ✓ Águeda + ✓ Râșcani + ✓ Năsăud + ✓ Орехово-Зуево + ✓ Čereňany + ✓ Moravče + ✓ Šentjernej + ✓ Врање + ✓ Крушевац + ✓ Åkersberga + ✓ บอสเนียและเฮอร์เซโกวีนา + ✓ Birleşik Arap Emirlikleri + ✓ Німеччина + ✓ Nam Định + ✓ 呼和浩特 PASS Tests\Unit\TestSuite ✓ it does not allow to add the same test description twice @@ -948,4 +994,4 @@ PASS Tests\Visual\Version ✓ visual snapshot of help command output - Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 12 skipped, 653 passed (1604 assertions) \ No newline at end of file + Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 12 skipped, 695 passed (1680 assertions) diff --git a/tests/.snapshots/version-command.txt b/tests/.snapshots/version-command.txt index 0ad97038..a50a10ae 100644 --- a/tests/.snapshots/version-command.txt +++ b/tests/.snapshots/version-command.txt @@ -1,3 +1,3 @@ - Pest Testing Framework 2.0.2. + Pest Testing Framework 2.1.0. diff --git a/tests/Unit/TestName.php b/tests/Unit/TestName.php index 3f52e700..b7f91d54 100644 --- a/tests/Unit/TestName.php +++ b/tests/Unit/TestName.php @@ -11,3 +11,60 @@ it('may start with P', function (string $real, string $toBePrinted) { ['PPPackages\Foo', 'PPPackages\Foo'], ['PPPackages\Foo', 'PPPackages\Foo'], ]); + +$names = [ + 'ふ+が+' => '__pest_evaluable_ふ_が_', + 'ほげ' => '__pest_evaluable_ほげ', + '卜竹弓一十山' => '__pest_evaluable_卜竹弓一十山', + 'アゴデヸ' => '__pest_evaluable_アゴデヸ', + '!p8VrB' => '__pest_evaluable__p8VrB', + '&xe6VeKWF#n4' => '__pest_evaluable__xe6VeKWF_n4', + '%%HurHUnw7zM!' => '__pest_evaluable___HurHUnw7zM_', + 'rundeliekend' => '__pest_evaluable_rundeliekend', + 'g%%c!Jt9$fy#Kf' => '__pest_evaluable_g__c_Jt9_fy_Kf', + 'NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX' => '__pest_evaluable_NRs_Gz2_hmB_W_BPD__b2U_3P_z_apnwSX', + 'ÀĤ{¼÷' => '__pest_evaluable_ÀĤ_¼÷', + 'ìèéàòç' => '__pest_evaluable_ìèéàòç', + 'زهراء المعادي' => '__pest_evaluable_زهراء_المعادي', + 'الجبيهه' => '__pest_evaluable_الجبيهه', + 'الظهران' => '__pest_evaluable_الظهران', + 'Каролин' => '__pest_evaluable_Каролин', + 'অ্যান্টার্কটিকা' => '__pest_evaluable_অ্যান্টার্কটিকা', + 'Frýdek-Místek"' => '__pest_evaluable_Frýdek_Místek_', + 'Allingåbro&' => '__pest_evaluable_Allingåbro_', + 'Κεντροαφρικανική Δημοκρατία' => '__pest_evaluable_Κεντροαφρικανική_Δημοκρατία', + 'آذربایجان غربی' => '__pest_evaluable_آذربایجان_غربی', + 'זימבבואה' => '__pest_evaluable_זימבבואה', + 'Belišće' => '__pest_evaluable_Belišće', + 'Գվատեմալա' => '__pest_evaluable_Գվատեմալա', + 'パプアニューギニア' => '__pest_evaluable_パプアニューギニア', + '富山県' => '__pest_evaluable_富山県', + 'Қарағанды' => '__pest_evaluable_Қарағанды', + 'Қостанай' => '__pest_evaluable_Қостанай', + '안양시 동안구' => '__pest_evaluable_안양시_동안구', + 'Itālija' => '__pest_evaluable_Itālija', + 'Honningsvåg' => '__pest_evaluable_Honningsvåg', + 'Águeda' => '__pest_evaluable_Águeda', + 'Râșcani' => '__pest_evaluable_Râșcani', + 'Năsăud' => '__pest_evaluable_Năsăud', + 'Орехово-Зуево' => '__pest_evaluable_Орехово_Зуево', + 'Čereňany' => '__pest_evaluable_Čereňany', + 'Moravče' => '__pest_evaluable_Moravče', + 'Šentjernej' => '__pest_evaluable_Šentjernej', + 'Врање' => '__pest_evaluable_Врање', + 'Крушевац' => '__pest_evaluable_Крушевац', + 'Åkersberga' => '__pest_evaluable_Åkersberga', + 'บอสเนียและเฮอร์เซโกวีนา' => '__pest_evaluable_บอสเนียและเฮอร์เซโกวีนา', + 'Birleşik Arap Emirlikleri' => '__pest_evaluable_Birleşik_Arap_Emirlikleri', + 'Німеччина' => '__pest_evaluable_Німеччина', + 'Nam Định' => '__pest_evaluable_Nam_Định', + '呼和浩特' => '__pest_evaluable_呼和浩特', +]; + +foreach ($names as $name => $methodName) { + test($name) + ->expect(fn () => static::getLatestPrintableTestCaseMethodName()) + ->toBe($name) + ->and(fn () => $this->name()) + ->toBe($methodName); +} diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index b3817ef7..5c770e05 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -15,6 +15,6 @@ $run = function () { }; test('parallel', function () use ($run) { - expect($run())->toContain('Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 9 skipped, 644 passed (1592 assertions)') + expect($run())->toContain('Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 9 skipped, 686 passed (1668 assertions)') ->toContain('Parallel: 3 processes'); })->skip(PHP_OS_FAMILY === 'Windows');