Compare commits

..

6 Commits

Author SHA1 Message Date
nuno maduro 1af74a215c chore: new sponsor 2026-08-18 19:42:16 +01:00
Andrew Matia cfe89d20ac Fix repeat with named dataset arguments (#1769) 2026-08-16 15:08:46 +01:00
nuno maduro 2c7cc1dc87 fix: static callable datasets 2026-08-13 18:38:27 +01:00
Lazizbek Ergashev 9b36f44b3e fix(tia): include the PHP minor version in the fingerprint (#1860) 2026-08-13 16:16:15 +01:00
Lazizbek Ergashev 2e58918201 fix(tia): treat a test skipped from a hook as finished (#1863) 2026-08-13 16:15:45 +01:00
nuno maduro a8d4770c0b chore: fix version 2026-08-12 15:37:18 +01:00
13 changed files with 108 additions and 15 deletions
+1
View File
@@ -37,6 +37,7 @@ We cannot thank our sponsors enough for their incredible support in funding Pest
- **[Redberry](https://redberry.international/laravel-development/?utm_source=pest&utm_medium=banner&utm_campaign=pest_sponsorship)**
- **[Typesense](https://typesense.org/?ref=nunomaduro)**
- **[Pixel](https://wearepixel.com.au/?ref=nunomaduro)**
- **[NativePHP](https://nativephp.com/?ref=nunomaduro)**
- [TestMu AI](https://www.testmuai.com/?utm_medium=sponsor&utm_source=pest)
- [Zapiet](https://zapiet.com/?ref=nunomaduro)
- [LoadForge](https://loadforge.com/?ref=nunomaduro)
+15 -6
View File
@@ -408,16 +408,25 @@ trait Testable
private function __resolveTestArguments(array $arguments): array
{
$method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());
if ($method->repetitions > 1) {
$firstArgument = array_shift($arguments);
$arguments[] = $firstArgument;
}
$underlyingTest = Reflection::getFunctionVariable($this->__test, 'closure');
$testParameterTypesByName = Reflection::getFunctionArguments($underlyingTest);
$testParameterTypes = array_values($testParameterTypesByName);
if ($method->repetitions > 1) {
$firstArgument = array_shift($arguments);
if (array_is_list($arguments)) {
$arguments[] = $firstArgument;
} else {
$testParameterNames = array_keys($testParameterTypesByName);
$iterationParameterName = $testParameterNames[count($arguments)] ?? null;
if ($iterationParameterName !== null) {
$arguments[$iterationParameterName] = $firstArgument;
}
}
}
if (count($arguments) !== 1) {
foreach ($arguments as $argumentIndex => $argumentValue) {
if (! $argumentValue instanceof Closure) {
+1 -1
View File
@@ -6,7 +6,7 @@ namespace Pest;
function version(): string
{
return '5.0.5';
return '5.1.1';
}
function testDirectory(string $file = ''): string
+1 -1
View File
@@ -40,7 +40,7 @@ final readonly class Fingerprint
'js_config' => self::jsConfigHash($projectRoot),
],
'environmental' => [
'php_minor' => PHP_MAJOR_VERSION,
'php_minor' => PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION,
],
];
+1 -1
View File
@@ -117,7 +117,7 @@ final class ResultCollector
public function hasUnfinishedTest(): bool
{
return $this->currentTestId !== null;
return $this->currentTestId !== null && ! isset($this->results[$this->currentTestId]);
}
public function recordAssertions(string $testId, int $assertions): void
+1 -1
View File
@@ -141,7 +141,7 @@ final class DatasetsRepository
$datasets[$index] = self::getScopedDataset($data, $currentTestFile);
}
if (is_callable($datasets[$index])) {
if (! is_array($datasets[$index]) && is_callable($datasets[$index])) {
$datasets[$index] = call_user_func($datasets[$index]);
}
@@ -1,5 +1,5 @@
Pest Testing Framework 5.0.5.
Pest Testing Framework 5.1.1.
USAGE: pest <file> [options]
@@ -1,3 +1,3 @@
Pest Testing Framework 5.0.5.
Pest Testing Framework 5.1.1.
+10 -1
View File
@@ -1455,6 +1455,14 @@
✓ multiple times with repeat iterator with multiple dataset ('c') / ('d') @ repetition 2 of 2
✓ multiple times with repeat iterator with multiple dataset ('c') / ('e') @ repetition 2 of 2
✓ multiple times with repeat iterator with multiple dataset ('c') / ('f') @ repetition 2 of 2
✓ multiple times with named dataset arguments ('Taylor', 'taylor@laravel.com') @ repetition 1 of 2
✓ multiple times with named dataset arguments ('Nuno', 'enunomaduro@gmail.com') @ repetition 1 of 2
✓ multiple times with named dataset arguments ('Taylor', 'taylor@laravel.com') @ repetition 2 of 2
✓ multiple times with named dataset arguments ('Nuno', 'enunomaduro@gmail.com') @ repetition 2 of 2
✓ multiple times with named dataset arguments and repeat iterator ('Taylor', 'taylor@laravel.com') @ repetition 1 of 2
✓ multiple times with named dataset arguments and repeat iterator ('Nuno', 'enunomaduro@gmail.com') @ repetition 1 of 2
✓ multiple times with named dataset arguments and repeat iterator ('Taylor', 'taylor@laravel.com') @ repetition 2 of 2
✓ multiple times with named dataset arguments and repeat iterator ('Nuno', 'enunomaduro@gmail.com') @ repetition 2 of 2
✓ describe blocks → multiple times @ repetition 1 of 3
✓ describe blocks → multiple times @ repetition 2 of 3
✓ describe blocks → multiple times @ repetition 3 of 3
@@ -1764,6 +1772,7 @@
✓ it shows the correct description for long texts with newlines
✓ it shows the correct description for arrays with many elements
✓ it shows the correct description of datasets with html
✓ it does not treat a two element dataset of class names as a callable
PASS Tests\Unit\Expectations\OppositeExpectation
✓ it throw expectation failed exception with string argument
@@ -2225,4 +2234,4 @@
✓ pass with dataset with ('my-datas-set-value')
✓ within describe → pass with dataset with ('my-datas-set-value')
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1572 passed (3413 assertions)
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1581 passed (3434 assertions)
+22
View File
@@ -44,6 +44,28 @@ test('multiple times with repeat iterator with multiple dataset', function (stri
->toBeGreaterThan(0);
})->repeat(times: 2)->with(['a', 'b', 'c'], ['d', 'e', 'f']);
test('multiple times with named dataset arguments', function (string $name, string $email): void {
expect($name)
->toBeIn(['Taylor', 'Nuno'])
->and($email)
->toContain('@');
})->repeat(times: 2)->with([
['name' => 'Taylor', 'email' => 'taylor@laravel.com'],
['name' => 'Nuno', 'email' => 'enunomaduro@gmail.com'],
]);
test('multiple times with named dataset arguments and repeat iterator', function (string $name, string $email, int $iteration): void {
expect($name)
->toBeIn(['Taylor', 'Nuno'])
->and($email)
->toContain('@')
->and($iteration)
->toBeIn([1, 2]);
})->repeat(times: 2)->with([
['name' => 'Taylor', 'email' => 'taylor@laravel.com'],
['name' => 'Nuno', 'email' => 'enunomaduro@gmail.com'],
]);
describe('describe blocks', function (): void {
test('multiple times', function (): void {
expect(true)->toBeTrue();
@@ -33,6 +33,34 @@ test('a complete run prunes a deleted test', function (array $arguments): void {
->and($delta->structureMoved())->toBeFalse($delta->summary());
})->with(Project::SEQUENTIAL_AND_PARALLEL)->skipOnWindows();
test('a complete run stays complete when the last test is skipped from a hook', function (array $arguments): void {
$project = Project::make('master');
$project->seed('master');
$project->write('tests/Unit/GreeterTest.php', <<<'PHP'
<?php
declare(strict_types=1);
use Fixture\App\Greeter;
beforeEach(function (): void {
test()->markTestSkipped('not today');
});
test('greets a person', function (): void {
expect((new Greeter)->greet('Nuno'))->toBe('Hello, Nuno!');
});
PHP);
$result = $project->pest(...$arguments);
$delta = $project->delta();
expect($result->tally())->toContain('1 skipped')
->and($delta->removed())->toBe(1, $delta->summary())
->and($delta->added())->toBe(0, $delta->summary());
})->with(Project::SEQUENTIAL_AND_PARALLEL)->skipOnWindows();
test('a complete run records nothing for a test file the graph does not know', function (): void {
$project = Project::make('master');
$project->seed('master');
+24
View File
@@ -109,3 +109,27 @@ it('shows the correct description of datasets with html', function (): void {
expect($descriptions[0])->toBe('(\'<div class="flex items-center"></div>\')');
});
it('does not treat a two element dataset of class names as a callable', function (): void {
$datasets = DatasetsRepository::resolve([
[
MagicCallDataset::class,
AnotherMagicCallDataset::class,
],
], __FILE__);
expect(array_values($datasets))->toBe([
[MagicCallDataset::class],
[AnotherMagicCallDataset::class],
]);
});
class MagicCallDataset
{
public static function __callStatic(string $name, array $arguments): void
{
throw new RuntimeException('This dataset should not be called.');
}
}
class AnotherMagicCallDataset {}
+2 -2
View File
@@ -26,13 +26,13 @@ test('parallel', function () use ($run): void {
$file = file_get_contents(__FILE__);
$file = preg_replace(
'/\$expected = \'.*?\';/',
"\$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1554 passed (3358 assertions)';",
"\$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1563 passed (3379 assertions)';",
$file,
);
file_put_contents(__FILE__, $file);
}
$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1554 passed (3358 assertions)';
$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1563 passed (3379 assertions)';
expect($output)
->toContain("Tests: {$expected}")