mirror of
https://github.com/pestphp/pest.git
synced 2026-03-10 01:37:21 +01:00
Merge branch '2.x' into dirty_integration
This commit is contained in:
@ -5,7 +5,8 @@ declare(strict_types=1);
|
||||
namespace Pest\Repositories;
|
||||
|
||||
use Closure;
|
||||
use Pest\Exceptions\DatasetAlreadyExist;
|
||||
use Generator;
|
||||
use Pest\Exceptions\DatasetAlreadyExists;
|
||||
use Pest\Exceptions\DatasetDoesNotExist;
|
||||
use Pest\Exceptions\ShouldNotHappen;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
@ -17,6 +18,8 @@ use Traversable;
|
||||
*/
|
||||
final class DatasetsRepository
|
||||
{
|
||||
private const SEPARATOR = '>>';
|
||||
|
||||
/**
|
||||
* Holds the datasets.
|
||||
*
|
||||
@ -36,13 +39,15 @@ final class DatasetsRepository
|
||||
*
|
||||
* @param Closure|iterable<int|string, mixed> $data
|
||||
*/
|
||||
public static function set(string $name, Closure|iterable $data): void
|
||||
public static function set(string $name, Closure|iterable $data, string $scope): void
|
||||
{
|
||||
if (array_key_exists($name, self::$datasets)) {
|
||||
throw new DatasetAlreadyExist($name);
|
||||
$datasetKey = "$scope".self::SEPARATOR."$name";
|
||||
|
||||
if (array_key_exists("$datasetKey", self::$datasets)) {
|
||||
throw new DatasetAlreadyExists($name, $scope);
|
||||
}
|
||||
|
||||
self::$datasets[$name] = $data;
|
||||
self::$datasets[$datasetKey] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,12 +57,12 @@ final class DatasetsRepository
|
||||
*/
|
||||
public static function with(string $filename, string $description, array $with): void
|
||||
{
|
||||
self::$withs[$filename.'>>>'.$description] = $with;
|
||||
self::$withs["$filename".self::SEPARATOR."$description"] = $with;
|
||||
}
|
||||
|
||||
public static function has(string $filename, string $description): bool
|
||||
{
|
||||
return array_key_exists($filename.'>>>'.$description, self::$withs);
|
||||
return array_key_exists($filename.self::SEPARATOR.$description, self::$withs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,9 +72,9 @@ final class DatasetsRepository
|
||||
*/
|
||||
public static function get(string $filename, string $description)
|
||||
{
|
||||
$dataset = self::$withs[$filename.'>>>'.$description];
|
||||
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
|
||||
|
||||
$dataset = self::resolve($description, $dataset);
|
||||
$dataset = self::resolve($dataset, $filename);
|
||||
|
||||
if ($dataset === null) {
|
||||
throw ShouldNotHappen::fromMessage('Dataset [%s] not resolvable.');
|
||||
@ -84,14 +89,13 @@ final class DatasetsRepository
|
||||
* @param array<Closure|iterable<int|string, mixed>|string> $dataset
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public static function resolve(string $description, array $dataset): array|null
|
||||
public static function resolve(array $dataset, string $currentTestFile): array|null
|
||||
{
|
||||
/* @phpstan-ignore-next-line */
|
||||
if (empty($dataset)) {
|
||||
if ($dataset === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dataset = self::processDatasets($dataset);
|
||||
$dataset = self::processDatasets($dataset, $currentTestFile);
|
||||
|
||||
$datasetCombinations = self::getDatasetsCombinations($dataset);
|
||||
|
||||
@ -136,7 +140,7 @@ final class DatasetsRepository
|
||||
* @param array<Closure|iterable<int|string, mixed>|string> $datasets
|
||||
* @return array<array<mixed>>
|
||||
*/
|
||||
private static function processDatasets(array $datasets): array
|
||||
private static function processDatasets(array $datasets, string $currentTestFile): array
|
||||
{
|
||||
$processedDatasets = [];
|
||||
|
||||
@ -144,11 +148,7 @@ final class DatasetsRepository
|
||||
$processedDataset = [];
|
||||
|
||||
if (is_string($data)) {
|
||||
if (! array_key_exists($data, self::$datasets)) {
|
||||
throw new DatasetDoesNotExist($data);
|
||||
}
|
||||
|
||||
$datasets[$index] = self::$datasets[$data];
|
||||
$datasets[$index] = self::getScopedDataset($data, $currentTestFile);
|
||||
}
|
||||
|
||||
if (is_callable($datasets[$index])) {
|
||||
@ -156,14 +156,16 @@ final class DatasetsRepository
|
||||
}
|
||||
|
||||
if ($datasets[$index] instanceof Traversable) {
|
||||
$datasets[$index] = iterator_to_array($datasets[$index], false);
|
||||
$preserveKeysForArrayIterator = $datasets[$index] instanceof Generator
|
||||
&& is_string($datasets[$index]->key());
|
||||
|
||||
$datasets[$index] = iterator_to_array($datasets[$index], $preserveKeysForArrayIterator);
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
foreach ($datasets[$index] as $key => $values) {
|
||||
$values = is_array($values) ? $values : [$values];
|
||||
$processedDataset[] = [
|
||||
'label' => self::getDatasetDescription($key, $values), // @phpstan-ignore-line
|
||||
'label' => self::getDatasetDescription($key, $values),
|
||||
'values' => $values,
|
||||
];
|
||||
}
|
||||
@ -174,6 +176,33 @@ final class DatasetsRepository
|
||||
return $processedDatasets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Closure|iterable<int|string, mixed>
|
||||
*/
|
||||
private static function getScopedDataset(string $name, string $currentTestFile): Closure|iterable
|
||||
{
|
||||
$matchingDatasets = array_filter(self::$datasets, function (string $key) use ($name, $currentTestFile): bool {
|
||||
[$datasetScope, $datasetName] = explode(self::SEPARATOR, $key);
|
||||
|
||||
if ($name !== $datasetName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return str_starts_with($currentTestFile, $datasetScope);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
$closestScopeDatasetKey = array_reduce(
|
||||
array_keys($matchingDatasets),
|
||||
fn ($keyA, $keyB) => $keyA !== null && strlen((string) $keyA) > strlen($keyB) ? $keyA : $keyB
|
||||
);
|
||||
|
||||
if ($closestScopeDatasetKey === null) {
|
||||
throw new DatasetDoesNotExist($name);
|
||||
}
|
||||
|
||||
return $matchingDatasets[$closestScopeDatasetKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array<mixed>> $combinations
|
||||
* @return array<array<array<mixed>>>
|
||||
|
||||
@ -7,9 +7,15 @@ namespace Pest\Repositories;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TempRepository
|
||||
final class RetryRepository
|
||||
{
|
||||
private const FOLDER = __DIR__.'/../../.temp';
|
||||
private const TEMPORARY_FOLDER = __DIR__
|
||||
.DIRECTORY_SEPARATOR
|
||||
.'..'
|
||||
.DIRECTORY_SEPARATOR
|
||||
.'..'
|
||||
.DIRECTORY_SEPARATOR
|
||||
.'.temp';
|
||||
|
||||
/**
|
||||
* Creates a new Temp Repository instance.
|
||||
@ -32,11 +38,19 @@ final class TempRepository
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
@unlink(self::FOLDER.'/'.$this->filename.'.json'); // @phpstan-ignore-line
|
||||
@unlink(self::TEMPORARY_FOLDER.'/'.$this->filename.'.json'); // @phpstan-ignore-line
|
||||
|
||||
$this->save([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is any element.
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->all() === [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given element exists.
|
||||
*/
|
||||
@ -52,7 +66,9 @@ final class TempRepository
|
||||
*/
|
||||
private function all(): array
|
||||
{
|
||||
$contents = file_get_contents(self::FOLDER.'/'.$this->filename.'.json');
|
||||
$path = self::TEMPORARY_FOLDER.'/'.$this->filename.'.json';
|
||||
|
||||
$contents = file_exists($path) ? file_get_contents($path) : '{}';
|
||||
|
||||
assert(is_string($contents));
|
||||
|
||||
@ -70,6 +86,6 @@ final class TempRepository
|
||||
{
|
||||
$contents = json_encode($elements, JSON_THROW_ON_ERROR);
|
||||
|
||||
file_put_contents(self::FOLDER.'/'.$this->filename.'.json', $contents);
|
||||
file_put_contents(self::TEMPORARY_FOLDER.'/'.$this->filename.'.json', $contents);
|
||||
}
|
||||
}
|
||||
@ -50,7 +50,7 @@ final class TestRepository
|
||||
*/
|
||||
public function getFilenames(): array
|
||||
{
|
||||
$testCases = array_filter($this->testCases, static fn(TestCaseFactory $testCase) => $testCase->methodsUsingOnly() !== []);
|
||||
$testCases = array_filter($this->testCases, static fn (TestCaseFactory $testCase): bool => $testCase->methodsUsingOnly() !== []);
|
||||
|
||||
if ($testCases === []) {
|
||||
$testCases = $this->testCases;
|
||||
|
||||
Reference in New Issue
Block a user