Compare commits

..

23 Commits

Author SHA1 Message Date
08b09f2e98 release: 4.1.2 2025-10-05 20:09:49 +01:00
b0fab7e437 chore: uses phpunit@12.4 2025-10-05 20:09:42 +01:00
8e3444e1db chore: bumps requirements 2025-10-01 14:30:25 +01:00
fc7a4182b5 adjusts sponsors 2025-09-18 20:13:01 +01:00
b7406938ac release: v4.1.0 2025-09-10 14:41:09 +01:00
314caabd1d chore: improves types 2025-09-10 14:41:02 +01:00
65cabf91b1 chore: bumps dependencies 2025-09-10 14:40:52 +01:00
f91c6c1e1e Update social media links in Thanks.php 2025-09-01 00:09:31 +01:00
843dbbf18a Update README.md 2025-08-31 23:50:16 +01:00
47fb1d7763 release: v4.0.4 2025-08-28 19:19:42 +01:00
639df4cb43 chore: uses phpunit 12.3.7 2025-08-28 19:19:32 +01:00
e54e4a0178 release: 4.0.3 2025-08-24 15:17:23 +01:00
7749775f50 chore: uses phpunit 12.3.6 2025-08-24 15:17:19 +01:00
f11f3aa0a4 Merge pull request #1464 from gehrisandro/sandro/prevent-duplicate-attributes
Prevent duplicate attributes
2025-08-23 22:43:15 +01:00
33817013fe Prevent duplicate attributes 2025-08-23 12:35:32 +02:00
7f11ace329 release: 4.0.2 2025-08-22 11:34:24 +01:00
3d776f1f20 fix: revert reading coverage by chunks 2025-08-22 11:12:55 +01:00
d5ced0a5ca release: 4.0.1 2025-08-22 09:24:07 +01:00
af1e214be4 chore: bumps dependencies 2025-08-22 09:22:16 +01:00
7f9b50974a Merge pull request #1460 from Admiral-Enigma/4.x
Cast "testdox-columns" to an int
2025-08-22 09:20:44 +01:00
cd5272d8cc Cast "testdox-columns" to an int 2025-08-22 10:00:49 +02:00
a7b2039175 Merge branch '3.x' into 4.x 2025-08-20 20:14:15 +01:00
72cf695554 release: 3.8.4 2025-08-20 20:12:42 +01:00
12 changed files with 38 additions and 138 deletions

View File

