This commit is contained in:
Nuno Maduro
2020-05-11 18:38:30 +02:00
commit de2929077b
112 changed files with 6211 additions and 0 deletions

View File

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use Pest\Console\Coverage;
use Pest\Support\Str;
use Pest\TestSuite;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
/**
* @internal
*/
final class AddsCoverage
{
/**
* @var string
*/
private const COVERAGE_OPTION = 'coverage';
/**
* @var string
*/
private const MIN_OPTION = 'min';
/**
* Holds the coverage related options.
*
* @var array<int, string>
*/
private const OPTIONS = [self::COVERAGE_OPTION, self::MIN_OPTION];
/**
* If any, adds the coverage params to the given original arguments.
*
* @param array<int, string> $originals
*
* @return array<int, string>
*/
public static function from(TestSuite $testSuite, array $originals): array
{
$arguments = array_merge([''], array_values(array_filter($originals, function ($original): bool {
foreach (self::OPTIONS as $option) {
if ($original === sprintf('--%s', $option) || Str::startsWith($original, sprintf('--%s=', $option))) {
return true;
}
}
return false;
})));
$originals = array_flip($originals);
foreach ($arguments as $argument) {
unset($originals[$argument]);
}
$originals = array_flip($originals);
$inputs = [];
$inputs[] = new InputOption(self::COVERAGE_OPTION, null, InputOption::VALUE_NONE);
$inputs[] = new InputOption(self::MIN_OPTION, null, InputOption::VALUE_REQUIRED);
$input = new ArgvInput($arguments, new InputDefinition($inputs));
if ((bool) $input->getOption(self::COVERAGE_OPTION)) {
$testSuite->coverage = true;
$originals[] = '--coverage-php';
$originals[] = Coverage::getPath();
}
if ($input->getOption(self::MIN_OPTION) !== null) {
/* @phpstan-ignore-next-line */
$testSuite->coverageMin = (float) $input->getOption(self::MIN_OPTION);
}
return $originals;
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use NunoMaduro\Collision\Adapters\Phpunit\Printer;
/**
* @internal
*/
final class AddsDefaults
{
/**
* Adds default arguments to the given `arguments` array.
*
* @param array<string, mixed> $arguments
*
* @return array<string, mixed>
*/
public static function to(array $arguments): array
{
if (!array_key_exists('printer', $arguments)) {
$arguments['printer'] = new Printer();
}
return $arguments;
}
}

66
src/Actions/AddsTests.php Normal file
View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\WarningTestCase;
/**
* @internal
*/
final class AddsTests
{
/**
* Adds tests to the given test suite.
*
* @param TestSuite<\PHPUnit\Framework\TestCase> $testSuite
*/
public static function to(TestSuite $testSuite, \Pest\TestSuite $pestTestSuite): void
{
self::removeTestClosureWarnings($testSuite);
// @todo refactor this...
$testSuites = [];
$pestTestSuite->tests->build($pestTestSuite, function (TestCase $testCase) use (&$testSuites): void {
$testCaseClass = get_class($testCase);
if (!array_key_exists($testCaseClass, $testSuites)) {
$testSuites[$testCaseClass] = [];
}
$testSuites[$testCaseClass][] = $testCase;
});
foreach ($testSuites as $testCaseName => $testCases) {
$testTestSuite = new TestSuite($testCaseName);
$testTestSuite->setTests([]);
foreach ($testCases as $testCase) {
$testTestSuite->addTest($testCase, $testCase->getGroups());
}
$testSuite->addTestSuite($testTestSuite);
}
}
/**
* @param TestSuite<\PHPUnit\Framework\TestCase> $testSuite
*/
private static function removeTestClosureWarnings(TestSuite $testSuite): void
{
$tests = $testSuite->tests();
foreach ($tests as $key => $test) {
if ($test instanceof TestSuite) {
self::removeTestClosureWarnings($test);
}
if ($test instanceof WarningTestCase) {
unset($tests[$key]);
}
}
$testSuite->setTests($tests);
}
}

View File

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use Pest\Support\Str;
use PHPUnit\TextUI\Configuration\Configuration;
use PHPUnit\Util\FileLoader;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
/**
* @internal
*/
final class LoadStructure
{
/**
* The Pest convention.
*
* @var array<int, string>
*/
private const STRUCTURE = [
'Datasets.php',
'Pest.php',
'Datasets',
];
/**
* Validates the configuration in the given `configuration`.
*/
public static function in(string $rootPath): void
{
$testsPath = $rootPath . DIRECTORY_SEPARATOR . 'tests';
$load = function ($filename): bool {
return file_exists($filename) && (bool) FileLoader::checkAndLoad($filename);
};
foreach (self::STRUCTURE as $filename) {
$filename = sprintf('%s%s%s', $testsPath, DIRECTORY_SEPARATOR, $filename);
if (!file_exists($filename)) {
continue;
}
if (is_dir($filename)) {
$directory = new RecursiveDirectoryIterator($filename);
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $file) {
$filename = $file->__toString();
if (Str::endsWith($filename, '.php') && file_exists($filename)) {
require_once $filename;
}
}
} else {
$load($filename);
}
}
}
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use Pest\Exceptions\AttributeNotSupportedYet;
use Pest\Exceptions\FileOrFolderNotFound;
use PHPUnit\TextUI\Configuration\Configuration;
use PHPUnit\TextUI\Configuration\Registry;
/**
* @internal
*/
final class ValidatesConfiguration
{
/**
* @var string
*/
private const CONFIGURATION_KEY = 'configuration';
/**
* Validates the configuration in the given `configuration`.
*
* @param array<string, mixed> $arguments
*/
public static function in($arguments): void
{
if (!array_key_exists(self::CONFIGURATION_KEY, $arguments) || !file_exists($arguments[self::CONFIGURATION_KEY])) {
throw new FileOrFolderNotFound('phpunit.xml');
}
$configuration = Registry::getInstance()
->get($arguments[self::CONFIGURATION_KEY])
->phpunit();
if ($configuration->processIsolation()) {
throw new AttributeNotSupportedYet('processIsolation', 'true');
}
}
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Pest\Actions;
use Pest\Exceptions\FileOrFolderNotFound;
use Pest\TestSuite;
/**
* @internal
*/
final class ValidatesEnvironment
{
/**
* The need files on the root path.
*
* @var array<int, string>
*/
private const NEEDED_FILES = [
'composer.json',
'tests',
];
/**
* Validates the environment.
*/
public static function in(TestSuite $testSuite): void
{
$rootPath = $testSuite->rootPath;
$exists = function ($neededFile) use ($rootPath): bool {
return file_exists(sprintf('%s%s%s', $rootPath, DIRECTORY_SEPARATOR, $neededFile));
};
foreach (self::NEEDED_FILES as $neededFile) {
if (!$exists($neededFile)) {
throw new FileOrFolderNotFound($neededFile);
}
}
}
}