mirror of
https://github.com/pestphp/pest.git
synced 2026-03-05 23:37:22 +01:00
feat: toHavePrivateMethodsBesides, toHaveProtectedMethodsBesides, toHavePublicMethodsBesides
This commit is contained in:
@ -31,14 +31,15 @@ final class Laravel extends AbstractPreset
|
||||
->not->toImplement(Throwable::class)
|
||||
->ignoring('App\Exceptions');
|
||||
|
||||
$this->expectations[] = expect('App\Http\Controllers')
|
||||
->classes()
|
||||
->toHaveSuffix('Controller');
|
||||
|
||||
$this->expectations[] = expect('App')
|
||||
->not->toHaveSuffix('Controller')
|
||||
->ignoring('App\Http\Controllers');
|
||||
|
||||
$this->expectations[] = expect('App\Http\Controllers')
|
||||
->classes()
|
||||
->toHaveSuffix('Controller')
|
||||
->not->toHavePublicMethodsBesides(['__construct', '__invoke', 'index', 'show', 'create', 'store', 'edit', 'update', 'destroy']);
|
||||
|
||||
$this->expectations[] = expect('App\Http\Middleware')
|
||||
->classes()
|
||||
->toHaveMethod('handle');
|
||||
|
||||
@ -20,6 +20,7 @@ final class Relaxed extends AbstractPreset
|
||||
$this->eachUserNamespace(
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->not->toUseStrictTypes(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeFinal(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHavePrivateMethodsBesides([]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ final class Strict extends AbstractPreset
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictTypes(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->toBeFinal(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeAbstract(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHaveProtectedMethodsBesides([])
|
||||
);
|
||||
|
||||
$this->expectations[] = expect([
|
||||
|
||||
@ -588,6 +588,30 @@ final class Expectation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
*/
|
||||
public function toHavePublicMethodsBesides(): never
|
||||
{
|
||||
throw InvalidExpectation::fromMethods(['toHavePublicMethodsBesides']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
*/
|
||||
public function toHaveProtectedMethodsBesides(): never
|
||||
{
|
||||
throw InvalidExpectation::fromMethods(['toHaveProtectedMethodsBesides']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
*/
|
||||
public function toHavePrivateMethodsBesides(): never
|
||||
{
|
||||
throw InvalidExpectation::fromMethods(['toHavePrivateMethodsBesides']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given expectation target is enum.
|
||||
*/
|
||||
|
||||
@ -224,6 +224,93 @@ final class OppositeExpectation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given expectation target not to have the public methods besides the given methods.
|
||||
*/
|
||||
public function toHavePublicMethodsBesides(array|string $methods): ArchExpectation
|
||||
{
|
||||
$methods = is_array($methods) ? $methods : [$methods];
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
function (ObjectDescription $object) use ($methods): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)
|
||||
: [];
|
||||
|
||||
foreach ($reflectionMethods as $reflectionMethod) {
|
||||
if (! in_array($reflectionMethod->name, $methods, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
count($methods) === 0
|
||||
? 'not to have public methods'
|
||||
: sprintf("not to have public methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'public function')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given expectation target not to have the protected methods besides the given methods.
|
||||
*/
|
||||
public function toHaveProtectedMethodsBesides(array|string $methods): ArchExpectation
|
||||
{
|
||||
$methods = is_array($methods) ? $methods : [$methods];
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
function (ObjectDescription $object) use ($methods): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)
|
||||
: [];
|
||||
|
||||
foreach ($reflectionMethods as $reflectionMethod) {
|
||||
if (! in_array($reflectionMethod->name, $methods, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
count($methods) === 0
|
||||
? 'not to have protected methods'
|
||||
: sprintf("not to have protected methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'protected function')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given expectation target not to have the private methods besides the given methods.
|
||||
*/
|
||||
public function toHavePrivateMethodsBesides(array|string $methods): ArchExpectation
|
||||
{
|
||||
$methods = is_array($methods) ? $methods : [$methods];
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
function (ObjectDescription $object) use ($methods): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)
|
||||
: [];
|
||||
|
||||
foreach ($reflectionMethods as $reflectionMethod) {
|
||||
if (! in_array($reflectionMethod->name, $methods, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
count($methods) === 0
|
||||
? 'not to have private methods'
|
||||
: sprintf("not to have private methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'private function')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given expectation target is not enum.
|
||||
*/
|
||||
|
||||
@ -19,7 +19,7 @@ abstract class Subscriber // @pest-arch-ignore-line
|
||||
/**
|
||||
* Creates a new TeamCityLogger instance.
|
||||
*/
|
||||
final protected function logger(): TeamCityLogger
|
||||
final protected function logger(): TeamCityLogger // @pest-arch-ignore-line
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ final class CleanConsoleOutput extends ConsoleOutput
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doWrite(string $message, bool $newline): void
|
||||
protected function doWrite(string $message, bool $newline): void // @pest-arch-ignore-line
|
||||
{
|
||||
if ($this->isOpeningHeadline($message)) {
|
||||
return;
|
||||
|
||||
@ -258,12 +258,12 @@ final class Reflection
|
||||
* @param ReflectionClass<object> $reflectionClass
|
||||
* @return array<int, ReflectionMethod>
|
||||
*/
|
||||
public static function getMethodsFromReflectionClass(ReflectionClass $reflectionClass): array
|
||||
public static function getMethodsFromReflectionClass(ReflectionClass $reflectionClass, int $filter = ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE): array
|
||||
{
|
||||
$getMethods = fn (ReflectionClass $reflectionClass): array => array_filter(
|
||||
array_map(
|
||||
fn (ReflectionMethod $method): \ReflectionMethod => $method,
|
||||
$reflectionClass->getMethods(),
|
||||
$reflectionClass->getMethods($filter),
|
||||
), fn (ReflectionMethod $method): bool => $method->getDeclaringClass()->getName() === $reflectionClass->getName(),
|
||||
);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
|
||||
PASS Tests\Arch
|
||||
✓ arch "base" preset
|
||||
✓ arch "php" preset
|
||||
✓ arch "strict" preset
|
||||
✓ arch "security" preset
|
||||
✓ globals
|
||||
@ -831,6 +831,10 @@
|
||||
✓ opposite missing prefix
|
||||
✓ opposite has prefix
|
||||
|
||||
PASS Tests\Features\Expect\toHavePrivateMethodsBesides
|
||||
✓ pass
|
||||
✓ failures
|
||||
|
||||
PASS Tests\Features\Expect\toHaveProperties
|
||||
✓ pass
|
||||
✓ failures
|
||||
@ -849,6 +853,14 @@
|
||||
✓ failures with message and Any matcher
|
||||
✓ not failures
|
||||
|
||||
PASS Tests\Features\Expect\toHaveProtectedMethodsBesides
|
||||
✓ pass
|
||||
✓ failures
|
||||
|
||||
PASS Tests\Features\Expect\toHavePublicMethodsBesides
|
||||
✓ pass
|
||||
✓ failures
|
||||
|
||||
PASS Tests\Features\Expect\toHaveSameSize
|
||||
✓ failures with wrong type
|
||||
✓ pass
|
||||
@ -1547,4 +1559,4 @@
|
||||
WARN Tests\Visual\Version
|
||||
- visual snapshot of help command output
|
||||
|
||||
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 24 skipped, 1078 passed (2632 assertions)
|
||||
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 24 skipped, 1084 passed (2644 assertions)
|
||||
12
tests/Features/Expect/toHavePrivateMethodsBesides.php
Normal file
12
tests/Features/Expect/toHavePrivateMethodsBesides.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Pest\Arch\Exceptions\ArchExpectationFailedException;
|
||||
use Tests\Fixtures\Arch\ToHavePublicMethodsBesides\UserController;
|
||||
|
||||
test('pass', function () {
|
||||
expect(UserController::class)->not->toHavePrivateMethodsBesides(['privateMethod']);
|
||||
});
|
||||
|
||||
test('failures', function () {
|
||||
expect(UserController::class)->not->toHavePrivateMethodsBesides([]);
|
||||
})->throws(ArchExpectationFailedException::class);
|
||||
12
tests/Features/Expect/toHaveProtectedMethodsBesides.php
Normal file
12
tests/Features/Expect/toHaveProtectedMethodsBesides.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Pest\Arch\Exceptions\ArchExpectationFailedException;
|
||||
use Tests\Fixtures\Arch\ToHavePublicMethodsBesides\UserController;
|
||||
|
||||
test('pass', function () {
|
||||
expect(UserController::class)->not->toHaveProtectedMethodsBesides(['protectedMethod']);
|
||||
});
|
||||
|
||||
test('failures', function () {
|
||||
expect(UserController::class)->not->toHaveProtectedMethodsBesides([]);
|
||||
})->throws(ArchExpectationFailedException::class);
|
||||
12
tests/Features/Expect/toHavePublicMethodsBesides.php
Normal file
12
tests/Features/Expect/toHavePublicMethodsBesides.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Pest\Arch\Exceptions\ArchExpectationFailedException;
|
||||
use Tests\Fixtures\Arch\ToHavePublicMethodsBesides\UserController;
|
||||
|
||||
test('pass', function () {
|
||||
expect(UserController::class)->not->toHavePublicMethodsBesides(['publicMethod']);
|
||||
});
|
||||
|
||||
test('failures', function () {
|
||||
expect(UserController::class)->not->toHavePublicMethodsBesides([]);
|
||||
})->throws(ArchExpectationFailedException::class);
|
||||
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Fixtures\Arch\ToHavePublicMethodsBesides;
|
||||
|
||||
class UserController
|
||||
{
|
||||
public function publicMethod(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function protectedMethod(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
private function privateMethod(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ $run = function () {
|
||||
|
||||
test('parallel', function () use ($run) {
|
||||
expect($run('--exclude-group=integration'))
|
||||
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 19 skipped, 1064 passed (2602 assertions)')
|
||||
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 19 skipped, 1070 passed (2612 assertions)')
|
||||
->toContain('Parallel: 3 processes');
|
||||
})->skipOnWindows();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user