Compare commits

...

7 Commits

Author SHA1 Message Date
989e43d1a0 release: v3.2.2 2024-09-24 10:23:43 +01:00
7cd42aafd8 fix: auto-complete on presets 2024-09-24 10:23:32 +01:00
48a1de273f release: v3.2.1 2024-09-23 14:09:55 +01:00
970e16e949 Ignores 2024-09-23 14:08:30 +01:00
432ff221c6 fix: missing != and !== on new toUseStrictEquality arch expectation 2024-09-23 14:08:21 +01:00
a55da85dd2 release: v3.2.0 2024-09-23 13:14:03 +01:00
f291cd1603 chore: bumps dependencies 2024-09-23 13:11:49 +01:00
15 changed files with 116 additions and 17 deletions

View File

@ -18,12 +18,12 @@
], ],
"require": { "require": {
"php": "^8.2.0", "php": "^8.2.0",
"brianium/paratest": "^7.5.4", "brianium/paratest": "^7.5.5",
"nunomaduro/collision": "^8.4.0", "nunomaduro/collision": "^8.4.0",
"nunomaduro/termwind": "^2.1.0", "nunomaduro/termwind": "^2.1.0",
"pestphp/pest-plugin": "^3.0.0", "pestphp/pest-plugin": "^3.0.0",
"pestphp/pest-plugin-arch": "^3.0.0", "pestphp/pest-plugin-arch": "^3.0.0",
"pestphp/pest-plugin-mutate": "^3.0.4", "pestphp/pest-plugin-mutate": "^3.0.5",
"phpunit/phpunit": "^11.3.6" "phpunit/phpunit": "^11.3.6"
}, },
"conflict": { "conflict": {
@ -54,7 +54,7 @@
"require-dev": { "require-dev": {
"pestphp/pest-dev-tools": "^3.0.0", "pestphp/pest-dev-tools": "^3.0.0",
"pestphp/pest-plugin-type-coverage": "^3.0.0", "pestphp/pest-plugin-type-coverage": "^3.0.0",
"symfony/process": "^7.1.3" "symfony/process": "^7.1.5"
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true, "prefer-stable": true,

View File

@ -21,6 +21,7 @@ final class Strict extends AbstractPreset
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHaveProtectedMethods(), fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHaveProtectedMethods(),
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeAbstract(), fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeAbstract(),
fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictTypes(), fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictTypes(),
fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictEquality(),
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->toBeFinal(), fn (Expectation $namespace): ArchExpectation => $namespace->classes()->toBeFinal(),
); );

View File

@ -223,7 +223,7 @@ final class Expectation
throw new BadMethodCallException('Expectation value is not iterable.'); throw new BadMethodCallException('Expectation value is not iterable.');
} }
if (count($callbacks) == 0) { if ($callbacks === []) {
throw new InvalidArgumentException('No sequence expectations defined.'); throw new InvalidArgumentException('No sequence expectations defined.');
} }
@ -264,7 +264,7 @@ final class Expectation
$matched = false; $matched = false;
foreach ($expressions as $key => $callback) { foreach ($expressions as $key => $callback) {
if ($subject != $key) { if ($subject != $key) { // @pest-arch-ignore-line
continue; continue;
} }
@ -380,7 +380,7 @@ final class Expectation
if (self::hasExtend($name)) { if (self::hasExtend($name)) {
$extend = self::$extends[$name]->bindTo($this, Expectation::class); $extend = self::$extends[$name]->bindTo($this, Expectation::class);
if ($extend != false) { if ($extend != false) { // @pest-arch-ignore-line
return $extend; return $extend;
} }
} }
@ -515,6 +515,19 @@ final class Expectation
); );
} }
/**
* Asserts that the given expectation target uses strict equality.
*/
public function toUseStrictEquality(): ArchExpectation
{
return Targeted::make(
$this,
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' == ') && ! str_contains((string) file_get_contents($object->path), ' != '),
'to use strict equality',
FileLineFinder::where(fn (string $line): bool => str_contains($line, ' == ') || str_contains($line, ' != ')),
);
}
/** /**
* Asserts that the given expectation target is final. * Asserts that the given expectation target is final.
*/ */

View File

@ -152,6 +152,19 @@ final readonly class OppositeExpectation
); );
} }
/**
* Asserts that the given expectation target does not use the strict equality operator.
*/
public function toUseStrictEquality(): ArchExpectation
{
return Targeted::make(
$this->original,
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' === ') && ! str_contains((string) file_get_contents($object->path), ' !== '),
'to use strict equality',
FileLineFinder::where(fn (string $line): bool => str_contains($line, ' === ') || str_contains($line, ' !== ')),
);
}
/** /**
* Asserts that the given expectation target is not final. * Asserts that the given expectation target is not final.
*/ */

View File

