feat: adds pest function

This commit is contained in:
Nuno Maduro
2024-05-14 01:58:44 +01:00
parent 8169382362
commit c919bb5bc4
12 changed files with 293 additions and 14 deletions

View File

@ -91,6 +91,7 @@
"extra": { "extra": {
"pest": { "pest": {
"plugins": [ "plugins": [
"Pest\\Plugins\\Configuration",
"Pest\\Plugins\\Bail", "Pest\\Plugins\\Bail",
"Pest\\Plugins\\Cache", "Pest\\Plugins\\Cache",
"Pest\\Plugins\\Coverage", "Pest\\Plugins\\Coverage",

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Default">
<directory>tests/</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>app</directory>
<directory>src</directory>
</include>
</source>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>

71
src/Configuration.php Normal file
View File

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace Pest;
use Pest\PendingCalls\UsesCall;
use Pest\Support\Backtrace;
/**
* @internal
*/
final class Configuration
{
/**
* The instance of the configuration.
*/
private static ?Configuration $instance = null;
/**
* Gets the instance of the configuration.
*/
public static function getInstance(): Configuration
{
return self::$instance ??= new Configuration(
Backtrace::file(),
);
}
/**
* Creates a new configuration instance.
*/
private function __construct(
private readonly string $filename,
) {
}
/**
* Gets the configuration of a certain folder.
*/
public function in(string ...$targets): UsesCall
{
return (new UsesCall($this->filename, []))->in(...$targets);
}
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function extend(string ...$classAndTraits): UsesCall
{
return (new UsesCall($this->filename, array_values($classAndTraits)))
->in($this->filename)
->extend(...$classAndTraits);
}
/**
* Depending on where is called, it will extend the given classes and traits globally or locally.
*/
public function use(string ...$classAndTraits): UsesCall
{
return $this->extend(...$classAndTraits);
}
/**
* Gets the theme configuration.
*/
public function theme(): Configuration\Theme
{
return new Configuration\Theme();
}
}

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Pest\Configuration;
use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
/**
* @internal
*/
final readonly class Theme
{
/**
* Sets the theme to compact.
*/
public function compact(): self
{
DefaultPrinter::compact(true);
return $this;
}
}

View File

@ -3,6 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use Pest\Concerns\Expectable; use Pest\Concerns\Expectable;
use Pest\Configuration;
use Pest\Exceptions\AfterAllWithinDescribe; use Pest\Exceptions\AfterAllWithinDescribe;
use Pest\Exceptions\BeforeAllWithinDescribe; use Pest\Exceptions\BeforeAllWithinDescribe;
use Pest\Expectation; use Pest\Expectation;
@ -108,6 +109,16 @@ if (! function_exists('uses')) {
} }
} }
if (! function_exists('pest')) {
/**
* Creates a new Pest configuration instance.
*/
function pest(): Configuration
{
return Configuration::getInstance();
}
}
if (! function_exists('test')) { if (! function_exists('test')) {
/** /**
* Adds the given closure as a test. The first argument * Adds the given closure as a test. The first argument

View File

@ -48,11 +48,14 @@ final class UsesCall
*/ */
public function __construct( public function __construct(
private readonly string $filename, private readonly string $filename,
private readonly array $classAndTraits private array $classAndTraits
) { ) {
$this->targets = [$filename]; $this->targets = [$filename];
} }
/**
* @deprecated Use `pest()->theme()->compact()` instead.
*/
public function compact(): self public function compact(): self
{ {
DefaultPrinter::compact(true); DefaultPrinter::compact(true);
@ -60,11 +63,31 @@ final class UsesCall
return $this; return $this;
} }
/**
* Specifies the class or traits to use.
*
* @alias extend
*/
public function use(string ...$classAndTraits): self
{
return $this->extend(...$classAndTraits);
}
/**
* Specifies the class or traits to use.
*/
public function extend(string ...$classAndTraits): self
{
$this->classAndTraits = array_values($classAndTraits);
return $this;
}
/** /**
* The directories or file where the * The directories or file where the
* class or traits should be used. * class or traits should be used.
*/ */
public function in(string ...$targets): void public function in(string ...$targets): self
{ {
$targets = array_map(function (string $path): string { $targets = array_map(function (string $path): string {
$startChar = DIRECTORY_SEPARATOR; $startChar = DIRECTORY_SEPARATOR;
@ -92,6 +115,8 @@ final class UsesCall
return $accumulator; return $accumulator;
}, []); }, []);
return $this;
} }
/** /**

View File

@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace Pest\Plugins;
use DOMDocument;
use Pest\Contracts\Plugins\HandlesArguments;
use Pest\Contracts\Plugins\Terminable;
use Pest\Plugins\Concerns\HandleArguments;
use PHPUnit\TextUI\CliArguments\Builder as CliConfigurationBuilder;
use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder;
/**
* @internal
*/
final class Configuration implements HandlesArguments, Terminable
{
use HandleArguments;
/**
* The base PHPUnit file.
*/
public const BASE_PHPUNIT_FILE = __DIR__
.DIRECTORY_SEPARATOR
.'..'
.DIRECTORY_SEPARATOR
.'..'
.DIRECTORY_SEPARATOR
.'resources/base-phpunit.xml';
/**
* Handles the arguments, adding the cache directory and the cache result arguments.
*/
public function handleArguments(array $arguments): array
{
if ($this->hasArgument('--configuration', $arguments) || $this->hasCustomConfigurationFile()) {
return $arguments;
}
$arguments = $this->pushArgument('--configuration', $arguments);
return $this->pushArgument((string) realpath($this->fromGeneratedConfigurationFile()), $arguments);
}
/**
* Get the configuration file from the generated configuration file.
*/
private function fromGeneratedConfigurationFile(): string
{
$path = $this->getTempPhpunitXmlPath();
if (file_exists($path)) {
unlink($path);
}
$doc = new DOMDocument();
$doc->load(self::BASE_PHPUNIT_FILE);
$contents = $doc->saveXML();
assert(is_int(file_put_contents($path, $contents)));
return $path;
}
/**
* Check if the configuration file is custom.
*/
private function hasCustomConfigurationFile(): bool
{
$cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);
$configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration);
return is_string($configurationFile);
}
/**
* Get the temporary phpunit.xml path.
*/
private function getTempPhpunitXmlPath(): string
{
return getcwd().'/.pest.xml';
}
/**
* Terminates the plugin.
*/
public function terminate(): void
{
$path = $this->getTempPhpunitXmlPath();
if (file_exists($path)) {
unlink($path);
}
}
}

View File

@ -1272,6 +1272,12 @@
✓ it allows global uses ✓ it allows global uses
✓ it allows multiple global uses registered in the same path ✓ it allows multiple global uses registered in the same path
PASS Tests\Unit\Configuration\In
✓ it proxies to uses call
PASS Tests\Unit\Configuration\Theme
✓ it creates a theme instance
PASS Tests\Unit\Console\Help PASS Tests\Unit\Console\Help
✓ it outputs the help information when --help is used ✓ it outputs the help information when --help is used
@ -1455,4 +1461,4 @@
WARN Tests\Visual\Version WARN Tests\Visual\Version
- visual snapshot of help command output - visual snapshot of help command output
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1040 passed (2561 assertions) Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1042 passed (2563 assertions)

View File

@ -7,20 +7,21 @@ error_reporting(E_ALL);
$GLOBALS['__PEST_INTERNAL_TEST_SUITE'] = true; $GLOBALS['__PEST_INTERNAL_TEST_SUITE'] = true;
uses(CustomTestCaseInSubFolder::class)->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder'); pest()->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder')->use(CustomTestCaseInSubFolder::class);
// test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/ // test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/
uses(CustomTestCase::class)->in('PHPUnit/GlobPatternTests/SubFolder/*/'); pest()->in('PHPUnit/GlobPatternTests/SubFolder/*')->extend(CustomTestCase::class);
// test case for all the files that end with AsPattern.php inside PHPUnit/GlobPatternTests/SubFolder2/ // test case for all the files that end with AsPattern.php inside PHPUnit/GlobPatternTests/SubFolder2/
uses(CustomTestCase::class)->in('PHPUnit/GlobPatternTests/SubFolder2/*AsPattern.php'); pest()->in('PHPUnit/GlobPatternTests/SubFolder2/*AsPattern.php')->use(CustomTestCase::class);
uses()->group('integration')->in('Visual'); pest()->in('Visual')->group('integration');
// NOTE: global test value container to be mutated and checked across files, as needed // NOTE: global test value container to be mutated and checked across files, as needed
$_SERVER['globalHook'] = (object) ['calls' => (object) ['beforeAll' => 0, 'afterAll' => 0]]; $_SERVER['globalHook'] = (object) ['calls' => (object) ['beforeAll' => 0, 'afterAll' => 0]];
uses() pest()
->in('Hooks')
->beforeEach(function () { ->beforeEach(function () {
$this->baz = 0; $this->baz = 0;
}) })
@ -34,10 +35,9 @@ uses()
->afterAll(function () { ->afterAll(function () {
$_SERVER['globalHook']->afterAll = 0; $_SERVER['globalHook']->afterAll = 0;
$_SERVER['globalHook']->calls->afterAll++; $_SERVER['globalHook']->calls->afterAll++;
}) });
->in('Hooks');
uses() pest()->in('Hooks')
->beforeEach(function () { ->beforeEach(function () {
expect($this) expect($this)
->toHaveProperty('baz') ->toHaveProperty('baz')
@ -69,8 +69,7 @@ uses()
->toBe(0); ->toBe(0);
$_SERVER['globalHook']->afterAll = 1; $_SERVER['globalHook']->afterAll = 1;
}) });
->in('Hooks');
function helper_returns_string() function helper_returns_string()
{ {

View File

@ -0,0 +1,9 @@
<?php
use Pest\PendingCalls\UsesCall;
it('proxies to uses call', function () {
$in = pest()->in();
expect($in)->toBeInstanceOf(UsesCall::class);
});

View File

@ -0,0 +1,7 @@
<?php
it('creates a theme instance', function () {
$theme = pest()->theme();
expect($theme)->toBeInstanceOf(Pest\Configuration\Theme::class);
});

View File

@ -16,7 +16,7 @@ $run = function () {
test('parallel', function () use ($run) { test('parallel', function () use ($run) {
expect($run('--exclude-group=integration')) expect($run('--exclude-group=integration'))
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1026 passed (2529 assertions)') ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1028 passed (2531 assertions)')
->toContain('Parallel: 3 processes'); ->toContain('Parallel: 3 processes');
})->skipOnWindows(); })->skipOnWindows();