Primo Committ
This commit is contained in:
90
vendor/nunomaduro/collision/src/Adapters/Laravel/CollisionServiceProvider.php
vendored
Normal file
90
vendor/nunomaduro/collision/src/Adapters/Laravel/CollisionServiceProvider.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Laravel;
|
||||
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use NunoMaduro\Collision\Adapters\Laravel\Commands\TestCommand;
|
||||
use NunoMaduro\Collision\Contracts\Provider as ProviderContract;
|
||||
use NunoMaduro\Collision\Handler;
|
||||
use NunoMaduro\Collision\Provider;
|
||||
use NunoMaduro\Collision\SolutionsRepositories\NullSolutionsRepository;
|
||||
use NunoMaduro\Collision\Writer;
|
||||
|
||||
/**
|
||||
* This is an Collision Laravel Adapter Service Provider implementation.
|
||||
*
|
||||
* Registers the Error Handler on Laravel.
|
||||
*
|
||||
* @author Nuno Maduro <enunomaduro@gmail.com>
|
||||
*/
|
||||
class CollisionServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Boots application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->commands([
|
||||
TestCommand::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if ($this->app->runningInConsole() && !$this->app->runningUnitTests()) {
|
||||
$this->app->bind(ProviderContract::class, function () {
|
||||
if ($this->app->has(\Facade\IgnitionContracts\SolutionProviderRepository::class)) {
|
||||
$solutionsRepository = new IgnitionSolutionsRepository(
|
||||
$this->app->get(\Facade\IgnitionContracts\SolutionProviderRepository::class)
|
||||
);
|
||||
} else {
|
||||
$solutionsRepository = new NullSolutionsRepository();
|
||||
}
|
||||
|
||||
$writer = new Writer($solutionsRepository);
|
||||
$handler = new Handler($writer);
|
||||
|
||||
return new Provider(null, $handler);
|
||||
});
|
||||
|
||||
$appExceptionHandler = $this->app->make(ExceptionHandlerContract::class);
|
||||
|
||||
$this->app->singleton(
|
||||
ExceptionHandlerContract::class,
|
||||
function ($app) use ($appExceptionHandler) {
|
||||
return new ExceptionHandler($app, $appExceptionHandler);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [ProviderContract::class];
|
||||
}
|
||||
}
|
||||
143
vendor/nunomaduro/collision/src/Adapters/Laravel/Commands/TestCommand.php
vendored
Normal file
143
vendor/nunomaduro/collision/src/Adapters/Laravel/Commands/TestCommand.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Laravel\Commands;
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use Dotenv\Repository\RepositoryBuilder;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Process\Exception\ProcessSignaledException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class TestCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'test {--without-tty : Disable output to TTY}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the application tests';
|
||||
|
||||
/**
|
||||
* The arguments to be used while calling phpunit.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $arguments = [
|
||||
'--printer',
|
||||
'NunoMaduro\Collision\Adapters\Phpunit\Printer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->ignoreValidationErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$options = array_slice($_SERVER['argv'], $this->option('without-tty') ? 3 : 2);
|
||||
|
||||
$this->clearEnv();
|
||||
|
||||
$process = (new Process(array_merge(
|
||||
$this->binary(),
|
||||
array_merge(
|
||||
$this->arguments,
|
||||
$this->phpunitArguments($options)
|
||||
)
|
||||
)))->setTimeout(null);
|
||||
|
||||
try {
|
||||
$process->setTty(!$this->option('without-tty'));
|
||||
} catch (RuntimeException $e) {
|
||||
$this->output->writeln('Warning: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write($line);
|
||||
});
|
||||
} catch (ProcessSignaledException $e) {
|
||||
if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PHP binary to execute.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function binary()
|
||||
{
|
||||
if ('phpdbg' === PHP_SAPI) {
|
||||
return [PHP_BINARY, '-qrr', 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
return [PHP_BINARY, 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of arguments for running PHPUnit.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function phpunitArguments($options)
|
||||
{
|
||||
$options = array_values(array_filter($options, function ($option) {
|
||||
return !Str::startsWith($option, '--env=');
|
||||
}));
|
||||
|
||||
if (!file_exists($file = base_path('phpunit.xml'))) {
|
||||
$file = base_path('phpunit.xml.dist');
|
||||
}
|
||||
|
||||
return array_merge(['-c', $file], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any set Environment variables set by Laravel if the --env option is empty.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clearEnv()
|
||||
{
|
||||
if (!$this->option('env')) {
|
||||
$repositories = RepositoryBuilder::create()
|
||||
->make();
|
||||
|
||||
$envs = Dotenv::create(
|
||||
$repositories,
|
||||
$this->laravel->environmentPath(),
|
||||
$this->laravel->environmentFile()
|
||||
)->safeLoad();
|
||||
|
||||
foreach ($envs as $name => $value) {
|
||||
$repositories->clear($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
96
vendor/nunomaduro/collision/src/Adapters/Laravel/ExceptionHandler.php
vendored
Normal file
96
vendor/nunomaduro/collision/src/Adapters/Laravel/ExceptionHandler.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Laravel;
|
||||
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract;
|
||||
use NunoMaduro\Collision\Contracts\Provider as ProviderContract;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface as SymfonyConsoleExceptionInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* This is an Collision Laravel Adapter ExceptionHandler implementation.
|
||||
*
|
||||
* Registers the Error Handler on Laravel.
|
||||
*
|
||||
* @author Nuno Maduro <enunomaduro@gmail.com>
|
||||
*/
|
||||
class ExceptionHandler implements ExceptionHandlerContract
|
||||
{
|
||||
/**
|
||||
* Holds an instance of the application exception handler.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Debug\ExceptionHandler
|
||||
*/
|
||||
protected $appExceptionHandler;
|
||||
|
||||
/**
|
||||
* Holds an instance of the container.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the ExceptionHandler.
|
||||
*/
|
||||
public function __construct(Container $container, ExceptionHandlerContract $appExceptionHandler)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->appExceptionHandler = $appExceptionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function report(Throwable $e)
|
||||
{
|
||||
$this->appExceptionHandler->report($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
return $this->appExceptionHandler->render($request, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderForConsole($output, Throwable $e)
|
||||
{
|
||||
if ($e instanceof SymfonyConsoleExceptionInterface) {
|
||||
$this->appExceptionHandler->renderForConsole($output, $e);
|
||||
} else {
|
||||
$handler = $this->container->make(ProviderContract::class)
|
||||
->register()
|
||||
->getHandler()
|
||||
->setOutput($output);
|
||||
|
||||
$handler->setInspector((new Inspector($e)));
|
||||
|
||||
$handler->handle();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the exception should be reported.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldReport(Throwable $e)
|
||||
{
|
||||
return $this->appExceptionHandler->shouldReport($e);
|
||||
}
|
||||
}
|
||||
49
vendor/nunomaduro/collision/src/Adapters/Laravel/IgnitionSolutionsRepository.php
vendored
Normal file
49
vendor/nunomaduro/collision/src/Adapters/Laravel/IgnitionSolutionsRepository.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Laravel;
|
||||
|
||||
use Facade\IgnitionContracts\SolutionProviderRepository;
|
||||
use NunoMaduro\Collision\Contracts\SolutionsRepository;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* This is an Collision Laravel Adapter Solutions Provider implementation.
|
||||
*
|
||||
* Registers the Error Handler on Laravel.
|
||||
*
|
||||
* @author Nuno Maduro <enunomaduro@gmail.com>
|
||||
*/
|
||||
class IgnitionSolutionsRepository implements SolutionsRepository
|
||||
{
|
||||
/**
|
||||
* Holds an instance of ignition solutions provider repository.
|
||||
*
|
||||
* @var \Facade\IgnitionContracts\SolutionProviderRepository
|
||||
*/
|
||||
protected $solutionProviderRepository;
|
||||
|
||||
/**
|
||||
* IgnitionSolutionsRepository constructor.
|
||||
*/
|
||||
public function __construct(SolutionProviderRepository $solutionProviderRepository)
|
||||
{
|
||||
$this->solutionProviderRepository = $solutionProviderRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFromThrowable(Throwable $throwable): array
|
||||
{
|
||||
return $this->solutionProviderRepository->getSolutionsForThrowable($throwable);
|
||||
}
|
||||
}
|
||||
30
vendor/nunomaduro/collision/src/Adapters/Laravel/Inspector.php
vendored
Normal file
30
vendor/nunomaduro/collision/src/Adapters/Laravel/Inspector.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Laravel;
|
||||
|
||||
use Whoops\Exception\Inspector as BaseInspector;
|
||||
|
||||
/**
|
||||
* This is an Collision Laravel Adapter Inspector implementation.
|
||||
*
|
||||
* @author Nuno Maduro <enunomaduro@gmail.com>
|
||||
*/
|
||||
class Inspector extends BaseInspector
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getTrace($e)
|
||||
{
|
||||
return $e->getTrace();
|
||||
}
|
||||
}
|
||||
38
vendor/nunomaduro/collision/src/Adapters/Phpunit/ConfigureIO.php
vendored
Normal file
38
vendor/nunomaduro/collision/src/Adapters/Phpunit/ConfigureIO.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
use ReflectionObject;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ConfigureIO
|
||||
{
|
||||
/**
|
||||
* Configures both given input and output with
|
||||
* options from the enviroment.
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function of(InputInterface $input, Output $output): void
|
||||
{
|
||||
$application = new Application();
|
||||
$reflector = new ReflectionObject($application);
|
||||
$method = $reflector->getMethod('configureIO');
|
||||
$method->setAccessible(true);
|
||||
$method->invoke($application, $input, $output);
|
||||
}
|
||||
}
|
||||
56
vendor/nunomaduro/collision/src/Adapters/Phpunit/Printer.php
vendored
Normal file
56
vendor/nunomaduro/collision/src/Adapters/Phpunit/Printer.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
/*
|
||||
* This `if` condition exists because phpunit
|
||||
* is not a direct dependency of Collision.
|
||||
*
|
||||
* This code bellow it's for phpunit@8
|
||||
*/
|
||||
if (class_exists(\PHPUnit\Runner\Version::class) && intval(substr(\PHPUnit\Runner\Version::id(), 0, 1)) === 8) {
|
||||
/**
|
||||
* This is an Collision Phpunit Adapter implementation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Printer extends \PHPUnit\Util\Printer implements \PHPUnit\Framework\TestListener
|
||||
{
|
||||
use PrinterContents;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This `if` condition exists because phpunit
|
||||
* is not a direct dependency of Collision.
|
||||
*
|
||||
* This code bellow it's for phpunit@9
|
||||
*/
|
||||
if (class_exists(\PHPUnit\Runner\Version::class) && intval(substr(\PHPUnit\Runner\Version::id(), 0, 1)) === 9) {
|
||||
/**
|
||||
* This is an Collision Phpunit Adapter implementation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Printer implements \PHPUnit\TextUI\ResultPrinter
|
||||
{
|
||||
use PrinterContents;
|
||||
|
||||
/**
|
||||
* Intentionally left blank as we output things on events of the listener.
|
||||
*/
|
||||
public function printResult(\PHPUnit\Framework\TestResult $result): void
|
||||
{
|
||||
// ..
|
||||
}
|
||||
}
|
||||
}
|
||||
224
vendor/nunomaduro/collision/src/Adapters/Phpunit/PrinterContents.php
vendored
Normal file
224
vendor/nunomaduro/collision/src/Adapters/Phpunit/PrinterContents.php
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
use NunoMaduro\Collision\Exceptions\ShouldNotHappen;
|
||||
use PHPUnit\Framework\AssertionFailedError;
|
||||
use PHPUnit\Framework\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\TestSuite;
|
||||
use PHPUnit\Framework\Warning;
|
||||
use ReflectionObject;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Throwable;
|
||||
|
||||
trait PrinterContents
|
||||
{
|
||||
/**
|
||||
* Holds an instance of the style.
|
||||
*
|
||||
* Style is a class we use to interact with output.
|
||||
*
|
||||
* @var Style
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Holds the duration time of the test suite.
|
||||
*
|
||||
* @var Timer
|
||||
*/
|
||||
private $timer;
|
||||
|
||||
/**
|
||||
* Holds the state of the test
|
||||
* suite. The number of tests, etc.
|
||||
*
|
||||
* @var State
|
||||
*/
|
||||
private $state;
|
||||
|
||||
/**
|
||||
* If the test suite has ended before.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $ended = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the listener.
|
||||
*
|
||||
* @param ConsoleOutput $output
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function __construct(ConsoleOutput $output = null)
|
||||
{
|
||||
if (intval(substr(\PHPUnit\Runner\Version::id(), 0, 1)) === 8) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
$this->timer = Timer::start();
|
||||
|
||||
$output = $output ?? new ConsoleOutput();
|
||||
ConfigureIO::of(new ArgvInput(), $output);
|
||||
|
||||
$this->style = new Style($output);
|
||||
$dummyTest = new class() extends TestCase {
|
||||
};
|
||||
|
||||
$this->state = State::from($dummyTest);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addError(Test $testCase, Throwable $throwable, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::FAIL));
|
||||
|
||||
$this->style->writeError($this->state, $throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addWarning(Test $testCase, Warning $warning, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::WARN, $warning->getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addFailure(Test $testCase, AssertionFailedError $error, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::FAIL));
|
||||
|
||||
$reflector = new ReflectionObject($error);
|
||||
|
||||
if ($reflector->hasProperty('message')) {
|
||||
$message = trim((string) preg_replace("/\r|\n/", ' ', $error->getMessage()));
|
||||
$property = $reflector->getProperty('message');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($error, $message);
|
||||
}
|
||||
|
||||
$this->style->writeError($this->state, $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addIncompleteTest(Test $testCase, Throwable $t, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::INCOMPLETE));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addRiskyTest(Test $testCase, Throwable $t, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::RISKY, $t->getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addSkippedTest(Test $testCase, Throwable $t, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::SKIPPED, $t->getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function startTestSuite(TestSuite $suite): void
|
||||
{
|
||||
if ($this->state->suiteTotalTests === null) {
|
||||
$this->state->suiteTotalTests = $suite->count();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function endTestSuite(TestSuite $suite): void
|
||||
{
|
||||
if (!$this->ended && $this->state->suiteTotalTests === $this->state->testSuiteTestsCount()) {
|
||||
$this->ended = true;
|
||||
|
||||
$this->style->writeCurrentRecap($this->state);
|
||||
|
||||
$this->style->updateFooter($this->state);
|
||||
$this->style->writeRecap($this->timer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function startTest(Test $testCase): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
// Let's check first if the testCase is over.
|
||||
if ($this->state->testCaseHasChanged($testCase)) {
|
||||
$this->style->writeCurrentRecap($this->state);
|
||||
|
||||
$this->state->moveTo($testCase);
|
||||
}
|
||||
|
||||
$this->style->updateFooter($this->state, $testCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function endTest(Test $testCase, float $time): void
|
||||
{
|
||||
$testCase = $this->testCaseFromTest($testCase);
|
||||
|
||||
if (!$this->state->existsInTestCase($testCase)) {
|
||||
$this->state->add(TestResult::fromTestCase($testCase, TestResult::PASS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intentionally left blank as we output things on events of the listener.
|
||||
*/
|
||||
public function write(string $content): void
|
||||
{
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a test case from the given test.
|
||||
*
|
||||
* Note: This printer is do not work with normal Test classes - only
|
||||
* with Test Case classes. Please report an issue if you think
|
||||
* this should work any other way.
|
||||
*/
|
||||
private function testCaseFromTest(Test $test): TestCase
|
||||
{
|
||||
if (!$test instanceof TestCase) {
|
||||
throw new ShouldNotHappen();
|
||||
}
|
||||
|
||||
return $test;
|
||||
}
|
||||
}
|
||||
194
vendor/nunomaduro/collision/src/Adapters/Phpunit/State.php
vendored
Normal file
194
vendor/nunomaduro/collision/src/Adapters/Phpunit/State.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
use NunoMaduro\Collision\Contracts\Adapters\Phpunit\HasPrintableTestCaseName;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class State
|
||||
{
|
||||
/**
|
||||
* The complete test suite number of tests.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $suiteTotalTests;
|
||||
|
||||
/**
|
||||
* The complete test suite tests.
|
||||
*
|
||||
* @var array<int, TestResult>
|
||||
*/
|
||||
public $suiteTests = [];
|
||||
|
||||
/**
|
||||
* The current test case class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $testCaseName;
|
||||
|
||||
/**
|
||||
* The current test case tests.
|
||||
*
|
||||
* @var array<int, TestResult>
|
||||
*/
|
||||
public $testCaseTests = [];
|
||||
|
||||
/**
|
||||
* The state constructor.
|
||||
*/
|
||||
private function __construct(string $testCaseName)
|
||||
{
|
||||
$this->testCaseName = $testCaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new State starting from the given test case.
|
||||
*/
|
||||
public static function from(TestCase $test): self
|
||||
{
|
||||
return new self(self::getPrintableTestCaseName($test));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given test to the State.
|
||||
*/
|
||||
public function add(TestResult $test): void
|
||||
{
|
||||
$this->testCaseTests[] = $test;
|
||||
|
||||
$this->suiteTests[] = $test;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the test case title.
|
||||
*/
|
||||
public function getTestCaseTitle(): string
|
||||
{
|
||||
foreach ($this->testCaseTests as $test) {
|
||||
if ($test->type === TestResult::FAIL) {
|
||||
return 'FAIL';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->testCaseTests as $test) {
|
||||
if ($test->type !== TestResult::PASS) {
|
||||
return 'WARN';
|
||||
}
|
||||
}
|
||||
|
||||
return 'PASS';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the test case title color.
|
||||
*/
|
||||
public function getTestCaseTitleColor(): string
|
||||
{
|
||||
foreach ($this->testCaseTests as $test) {
|
||||
if ($test->type === TestResult::FAIL) {
|
||||
return 'red';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->testCaseTests as $test) {
|
||||
if ($test->type !== TestResult::PASS) {
|
||||
return 'yellow';
|
||||
}
|
||||
}
|
||||
|
||||
return 'green';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tests on the current test case.
|
||||
*/
|
||||
public function testCaseTestsCount(): int
|
||||
{
|
||||
return count($this->testCaseTests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tests on the complete test suite.
|
||||
*/
|
||||
public function testSuiteTestsCount(): int
|
||||
{
|
||||
return count($this->suiteTests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given test case is different from the current one.
|
||||
*/
|
||||
public function testCaseHasChanged(TestCase $testCase): bool
|
||||
{
|
||||
return self::getPrintableTestCaseName($testCase) !== $this->testCaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the a new test case.
|
||||
*/
|
||||
public function moveTo(TestCase $testCase): void
|
||||
{
|
||||
$this->testCaseName = self::getPrintableTestCaseName($testCase);
|
||||
|
||||
$this->testCaseTests = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Foreach test in the test case.
|
||||
*/
|
||||
public function eachTestCaseTests(callable $callback): void
|
||||
{
|
||||
foreach ($this->testCaseTests as $test) {
|
||||
$callback($test);
|
||||
}
|
||||
}
|
||||
|
||||
public function countTestsInTestSuiteBy(string $type): int
|
||||
{
|
||||
return count(array_filter($this->suiteTests, function (TestResult $testResult) use ($type) {
|
||||
return $testResult->type === $type;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given test already contains a result.
|
||||
*/
|
||||
public function existsInTestCase(TestCase $test): bool
|
||||
{
|
||||
foreach ($this->testCaseTests as $testResult) {
|
||||
if (TestResult::makeDescription($test) === $testResult->description) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the printable test case name from the given `TestCase`.
|
||||
*/
|
||||
private static function getPrintableTestCaseName(TestCase $test): string
|
||||
{
|
||||
if ($test instanceof HasPrintableTestCaseName) {
|
||||
$name = $test->getPrintableTestCaseName();
|
||||
} else {
|
||||
$name = get_class($test);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
239
vendor/nunomaduro/collision/src/Adapters/Phpunit/Style.php
vendored
Normal file
239
vendor/nunomaduro/collision/src/Adapters/Phpunit/Style.php
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
use NunoMaduro\Collision\Writer;
|
||||
use PHPUnit\Framework\AssertionFailedError;
|
||||
use PHPUnit\Framework\ExceptionWrapper;
|
||||
use PHPUnit\Framework\ExpectationFailedException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\ConsoleSectionOutput;
|
||||
use Throwable;
|
||||
use Whoops\Exception\Inspector;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Style
|
||||
{
|
||||
/**
|
||||
* @var ConsoleOutput
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* @var ConsoleSectionOutput
|
||||
*/
|
||||
private $footer;
|
||||
|
||||
/**
|
||||
* Style constructor.
|
||||
*/
|
||||
public function __construct(ConsoleOutput $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
$this->footer = $output->section();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the content similar too:.
|
||||
*
|
||||
* ```
|
||||
* PASS Unit\ExampleTest
|
||||
* ✓ basic test
|
||||
* ```
|
||||
*/
|
||||
public function writeCurrentRecap(State $state): void
|
||||
{
|
||||
if (!$state->testCaseTestsCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->footer->clear();
|
||||
|
||||
$this->output->writeln($this->titleLineFrom(
|
||||
$state->getTestCaseTitle() === 'FAIL' ? 'white' : 'black',
|
||||
$state->getTestCaseTitleColor(),
|
||||
$state->getTestCaseTitle(),
|
||||
$state->testCaseName
|
||||
));
|
||||
|
||||
$state->eachTestCaseTests(function (TestResult $testResult) {
|
||||
$this->output->writeln($this->testLineFrom(
|
||||
$testResult->color,
|
||||
$testResult->icon,
|
||||
$testResult->description,
|
||||
$testResult->warning
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the content similar too on the footer. Where
|
||||
* we are updating the current test.
|
||||
*
|
||||
* ```
|
||||
* Runs Unit\ExampleTest
|
||||
* • basic test
|
||||
* ```
|
||||
*/
|
||||
public function updateFooter(State $state, TestCase $testCase = null): void
|
||||
{
|
||||
$runs = [];
|
||||
|
||||
if ($testCase) {
|
||||
$runs[] = $this->titleLineFrom(
|
||||
'black',
|
||||
'yellow',
|
||||
'RUNS',
|
||||
get_class($testCase)
|
||||
);
|
||||
|
||||
$testResult = TestResult::fromTestCase($testCase, TestResult::RUNS);
|
||||
$runs[] = $this->testLineFrom(
|
||||
$testResult->color,
|
||||
$testResult->icon,
|
||||
$testResult->description
|
||||
);
|
||||
}
|
||||
|
||||
$types = [TestResult::FAIL, TestResult::WARN, TestResult::RISKY, TestResult::INCOMPLETE, TestResult::SKIPPED, TestResult::PASS];
|
||||
|
||||
foreach ($types as $type) {
|
||||
if ($countTests = $state->countTestsInTestSuiteBy($type)) {
|
||||
$color = TestResult::makeColor($type);
|
||||
$tests[] = "<fg=$color;options=bold>$countTests $type</>";
|
||||
}
|
||||
}
|
||||
|
||||
$pending = $state->suiteTotalTests - $state->testSuiteTestsCount();
|
||||
if ($pending) {
|
||||
$tests[] = "\e[2m$pending pending\e[22m";
|
||||
}
|
||||
|
||||
if (!empty($tests)) {
|
||||
$this->footer->overwrite(array_merge($runs, [
|
||||
'',
|
||||
sprintf(
|
||||
' <fg=white;options=bold>Tests: </><fg=default>%s</>',
|
||||
implode(', ', $tests)
|
||||
),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the final recap.
|
||||
*/
|
||||
public function writeRecap(Timer $timer): void
|
||||
{
|
||||
$timeElapsed = number_format($timer->result(), 2, '.', '');
|
||||
$this->footer->writeln(
|
||||
sprintf(
|
||||
' <fg=white;options=bold>Time: </><fg=default>%ss</>',
|
||||
$timeElapsed
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the error using Collision's writer
|
||||
* and terminates with exit code === 1.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function writeError(State $state, Throwable $throwable)
|
||||
{
|
||||
$this->writeCurrentRecap($state);
|
||||
|
||||
$this->updateFooter($state);
|
||||
|
||||
$writer = (new Writer())->setOutput($this->output);
|
||||
|
||||
if ($throwable instanceof AssertionFailedError) {
|
||||
$writer->showTitle(false);
|
||||
$this->output->write('', true);
|
||||
}
|
||||
|
||||
$writer->ignoreFilesIn([
|
||||
'/vendor\/phpunit\/phpunit\/src/',
|
||||
'/vendor\/mockery\/mockery/',
|
||||
'/vendor\/laravel\/framework\/src\/Illuminate\/Testing/',
|
||||
'/vendor\/laravel\/framework\/src\/Illuminate\/Foundation\/Testing/',
|
||||
]);
|
||||
|
||||
if ($throwable instanceof ExceptionWrapper && $throwable->getOriginalException() !== null) {
|
||||
$throwable = $throwable->getOriginalException();
|
||||
}
|
||||
|
||||
$inspector = new Inspector($throwable);
|
||||
|
||||
$writer->write($inspector);
|
||||
|
||||
if ($throwable instanceof ExpectationFailedException && $comparisionFailure = $throwable->getComparisonFailure()) {
|
||||
$this->output->write($comparisionFailure->getDiff());
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title contents.
|
||||
*/
|
||||
private function titleLineFrom(string $fg, string $bg, string $title, string $testCaseName): string
|
||||
{
|
||||
if (class_exists($testCaseName)) {
|
||||
$nameParts = explode('\\', $testCaseName);
|
||||
$highlightedPart = array_pop($nameParts);
|
||||
$nonHighlightedPart = implode('\\', $nameParts);
|
||||
$testCaseName = sprintf("\e[2m%s\e[22m<fg=white;options=bold>%s</>", "$nonHighlightedPart\\", $highlightedPart);
|
||||
} elseif (file_exists($testCaseName)) {
|
||||
$testCaseName = substr($testCaseName, strlen((string) getcwd()) + 1);
|
||||
$nameParts = explode(DIRECTORY_SEPARATOR, $testCaseName);
|
||||
$highlightedPart = (string) array_pop($nameParts);
|
||||
$highlightedPart = substr($highlightedPart, 0, (int) strrpos($highlightedPart, '.'));
|
||||
$nonHighlightedPart = implode('\\', $nameParts);
|
||||
$testCaseName = sprintf("\e[2m%s\e[22m<fg=white;options=bold>%s</>", "$nonHighlightedPart\\", $highlightedPart);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
"\n <fg=%s;bg=%s;options=bold> %s </><fg=default> %s</>",
|
||||
$fg,
|
||||
$bg,
|
||||
$title,
|
||||
$testCaseName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the test contents.
|
||||
*/
|
||||
private function testLineFrom(string $fg, string $icon, string $description, string $warning = null): string
|
||||
{
|
||||
if (!empty($warning)) {
|
||||
$warning = sprintf(
|
||||
' → %s',
|
||||
$warning
|
||||
);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
" <fg=%s;options=bold>%s</><fg=default> \e[2m%s\e[22m</><fg=yellow>%s</>",
|
||||
$fg,
|
||||
$icon,
|
||||
$description,
|
||||
$warning
|
||||
);
|
||||
}
|
||||
}
|
||||
156
vendor/nunomaduro/collision/src/Adapters/Phpunit/TestResult.php
vendored
Normal file
156
vendor/nunomaduro/collision/src/Adapters/Phpunit/TestResult.php
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class TestResult
|
||||
{
|
||||
public const FAIL = 'failed';
|
||||
public const SKIPPED = 'skipped';
|
||||
public const INCOMPLETE = 'incompleted';
|
||||
public const RISKY = 'risked';
|
||||
public const WARN = 'warnings';
|
||||
public const RUNS = 'pending';
|
||||
public const PASS = 'passed';
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $icon;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $color;
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $warning;
|
||||
|
||||
/**
|
||||
* Test constructor.
|
||||
*
|
||||
* @param string $warning
|
||||
*/
|
||||
private function __construct(string $description, string $type, string $icon, string $color, string $warning = null)
|
||||
{
|
||||
$this->description = $description;
|
||||
$this->type = $type;
|
||||
$this->icon = $icon;
|
||||
$this->color = $color;
|
||||
$this->warning = trim((string) preg_replace("/\r|\n/", ' ', (string) $warning));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new test from the given test case.
|
||||
*/
|
||||
public static function fromTestCase(TestCase $testCase, string $type, string $warning = null): self
|
||||
{
|
||||
$description = self::makeDescription($testCase);
|
||||
|
||||
$icon = self::makeIcon($type);
|
||||
|
||||
$color = self::makeColor($type);
|
||||
|
||||
return new self($description, $type, $icon, $color, $warning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the test case description.
|
||||
*/
|
||||
public static function makeDescription(TestCase $testCase): string
|
||||
{
|
||||
$name = $testCase->getName(true);
|
||||
|
||||
// First, lets replace underscore by spaces.
|
||||
$name = str_replace('_', ' ', $name);
|
||||
|
||||
// Then, replace upper cases by spaces.
|
||||
$name = (string) preg_replace('/([A-Z])/', ' $1', $name);
|
||||
|
||||
// Finally, if it starts with `test`, we remove it.
|
||||
$name = (string) preg_replace('/^test/', '', $name);
|
||||
|
||||
// Removes spaces
|
||||
$name = (string) trim($name);
|
||||
|
||||
// Finally, lower case everything
|
||||
return (string) mb_strtolower($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the test case icon.
|
||||
*/
|
||||
public static function makeIcon(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case self::FAIL:
|
||||
return '✕';
|
||||
case self::SKIPPED:
|
||||
return 's';
|
||||
case self::RISKY:
|
||||
return 'r';
|
||||
case self::INCOMPLETE:
|
||||
return 'i';
|
||||
case self::WARN:
|
||||
return 'w';
|
||||
case self::RUNS:
|
||||
return '•';
|
||||
default:
|
||||
return '✓';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the test case color.
|
||||
*/
|
||||
public static function makeColor(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case self::FAIL:
|
||||
return 'red';
|
||||
case self::SKIPPED:
|
||||
case self::INCOMPLETE:
|
||||
case self::RISKY:
|
||||
case self::WARN:
|
||||
case self::RUNS:
|
||||
return 'yellow';
|
||||
default:
|
||||
return 'green';
|
||||
}
|
||||
}
|
||||
}
|
||||
47
vendor/nunomaduro/collision/src/Adapters/Phpunit/Timer.php
vendored
Normal file
47
vendor/nunomaduro/collision/src/Adapters/Phpunit/Timer.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Collision.
|
||||
*
|
||||
* (c) Nuno Maduro <enunomaduro@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace NunoMaduro\Collision\Adapters\Phpunit;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Timer
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $start;
|
||||
|
||||
/**
|
||||
* Timer constructor.
|
||||
*/
|
||||
private function __construct(float $start)
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the timer.
|
||||
*/
|
||||
public static function start(): Timer
|
||||
{
|
||||
return new self(microtime(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elapsed time in microseconds.
|
||||
*/
|
||||
public function result(): float
|
||||
{
|
||||
return microtime(true) - $this->start;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user