mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7796630eaf | |||
| 3aec2b26ef | |||
| 7a7c35292c | |||
| 72cf695554 | |||
| 027f4e4832 | |||
| 165c879fe6 | |||
| 4c8bf4b2fd | |||
| 1b0a846a81 | |||
| f692be3637 | |||
| 127ad618d3 | |||
| 55218bcf78 | |||
| 2a47b514ec | |||
| 7d77bbf1bb | |||
| 97c136cd94 | |||
| d6cbd12d8b | |||
| c6244a8712 | |||
| eed68f2840 | |||
| 6080f51a0b | |||
| e0f07be017 | |||
| 42e1b9f17f | |||
| 0171617c1d | |||
| 2e11e9e65d | |||
| 4969526ef2 | |||
| d7b1c36fdd | |||
| 003fc96e8f | |||
| f68d11ccae | |||
| ed70c9dc2b | |||
| 157a753d87 | |||
| a5317c5640 | |||
| 66ceb64faa | |||
| fa4098db8d | |||
| c4c9e915f4 | |||
| e834527db2 | |||
| 23f130b0f9 | |||
| 0cb8c42497 | |||
| fe4b5e5e1f | |||
| 8ee9d66d80 | |||
| 7760d945bb | |||
| 1ac594bdf0 |
44
.github/workflows/static.yml
vendored
44
.github/workflows/static.yml
vendored
@ -1,44 +0,0 @@
|
||||
name: Static Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
static:
|
||||
if: github.event_name != 'schedule' || github.repository == 'pestphp/pest'
|
||||
name: Static Tests
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.2
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer update --prefer-stable --no-interaction --no-progress --ansi
|
||||
|
||||
# - name: Type Check
|
||||
# run: composer test:type:check
|
||||
|
||||
- name: Type Coverage
|
||||
run: composer test:type:coverage
|
||||
|
||||
- name: Refacto
|
||||
run: composer test:refacto
|
||||
|
||||
- name: Style
|
||||
run: composer test:lint
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
symfony: ['7.1']
|
||||
php: ['8.2', '8.3', '8.4']
|
||||
dependency_version: [prefer-lowest, prefer-stable]
|
||||
dependency_version: [prefer-stable]
|
||||
|
||||
name: PHP ${{ matrix.php }} - Symfony ^${{ matrix.symfony }} - ${{ matrix.os }} - ${{ matrix.dependency_version }}
|
||||
|
||||
|
||||
16
README.md
16
README.md
@ -15,8 +15,13 @@
|
||||
**Pest** is an elegant PHP testing Framework with a focus on simplicity, meticulously designed to bring back the joy of testing in PHP.
|
||||
|
||||
- Explore our docs at **[pestphp.com »](https://pestphp.com)**
|
||||
- Follow us on Twitter at **[@pestphp »](https://twitter.com/pestphp)**
|
||||
- Join us at **[discord.gg/kaHY6p54JH »](https://discord.gg/kaHY6p54JH)** or **[t.me/+kYH5G4d5MV83ODk0 »](https://t.me/+kYH5G4d5MV83ODk0)**
|
||||
- Follow the creator Nuno Maduro:
|
||||
- YouTube: **[youtube.com/@nunomaduro](https://www.youtube.com/@nunomaduro)** — Videos every weekday
|
||||
- Twitch: **[twitch.tv/enunomaduro](https://www.twitch.tv/enunomaduro)** — Streams (almost) every weekday
|
||||
- Twitter / X: **[x.com/enunomaduro](https://x.com/enunomaduro)**
|
||||
- LinkedIn: **[linkedin.com/in/nunomaduro](https://www.linkedin.com/in/nunomaduro)**
|
||||
- Instagram: **[instagram.com/enunomaduro](https://www.instagram.com/enunomaduro)**
|
||||
- Tiktok: **[tiktok.com/@enunomaduro](https://www.tiktok.com/@enunomaduro)**
|
||||
|
||||
## Sponsors
|
||||
|
||||
@ -30,16 +35,15 @@ We cannot thank our sponsors enough for their incredible support in funding Pest
|
||||
### Gold Sponsors
|
||||
|
||||
- **[CodeRabbit](https://coderabbit.ai/?ref=pestphp)**
|
||||
- **[LaraJobs](https://larajobs.com/?ref=pestphp)**
|
||||
- **[Brokerchooser](https://brokerchooser.com/?ref=pestphp)**
|
||||
- **[Forge](https://forge.laravel.com/?ref=pestphp)**
|
||||
- **[NativePHP](https://nativephp.com/mobile?ref=pestphp.com)**
|
||||
- **[CMS Max](https://cmsmax.com/?ref=pestphp)**
|
||||
|
||||
### Premium Sponsors
|
||||
|
||||
- [Akaunting](https://akaunting.com/?ref=pestphp)
|
||||
- [Codecourse](https://codecourse.com/?ref=pestphp)
|
||||
- [DocuWriter.ai](https://www.docuwriter.ai/?ref=pestphp)
|
||||
- [Localazy](https://localazy.com/?ref=pestphp)
|
||||
- [Forge](https://forge.laravel.com/?ref=pestphp)
|
||||
- [Route4Me](https://www.route4me.com/?ref=pestphp)
|
||||
- [Spatie](https://spatie.be/?ref=pestphp)
|
||||
- [Worksome](https://www.worksome.com/?ref=pestphp)
|
||||
|
||||
@ -18,17 +18,17 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.2.0",
|
||||
"brianium/paratest": "^7.7.0",
|
||||
"nunomaduro/collision": "^8.6.1",
|
||||
"nunomaduro/termwind": "^2.3.0",
|
||||
"brianium/paratest": "^7.8.5",
|
||||
"nunomaduro/collision": "^8.8.3",
|
||||
"nunomaduro/termwind": "^2.3.3",
|
||||
"pestphp/pest-plugin": "^3.0.0",
|
||||
"pestphp/pest-plugin-arch": "^3.0.0",
|
||||
"pestphp/pest-plugin-arch": "^3.1.1",
|
||||
"pestphp/pest-plugin-mutate": "^3.0.5",
|
||||
"phpunit/phpunit": "^11.5.3"
|
||||
"phpunit/phpunit": "^11.5.50"
|
||||
},
|
||||
"conflict": {
|
||||
"filp/whoops": "<2.16.0",
|
||||
"phpunit/phpunit": ">11.5.3",
|
||||
"phpunit/phpunit": ">11.5.50",
|
||||
"sebastian/exporter": "<6.0.0",
|
||||
"webmozart/assert": "<1.11.0"
|
||||
},
|
||||
@ -53,9 +53,9 @@
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest-dev-tools": "^3.3.0",
|
||||
"pestphp/pest-plugin-type-coverage": "^3.2.3",
|
||||
"symfony/process": "^7.2.0"
|
||||
"pestphp/pest-dev-tools": "^3.4.0",
|
||||
"pestphp/pest-plugin-type-coverage": "^3.6.1",
|
||||
"symfony/process": "^7.4.4"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
@ -71,21 +71,12 @@
|
||||
],
|
||||
"scripts": {
|
||||
"refacto": "rector",
|
||||
"lint": "pint",
|
||||
"test:refacto": "rector --dry-run",
|
||||
"test:lint": "pint --test",
|
||||
"test:type:check": "phpstan analyse --ansi --memory-limit=-1 --debug",
|
||||
"test:type:coverage": "php -d memory_limit=-1 bin/pest --type-coverage --min=100",
|
||||
"test:unit": "php bin/pest --colors=always --exclude-group=integration --compact",
|
||||
"test:inline": "php bin/pest --colors=always --configuration=phpunit.inline.xml",
|
||||
"test:parallel": "php bin/pest --colors=always --exclude-group=integration --parallel --processes=3",
|
||||
"test:integration": "php bin/pest --colors=always --group=integration -v",
|
||||
"update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always --update-snapshots",
|
||||
"test": [
|
||||
"@test:refacto",
|
||||
"@test:lint",
|
||||
"@test:type:check",
|
||||
"@test:type:coverage",
|
||||
"@test:unit",
|
||||
"@test:parallel",
|
||||
"@test:integration"
|
||||
|
||||
@ -27,6 +27,7 @@ use PHPUnit\Event\Test\Finished;
|
||||
use PHPUnit\Event\Test\MarkedIncomplete;
|
||||
use PHPUnit\Event\Test\PreparationStarted;
|
||||
use PHPUnit\Event\Test\Prepared;
|
||||
use PHPUnit\Event\Test\PrintedUnexpectedOutput;
|
||||
use PHPUnit\Event\Test\Skipped;
|
||||
use PHPUnit\Event\TestSuite\Started;
|
||||
use PHPUnit\Event\UnknownSubscriberTypeException;
|
||||
@ -41,6 +42,8 @@ use function str_replace;
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for PHPUnit
|
||||
*/
|
||||
final class JunitXmlLogger
|
||||
@ -59,32 +62,32 @@ final class JunitXmlLogger
|
||||
private array $testSuites = [];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteTests = [0];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteAssertions = [0];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteErrors = [0];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteFailures = [0];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteSkipped = [0];
|
||||
|
||||
/**
|
||||
* @psalm-var array<int,int>
|
||||
* @var array<int,int>
|
||||
*/
|
||||
private array $testSuiteTimes = [0];
|
||||
|
||||
@ -113,7 +116,7 @@ final class JunitXmlLogger
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
$this->printer->print($this->document->saveXML());
|
||||
$this->printer->print($this->document->saveXML() ?: '');
|
||||
|
||||
$this->printer->flush();
|
||||
}
|
||||
@ -195,28 +198,34 @@ final class JunitXmlLogger
|
||||
$this->createTestCase($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function testPreparationFailed(): void
|
||||
{
|
||||
$this->preparationFailed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function testPrepared(): void
|
||||
{
|
||||
$this->prepared = true;
|
||||
}
|
||||
|
||||
public function testPrintedUnexpectedOutput(PrintedUnexpectedOutput $event): void
|
||||
{
|
||||
assert($this->currentTestCase !== null);
|
||||
|
||||
$systemOut = $this->document->createElement(
|
||||
'system-out',
|
||||
Xml::prepareString($event->output()),
|
||||
);
|
||||
|
||||
$this->currentTestCase->appendChild($systemOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function testFinished(Finished $event): void
|
||||
{
|
||||
if ($this->preparationFailed) {
|
||||
if (! $this->prepared || $this->preparationFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -305,9 +314,11 @@ final class JunitXmlLogger
|
||||
new TestPreparationStartedSubscriber($this),
|
||||
new TestPreparationFailedSubscriber($this),
|
||||
new TestPreparedSubscriber($this),
|
||||
new TestPrintedUnexpectedOutputSubscriber($this),
|
||||
new TestFinishedSubscriber($this),
|
||||
new TestErroredSubscriber($this),
|
||||
new TestFailedSubscriber($this),
|
||||
new TestMarkedIncompleteSubscriber($this),
|
||||
new TestSkippedSubscriber($this),
|
||||
new TestRunnerExecutionFinishedSubscriber($this),
|
||||
);
|
||||
@ -431,7 +442,7 @@ final class JunitXmlLogger
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @psalm-assert !null $this->currentTestCase
|
||||
* @phpstan-assert !null $this->currentTestCase
|
||||
*/
|
||||
private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void
|
||||
{
|
||||
|
||||
@ -46,9 +46,10 @@ declare(strict_types=1);
|
||||
namespace PHPUnit\Runner\ResultCache;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const LOCK_EX;
|
||||
|
||||
use PHPUnit\Framework\TestStatus\TestStatus;
|
||||
use PHPUnit\Runner\DirectoryCannotBeCreatedException;
|
||||
use PHPUnit\Runner\DirectoryDoesNotExistException;
|
||||
use PHPUnit\Runner\Exception;
|
||||
use PHPUnit\Util\Filesystem;
|
||||
|
||||
@ -65,6 +66,8 @@ use function json_encode;
|
||||
use function Pest\version;
|
||||
|
||||
/**
|
||||
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
|
||||
*
|
||||
* @internal This class is not covered by the backward compatibility promise for PHPUnit
|
||||
*/
|
||||
final class DefaultResultCache implements ResultCache
|
||||
@ -77,12 +80,12 @@ final class DefaultResultCache implements ResultCache
|
||||
private readonly string $cacheFilename;
|
||||
|
||||
/**
|
||||
* @psalm-var array<string, TestStatus>
|
||||
* @var array<string, TestStatus>
|
||||
*/
|
||||
private array $defects = [];
|
||||
|
||||
/**
|
||||
* @psalm-var array<string, float>
|
||||
* @var array<string, float>
|
||||
*/
|
||||
private array $times = [];
|
||||
|
||||
@ -95,28 +98,39 @@ final class DefaultResultCache implements ResultCache
|
||||
$this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;
|
||||
}
|
||||
|
||||
public function setStatus(string $id, TestStatus $status): void
|
||||
public function setStatus(ResultCacheId $id, TestStatus $status): void
|
||||
{
|
||||
if ($status->isSuccess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->defects[$id] = $status;
|
||||
$this->defects[$id->asString()] = $status;
|
||||
}
|
||||
|
||||
public function status(string $id): TestStatus
|
||||
public function status(ResultCacheId $id): TestStatus
|
||||
{
|
||||
return $this->defects[$id] ?? TestStatus::unknown();
|
||||
return $this->defects[$id->asString()] ?? TestStatus::unknown();
|
||||
}
|
||||
|
||||
public function setTime(string $id, float $time): void
|
||||
public function setTime(ResultCacheId $id, float $time): void
|
||||
{
|
||||
$this->times[$id] = $time;
|
||||
$this->times[$id->asString()] = $time;
|
||||
}
|
||||
|
||||
public function time(string $id): float
|
||||
public function time(ResultCacheId $id): float
|
||||
{
|
||||
return $this->times[$id] ?? 0.0;
|
||||
return $this->times[$id->asString()] ?? 0.0;
|
||||
}
|
||||
|
||||
public function mergeWith(self $other): void
|
||||
{
|
||||
foreach ($other->defects as $id => $defect) {
|
||||
$this->defects[$id] = $defect;
|
||||
}
|
||||
|
||||
foreach ($other->times as $id => $time) {
|
||||
$this->times[$id] = $time;
|
||||
}
|
||||
}
|
||||
|
||||
public function load(): void
|
||||
@ -165,7 +179,7 @@ final class DefaultResultCache implements ResultCache
|
||||
public function persist(): void
|
||||
{
|
||||
if (! Filesystem::createDirectory(dirname($this->cacheFilename))) {
|
||||
throw new DirectoryCannotBeCreatedException($this->cacheFilename);
|
||||
throw new DirectoryDoesNotExistException(dirname($this->cacheFilename));
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
||||
199
phpstan-baseline.neon
Normal file
199
phpstan-baseline.neon
Normal file
@ -0,0 +1,199 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: '#^Parameter \#1 of callable callable\(Pest\\Expectation\<string\|null\>\)\: Pest\\Arch\\Contracts\\ArchExpectation expects Pest\\Expectation\<string\|null\>, Pest\\Expectation\<string\|null\> given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/ArchPresets/AbstractPreset.php
|
||||
|
||||
-
|
||||
message: '#^Trait Pest\\Concerns\\Expectable is used zero times and is not analysed\.$#'
|
||||
identifier: trait.unused
|
||||
count: 1
|
||||
path: src/Concerns/Expectable.php
|
||||
|
||||
-
|
||||
message: '#^Trait Pest\\Concerns\\Logging\\WritesToConsole is used zero times and is not analysed\.$#'
|
||||
identifier: trait.unused
|
||||
count: 1
|
||||
path: src/Concerns/Logging/WritesToConsole.php
|
||||
|
||||
-
|
||||
message: '#^Trait Pest\\Concerns\\Testable is used zero times and is not analysed\.$#'
|
||||
identifier: trait.unused
|
||||
count: 1
|
||||
path: src/Concerns/Testable.php
|
||||
|
||||
-
|
||||
message: '#^Loose comparison using \!\= between \(Closure\|null\) and false will always evaluate to false\.$#'
|
||||
identifier: notEqual.alwaysFalse
|
||||
count: 1
|
||||
path: src/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Method Pest\\Expectation\:\:and\(\) should return Pest\\Expectation\<TAndValue\> but returns \(Pest\\Expectation&TAndValue\)\|Pest\\Expectation\<TAndValue of mixed\>\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^PHPDoc tag @property for property Pest\\Expectation\:\:\$each contains generic class Pest\\Expectations\\EachExpectation but does not specify its types\: TValue$#'
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^PHPDoc tag @property for property Pest\\Expectation\:\:\$not contains generic class Pest\\Expectations\\OppositeExpectation but does not specify its types\: TValue$#'
|
||||
identifier: missingType.generics
|
||||
count: 1
|
||||
path: src/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#2 \$newScope of method Closure\:\:bindTo\(\) expects ''static''\|class\-string\|object\|null, string given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Function expect\(\) should return Pest\\Expectation\<TValue\|null\> but returns Pest\\Expectation\<TValue\|null\>\.$#'
|
||||
identifier: return.type
|
||||
count: 1
|
||||
path: src/Functions.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$argv of method PHPUnit\\TextUI\\Application\:\:run\(\) expects list\<string\>, array\<int, string\> given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Kernel.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method object&TValue of mixed\:\:__toString\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mixins/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method object&TValue of mixed\:\:toArray\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 4
|
||||
path: src/Mixins/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method object&TValue of mixed\:\:toSnapshot\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mixins/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method object&TValue of mixed\:\:toString\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mixins/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#'
|
||||
identifier: staticMethod.alreadyNarrowedType
|
||||
count: 2
|
||||
path: src/Mixins/Expectation.php
|
||||
|
||||
-
|
||||
message: '#^PHPDoc tag @var with type callable\(\)\: bool is not subtype of native type Closure\|null\.$#'
|
||||
identifier: varTag.nativeType
|
||||
count: 1
|
||||
path: src/PendingCalls/TestCall.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$argv of class Symfony\\Component\\Console\\Input\\ArgvInput constructor expects list\<string\>\|null, array\<int, string\> given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#13 \$testRunnerTriggeredDeprecationEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\TestRunner\\DeprecationTriggered\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#14 \$testRunnerTriggeredWarningEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\TestRunner\\WarningTriggered\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#15 \$errors of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#16 \$deprecations of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#17 \$notices of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#18 \$warnings of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#19 \$phpDeprecations of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#20 \$phpNotices of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#21 \$phpWarnings of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\TestRunner\\TestResult\\Issues\\Issue\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#4 \$testErroredEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\Test\\AfterLastTestMethodErrored\|PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored\|PHPUnit\\Event\\Test\\Errored\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#5 \$testFailedEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\Test\\Failed\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#7 \$testSuiteSkippedEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\TestSuite\\Skipped\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#8 \$testSkippedEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\Test\\Skipped\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#9 \$testMarkedIncompleteEvents of class PHPUnit\\TestRunner\\TestResult\\TestResult constructor expects list\<PHPUnit\\Event\\Test\\MarkedIncomplete\>, array given\.$#'
|
||||
identifier: argument.type
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
|
||||
-
|
||||
message: '#^Property Pest\\Plugins\\Parallel\\Paratest\\WrapperRunner\:\:\$pending \(list\<non\-empty\-string\>\) does not accept array\<int, non\-empty\-string\>\.$#'
|
||||
identifier: assign.propertyType
|
||||
count: 1
|
||||
path: src/Plugins/Parallel/Paratest/WrapperRunner.php
|
||||
@ -1,14 +1,12 @@
|
||||
includes:
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
- vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
|
||||
- phpstan-baseline.neon
|
||||
|
||||
parameters:
|
||||
level: max
|
||||
level: 7
|
||||
paths:
|
||||
- src
|
||||
|
||||
checkMissingIterableValueType: true
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
|
||||
ignoreErrors:
|
||||
- "#type mixed is not subtype of native#"
|
||||
|
||||
@ -35,7 +35,8 @@ final class Laravel extends AbstractPreset
|
||||
->ignoring('App\Features\Concerns');
|
||||
|
||||
$this->expectations[] = expect('App\Features')
|
||||
->toHaveMethod('resolve');
|
||||
->toHaveMethod('resolve')
|
||||
->ignoring('App\Features\Concerns');
|
||||
|
||||
$this->expectations[] = expect('App\Exceptions')
|
||||
->classes()
|
||||
@ -166,5 +167,11 @@ final class Laravel extends AbstractPreset
|
||||
$this->expectations[] = expect('App\Policies')
|
||||
->classes()
|
||||
->toHaveSuffix('Policy');
|
||||
|
||||
$this->expectations[] = expect('App\Attributes')
|
||||
->classes()
|
||||
->toImplement('Illuminate\Contracts\Container\ContextualAttribute')
|
||||
->toHaveAttribute('Attribute')
|
||||
->toHaveMethod('resolve');
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,8 +24,12 @@ final readonly class Thanks
|
||||
*/
|
||||
private const FUNDING_MESSAGES = [
|
||||
'Star' => 'https://github.com/pestphp/pest',
|
||||
'News' => 'https://twitter.com/pestphp',
|
||||
'Videos' => 'https://youtube.com/@nunomaduro',
|
||||
'YouTube' => 'https://youtube.com/@nunomaduro',
|
||||
'TikTok' => 'https://tiktok.com/@nunomaduro',
|
||||
'Twitch' => 'https://twitch.tv/enunomaduro',
|
||||
'LinkedIn' => 'https://linkedin.com/in/nunomaduro',
|
||||
'Instagram' => 'https://instagram.com/enunomaduro',
|
||||
'X' => 'https://x.com/enunomaduro',
|
||||
'Sponsor' => 'https://github.com/sponsors/nunomaduro',
|
||||
];
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ final class ShouldNotHappen extends RuntimeException
|
||||
$message = $exception->getMessage();
|
||||
|
||||
parent::__construct(sprintf(<<<'EOF'
|
||||
This should not happen - please create an new issue here: https://github.com/pestphp/pest.
|
||||
This should not happen - please create an new issue here: https://github.com/pestphp/pest/issues
|
||||
|
||||
Issue: %s
|
||||
PHP version: %s
|
||||
|
||||
@ -535,7 +535,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && $object->reflectionClass->isFinal(),
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isFinal(),
|
||||
'to be final',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -548,7 +548,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line
|
||||
'to be readonly',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -561,7 +561,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isTrait(),
|
||||
'to be trait',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -582,7 +582,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isAbstract(),
|
||||
'to be abstract',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -599,7 +599,7 @@ final class Expectation
|
||||
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => count(array_filter($methods, fn (string $method): bool => $object->reflectionClass->hasMethod($method))) === count($methods),
|
||||
fn (ObjectDescription $object): bool => count(array_filter($methods, fn (string $method): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod($method))) === count($methods),
|
||||
sprintf("to have method '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -670,7 +670,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isEnum(),
|
||||
'to be enum',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -712,7 +712,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isInterface(),
|
||||
'to be interface',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -733,7 +733,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $class === $object->reflectionClass->getName() || $object->reflectionClass->isSubclassOf($class),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && ($class === $object->reflectionClass->getName() || $object->reflectionClass->isSubclassOf($class)),
|
||||
sprintf("to extend '%s'", $class),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -773,6 +773,10 @@ final class Expectation
|
||||
$this,
|
||||
function (ObjectDescription $object) use ($traits): bool {
|
||||
foreach ($traits as $trait) {
|
||||
if (isset($object->reflectionClass) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
|
||||
return false;
|
||||
}
|
||||
@ -792,7 +796,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [],
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getInterfaceNames() === [],
|
||||
'to implement nothing',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -809,7 +813,8 @@ final class Expectation
|
||||
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => count($interfaces) === count($object->reflectionClass->getInterfaceNames())
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass)
|
||||
&& (count($interfaces) === count($object->reflectionClass->getInterfaceNames()))
|
||||
&& array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [],
|
||||
"to only implement '".implode("', '", $interfaces)."'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
@ -823,7 +828,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
"to have prefix '{$prefix}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -836,7 +841,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
"to have suffix '{$suffix}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -855,7 +860,7 @@ final class Expectation
|
||||
$this,
|
||||
function (ObjectDescription $object) use ($interfaces): bool {
|
||||
foreach ($interfaces as $interface) {
|
||||
if (! $object->reflectionClass->implementsInterface($interface)) {
|
||||
if (! isset($object->reflectionClass) || ! $object->reflectionClass->implementsInterface($interface)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -928,7 +933,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->hasMethod('__invoke'),
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod('__invoke'),
|
||||
'to be invokable',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||
);
|
||||
@ -1037,7 +1042,7 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) !== [],
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getAttributes($attribute) !== [],
|
||||
"to have attribute '{$attribute}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -1066,7 +1071,8 @@ final class Expectation
|
||||
{
|
||||
return Targeted::make(
|
||||
$this,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum()
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass)
|
||||
&& $object->reflectionClass->isEnum()
|
||||
&& (new ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|
||||
&& (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line
|
||||
'to be '.$backingType.' backed enum',
|
||||
|
||||
@ -74,7 +74,10 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toUse(array|string $targets): ArchExpectation
|
||||
{
|
||||
return GroupArchExpectation::fromExpectations($this->original, array_map(fn (string $target): SingleArchExpectation => ToUse::make($this->original, $target)->opposite(
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): SingleArchExpectation => ToUse::make($original, $target)->opposite(
|
||||
fn () => $this->throwExpectationFailedException('toUse', $target),
|
||||
), is_string($targets) ? [$targets] : $targets));
|
||||
}
|
||||
@ -84,8 +87,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) !== $permissions,
|
||||
sprintf('permissions not to be [%s]', $permissions),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||
@ -105,8 +111,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHaveMethodsDocumented(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||
|| array_filter(
|
||||
Reflection::getMethodsFromReflectionClass($object->reflectionClass),
|
||||
@ -124,8 +133,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHavePropertiesDocumented(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||
|| array_filter(
|
||||
Reflection::getPropertiesFromReflectionClass($object->reflectionClass),
|
||||
@ -144,8 +156,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toUseStrictTypes(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => ! (bool) preg_match('/^<\?php\s+declare\(.*?strict_types\s?=\s?1.*?\);/', (string) file_get_contents($object->path)),
|
||||
'not to use strict types',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||
@ -157,8 +172,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toUseStrictEquality(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$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, ' !== ')),
|
||||
@ -170,9 +188,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeFinal(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isFinal(),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isFinal()),
|
||||
'not to be final',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -183,9 +204,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeReadonly(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isReadOnly()) && assert(true), // @phpstan-ignore-line
|
||||
'not to be readonly',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -196,9 +220,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeTrait(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isTrait(),
|
||||
'not to be trait',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -217,9 +244,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeAbstract(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isAbstract(),
|
||||
'not to be abstract',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -234,11 +264,14 @@ final readonly class OppositeExpectation
|
||||
{
|
||||
$methods = is_array($method) ? $method : [$method];
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => array_filter(
|
||||
$methods,
|
||||
fn (string $method): bool => $object->reflectionClass->hasMethod($method),
|
||||
fn (string $method): bool => isset($object->reflectionClass) === false || $object->reflectionClass->hasMethod($method),
|
||||
) === [],
|
||||
'to not have methods: '.implode(', ', $methods),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
@ -266,8 +299,11 @@ final readonly class OppositeExpectation
|
||||
|
||||
$state = new stdClass;
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)
|
||||
@ -286,7 +322,7 @@ final readonly class OppositeExpectation
|
||||
$methods === []
|
||||
? 'not to have public methods'
|
||||
: sprintf("not to have public methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, $state->contains)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -309,8 +345,11 @@ final readonly class OppositeExpectation
|
||||
|
||||
$state = new stdClass;
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)
|
||||
@ -329,7 +368,7 @@ final readonly class OppositeExpectation
|
||||
$methods === []
|
||||
? 'not to have protected methods'
|
||||
: sprintf("not to have protected methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, $state->contains)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -352,8 +391,11 @@ final readonly class OppositeExpectation
|
||||
|
||||
$state = new stdClass;
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||
$reflectionMethods = isset($object->reflectionClass)
|
||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)
|
||||
@ -372,7 +414,7 @@ final readonly class OppositeExpectation
|
||||
$methods === []
|
||||
? 'not to have private methods'
|
||||
: sprintf("not to have private methods besides '%s'", implode("', '", $methods)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, $state->contains)),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -389,9 +431,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeEnum(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isEnum(),
|
||||
'not to be enum',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -410,8 +455,11 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeClass(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => ! class_exists($object->name),
|
||||
'not to be class',
|
||||
FileLineFinder::where(fn (string $line): bool => true),
|
||||
@ -431,9 +479,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeInterface(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isInterface(),
|
||||
'not to be interface',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -452,9 +503,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toExtend(string $class): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isSubclassOf($class),
|
||||
sprintf("not to extend '%s'", $class),
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -465,9 +519,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toExtendNothing(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false,
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getParentClass() !== false,
|
||||
'to extend a class',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -490,11 +547,14 @@ final readonly class OppositeExpectation
|
||||
{
|
||||
$traits = is_array($traits) ? $traits : [$traits];
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
function (ObjectDescription $object) use ($traits): bool {
|
||||
foreach ($traits as $trait) {
|
||||
if (in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
|
||||
if (isset($object->reflectionClass) && in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -515,11 +575,14 @@ final readonly class OppositeExpectation
|
||||
{
|
||||
$interfaces = is_array($interfaces) ? $interfaces : [$interfaces];
|
||||
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
$original,
|
||||
function (ObjectDescription $object) use ($interfaces): bool {
|
||||
foreach ($interfaces as $interface) {
|
||||
if ($object->reflectionClass->implementsInterface($interface)) {
|
||||
if (isset($object->reflectionClass) && $object->reflectionClass->implementsInterface($interface)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -536,9 +599,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toImplementNothing(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [],
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getInterfaceNames() !== [],
|
||||
'to implement an interface',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -557,9 +623,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHavePrefix(string $prefix): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||
"not to have prefix '{$prefix}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -570,9 +639,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHaveSuffix(string $suffix): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||
"not to have suffix '{$suffix}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||
);
|
||||
@ -599,7 +671,10 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeUsed(): ArchExpectation
|
||||
{
|
||||
return ToBeUsedInNothing::make($this->original);
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return ToBeUsedInNothing::make($original);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -609,7 +684,10 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeUsedIn(array|string $targets): ArchExpectation
|
||||
{
|
||||
return GroupArchExpectation::fromExpectations($this->original, array_map(fn (string $target): GroupArchExpectation => ToBeUsedIn::make($this->original, $target)->opposite(
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): GroupArchExpectation => ToBeUsedIn::make($original, $target)->opposite(
|
||||
fn () => $this->throwExpectationFailedException('toBeUsedIn', $target),
|
||||
), is_string($targets) ? [$targets] : $targets));
|
||||
}
|
||||
@ -632,9 +710,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toBeInvokable(): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->hasMethod('__invoke'),
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->hasMethod('__invoke'),
|
||||
'to not be invokable',
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||
);
|
||||
@ -645,9 +726,12 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
public function toHaveAttribute(string $attribute): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) === [],
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getAttributes($attribute) === [],
|
||||
"to not have attribute '{$attribute}'",
|
||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||
);
|
||||
@ -737,9 +821,13 @@ final readonly class OppositeExpectation
|
||||
*/
|
||||
private function toBeBackedEnum(string $backingType): ArchExpectation
|
||||
{
|
||||
/** @var Expectation<array<int, string>|string> $original */
|
||||
$original = $this->original;
|
||||
|
||||
return Targeted::make(
|
||||
$this->original,
|
||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum()
|
||||
$original,
|
||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||
|| ! $object->reflectionClass->isEnum()
|
||||
|| ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|
||||
|| (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line
|
||||
'not to be '.$backingType.' backed enum',
|
||||
|
||||
@ -155,7 +155,7 @@ final class TestCaseMethodFactory
|
||||
assert($testCase instanceof TestCaseFactory);
|
||||
$method = $this;
|
||||
|
||||
return function (...$arguments) use ($testCase, $method, $closure): mixed { // @phpstan-ignore-line
|
||||
return function (...$arguments) use ($testCase, $method, $closure): mixed {
|
||||
/* @var TestCase $this */
|
||||
$testCase->proxies->proxy($this);
|
||||
$method->proxies->proxy($this);
|
||||
|
||||
@ -232,7 +232,6 @@ final class TeamCityLogger
|
||||
$reflector = new ReflectionClass($telemetry);
|
||||
|
||||
$property = $reflector->getProperty('current');
|
||||
$property->setAccessible(true);
|
||||
$snapshot = $property->getValue($telemetry);
|
||||
assert($snapshot instanceof Snapshot);
|
||||
|
||||
|
||||
@ -183,7 +183,6 @@ final class Expectation
|
||||
{
|
||||
foreach ($needles as $needle) {
|
||||
if (is_string($this->value)) {
|
||||
// @phpstan-ignore-next-line
|
||||
Assert::assertStringContainsString((string) $needle, $this->value);
|
||||
} else {
|
||||
if (! is_iterable($this->value)) {
|
||||
|
||||
@ -46,7 +46,7 @@ final readonly class Panic
|
||||
{
|
||||
try {
|
||||
$output = Container::getInstance()->get(OutputInterface::class);
|
||||
} catch (Throwable) { // @phpstan-ignore-line
|
||||
} catch (Throwable) {
|
||||
$output = new ConsoleOutput;
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ final class DescribeCall
|
||||
$this->currentBeforeEachCall->describing[] = $this->description;
|
||||
}
|
||||
|
||||
$this->currentBeforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line
|
||||
$this->currentBeforeEachCall->{$name}(...$arguments);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ final class TestCall // @phpstan-ignore-line
|
||||
*/
|
||||
public function only(): self
|
||||
{
|
||||
Only::enable($this, ...func_get_args()); // @phpstan-ignore-line
|
||||
Only::enable($this, ...func_get_args());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace Pest;
|
||||
|
||||
function version(): string
|
||||
{
|
||||
return '3.7.4';
|
||||
return '3.8.5';
|
||||
}
|
||||
|
||||
function testDirectory(string $file = ''): string
|
||||
|
||||
@ -119,6 +119,6 @@ final readonly class Init implements HandlesArguments
|
||||
*/
|
||||
private function isLaravelInstalled(): bool
|
||||
{
|
||||
return InstalledVersions::isInstalled('laravel/laravel');
|
||||
return InstalledVersions::isInstalled('laravel/framework');
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ final class DatasetsRepository
|
||||
*
|
||||
* @throws ShouldNotHappen
|
||||
*/
|
||||
public static function get(string $filename, string $description): Closure|array
|
||||
public static function get(string $filename, string $description): Closure|array // @phpstan-ignore-line
|
||||
{
|
||||
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
|
||||
|
||||
@ -110,7 +110,6 @@ final class DatasetsRepository
|
||||
foreach ($datasetCombination as $datasetCombinationElement) {
|
||||
$partialDescriptions[] = $datasetCombinationElement['label'];
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$values = array_merge($values, $datasetCombinationElement['values']);
|
||||
}
|
||||
|
||||
@ -221,7 +220,6 @@ final class DatasetsRepository
|
||||
$result = $tmp;
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
@ -19,8 +19,8 @@ final class SnapshotRepository
|
||||
* Creates a snapshot repository instance.
|
||||
*/
|
||||
public function __construct(
|
||||
readonly private string $testsPath,
|
||||
readonly private string $snapshotsPath,
|
||||
private readonly string $testsPath,
|
||||
private readonly string $snapshotsPath,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
||||
@ -40,7 +40,7 @@ final class Result
|
||||
*/
|
||||
public static function exitCode(Configuration $configuration, TestResult $result): int
|
||||
{
|
||||
if ($result->wasSuccessfulIgnoringPhpunitWarnings()) {
|
||||
if ($result->wasSuccessful()) {
|
||||
if ($configuration->failOnWarning()) {
|
||||
$warnings = $result->numberOfTestsWithTestTriggeredPhpunitWarningEvents()
|
||||
+ count($result->warnings())
|
||||
@ -60,7 +60,7 @@ final class Result
|
||||
return self::FAILURE_EXIT;
|
||||
}
|
||||
|
||||
if ($result->wasSuccessfulIgnoringPhpunitWarnings()) {
|
||||
if ($result->wasSuccessful()) {
|
||||
if ($configuration->failOnRisky() && $result->hasTestConsideredRiskyEvents()) {
|
||||
$returnCode = self::FAILURE_EXIT;
|
||||
}
|
||||
|
||||
@ -23,14 +23,12 @@ final class EnsureIgnorableTestCasesAreIgnored implements StartedSubscriber
|
||||
{
|
||||
$reflection = new ReflectionClass(Facade::class);
|
||||
$property = $reflection->getProperty('collector');
|
||||
$property->setAccessible(true);
|
||||
$collector = $property->getValue();
|
||||
|
||||
assert($collector instanceof Collector);
|
||||
|
||||
$reflection = new ReflectionClass($collector);
|
||||
$property = $reflection->getProperty('testRunnerTriggeredWarningEvents');
|
||||
$property->setAccessible(true);
|
||||
|
||||
/** @var array<int, WarningTriggered> $testRunnerTriggeredWarningEvents */
|
||||
$testRunnerTriggeredWarningEvents = $property->getValue($collector);
|
||||
|
||||
@ -15,7 +15,6 @@ final class Closure
|
||||
/**
|
||||
* Binds the given closure to the given "this".
|
||||
*
|
||||
*
|
||||
* @throws ShouldNotHappen
|
||||
*/
|
||||
public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure
|
||||
@ -24,6 +23,7 @@ final class Closure
|
||||
throw ShouldNotHappen::fromMessage('Could not bind null closure.');
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$closure = BaseClosure::bind($closure, $newThis, $newScope);
|
||||
|
||||
if (! $closure instanceof \Closure) {
|
||||
|
||||
@ -66,6 +66,7 @@ final readonly class Exporter
|
||||
|
||||
$result[] = $context->contains($data[$key]) !== false
|
||||
? '*RECURSION*'
|
||||
// @phpstan-ignore-next-line
|
||||
: sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context));
|
||||
}
|
||||
|
||||
|
||||
@ -50,14 +50,13 @@ final class HigherOrderMessage
|
||||
}
|
||||
|
||||
if ($this->hasHigherOrderCallable()) {
|
||||
/* @phpstan-ignore-next-line */
|
||||
return (new HigherOrderCallables($target))->{$this->name}(...$this->arguments);
|
||||
}
|
||||
|
||||
try {
|
||||
return is_array($this->arguments)
|
||||
? Reflection::call($target, $this->name, $this->arguments)
|
||||
: $target->{$this->name}; /* @phpstan-ignore-line */
|
||||
: $target->{$this->name};
|
||||
} catch (Throwable $throwable) {
|
||||
Reflection::setPropertyValue($throwable, 'file', $this->filename);
|
||||
Reflection::setPropertyValue($throwable, 'line', $this->line);
|
||||
@ -65,7 +64,6 @@ final class HigherOrderMessage
|
||||
if ($throwable->getMessage() === $this->getUndefinedMethodMessage($target, $this->name)) {
|
||||
/** @var ReflectionClass<TValue> $reflection */
|
||||
$reflection = new ReflectionClass($target);
|
||||
/* @phpstan-ignore-next-line */
|
||||
$reflection = $reflection->getParentClass() ?: $reflection;
|
||||
Reflection::setPropertyValue($throwable, 'message', sprintf('Call to undefined method %s::%s()', $reflection->getName(), $this->name));
|
||||
}
|
||||
@ -96,10 +94,6 @@ final class HigherOrderMessage
|
||||
|
||||
private function getUndefinedMethodMessage(object $target, string $methodName): string
|
||||
{
|
||||
if (\PHP_MAJOR_VERSION >= 8) {
|
||||
return sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', $target::class, $methodName));
|
||||
}
|
||||
|
||||
return sprintf(self::UNDEFINED_METHOD, $methodName);
|
||||
return sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', $target::class, $methodName));
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,6 @@ final class HigherOrderMessageCollection
|
||||
public function chain(object $target): void
|
||||
{
|
||||
foreach ($this->messages as $message) {
|
||||
// @phpstan-ignore-next-line
|
||||
$target = $message->call($target) ?? $target;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ final class HigherOrderTapProxy
|
||||
*/
|
||||
public function __set(string $property, mixed $value): void
|
||||
{
|
||||
$this->target->{$property} = $value; // @phpstan-ignore-line
|
||||
$this->target->{$property} = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +37,7 @@ final class HigherOrderTapProxy
|
||||
public function __get(string $property)
|
||||
{
|
||||
if (property_exists($this->target, $property)) {
|
||||
return $this->target->{$property}; // @phpstan-ignore-line
|
||||
return $this->target->{$property};
|
||||
}
|
||||
|
||||
$className = (new ReflectionClass($this->target))->getName();
|
||||
|
||||
@ -34,8 +34,6 @@ final class Reflection
|
||||
try {
|
||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||
|
||||
$reflectionMethod->setAccessible(true);
|
||||
|
||||
return $reflectionMethod->invoke($object, ...$args);
|
||||
} catch (ReflectionException $exception) {
|
||||
if (method_exists($object, '__call')) {
|
||||
@ -113,8 +111,6 @@ final class Reflection
|
||||
}
|
||||
}
|
||||
|
||||
$reflectionProperty->setAccessible(true);
|
||||
|
||||
return $reflectionProperty->getValue($object);
|
||||
}
|
||||
|
||||
@ -144,8 +140,6 @@ final class Reflection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($object, $value);
|
||||
}
|
||||
|
||||
|
||||
@ -1,31 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
<directory>tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
<directory>tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory>app</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_DRIVER" value="array"/>
|
||||
<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>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">./app</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
|
||||
*/
|
||||
|
||||
// pest()->extend(Tests\TestCase::class)->in('Feature');
|
||||
pest()->extend(Tests\TestCase::class)->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
@ -11,8 +11,8 @@
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">./app</directory>
|
||||
<directory suffix=".php">./src</directory>
|
||||
<directory>app</directory>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
Pest Testing Framework 3.7.4.
|
||||
Pest Testing Framework 3.8.5.
|
||||
|
||||
USAGE: pest <file> [options]
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
--disallow-test-output ................. Be strict about output during tests
|
||||
--enforce-time-limit ................. Enforce time limit based on test size
|
||||
--default-time-limit [sec] Timeout in seconds for tests that have no declared size
|
||||
--dont-report-useless-tests .. Do not report tests that do not test anything
|
||||
--do-not-report-useless-tests Do not report tests that do not test anything
|
||||
--stop-on-defect ... Stop after first error, failure, warning, or risky test
|
||||
--stop-on-error ..................................... Stop after first error
|
||||
--stop-on-failure ................................. Stop after first failure
|
||||
@ -68,9 +68,20 @@
|
||||
--fail-on-risky Signal failure using shell exit code when a test was considered risky
|
||||
--fail-on-deprecation Signal failure using shell exit code when a deprecation was triggered
|
||||
--fail-on-phpunit-deprecation Signal failure using shell exit code when a PHPUnit deprecation was triggered
|
||||
--fail-on-phpunit-warning Signal failure using shell exit code when a PHPUnit warning was triggered
|
||||
--fail-on-notice Signal failure using shell exit code when a notice was triggered
|
||||
--fail-on-skipped Signal failure using shell exit code when a test was skipped
|
||||
--fail-on-incomplete Signal failure using shell exit code when a test was marked incomplete
|
||||
--fail-on-all-issues Signal failure using shell exit code when an issue is triggered
|
||||
--do-not-fail-on-empty-test-suite Do not signal failure using shell exit code when no tests were run
|
||||
--do-not-fail-on-warning Do not signal failure using shell exit code when a warning was triggered
|
||||
--do-not-fail-on-risky Do not signal failure using shell exit code when a test was considered risky
|
||||
--do-not-fail-on-deprecation Do not signal failure using shell exit code when a deprecation was triggered
|
||||
--do-not-fail-on-phpunit-deprecation Do not signal failure using shell exit code when a PHPUnit deprecation was triggered
|
||||
--do-not-fail-on-phpunit-warning Do not signal failure using shell exit code when a PHPUnit warning was triggered
|
||||
--do-not-fail-on-notice Do not signal failure using shell exit code when a notice was triggered
|
||||
--do-not-fail-on-skipped Do not signal failure using shell exit code when a test was skipped
|
||||
--do-not-fail-on-incomplete Do not signal failure using shell exit code when a test was marked incomplete
|
||||
--cache-result ............................ Write test results to cache file
|
||||
--do-not-cache-result .............. Do not write test results to cache file
|
||||
--order-by [order] Run tests in order: default|defects|depends|duration|no-depends|random|reverse|size
|
||||
@ -91,6 +102,7 @@
|
||||
--display-errors ............. Display details for errors triggered by tests
|
||||
--display-notices ........... Display details for notices triggered by tests
|
||||
--display-warnings ......... Display details for warnings triggered by tests
|
||||
--display-all-issues ..... Display details for all issues that are triggered
|
||||
--reverse-list .............................. Print defects in reverse order
|
||||
--teamcity . Replace default progress and result output with TeamCity format
|
||||
--testdox ................ Replace default result output with TestDox format
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
|
||||
Pest Testing Framework 3.7.4.
|
||||
Pest Testing Framework 3.8.5.
|
||||
|
||||
|
||||
@ -1428,16 +1428,6 @@
|
||||
PASS Tests\Hooks\BeforeEachTest
|
||||
✓ global beforeEach execution order
|
||||
|
||||
PASS Tests\Overrides\VersionsTest
|
||||
✓ versions with dataset "Runner/Filter/NameFilterIterator.php"
|
||||
✓ versions with dataset "Runner/ResultCache/DefaultResultCache.php"
|
||||
✓ versions with dataset "Runner/TestSuiteLoader.php"
|
||||
✓ versions with dataset "TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php"
|
||||
✓ versions with dataset "TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php"
|
||||
✓ versions with dataset "TextUI/TestSuiteFilterProcessor.php"
|
||||
✓ versions with dataset "Event/Value/ThrowableBuilder.php"
|
||||
✓ versions with dataset "Logging/JUnit/JunitXmlLogger.php"
|
||||
|
||||
PASS Tests\PHPUnit\CustomAffixes\InvalidTestName
|
||||
✓ it runs file names like @#$%^&()-_=+.php
|
||||
|
||||
@ -1708,4 +1698,4 @@
|
||||
WARN Tests\Visual\Version
|
||||
- visual snapshot of help command output
|
||||
|
||||
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 38 todos, 33 skipped, 1152 passed (2744 assertions)
|
||||
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 38 todos, 33 skipped, 1144 passed (2736 assertions)
|
||||
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Pest\Bootstrappers\BootOverrides;
|
||||
|
||||
test('versions', function (string $vendorPath, string $expectedHash) {
|
||||
expect(hash_file('sha256', $vendorPath))->toBe($expectedHash);
|
||||
})->with(function () {
|
||||
foreach (BootOverrides::FILES as $hash => $file) {
|
||||
$path = implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__, 2),
|
||||
'vendor/phpunit/phpunit/src',
|
||||
$file,
|
||||
]);
|
||||
yield $file => [$path, $hash];
|
||||
}
|
||||
});
|
||||
@ -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, 38 todos, 24 skipped, 1142 passed (2720 assertions)')
|
||||
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 38 todos, 24 skipped, 1134 passed (2712 assertions)')
|
||||
->toContain('Parallel: 3 processes');
|
||||
})->skipOnWindows();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user