@ -16,8 +16,8 @@
- Explore our docs at **[pestphp.com »](https://pestphp.com)**
- Follow the creator Nuno Maduro:
- YouTube: **[youtube.com/@nunomaduro](https://www.youtube.com/@nunomaduro)** — Videos every weekday
- Twitch: **[twitch.tv/enunomaduro](https://www.twitch.tv/enunomaduro)** — Streams (almost) every weekday
- YouTube: **[youtube.com/@nunomaduro](https://youtube.com/@nunomaduro)** — Videos every week
- Twitch: **[twitch.tv/nunomaduro](https://twitch.tv/nunomaduro)** — Live coding on Mondays, Wednesdays, and Fridays at 9PM UTC
- Twitter / X: **[x.com/enunomaduro](https://x.com/enunomaduro)**
- LinkedIn: **[linkedin.com/in/nunomaduro](https://www.linkedin.com/in/nunomaduro)**
- Instagram: **[instagram.com/enunomaduro](https://www.instagram.com/enunomaduro)**
@ -31,22 +31,24 @@ We cannot thank our sponsors enough for their incredible support in funding Pest
### Platinum Sponsors
- **[Laracasts](https://laracasts.com/?ref=pestphp)**
- **[NativePHP](https://nativephp.com/mobile?ref=pestphp.com)**
### Gold Sponsors
- **[CodeRabbit](https://coderabbit.ai/?ref=pestphp)**
- **[NativePHP](https://nativephp.com/mobile?ref=pestphp.com)**
- **[CMS Max](https://cmsmax.com/?ref=pestphp)**
### Premium Sponsors
- [Akaunting](https://akaunting.com/?ref=pestphp)
- [DocuWriter.ai](https://www.docuwriter.ai/?ref=pestphp)
- [Localazy](https://localazy.com/?ref=pestphp)
- [Forge](https://forge.laravel.com/?ref=pestphp)
- [Route4Me](https://www.route4me.com/?ref=pestphp)
- [Spatie](https://spatie.be/?ref=pestphp)
- [Worksome](https://www.worksome.com/?ref=pestphp)
- [Zapiet](https://www.zapiet.com/?ref=pestphp)
- [Localazy](https://localazy.com/?ref=pestphp)
- [Load Forge](https://loadforge.com/?ref=pestphp)
- [DocuWriter.ai](https://www.docuwriter.ai/?ref=pestphp)
- [Route4Me](https://www.route4me.com/?ref=pestphp)
- [Devtools for Livewire](https://devtools-for-livewire.com/?ref=pestphp)
- [Nerdify](https://www.getnerdify.com/?ref=pestphp)
- [Akaunting](https://akaunting.com/?ref=pestphp)
- [LambdaTest](https://lambdatest.com/?ref=pestphp)
Pest is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.

View File

@ -86,7 +86,7 @@ $bootPest = (static function (): void {
$getopt['teamcity-file'] ?? null,
$getopt['testdox-file'] ?? null,
isset($getopt['testdox-color']),
$getopt['testdox-columns'] ?? null,
(int) $getopt['testdox-columns'] ?? null,
);
while (true) {

View File

@ -18,19 +18,19 @@
],
"require": {
"php": "^8.3.0",
"brianium/paratest": "^7.11.2",
"brianium/paratest": "^7.14.0",
"nunomaduro/collision": "^8.8.2",
"nunomaduro/termwind": "^2.3.1",
"pestphp/pest-plugin": "^4.0.0",
"pestphp/pest-plugin-arch": "^4.0.0",
"pestphp/pest-plugin-mutate": "^4.0.0",
"pestphp/pest-plugin-profanity": "^4.0.0",
"phpunit/phpunit": "^12.3.5",
"symfony/process": "^7.3.0"
"pestphp/pest-plugin-mutate": "^4.0.1",
"pestphp/pest-plugin-profanity": "^4.1.0",
"phpunit/phpunit": "^12.4.0",
"symfony/process": "^7.3.4"
},
"conflict": {
"filp/whoops": "<2.18.3",
"phpunit/phpunit": ">12.3.5",
"phpunit/phpunit": ">12.4.0",
"sebastian/exporter": "<7.0.0",
"webmozart/assert": "<1.11.0"
},
@ -56,9 +56,9 @@
},
"require-dev": {
"pestphp/pest-dev-tools": "^4.0.0",
"pestphp/pest-plugin-browser": "^4.0.0",
"pestphp/pest-plugin-type-coverage": "^4.0.1",
"psy/psysh": "^0.12.10"
"pestphp/pest-plugin-browser": "^4.1.1",
"pestphp/pest-plugin-type-coverage": "^4.0.2",
"psy/psysh": "^0.12.12"
},
"minimum-stability": "dev",
"prefer-stable": true,

View File

@ -1,98 +0,0 @@
<?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.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report;
use const PHP_EOL;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Util\Filesystem;
use SebastianBergmann\CodeCoverage\WriteOperationFailedException;
use function dirname;
use function serialize;
use function str_contains;
final class PHP
{
public function process(CodeCoverage $coverage, ?string $target = null): string
{
$coverage->clearCache();
$buffer = "<?php return \unserialize(<<<'END_OF_COVERAGE_SERIALIZATION'".PHP_EOL.serialize($coverage).PHP_EOL.'END_OF_COVERAGE_SERIALIZATION'.PHP_EOL.');';
if ($target !== null) {
if (! str_contains($target, '://')) {
Filesystem::createDirectory(dirname($target));
}
if (! is_writable(dirname($target))) {
throw new WriteOperationFailedException($target);
}
$fp = @fopen($target, 'wb');
if (! $fp) {
throw new WriteOperationFailedException($target);
}
$chunkSize = 1024 * 1024 * 8;
$offset = 0;
$total = strlen($buffer);
while ($offset < $total) {
$written = @fwrite($fp, substr($buffer, $offset, $chunkSize));
if ($written === false) {
fclose($fp);
throw new WriteOperationFailedException($target);
}
$offset += $written;
}
fclose($fp);
}
return $buffer;
}
}

View File

@ -26,7 +26,6 @@ final class BootOverrides implements Bootstrapper
'TextUI/TestSuiteFilterProcessor.php',
'Event/Value/ThrowableBuilder.php',
'Logging/JUnit/JunitXmlLogger.php',
'Report/PHP.php',
];
/**

View File

@ -25,8 +25,8 @@ final readonly class Thanks
private const array FUNDING_MESSAGES = [
'Star' => 'https://github.com/pestphp/pest',
'YouTube' => 'https://youtube.com/@nunomaduro',
'TikTok' => 'https://tiktok.com/@nunomaduro',
'Twitch' => 'https://twitch.tv/enunomaduro',
'TikTok' => 'https://tiktok.com/@enunomaduro',
'Twitch' => 'https://twitch.tv/nunomaduro',
'LinkedIn' => 'https://linkedin.com/in/nunomaduro',
'Instagram' => 'https://instagram.com/enunomaduro',
'X' => 'https://x.com/enunomaduro',

View File

@ -759,7 +759,12 @@ final class TestCall // @phpstan-ignore-line
$this->testSuite->tests->set($this->testCaseMethod);
if (! is_null($testCase = $this->testSuite->tests->get($this->filename))) {
$testCase->attributes = array_merge($testCase->attributes, $this->testCaseFactoryAttributes);
$attributesToMerge = array_filter(
$this->testCaseFactoryAttributes,
fn (Attribute $attributeToMerge): bool => array_filter($testCase->attributes, fn (Attribute $attribute): bool => serialize($attributeToMerge) === serialize($attribute)) === []
);
$testCase->attributes = array_merge($testCase->attributes, $attributesToMerge);
}
}
}

View File

@ -6,7 +6,7 @@ namespace Pest;
function version(): string
{
return '4.0.0';
return '4.1.2';
}
function testDirectory(string $file = ''): string

View File

@ -67,11 +67,11 @@ final class DatasetsRepository
}
/**
* @return Closure|array<int|string, mixed>
* @return array<int|string, mixed>
*
* @throws ShouldNotHappen
*/
public static function get(string $filename, string $description): Closure|array // @phpstan-ignore-line
public static function get(string $filename, string $description): array // @phpstan-ignore-line
{
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
@ -191,6 +191,7 @@ final class DatasetsRepository
return str_starts_with($currentTestFile, $datasetScope);
}, ARRAY_FILTER_USE_KEY);
/** @var string|null $closestScopeDatasetKey */
$closestScopeDatasetKey = array_reduce(
array_keys($matchingDatasets),
fn (string|int|null $keyA, string|int|null $keyB): string|int|null => $keyA !== null && strlen((string) $keyA) > strlen((string) $keyB) ? $keyA : $keyB

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Pest\Support;
use Pest\Exceptions\ShouldNotHappen;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Node\Directory;
use SebastianBergmann\CodeCoverage\Node\File;
use SebastianBergmann\Environment\Runtime;
@ -87,20 +88,10 @@ final class Coverage
throw ShouldNotHappen::fromMessage(sprintf('Coverage not found in path: %s.', $reportPath));
}
$handle = fopen($reportPath, 'r');
$code = '';
while (is_resource($handle) && ! feof($handle)) {
$code .= fread($handle, 8192);
}
if (is_resource($handle)) {
fclose($handle);
}
/** @var CodeCoverage $codeCoverage */
$codeCoverage = require $reportPath;
unlink($reportPath);
$codeCoverage = eval(substr($code, 5));
$totalCoverage = $codeCoverage->getReport()->percentageOfExecutedLines();
/** @var Directory<File|Directory> $report */

View File

@ -1,5 +1,5 @@
Pest Testing Framework 4.0.0.
Pest Testing Framework 4.1.2.
USAGE: pest <file> [options]

View File

@ -1,3 +1,3 @@
Pest Testing Framework 4.0.0.
Pest Testing Framework 4.1.2.