@ -150,7 +150,7 @@ final readonly class Converter
{ {
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) { if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
$firstTest = $this->getFirstTest($testSuite); $firstTest = $this->getFirstTest($testSuite);
if ($firstTest != null) { if ($firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
return $this->getTestMethodNameWithoutDatasetSuffix($firstTest); return $this->getTestMethodNameWithoutDatasetSuffix($firstTest);
} }
} }
@ -178,7 +178,7 @@ final readonly class Converter
public function getTestSuiteLocation(TestSuite $testSuite): ?string public function getTestSuiteLocation(TestSuite $testSuite): ?string
{ {
$firstTest = $this->getFirstTest($testSuite); $firstTest = $this->getFirstTest($testSuite);
if ($firstTest == null) { if (! $firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
return null; return null;
} }
$path = $firstTest->testDox()->prettifiedClassName(); $path = $firstTest->testDox()->prettifiedClassName();

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Pest\PendingCalls; namespace Pest\PendingCalls;
use Closure; use Closure;
use Pest\Concerns\Testable;
use Pest\Exceptions\InvalidArgumentException; use Pest\Exceptions\InvalidArgumentException;
use Pest\Exceptions\TestDescriptionMissing; use Pest\Exceptions\TestDescriptionMissing;
use Pest\Factories\Attribute; use Pest\Factories\Attribute;
@ -25,9 +26,9 @@ use PHPUnit\Framework\TestCase;
/** /**
* @internal * @internal
* *
* @mixin HigherOrderCallables|TestCase * @mixin HigherOrderCallables|TestCase|Testable
*/ */
final class TestCall final class TestCall // @phpstan-ignore-line
{ {
use Describable; use Describable;

View File

@ -6,7 +6,7 @@ namespace Pest;
function version(): string function version(): string
{ {
return '3.1.0'; return '3.2.2';
} }
function testDirectory(string $file = ''): string function testDirectory(string $file = ''): string

View File

@ -20,13 +20,13 @@ final class Closure
*/ */
public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure
{ {
if ($closure == null) { if (! $closure instanceof \Closure) {
throw ShouldNotHappen::fromMessage('Could not bind null closure.'); throw ShouldNotHappen::fromMessage('Could not bind null closure.');
} }
$closure = BaseClosure::bind($closure, $newThis, $newScope); $closure = BaseClosure::bind($closure, $newThis, $newScope);
if ($closure == false) { if (! $closure instanceof \Closure) {
throw ShouldNotHappen::fromMessage('Could not bind closure.'); throw ShouldNotHappen::fromMessage('Could not bind closure.');
} }

View File

@ -1,5 +1,5 @@
Pest Testing Framework 3.1.0. Pest Testing Framework 3.2.2.
USAGE: pest <file> [options] USAGE: pest <file> [options]

View File

@ -1,3 +1,3 @@
Pest Testing Framework 3.1.0. Pest Testing Framework 3.2.2.

View File

@ -968,6 +968,12 @@
✓ it can handle a non-defined exception ✓ it can handle a non-defined exception
✓ it can handle a class not found Error ✓ it can handle a class not found Error
PASS Tests\Features\Expect\toUseStrictEquality
✓ missing strict equality
✓ has strict equality
✓ opposite missing strict equality
✓ opposite has strict equality
PASS Tests\Features\Expect\toUseTrait PASS Tests\Features\Expect\toUseTrait
✓ pass ✓ pass
✓ failures ✓ failures
@ -1574,4 +1580,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, 17 todos, 28 skipped, 1089 passed (2637 assertions) Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 28 skipped, 1093 passed (2644 assertions)

View File

@ -0,0 +1,21 @@
<?php
use Pest\Arch\Exceptions\ArchExpectationFailedException;
test('missing strict equality')
->throws(ArchExpectationFailedException::class)
->expect('Tests\\Fixtures\\Arch\\ToUseStrictEquality\\NotStrictEquality')
->toUseStrictEquality();
test('has strict equality')
->expect('Tests\\Fixtures\\Arch\\ToUseStrictEquality\\StrictEquality')
->toUseStrictEquality();
test('opposite missing strict equality')
->throws(ArchExpectationFailedException::class)
->expect('Tests\\Fixtures\\Arch\\ToUseStrictEquality\\StrictEquality')
->not->toUseStrictEquality();
test('opposite has strict equality')
->expect('Tests\\Fixtures\\Arch\\ToUseStrictEquality\\NotStrictEquality')
->not->toUseStrictEquality();

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Tests\Fixtures\Arch\ToUseStrictEquality;
class NotStrictEquality
{
public function test(): void
{
$a = 1;
$b = '1';
if ($a == $b) {
echo 'Equal';
}
if ($a != $b) {
echo 'Equal';
}
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Tests\Fixtures\Arch\ToUseStrictEquality;
class StrictEquality
{
public function test(): void
{
$a = 1;
$b = '1';
if ($a === $b) {
echo 'Equal';
}
if ($a !== $b) {
echo 'Equal';
}
}
}

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, 17 todos, 19 skipped, 1079 passed (2613 assertions)') ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 19 skipped, 1083 passed (2620 assertions)')
->toContain('Parallel: 3 processes'); ->toContain('Parallel: 3 processes');
})->skipOnWindows(); })->skipOnWindows();