mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
54
src/ArchPresets/AbstractPreset.php
Normal file
54
src/ArchPresets/AbstractPreset.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\ArchPresets;
|
||||||
|
|
||||||
|
use Pest\Arch\Contracts\ArchExpectation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract class AbstractPreset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new preset instance.
|
||||||
|
*
|
||||||
|
* @param array<int, string> $userNamespaces
|
||||||
|
* @param array<int, ArchExpectation> $expectations
|
||||||
|
*/
|
||||||
|
final public function __construct(// @phpstan-ignore-line
|
||||||
|
protected array $userNamespaces,
|
||||||
|
protected array $expectations = [],
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the arch preset.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract public function execute(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignores the given "targets" or "dependencies".
|
||||||
|
*
|
||||||
|
* @param array<int, string>|string $targetsOrDependencies
|
||||||
|
*/
|
||||||
|
final public function ignoring(array|string $targetsOrDependencies): void
|
||||||
|
{
|
||||||
|
$this->expectations = array_map(
|
||||||
|
fn (ArchExpectation $expectation): \Pest\Arch\Contracts\ArchExpectation => $expectation->ignoring($targetsOrDependencies),
|
||||||
|
$this->expectations,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the expectations.
|
||||||
|
*/
|
||||||
|
final public function flush(): void
|
||||||
|
{
|
||||||
|
$this->expectations = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
94
src/ArchPresets/Base.php
Normal file
94
src/ArchPresets/Base.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\ArchPresets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Base extends AbstractPreset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executes the arch preset.
|
||||||
|
*/
|
||||||
|
public function execute(): void
|
||||||
|
{
|
||||||
|
$this->expectations[] = expect([
|
||||||
|
'debug_zval_dump',
|
||||||
|
'debug_backtrace',
|
||||||
|
'debug_print_backtrace',
|
||||||
|
'dd',
|
||||||
|
'ddd',
|
||||||
|
'dump',
|
||||||
|
'ray',
|
||||||
|
'die',
|
||||||
|
'goto',
|
||||||
|
'global',
|
||||||
|
'var_dump',
|
||||||
|
'phpinfo',
|
||||||
|
'echo',
|
||||||
|
'ereg',
|
||||||
|
'eregi',
|
||||||
|
'mysql_connect',
|
||||||
|
'mysql_pconnect',
|
||||||
|
'mysql_query',
|
||||||
|
'mysql_select_db',
|
||||||
|
'mysql_fetch_array',
|
||||||
|
'mysql_fetch_assoc',
|
||||||
|
'mysql_fetch_object',
|
||||||
|
'mysql_fetch_row',
|
||||||
|
'mysql_num_rows',
|
||||||
|
'mysql_affected_rows',
|
||||||
|
'mysql_free_result',
|
||||||
|
'mysql_insert_id',
|
||||||
|
'mysql_error',
|
||||||
|
'mysql_real_escape_string',
|
||||||
|
'print',
|
||||||
|
'print_r',
|
||||||
|
'var_export',
|
||||||
|
'xdebug_break',
|
||||||
|
'xdebug_call_class',
|
||||||
|
'xdebug_call_file',
|
||||||
|
'xdebug_call_int',
|
||||||
|
'xdebug_call_line',
|
||||||
|
'xdebug_code_coverage_started',
|
||||||
|
'xdebug_connect_to_client',
|
||||||
|
'xdebug_debug_zval',
|
||||||
|
'xdebug_debug_zval_stdout',
|
||||||
|
'xdebug_dump_superglobals',
|
||||||
|
'xdebug_get_code_coverage',
|
||||||
|
'xdebug_get_collected_errors',
|
||||||
|
'xdebug_get_function_count',
|
||||||
|
'xdebug_get_function_stack',
|
||||||
|
'xdebug_get_gc_run_count',
|
||||||
|
'xdebug_get_gc_total_collected_roots',
|
||||||
|
'xdebug_get_gcstats_filename',
|
||||||
|
'xdebug_get_headers',
|
||||||
|
'xdebug_get_monitored_functions',
|
||||||
|
'xdebug_get_profiler_filename',
|
||||||
|
'xdebug_get_stack_depth',
|
||||||
|
'xdebug_get_tracefile_name',
|
||||||
|
'xdebug_info',
|
||||||
|
'xdebug_is_debugger_active',
|
||||||
|
'xdebug_memory_usage',
|
||||||
|
'xdebug_notify',
|
||||||
|
'xdebug_peak_memory_usage',
|
||||||
|
'xdebug_print_function_stack',
|
||||||
|
'xdebug_set_filter',
|
||||||
|
'xdebug_start_code_coverage',
|
||||||
|
'xdebug_start_error_collection',
|
||||||
|
'xdebug_start_function_monitor',
|
||||||
|
'xdebug_start_gcstats',
|
||||||
|
'xdebug_start_trace',
|
||||||
|
'xdebug_stop_code_coverage',
|
||||||
|
'xdebug_stop_error_collection',
|
||||||
|
'xdebug_stop_function_monitor',
|
||||||
|
'xdebug_stop_gcstats',
|
||||||
|
'xdebug_stop_trace',
|
||||||
|
'xdebug_time_index',
|
||||||
|
'xdebug_var_dump',
|
||||||
|
'trap',
|
||||||
|
])->not->toBeUsed();
|
||||||
|
}
|
||||||
|
}
|
||||||
61
src/ArchPresets/Laravel.php
Normal file
61
src/ArchPresets/Laravel.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\ArchPresets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Laravel extends AbstractPreset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executes the arch preset.
|
||||||
|
*/
|
||||||
|
public function execute(): void
|
||||||
|
{
|
||||||
|
$this->expectations[] = expect([
|
||||||
|
'env',
|
||||||
|
'exit',
|
||||||
|
])->not->toBeUsed();
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Http\Controllers')
|
||||||
|
->toHaveSuffix('Controller');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Http\Middleware')
|
||||||
|
->toHaveMethod('handle');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Models')
|
||||||
|
->not->toHaveSuffix('Model');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Http\Requests')
|
||||||
|
->toHaveSuffix('Request')
|
||||||
|
->toExtend('Illuminate\Foundation\Http\FormRequest')
|
||||||
|
->toHaveMethod('rules');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Console\Commands')
|
||||||
|
->toHaveSuffix('Command')
|
||||||
|
->toExtend('Illuminate\Console\Command')
|
||||||
|
->toHaveMethod('handle');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Exceptions')
|
||||||
|
->toImplement('Throwable');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Mail')
|
||||||
|
->toExtend('Illuminate\Mail\Mailable');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Jobs')
|
||||||
|
->toHaveMethod('handle');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Listeners')
|
||||||
|
->toHaveMethod('handle');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Notifications')
|
||||||
|
->toExtend('Illuminate\Notifications\Notification');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Providers')
|
||||||
|
->toHaveSuffix('ServiceProvider')
|
||||||
|
->toExtend('Illuminate\Support\ServiceProvider')
|
||||||
|
->not->toBeUsed();
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/ArchPresets/Security.php
Normal file
41
src/ArchPresets/Security.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\ArchPresets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Security extends AbstractPreset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executes the arch preset.
|
||||||
|
*/
|
||||||
|
public function execute(): void
|
||||||
|
{
|
||||||
|
$this->expectations[] = expect([
|
||||||
|
'md5',
|
||||||
|
'sha1',
|
||||||
|
'uniqid',
|
||||||
|
'rand',
|
||||||
|
'mt_rand',
|
||||||
|
'tempnam',
|
||||||
|
'str_shuffle',
|
||||||
|
'shuffle',
|
||||||
|
'array_rand',
|
||||||
|
'eval',
|
||||||
|
'exec',
|
||||||
|
'shell_exec',
|
||||||
|
'system',
|
||||||
|
'passthru',
|
||||||
|
'create_function',
|
||||||
|
'unserialize',
|
||||||
|
'extract',
|
||||||
|
'parse_str',
|
||||||
|
'mb_parse_str',
|
||||||
|
'dl',
|
||||||
|
'assert',
|
||||||
|
])->not->toBeUsed();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/ArchPresets/Strict.php
Normal file
27
src/ArchPresets/Strict.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\ArchPresets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Strict extends AbstractPreset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executes the arch preset.
|
||||||
|
*/
|
||||||
|
public function execute(): void
|
||||||
|
{
|
||||||
|
foreach ($this->userNamespaces as $namespace) {
|
||||||
|
$this->expectations[] = expect([
|
||||||
|
'sleep',
|
||||||
|
'usleep',
|
||||||
|
])->not->toBeUsed();
|
||||||
|
|
||||||
|
$this->expectations[] = expect($namespace)
|
||||||
|
->toUseStrictTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Contracts/ArchPreset.php
Normal file
12
src/Contracts/ArchPreset.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\Contracts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
interface ArchPreset
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ use Pest\Factories\TestCaseMethodFactory;
|
|||||||
use Pest\Mutate\Decorators\TestCallDecorator as MutationTestCallDecorator;
|
use Pest\Mutate\Decorators\TestCallDecorator as MutationTestCallDecorator;
|
||||||
use Pest\PendingCalls\Concerns\Describable;
|
use Pest\PendingCalls\Concerns\Describable;
|
||||||
use Pest\Plugins\Only;
|
use Pest\Plugins\Only;
|
||||||
|
use Pest\Preset;
|
||||||
use Pest\Support\Backtrace;
|
use Pest\Support\Backtrace;
|
||||||
use Pest\Support\Exporter;
|
use Pest\Support\Exporter;
|
||||||
use Pest\Support\HigherOrderCallables;
|
use Pest\Support\HigherOrderCallables;
|
||||||
@ -521,4 +522,12 @@ final class TestCall
|
|||||||
$testCase->attributes = array_merge($testCase->attributes, $this->testCaseFactoryAttributes);
|
$testCase->attributes = array_merge($testCase->attributes, $this->testCaseFactoryAttributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the given preset on the test.
|
||||||
|
*/
|
||||||
|
public function preset(): Preset
|
||||||
|
{
|
||||||
|
return new Preset($this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/Preset.php
Normal file
108
src/Preset.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest;
|
||||||
|
|
||||||
|
use Pest\Arch\Support\Composer;
|
||||||
|
use Pest\ArchPresets\AbstractPreset;
|
||||||
|
use Pest\ArchPresets\Base;
|
||||||
|
use Pest\ArchPresets\Laravel;
|
||||||
|
use Pest\ArchPresets\Security;
|
||||||
|
use Pest\ArchPresets\Strict;
|
||||||
|
use Pest\PendingCalls\TestCall;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Preset
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The application / package base namespaces.
|
||||||
|
*
|
||||||
|
* @var ?array<int, string>
|
||||||
|
*/
|
||||||
|
private static ?array $baseNamespaces = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new preset instance.
|
||||||
|
*/
|
||||||
|
public function __construct(private readonly TestCall $testCall)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the Pest base preset and returns the test call instance.
|
||||||
|
*/
|
||||||
|
public function base(): Base
|
||||||
|
{
|
||||||
|
return $this->executePreset(new Base($this->baseNamespaces()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the Pest laravel preset and returns the test call instance.
|
||||||
|
*/
|
||||||
|
public function laravel(): Laravel
|
||||||
|
{
|
||||||
|
return $this->executePreset(new Laravel($this->baseNamespaces()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the Pest strict preset and returns the test call instance.
|
||||||
|
*/
|
||||||
|
public function strict(): Strict
|
||||||
|
{
|
||||||
|
return $this->executePreset(new Strict($this->baseNamespaces()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the Pest security preset and returns the test call instance.
|
||||||
|
*/
|
||||||
|
public function security(): AbstractPreset
|
||||||
|
{
|
||||||
|
return $this->executePreset(new Security($this->baseNamespaces()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the given preset.
|
||||||
|
*
|
||||||
|
* @template TPreset of AbstractPreset
|
||||||
|
*
|
||||||
|
* @param TPreset $preset
|
||||||
|
* @return TPreset
|
||||||
|
*/
|
||||||
|
private function executePreset(AbstractPreset $preset): AbstractPreset
|
||||||
|
{
|
||||||
|
if ((fn (): ?string => $this->description)->call($this->testCall) === null) {
|
||||||
|
$description = strtolower((new \ReflectionClass($preset))->getShortName());
|
||||||
|
|
||||||
|
(fn (): string => $this->description = sprintf('arch "%s" preset', $description))->call($this->testCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->baseNamespaces();
|
||||||
|
|
||||||
|
$preset->execute();
|
||||||
|
|
||||||
|
$this->testCall->testCaseMethod->closure = (function () use ($preset): void {
|
||||||
|
$preset->flush();
|
||||||
|
})->bindTo(new stdClass);
|
||||||
|
|
||||||
|
return $preset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the base namespaces for the application / package.
|
||||||
|
*
|
||||||
|
* @return array<int, string>
|
||||||
|
*/
|
||||||
|
private function baseNamespaces(): array
|
||||||
|
{
|
||||||
|
if (self::$baseNamespaces === null) {
|
||||||
|
self::$baseNamespaces = Composer::userNamespaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$baseNamespaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
PASS Tests\Arch
|
PASS Tests\Arch
|
||||||
|
✓ arch "base" preset
|
||||||
|
✓ arch "strict" preset
|
||||||
✓ globals
|
✓ globals
|
||||||
✓ dependencies
|
✓ dependencies
|
||||||
✓ contracts
|
✓ contracts
|
||||||
|
|||||||
@ -2,6 +2,26 @@
|
|||||||
|
|
||||||
use Pest\Expectation;
|
use Pest\Expectation;
|
||||||
|
|
||||||
|
arch()->preset()->base()->ignoring([
|
||||||
|
Expectation::class,
|
||||||
|
'debug_backtrace',
|
||||||
|
'var_export',
|
||||||
|
'xdebug_info',
|
||||||
|
]);
|
||||||
|
|
||||||
|
arch()->preset()->strict()->ignoring([
|
||||||
|
'usleep',
|
||||||
|
]);
|
||||||
|
|
||||||
|
arch()->preset()->security()->ignoring([
|
||||||
|
'eval',
|
||||||
|
'str_shuffle',
|
||||||
|
'exec',
|
||||||
|
'unserialize',
|
||||||
|
'extract',
|
||||||
|
'assert',
|
||||||
|
]);
|
||||||
|
|
||||||
arch('globals')
|
arch('globals')
|
||||||
->expect(['dd', 'dump', 'ray', 'die', 'var_dump', 'sleep'])
|
->expect(['dd', 'dump', 'ray', 'die', 'var_dump', 'sleep'])
|
||||||
->not->toBeUsed()
|
->not->toBeUsed()
|
||||||
@ -30,4 +50,6 @@ arch('contracts')
|
|||||||
'NunoMaduro\Collision\Contracts',
|
'NunoMaduro\Collision\Contracts',
|
||||||
'Pest\Factories\TestCaseMethodFactory',
|
'Pest\Factories\TestCaseMethodFactory',
|
||||||
'Symfony\Component\Console',
|
'Symfony\Component\Console',
|
||||||
|
'Pest\Arch\Contracts',
|
||||||
|
'Pest\PendingCalls',
|
||||||
])->toBeInterfaces();
|
])->toBeInterfaces();
|
||||||
|
|||||||
Reference in New Issue
Block a user