mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 67f217852c | |||
| 1bad148487 | |||
| e24f137b8e | |||
| 6d9189f3f5 | |||
| 1513ede73b | |||
| 8c65197881 | |||
| 3f65af9fdf | |||
| 42d89814e3 | |||
| 1e3156a5b6 | |||
| 97713c0832 | |||
| 62b0e3c9df | |||
| 647de2f1cf | |||
| 0a7bff0d24 | |||
| 7618434580 | |||
| 1e0bb88b73 | |||
| 83b76d7c2e | |||
| 5a870b3940 | |||
| 1115c64186 | |||
| e38a271ca2 | |||
| 43703ab40a | |||
| 86452765a4 | |||
| b8a1b7e5cc | |||
| 5fe79d9c18 | |||
| 2744da4292 | |||
| 87f4e5e7b3 | |||
| bb3decf3cc | |||
| 4e2987d438 | |||
| a25158bce8 | |||
| 49e77b1d4c | |||
| 989e43d1a0 | |||
| 7cd42aafd8 | |||
| 48a1de273f | |||
| 970e16e949 | |||
| 432ff221c6 | |||
| a55da85dd2 | |||
| f291cd1603 | |||
| 5de0c2254a | |||
| b98ce0ced3 | |||
| 28772c2609 | |||
| 452ffaf8df | |||
| e8338405b5 | |||
| 1b014e4b18 | |||
| 034715e8b1 | |||
| 669dc0da71 |
7
.github/workflows/tests.yml
vendored
7
.github/workflows/tests.yml
vendored
@ -13,8 +13,8 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
symfony: ['7.0']
|
||||
php: ['8.2', '8.3']
|
||||
symfony: ['7.1']
|
||||
php: ['8.2', '8.3', '8.4']
|
||||
dependency_version: [prefer-lowest, prefer-stable]
|
||||
|
||||
name: PHP ${{ matrix.php }} - Symfony ^${{ matrix.symfony }} - ${{ matrix.os }} - ${{ matrix.dependency_version }}
|
||||
@ -36,7 +36,8 @@ jobs:
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: Install PHP dependencies
|
||||
run: composer update --${{ matrix.dependency_version }} --no-interaction --no-progress --ansi --with="symfony/console:~${{ matrix.symfony }}"
|
||||
shell: bash
|
||||
run: composer update --${{ matrix.dependency_version }} --no-interaction --no-progress --ansi --with="symfony/console:^${{ matrix.symfony }}"
|
||||
|
||||
- name: Unit Tests
|
||||
run: composer test:unit
|
||||
|
||||
@ -42,7 +42,7 @@ composer test
|
||||
|
||||
Check types:
|
||||
```bash
|
||||
composer test:types
|
||||
composer test:type:check
|
||||
```
|
||||
|
||||
Unit tests:
|
||||
|
||||
23
bin/pest
23
bin/pest
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env php
|
||||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Pest\Kernel;
|
||||
use Pest\Panic;
|
||||
@ -37,7 +39,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--test-directory=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--test-directory') {
|
||||
} elseif ($value === '--test-directory') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -62,7 +64,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--assignee=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--assignee') {
|
||||
} elseif ($value === '--assignee') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -72,7 +74,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--issue=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--issue') {
|
||||
} elseif ($value === '--issue') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -82,7 +84,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--ticket=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--ticket') {
|
||||
} elseif ($value === '--ticket') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -92,7 +94,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--pr=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--pr') {
|
||||
} elseif ($value === '--pr') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -102,7 +104,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
if (str_contains($value, '--pull-request=')) {
|
||||
unset($arguments[$key]);
|
||||
} else if ($value === '--pull-request') {
|
||||
} elseif ($value === '--pull-request') {
|
||||
unset($arguments[$key]);
|
||||
|
||||
if (isset($arguments[$key + 1])) {
|
||||
@ -117,7 +119,6 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Used when Pest is required using composer.
|
||||
$vendorPath = dirname(__DIR__, 4).'/vendor/autoload.php';
|
||||
|
||||
@ -134,7 +135,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
// Get $rootPath based on $autoloadPath
|
||||
$rootPath = dirname($autoloadPath, 2);
|
||||
$input = new ArgvInput();
|
||||
$input = new ArgvInput;
|
||||
|
||||
$testSuite = TestSuite::getInstance(
|
||||
$rootPath,
|
||||
@ -146,11 +147,11 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
}
|
||||
|
||||
if ($todo) {
|
||||
$testSuite->tests->addTestCaseMethodFilter(new TodoTestCaseFilter());
|
||||
$testSuite->tests->addTestCaseMethodFilter(new TodoTestCaseFilter);
|
||||
}
|
||||
|
||||
if ($notes) {
|
||||
$testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter());
|
||||
$testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter);
|
||||
}
|
||||
|
||||
if ($assignee = $input->getParameterOption('--assignee')) {
|
||||
|
||||
@ -18,16 +18,17 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.2.0",
|
||||
"brianium/paratest": "^7.5.4",
|
||||
"nunomaduro/collision": "^8.4.0",
|
||||
"nunomaduro/termwind": "^2.1.0",
|
||||
"brianium/paratest": "^7.6.0",
|
||||
"nunomaduro/collision": "^8.5.0",
|
||||
"nunomaduro/termwind": "^2.2.0",
|
||||
"pestphp/pest-plugin": "^3.0.0",
|
||||
"pestphp/pest-plugin-arch": "^3.0.0",
|
||||
"pestphp/pest-plugin-mutate": "^3.0.3",
|
||||
"phpunit/phpunit": "^11.3.6"
|
||||
"pestphp/pest-plugin-mutate": "^3.0.5",
|
||||
"phpunit/phpunit": "^11.4.1"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": ">11.3.6",
|
||||
"filp/whoops": "<2.16.0",
|
||||
"phpunit/phpunit": ">11.4.1",
|
||||
"sebastian/exporter": "<6.0.0",
|
||||
"webmozart/assert": "<1.11.0"
|
||||
},
|
||||
@ -52,9 +53,9 @@
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest-dev-tools": "^3.0.0",
|
||||
"pestphp/pest-plugin-type-coverage": "^3.0.0",
|
||||
"symfony/process": "^7.1.3"
|
||||
"pestphp/pest-dev-tools": "^3.3.0",
|
||||
"pestphp/pest-plugin-type-coverage": "^3.1.0",
|
||||
"symfony/process": "^7.1.5"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
includes:
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
- vendor/ergebnis/phpstan-rules/rules.neon
|
||||
- vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
|
||||
|
||||
parameters:
|
||||
@ -12,12 +11,4 @@ parameters:
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
|
||||
ignoreErrors:
|
||||
- "#has a nullable return type declaration.#"
|
||||
- "#Language construct isset\\(\\) should not be used.#"
|
||||
- "#is not allowed to extend#"
|
||||
- "#is concrete, but does not have a Test suffix#"
|
||||
- "#with a nullable type declaration#"
|
||||
- "#type mixed is not subtype of native#"
|
||||
- "# with null as default value#"
|
||||
- "#has parameter \\$closure with default value.#"
|
||||
- "#has parameter \\$description with default value.#"
|
||||
|
||||
@ -27,17 +27,20 @@ final class Laravel extends AbstractPreset
|
||||
->ignoring('App\Enums');
|
||||
|
||||
$this->expectations[] = expect('App\Enums')
|
||||
->toBeEnums();
|
||||
->toBeEnums()
|
||||
->ignoring('App\Enums\Concerns');
|
||||
|
||||
$this->expectations[] = expect('App\Features')
|
||||
->toBeClasses();
|
||||
->toBeClasses()
|
||||
->ignoring('App\Features\Concerns');
|
||||
|
||||
$this->expectations[] = expect('App\Features')
|
||||
->toHaveMethod('resolve');
|
||||
|
||||
$this->expectations[] = expect('App\Exceptions')
|
||||
->classes()
|
||||
->toImplement('Throwable');
|
||||
->toImplement('Throwable')
|
||||
->ignoring('App\Exceptions\Handler');
|
||||
|
||||
$this->expectations[] = expect('App')
|
||||
->not->toImplement(Throwable::class)
|
||||
@ -149,7 +152,7 @@ final class Laravel extends AbstractPreset
|
||||
->toOnlyBeUsedIn('App\Http');
|
||||
|
||||
$this->expectations[] = expect('App\Http\Controllers')
|
||||
->not->toHavePublicMethodsBesides(['__construct', '__invoke', 'index', 'show', 'create', 'store', 'edit', 'update', 'destroy']);
|
||||
->not->toHavePublicMethodsBesides(['__construct', '__invoke', 'index', 'show', 'create', 'store', 'edit', 'update', 'destroy', 'middleware']);
|
||||
|
||||
$this->expectations[] = expect([
|
||||
'dd',
|
||||
@ -159,5 +162,9 @@ final class Laravel extends AbstractPreset
|
||||
'exit',
|
||||
'ray',
|
||||
])->not->toBeUsed();
|
||||
|
||||
$this->expectations[] = expect('App\Policies')
|
||||
->classes()
|
||||
->toHaveSuffix('Policy');
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ final class Strict extends AbstractPreset
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHaveProtectedMethods(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeAbstract(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictTypes(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictEquality(),
|
||||
fn (Expectation $namespace): ArchExpectation => $namespace->classes()->toBeFinal(),
|
||||
);
|
||||
|
||||
|
||||
@ -18,12 +18,12 @@ final class BootOverrides implements Bootstrapper
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public const FILES = [
|
||||
'c96b1cb57d7fc8e649f4c13a8abe418c2541bcfab194fb6702b99f777f52ee84' => 'Runner/Filter/NameFilterIterator.php',
|
||||
'53c246e5f416a39817ac81124cdd64ea8403038d01d7a202e1ffa486fbdf3fa7' => 'Runner/Filter/NameFilterIterator.php',
|
||||
'a4a43de01f641c6944ee83d963795a46d32b5206b5ab3bbc6cce76e67190acbf' => 'Runner/ResultCache/DefaultResultCache.php',
|
||||
'd0e81317889ad88c707db4b08a94cadee4c9010d05ff0a759f04e71af5efed89' => 'Runner/TestSuiteLoader.php',
|
||||
'3bb609b0d3bf6dee8df8d6cd62a3c8ece823c4bb941eaaae39e3cb267171b9d2' => 'TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php',
|
||||
'8abdad6413329c6fe0d7d44a8b9926e390af32c0b3123f3720bb9c5bbc6fbb7e' => 'TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php',
|
||||
'43883b7e5811886cf3731c8ed6304d5a77078d9731e1e505abc2da36bde19f3e' => 'TextUI/TestSuiteFilterProcessor.php',
|
||||
'b4250fc3ffad5954624cb5e682fd940b874e8d3422fa1ee298bd7225e1aa5fc2' => 'TextUI/TestSuiteFilterProcessor.php',
|
||||
'357d5cd7007f8559b26e1b8cdf43bb6fb15b51b79db981779da6f31b7ec39dad' => 'Event/Value/ThrowableBuilder.php',
|
||||
'676273f1fe483877cf2d95c5aedbf9ae5d6a8e2f4c12d6ce716df6591e6db023' => 'Logging/JUnit/JunitXmlLogger.php',
|
||||
];
|
||||
|
||||
@ -223,7 +223,7 @@ final class Expectation
|
||||
throw new BadMethodCallException('Expectation value is not iterable.');
|
||||
}
|
||||
|
||||
if (count($callbacks) == 0) {
|
||||
if ($callbacks === []) {
|
||||
throw new InvalidArgumentException('No sequence expectations defined.');
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@ final class Expectation
|
||||
$matched = false;
|
||||
|
||||
foreach ($expressions as $key => $callback) {
|
||||
if ($subject != $key) {
|
||||
if ($subject != $key) { // @pest-arch-ignore-line
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -380,7 +380,7 @@ final class Expectation
|
||||
if (self::hasExtend($name)) {
|
||||
$extend = self::$extends[$name]->bindTo($this, Expectation::class);
|
||||
|
||||
if ($extend != false) {
|
||||
if ($extend != false) { // @pest-arch-ignore-line
|
||||
return $extend;
|
||||
}
|
||||
}
|
||||
@ -509,12 +509,25 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => (bool) preg_match('/^<\?php\s+declare\(.*?strict_types\s?=\s?1.*?\);/', (string) file_get_contents($object->path)),
|
||||
fn (ObjectDescription $object): bool => (bool) preg_match('/^<\?php\s*(\/\*[\s\S]*?\*\/|\/\/[^\r\n]*(?:\r?\n|$)|\s)*declare\s*\(\s*strict_types\s*=\s*1\s*\)\s*;/m', (string) file_get_contents($object->path)),
|
||||
'to use strict types',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -166,7 +166,7 @@ final class TestCaseFactory
|
||||
}
|
||||
PHP;
|
||||
|
||||
eval($classCode); // @phpstan-ignore-line
|
||||
eval($classCode);
|
||||
} catch (ParseError $caught) {
|
||||
throw new RuntimeException(sprintf(
|
||||
"Unable to create test case for test file at %s. \n %s",
|
||||
|
||||
@ -217,7 +217,7 @@ if (! function_exists('afterAll')) {
|
||||
|
||||
if (! function_exists('covers')) {
|
||||
/**
|
||||
* Specifies which classes, or functions, a test method covers.
|
||||
* Specifies which classes, or functions, a test case covers.
|
||||
*
|
||||
* @param array<int, string>|string $classesOrFunctions
|
||||
*/
|
||||
@ -243,3 +243,38 @@ if (! function_exists('covers')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('mutates')) {
|
||||
/**
|
||||
* Specifies which classes, enums, or traits a test case mutates.
|
||||
*
|
||||
* @param array<int, string>|string $targets
|
||||
*/
|
||||
function mutates(array|string ...$targets): void
|
||||
{
|
||||
$filename = Backtrace::file();
|
||||
|
||||
$beforeEachCall = (new BeforeEachCall(TestSuite::getInstance(), $filename));
|
||||
$beforeEachCall->group('__pest_mutate_only');
|
||||
|
||||
/** @var MutationTestRunner $runner */
|
||||
$runner = Container::getInstance()->get(MutationTestRunner::class);
|
||||
/** @var \Pest\Mutate\Repositories\ConfigurationRepository $configurationRepository */
|
||||
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
||||
$everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;
|
||||
$classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;
|
||||
$paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;
|
||||
|
||||
if ($runner->isEnabled() && ! $everything && ! is_array($classes) && ! is_array($paths)) {
|
||||
$beforeEachCall->only('__pest_mutate_only');
|
||||
}
|
||||
|
||||
/** @var ConfigurationRepository $configurationRepository */
|
||||
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
||||
$paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;
|
||||
|
||||
if (! is_array($paths)) {
|
||||
$configurationRepository->globalConfiguration('default')->class(...$targets); // @phpstan-ignore-line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ final class KernelDump
|
||||
*/
|
||||
public function disable(): void
|
||||
{
|
||||
@ob_clean(); // @phpstan-ignore-line
|
||||
@ob_clean();
|
||||
|
||||
if ($this->buffer !== '') {
|
||||
$this->flush();
|
||||
|
||||
@ -150,7 +150,7 @@ final readonly class Converter
|
||||
{
|
||||
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
|
||||
$firstTest = $this->getFirstTest($testSuite);
|
||||
if ($firstTest != null) {
|
||||
if ($firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
|
||||
return $this->getTestMethodNameWithoutDatasetSuffix($firstTest);
|
||||
}
|
||||
}
|
||||
@ -178,7 +178,7 @@ final readonly class Converter
|
||||
public function getTestSuiteLocation(TestSuite $testSuite): ?string
|
||||
{
|
||||
$firstTest = $this->getFirstTest($testSuite);
|
||||
if ($firstTest == null) {
|
||||
if (! $firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
|
||||
return null;
|
||||
}
|
||||
$path = $firstTest->testDox()->prettifiedClassName();
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace Pest\PendingCalls;
|
||||
|
||||
use Closure;
|
||||
use Pest\Concerns\Testable;
|
||||
use Pest\Exceptions\InvalidArgumentException;
|
||||
use Pest\Exceptions\TestDescriptionMissing;
|
||||
use Pest\Factories\Attribute;
|
||||
@ -25,9 +26,9 @@ use PHPUnit\Framework\TestCase;
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @mixin HigherOrderCallables|TestCase
|
||||
* @mixin HigherOrderCallables|TestCase|Testable
|
||||
*/
|
||||
final class TestCall
|
||||
final class TestCall // @phpstan-ignore-line
|
||||
{
|
||||
use Describable;
|
||||
|
||||
@ -358,8 +359,8 @@ final class TestCall
|
||||
public function todo(// @phpstan-ignore-line
|
||||
array|string|null $note = null,
|
||||
array|string|null $assignee = null,
|
||||
array|string|null $issue = null,
|
||||
array|string|null $pr = null,
|
||||
array|string|int|null $issue = null,
|
||||
array|string|int|null $pr = null,
|
||||
): self {
|
||||
$this->skip('__TODO__');
|
||||
|
||||
@ -390,8 +391,8 @@ final class TestCall
|
||||
public function wip(// @phpstan-ignore-line
|
||||
array|string|null $note = null,
|
||||
array|string|null $assignee = null,
|
||||
array|string|null $issue = null,
|
||||
array|string|null $pr = null,
|
||||
array|string|int|null $issue = null,
|
||||
array|string|int|null $pr = null,
|
||||
): self {
|
||||
if ($issue !== null) {
|
||||
$this->issue($issue);
|
||||
@ -418,8 +419,8 @@ final class TestCall
|
||||
public function done(// @phpstan-ignore-line
|
||||
array|string|null $note = null,
|
||||
array|string|null $assignee = null,
|
||||
array|string|null $issue = null,
|
||||
array|string|null $pr = null,
|
||||
array|string|int|null $issue = null,
|
||||
array|string|int|null $pr = null,
|
||||
): self {
|
||||
if ($issue !== null) {
|
||||
$this->issue($issue);
|
||||
|
||||
@ -6,7 +6,7 @@ namespace Pest;
|
||||
|
||||
function version(): string
|
||||
{
|
||||
return '3.0.7';
|
||||
return '3.4.0';
|
||||
}
|
||||
|
||||
function testDirectory(string $file = ''): string
|
||||
|
||||
@ -20,13 +20,13 @@ final class Closure
|
||||
*/
|
||||
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.');
|
||||
}
|
||||
|
||||
$closure = BaseClosure::bind($closure, $newThis, $newScope);
|
||||
|
||||
if ($closure == false) {
|
||||
if (! $closure instanceof \Closure) {
|
||||
throw ShouldNotHappen::fromMessage('Could not bind closure.');
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
Pest Testing Framework 3.0.7.
|
||||
Pest Testing Framework 3.4.0.
|
||||
|
||||
USAGE: pest <file> [options]
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
--exclude-group [name] ........... Exclude tests from the specified group(s)
|
||||
--covers [name] ................. Only run tests that intend to cover [name]
|
||||
--uses [name] ..................... Only run tests that intend to use [name]
|
||||
--requires-php-extension [name] Only run tests that require PHP extension [name]
|
||||
--list-test-files ................................ List available test files
|
||||
--list-tests .......................................... List available tests
|
||||
--list-tests-xml [file] ................. List available tests in XML format
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
|
||||
Pest Testing Framework 3.0.7.
|
||||
Pest Testing Framework 3.4.0.
|
||||
|
||||
|
||||
@ -968,6 +968,16 @@
|
||||
✓ it can handle a non-defined exception
|
||||
✓ 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\toUseStrictTypes
|
||||
✓ pass
|
||||
✓ failures
|
||||
|
||||
PASS Tests\Features\Expect\toUseTrait
|
||||
✓ pass
|
||||
✓ failures
|
||||
@ -1574,4 +1584,4 @@
|
||||
WARN Tests\Visual\Version
|
||||
- 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, 1095 passed (2648 assertions)
|
||||
21
tests/Features/Expect/toUseStrictEquality.php
Normal file
21
tests/Features/Expect/toUseStrictEquality.php
Normal 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();
|
||||
17
tests/Features/Expect/toUseStrictTypes.php
Normal file
17
tests/Features/Expect/toUseStrictTypes.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Pest\Arch\Exceptions\ArchExpectationFailedException;
|
||||
use Tests\Fixtures\Arch\ToUseStrictTypes\HasNoStrictType;
|
||||
use Tests\Fixtures\Arch\ToUseStrictTypes\HasStrictType;
|
||||
use Tests\Fixtures\Arch\ToUseStrictTypes\HasStrictTypeWithCommentsAbove;
|
||||
|
||||
test('pass', function () {
|
||||
expect(HasStrictType::class)->toUseStrictTypes()
|
||||
->and(HasStrictTypeWithCommentsAbove::class)->toUseStrictTypes();
|
||||
});
|
||||
|
||||
test('failures', function () {
|
||||
expect(HasNoStrictType::class)->toUseStrictTypes();
|
||||
})->throws(ArchExpectationFailedException::class);
|
||||
@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
22
tests/Fixtures/Arch/ToUseStrictEquality/StrictEquality.php
Normal file
22
tests/Fixtures/Arch/ToUseStrictEquality/StrictEquality.php
Normal 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';
|
||||
}
|
||||
}
|
||||
}
|
||||
5
tests/Fixtures/Arch/ToUseStrictTypes/HasNoStrictType.php
Normal file
5
tests/Fixtures/Arch/ToUseStrictTypes/HasNoStrictType.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Fixtures\Arch\ToUseStrictTypes;
|
||||
|
||||
class HasNoStrictType {}
|
||||
7
tests/Fixtures/Arch/ToUseStrictTypes/HasStrictType.php
Normal file
7
tests/Fixtures/Arch/ToUseStrictTypes/HasStrictType.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Fixtures\Arch\ToUseStrictTypes;
|
||||
|
||||
class HasStrictType {}
|
||||
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
// some other comment
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Fixtures\Arch\ToUseStrictTypes;
|
||||
|
||||
class HasStrictTypeWithCommentsAbove {}
|
||||
@ -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, 1079 passed (2613 assertions)')
|
||||
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 19 skipped, 1085 passed (2624 assertions)')
|
||||
->toContain('Parallel: 3 processes');
|
||||
})->skipOnWindows();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user