mirror of
https://github.com/pestphp/pest.git
synced 2026-03-11 10:17:23 +01:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8871a6f5ef | |||
| e4b6fc08b6 | |||
| 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 | |||
| 4a987d3d5c | |||
| 4079a08f5f | |||
| e4aab77a34 | |||
| c4c9e915f4 | |||
| e834527db2 | |||
| 23f130b0f9 | |||
| 0cb8c42497 | |||
| fe4b5e5e1f | |||
| 8ee9d66d80 | |||
| 7760d945bb | |||
| 709ecb1ba2 | |||
| 6afb36519d | |||
| 150bb9478d | |||
| bf3178473d | |||
| d2eb94d723 | |||
| 9688b83a3d | |||
| 675372c794 | |||
| c18636b3d5 | |||
| 1ac594bdf0 | |||
| 145294a4a3 | |||
| c2cabaeae6 |
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]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
symfony: ['7.1']
|
symfony: ['7.1']
|
||||||
php: ['8.2', '8.3', '8.4']
|
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 }}
|
name: PHP ${{ matrix.php }} - Symfony ^${{ matrix.symfony }} - ${{ matrix.os }} - ${{ matrix.dependency_version }}
|
||||||
|
|
||||||
|
|||||||
28
README.md
28
README.md
@ -15,30 +15,38 @@
|
|||||||
**Pest** is an elegant PHP testing Framework with a focus on simplicity, meticulously designed to bring back the joy of testing in PHP.
|
**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)**
|
- Explore our docs at **[pestphp.com »](https://pestphp.com)**
|
||||||
- Follow us on Twitter at **[@pestphp »](https://twitter.com/pestphp)**
|
- Follow the creator Nuno Maduro:
|
||||||
- Join us at **[discord.gg/kaHY6p54JH »](https://discord.gg/kaHY6p54JH)** or **[t.me/+kYH5G4d5MV83ODk0 »](https://t.me/+kYH5G4d5MV83ODk0)**
|
- 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
|
## Sponsors
|
||||||
|
|
||||||
We cannot thank our sponsors enough for their incredible support in funding Pest's development. Their contributions have been instrumental in making Pest the best it can be. For those who are interested in becoming a sponsor, please visit Nuno Maduro's Sponsor page at **[github.com/sponsors/nunomaduro](https://github.com/sponsors/nunomaduro)**.
|
We cannot thank our sponsors enough for their incredible support in funding Pest's development. Their contributions have been instrumental in making Pest the best it can be. For those who are interested in becoming a sponsor, please visit Nuno Maduro's Sponsor page at **[github.com/sponsors/nunomaduro](https://github.com/sponsors/nunomaduro)**.
|
||||||
|
|
||||||
|
|
||||||
### Platinum Sponsors
|
### Platinum Sponsors
|
||||||
|
|
||||||
- **[CodeRabbit](https://coderabbit.ai)**
|
- **[Laracasts](https://laracasts.com/?ref=pestphp)**
|
||||||
- **[LaraJobs](https://larajobs.com)**
|
|
||||||
- **[Brokerchooser](https://brokerchooser.com)**
|
### Gold Sponsors
|
||||||
- **[Forge](https://forge.laravel.com)**
|
|
||||||
|
- **[CodeRabbit](https://coderabbit.ai/?ref=pestphp)**
|
||||||
|
- **[NativePHP](https://nativephp.com/mobile?ref=pestphp.com)**
|
||||||
|
- **[CMS Max](https://cmsmax.com/?ref=pestphp)**
|
||||||
|
|
||||||
### Premium Sponsors
|
### Premium Sponsors
|
||||||
|
|
||||||
- [Akaunting](https://akaunting.com/?ref=pestphp)
|
- [Akaunting](https://akaunting.com/?ref=pestphp)
|
||||||
- [Codecourse](https://codecourse.com/?ref=pestphp)
|
|
||||||
- [DocuWriter.ai](https://www.docuwriter.ai/?ref=pestphp)
|
- [DocuWriter.ai](https://www.docuwriter.ai/?ref=pestphp)
|
||||||
- [Laracasts](https://laracasts.com/?ref=pestphp)
|
|
||||||
- [Localazy](https://localazy.com/?ref=pestphp)
|
- [Localazy](https://localazy.com/?ref=pestphp)
|
||||||
|
- [Forge](https://forge.laravel.com/?ref=pestphp)
|
||||||
- [Route4Me](https://www.route4me.com/?ref=pestphp)
|
- [Route4Me](https://www.route4me.com/?ref=pestphp)
|
||||||
- [Spatie](https://spatie.be)
|
- [Spatie](https://spatie.be/?ref=pestphp)
|
||||||
- [Worksome](https://www.worksome.com/)
|
- [Worksome](https://www.worksome.com/?ref=pestphp)
|
||||||
- [Zapiet](https://www.zapiet.com/?ref=pestphp)
|
- [Zapiet](https://www.zapiet.com/?ref=pestphp)
|
||||||
|
|
||||||
Pest is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
Pest is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
||||||
|
|||||||
@ -32,10 +32,13 @@ $bootPest = (static function (): void {
|
|||||||
'status-file:',
|
'status-file:',
|
||||||
'progress-file:',
|
'progress-file:',
|
||||||
'unexpected-output-file:',
|
'unexpected-output-file:',
|
||||||
'testresult-file:',
|
'test-result-file:',
|
||||||
|
'result-cache-file:',
|
||||||
'teamcity-file:',
|
'teamcity-file:',
|
||||||
'testdox-file:',
|
'testdox-file:',
|
||||||
'testdox-color',
|
'testdox-color',
|
||||||
|
'testdox-columns:',
|
||||||
|
'testdox-summary',
|
||||||
'phpunit-argv:',
|
'phpunit-argv:',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -61,7 +64,8 @@ $bootPest = (static function (): void {
|
|||||||
|
|
||||||
assert(isset($getopt['progress-file']) && is_string($getopt['progress-file']));
|
assert(isset($getopt['progress-file']) && is_string($getopt['progress-file']));
|
||||||
assert(isset($getopt['unexpected-output-file']) && is_string($getopt['unexpected-output-file']));
|
assert(isset($getopt['unexpected-output-file']) && is_string($getopt['unexpected-output-file']));
|
||||||
assert(isset($getopt['testresult-file']) && is_string($getopt['testresult-file']));
|
assert(isset($getopt['test-result-file']) && is_string($getopt['test-result-file']));
|
||||||
|
assert(! isset($getopt['result-cache-file']) || is_string($getopt['result-cache-file']));
|
||||||
assert(! isset($getopt['teamcity-file']) || is_string($getopt['teamcity-file']));
|
assert(! isset($getopt['teamcity-file']) || is_string($getopt['teamcity-file']));
|
||||||
assert(! isset($getopt['testdox-file']) || is_string($getopt['testdox-file']));
|
assert(! isset($getopt['testdox-file']) || is_string($getopt['testdox-file']));
|
||||||
|
|
||||||
@ -77,7 +81,8 @@ $bootPest = (static function (): void {
|
|||||||
$phpunitArgv,
|
$phpunitArgv,
|
||||||
$getopt['progress-file'],
|
$getopt['progress-file'],
|
||||||
$getopt['unexpected-output-file'],
|
$getopt['unexpected-output-file'],
|
||||||
$getopt['testresult-file'],
|
$getopt['test-result-file'],
|
||||||
|
$getopt['result-cache-file'] ?? null,
|
||||||
$getopt['teamcity-file'] ?? null,
|
$getopt['teamcity-file'] ?? null,
|
||||||
$getopt['testdox-file'] ?? null,
|
$getopt['testdox-file'] ?? null,
|
||||||
isset($getopt['testdox-color']),
|
isset($getopt['testdox-color']),
|
||||||
|
|||||||
@ -18,17 +18,17 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2.0",
|
"php": "^8.2.0",
|
||||||
"brianium/paratest": "^7.6.0",
|
"brianium/paratest": "^7.8.5",
|
||||||
"nunomaduro/collision": "^8.5.0",
|
"nunomaduro/collision": "^8.9.1",
|
||||||
"nunomaduro/termwind": "^2.3.0",
|
"nunomaduro/termwind": "^2.4.0",
|
||||||
"pestphp/pest-plugin": "^3.0.0",
|
"pestphp/pest-plugin": "^3.0.0",
|
||||||
"pestphp/pest-plugin-arch": "^3.0.0",
|
"pestphp/pest-plugin-arch": "^3.1.1",
|
||||||
"pestphp/pest-plugin-mutate": "^3.0.5",
|
"pestphp/pest-plugin-mutate": "^3.0.5",
|
||||||
"phpunit/phpunit": "^11.4.4"
|
"phpunit/phpunit": "^11.5.50"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"filp/whoops": "<2.16.0",
|
"filp/whoops": "<2.16.0",
|
||||||
"phpunit/phpunit": ">11.4.4",
|
"phpunit/phpunit": ">11.5.50",
|
||||||
"sebastian/exporter": "<6.0.0",
|
"sebastian/exporter": "<6.0.0",
|
||||||
"webmozart/assert": "<1.11.0"
|
"webmozart/assert": "<1.11.0"
|
||||||
},
|
},
|
||||||
@ -53,9 +53,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"pestphp/pest-dev-tools": "^3.3.0",
|
"pestphp/pest-dev-tools": "^3.4.0",
|
||||||
"pestphp/pest-plugin-type-coverage": "^3.2.0",
|
"pestphp/pest-plugin-type-coverage": "^3.6.1",
|
||||||
"symfony/process": "^7.1.8"
|
"symfony/process": "^7.4.5"
|
||||||
},
|
},
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
@ -71,21 +71,12 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"refacto": "rector",
|
"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:unit": "php bin/pest --colors=always --exclude-group=integration --compact",
|
||||||
"test:inline": "php bin/pest --colors=always --configuration=phpunit.inline.xml",
|
"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:parallel": "php bin/pest --colors=always --exclude-group=integration --parallel --processes=3",
|
||||||
"test:integration": "php bin/pest --colors=always --group=integration -v",
|
"test:integration": "php bin/pest --colors=always --group=integration -v",
|
||||||
"update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always --update-snapshots",
|
"update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always --update-snapshots",
|
||||||
"test": [
|
"test": [
|
||||||
"@test:refacto",
|
|
||||||
"@test:lint",
|
|
||||||
"@test:type:check",
|
|
||||||
"@test:type:coverage",
|
|
||||||
"@test:unit",
|
"@test:unit",
|
||||||
"@test:parallel",
|
"@test:parallel",
|
||||||
"@test:integration"
|
"@test:integration"
|
||||||
|
|||||||
@ -68,7 +68,7 @@ final readonly class ThrowableBuilder
|
|||||||
$previous = self::from($previous);
|
$previous = self::from($previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
$trace = Filter::getFilteredStacktrace($t);
|
$trace = Filter::stackTraceFromThrowableAsString($t);
|
||||||
|
|
||||||
if ($t instanceof RenderableOnCollisionEditor && $frame = $t->toCollisionEditor()) {
|
if ($t instanceof RenderableOnCollisionEditor && $frame = $t->toCollisionEditor()) {
|
||||||
$file = $frame->getFile();
|
$file = $frame->getFile();
|
||||||
|
|||||||
@ -14,6 +14,9 @@ namespace PHPUnit\Logging\JUnit;
|
|||||||
|
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
|
use Pest\Logging\Converter;
|
||||||
|
use Pest\Support\Container;
|
||||||
|
use Pest\TestSuite;
|
||||||
use PHPUnit\Event\Code\Test;
|
use PHPUnit\Event\Code\Test;
|
||||||
use PHPUnit\Event\Code\TestMethod;
|
use PHPUnit\Event\Code\TestMethod;
|
||||||
use PHPUnit\Event\EventFacadeIsSealedException;
|
use PHPUnit\Event\EventFacadeIsSealedException;
|
||||||
@ -27,6 +30,7 @@ use PHPUnit\Event\Test\Finished;
|
|||||||
use PHPUnit\Event\Test\MarkedIncomplete;
|
use PHPUnit\Event\Test\MarkedIncomplete;
|
||||||
use PHPUnit\Event\Test\PreparationStarted;
|
use PHPUnit\Event\Test\PreparationStarted;
|
||||||
use PHPUnit\Event\Test\Prepared;
|
use PHPUnit\Event\Test\Prepared;
|
||||||
|
use PHPUnit\Event\Test\PrintedUnexpectedOutput;
|
||||||
use PHPUnit\Event\Test\Skipped;
|
use PHPUnit\Event\Test\Skipped;
|
||||||
use PHPUnit\Event\TestSuite\Started;
|
use PHPUnit\Event\TestSuite\Started;
|
||||||
use PHPUnit\Event\UnknownSubscriberTypeException;
|
use PHPUnit\Event\UnknownSubscriberTypeException;
|
||||||
@ -41,13 +45,15 @@ use function str_replace;
|
|||||||
use function trim;
|
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
|
* @internal This class is not covered by the backward compatibility promise for PHPUnit
|
||||||
*/
|
*/
|
||||||
final class JunitXmlLogger
|
final class JunitXmlLogger
|
||||||
{
|
{
|
||||||
private readonly Printer $printer;
|
private readonly Printer $printer;
|
||||||
|
|
||||||
private readonly \Pest\Logging\Converter $converter; // pest-added
|
private readonly Converter $converter; // pest-added
|
||||||
|
|
||||||
private DOMDocument $document;
|
private DOMDocument $document;
|
||||||
|
|
||||||
@ -59,32 +65,32 @@ final class JunitXmlLogger
|
|||||||
private array $testSuites = [];
|
private array $testSuites = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteTests = [0];
|
private array $testSuiteTests = [0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteAssertions = [0];
|
private array $testSuiteAssertions = [0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteErrors = [0];
|
private array $testSuiteErrors = [0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteFailures = [0];
|
private array $testSuiteFailures = [0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteSkipped = [0];
|
private array $testSuiteSkipped = [0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<int,int>
|
* @var array<int,int>
|
||||||
*/
|
*/
|
||||||
private array $testSuiteTimes = [0];
|
private array $testSuiteTimes = [0];
|
||||||
|
|
||||||
@ -105,7 +111,7 @@ final class JunitXmlLogger
|
|||||||
public function __construct(Printer $printer, Facade $facade)
|
public function __construct(Printer $printer, Facade $facade)
|
||||||
{
|
{
|
||||||
$this->printer = $printer;
|
$this->printer = $printer;
|
||||||
$this->converter = new \Pest\Logging\Converter(\Pest\Support\Container::getInstance()->get(\Pest\TestSuite::class)->rootPath); // pest-added
|
$this->converter = new Converter(Container::getInstance()->get(TestSuite::class)->rootPath); // pest-added
|
||||||
|
|
||||||
$this->registerSubscribers($facade);
|
$this->registerSubscribers($facade);
|
||||||
$this->createDocument();
|
$this->createDocument();
|
||||||
@ -113,7 +119,7 @@ final class JunitXmlLogger
|
|||||||
|
|
||||||
public function flush(): void
|
public function flush(): void
|
||||||
{
|
{
|
||||||
$this->printer->print($this->document->saveXML());
|
$this->printer->print($this->document->saveXML() ?: '');
|
||||||
|
|
||||||
$this->printer->flush();
|
$this->printer->flush();
|
||||||
}
|
}
|
||||||
@ -195,28 +201,34 @@ final class JunitXmlLogger
|
|||||||
$this->createTestCase($event);
|
$this->createTestCase($event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function testPreparationFailed(): void
|
public function testPreparationFailed(): void
|
||||||
{
|
{
|
||||||
$this->preparationFailed = true;
|
$this->preparationFailed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function testPrepared(): void
|
public function testPrepared(): void
|
||||||
{
|
{
|
||||||
$this->prepared = true;
|
$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
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function testFinished(Finished $event): void
|
public function testFinished(Finished $event): void
|
||||||
{
|
{
|
||||||
if ($this->preparationFailed) {
|
if (! $this->prepared || $this->preparationFailed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,9 +317,11 @@ final class JunitXmlLogger
|
|||||||
new TestPreparationStartedSubscriber($this),
|
new TestPreparationStartedSubscriber($this),
|
||||||
new TestPreparationFailedSubscriber($this),
|
new TestPreparationFailedSubscriber($this),
|
||||||
new TestPreparedSubscriber($this),
|
new TestPreparedSubscriber($this),
|
||||||
|
new TestPrintedUnexpectedOutputSubscriber($this),
|
||||||
new TestFinishedSubscriber($this),
|
new TestFinishedSubscriber($this),
|
||||||
new TestErroredSubscriber($this),
|
new TestErroredSubscriber($this),
|
||||||
new TestFailedSubscriber($this),
|
new TestFailedSubscriber($this),
|
||||||
|
new TestMarkedIncompleteSubscriber($this),
|
||||||
new TestSkippedSubscriber($this),
|
new TestSkippedSubscriber($this),
|
||||||
new TestRunnerExecutionFinishedSubscriber($this),
|
new TestRunnerExecutionFinishedSubscriber($this),
|
||||||
);
|
);
|
||||||
@ -431,7 +445,7 @@ final class JunitXmlLogger
|
|||||||
/**
|
/**
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*
|
*
|
||||||
* @psalm-assert !null $this->currentTestCase
|
* @phpstan-assert !null $this->currentTestCase
|
||||||
*/
|
*/
|
||||||
private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void
|
private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void
|
||||||
{
|
{
|
||||||
@ -446,7 +460,7 @@ final class JunitXmlLogger
|
|||||||
if ($test->isTestMethod()) {
|
if ($test->isTestMethod()) {
|
||||||
assert($test instanceof TestMethod);
|
assert($test instanceof TestMethod);
|
||||||
|
|
||||||
//$testCase->setAttribute('line', (string) $test->line()); // pest-removed
|
// $testCase->setAttribute('line', (string) $test->line()); // pest-removed
|
||||||
$className = $this->converter->getTrimmedTestClassName($test); // pest-added
|
$className = $this->converter->getTrimmedTestClassName($test); // pest-added
|
||||||
$testCase->setAttribute('class', $className); // pest-changed
|
$testCase->setAttribute('class', $className); // pest-changed
|
||||||
$testCase->setAttribute('classname', str_replace('\\', '.', $className)); // pest-changed
|
$testCase->setAttribute('classname', str_replace('\\', '.', $className)); // pest-changed
|
||||||
|
|||||||
@ -46,9 +46,10 @@ declare(strict_types=1);
|
|||||||
namespace PHPUnit\Runner\ResultCache;
|
namespace PHPUnit\Runner\ResultCache;
|
||||||
|
|
||||||
use const DIRECTORY_SEPARATOR;
|
use const DIRECTORY_SEPARATOR;
|
||||||
|
use const LOCK_EX;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestStatus\TestStatus;
|
use PHPUnit\Framework\TestStatus\TestStatus;
|
||||||
use PHPUnit\Runner\DirectoryCannotBeCreatedException;
|
use PHPUnit\Runner\DirectoryDoesNotExistException;
|
||||||
use PHPUnit\Runner\Exception;
|
use PHPUnit\Runner\Exception;
|
||||||
use PHPUnit\Util\Filesystem;
|
use PHPUnit\Util\Filesystem;
|
||||||
|
|
||||||
@ -65,6 +66,8 @@ use function json_encode;
|
|||||||
use function Pest\version;
|
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
|
* @internal This class is not covered by the backward compatibility promise for PHPUnit
|
||||||
*/
|
*/
|
||||||
final class DefaultResultCache implements ResultCache
|
final class DefaultResultCache implements ResultCache
|
||||||
@ -77,12 +80,12 @@ final class DefaultResultCache implements ResultCache
|
|||||||
private readonly string $cacheFilename;
|
private readonly string $cacheFilename;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<string, TestStatus>
|
* @var array<string, TestStatus>
|
||||||
*/
|
*/
|
||||||
private array $defects = [];
|
private array $defects = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @psalm-var array<string, float>
|
* @var array<string, float>
|
||||||
*/
|
*/
|
||||||
private array $times = [];
|
private array $times = [];
|
||||||
|
|
||||||
@ -95,28 +98,39 @@ final class DefaultResultCache implements ResultCache
|
|||||||
$this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;
|
$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()) {
|
if ($status->isSuccess()) {
|
||||||
return;
|
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
|
public function load(): void
|
||||||
@ -165,7 +179,7 @@ final class DefaultResultCache implements ResultCache
|
|||||||
public function persist(): void
|
public function persist(): void
|
||||||
{
|
{
|
||||||
if (! Filesystem::createDirectory(dirname($this->cacheFilename))) {
|
if (! Filesystem::createDirectory(dirname($this->cacheFilename))) {
|
||||||
throw new DirectoryCannotBeCreatedException($this->cacheFilename);
|
throw new DirectoryDoesNotExistException(dirname($this->cacheFilename));
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$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:
|
includes:
|
||||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
- phpstan-baseline.neon
|
||||||
- vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
|
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: max
|
level: 7
|
||||||
paths:
|
paths:
|
||||||
- src
|
- src
|
||||||
|
|
||||||
checkMissingIterableValueType: true
|
reportUnmatchedIgnoredErrors: false
|
||||||
reportUnmatchedIgnoredErrors: true
|
|
||||||
|
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
- "#type mixed is not subtype of native#"
|
- "#type mixed is not subtype of native#"
|
||||||
|
|||||||
@ -35,7 +35,8 @@ final class Laravel extends AbstractPreset
|
|||||||
->ignoring('App\Features\Concerns');
|
->ignoring('App\Features\Concerns');
|
||||||
|
|
||||||
$this->expectations[] = expect('App\Features')
|
$this->expectations[] = expect('App\Features')
|
||||||
->toHaveMethod('resolve');
|
->toHaveMethod('resolve')
|
||||||
|
->ignoring('App\Features\Concerns');
|
||||||
|
|
||||||
$this->expectations[] = expect('App\Exceptions')
|
$this->expectations[] = expect('App\Exceptions')
|
||||||
->classes()
|
->classes()
|
||||||
@ -166,5 +167,11 @@ final class Laravel extends AbstractPreset
|
|||||||
$this->expectations[] = expect('App\Policies')
|
$this->expectations[] = expect('App\Policies')
|
||||||
->classes()
|
->classes()
|
||||||
->toHaveSuffix('Policy');
|
->toHaveSuffix('Policy');
|
||||||
|
|
||||||
|
$this->expectations[] = expect('App\Attributes')
|
||||||
|
->classes()
|
||||||
|
->toImplement('Illuminate\Contracts\Container\ContextualAttribute')
|
||||||
|
->toHaveAttribute('Attribute')
|
||||||
|
->toHaveMethod('resolve');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,13 @@ final class BootOverrides implements Bootstrapper
|
|||||||
*/
|
*/
|
||||||
public const FILES = [
|
public const FILES = [
|
||||||
'53c246e5f416a39817ac81124cdd64ea8403038d01d7a202e1ffa486fbdf3fa7' => 'Runner/Filter/NameFilterIterator.php',
|
'53c246e5f416a39817ac81124cdd64ea8403038d01d7a202e1ffa486fbdf3fa7' => 'Runner/Filter/NameFilterIterator.php',
|
||||||
'a4a43de01f641c6944ee83d963795a46d32b5206b5ab3bbc6cce76e67190acbf' => 'Runner/ResultCache/DefaultResultCache.php',
|
'77ffb7647b583bd82e37962c6fbdc4b04d3344d8a2c1ed103e625ed1ff7cb5c2' => 'Runner/ResultCache/DefaultResultCache.php',
|
||||||
'd0e81317889ad88c707db4b08a94cadee4c9010d05ff0a759f04e71af5efed89' => 'Runner/TestSuiteLoader.php',
|
'd0e81317889ad88c707db4b08a94cadee4c9010d05ff0a759f04e71af5efed89' => 'Runner/TestSuiteLoader.php',
|
||||||
'3bb609b0d3bf6dee8df8d6cd62a3c8ece823c4bb941eaaae39e3cb267171b9d2' => 'TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php',
|
'3bb609b0d3bf6dee8df8d6cd62a3c8ece823c4bb941eaaae39e3cb267171b9d2' => 'TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php',
|
||||||
'8abdad6413329c6fe0d7d44a8b9926e390af32c0b3123f3720bb9c5bbc6fbb7e' => 'TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php',
|
'8abdad6413329c6fe0d7d44a8b9926e390af32c0b3123f3720bb9c5bbc6fbb7e' => 'TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php',
|
||||||
'b4250fc3ffad5954624cb5e682fd940b874e8d3422fa1ee298bd7225e1aa5fc2' => 'TextUI/TestSuiteFilterProcessor.php',
|
'b4250fc3ffad5954624cb5e682fd940b874e8d3422fa1ee298bd7225e1aa5fc2' => 'TextUI/TestSuiteFilterProcessor.php',
|
||||||
'357d5cd7007f8559b26e1b8cdf43bb6fb15b51b79db981779da6f31b7ec39dad' => 'Event/Value/ThrowableBuilder.php',
|
'8cfcb4999af79463eca51a42058e502ea4ddc776cba5677bf2f8eb6093e21a5c' => 'Event/Value/ThrowableBuilder.php',
|
||||||
'ede161507d4c9c27805f55a05a32c3bb528e53b6e1fc092bfafdb8207e0019e9' => 'Logging/JUnit/JunitXmlLogger.php',
|
'86cd9bcaa53cdd59c5b13e58f30064a015c549501e7629d93b96893d4dee1eb1' => 'Logging/JUnit/JunitXmlLogger.php',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -66,6 +66,6 @@ trait Pipeable
|
|||||||
*/
|
*/
|
||||||
private function pipes(string $name, object $context, string $scope): array
|
private function pipes(string $name, object $context, string $scope): array
|
||||||
{
|
{
|
||||||
return array_map(fn (Closure $pipe): \Closure => $pipe->bindTo($context, $scope), self::$pipes[$name] ?? []);
|
return array_map(fn (Closure $pipe): Closure => $pipe->bindTo($context, $scope), self::$pipes[$name] ?? []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -148,7 +148,7 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
public function __addBeforeAll(?Closure $hook): void
|
public function __addBeforeAll(?Closure $hook): void
|
||||||
{
|
{
|
||||||
if (! $hook instanceof \Closure) {
|
if (! $hook instanceof Closure) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
public function __addAfterAll(?Closure $hook): void
|
public function __addAfterAll(?Closure $hook): void
|
||||||
{
|
{
|
||||||
if (! $hook instanceof \Closure) {
|
if (! $hook instanceof Closure) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
private function __addHook(string $property, ?Closure $hook): void
|
private function __addHook(string $property, ?Closure $hook): void
|
||||||
{
|
{
|
||||||
if (! $hook instanceof \Closure) {
|
if (! $hook instanceof Closure) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,8 +24,12 @@ final readonly class Thanks
|
|||||||
*/
|
*/
|
||||||
private const FUNDING_MESSAGES = [
|
private const FUNDING_MESSAGES = [
|
||||||
'Star' => 'https://github.com/pestphp/pest',
|
'Star' => 'https://github.com/pestphp/pest',
|
||||||
'News' => 'https://twitter.com/pestphp',
|
'YouTube' => 'https://youtube.com/@nunomaduro',
|
||||||
'Videos' => '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',
|
'Sponsor' => 'https://github.com/sponsors/nunomaduro',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ final class ShouldNotHappen extends RuntimeException
|
|||||||
$message = $exception->getMessage();
|
$message = $exception->getMessage();
|
||||||
|
|
||||||
parent::__construct(sprintf(<<<'EOF'
|
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
|
Issue: %s
|
||||||
PHP version: %s
|
PHP version: %s
|
||||||
|
|||||||
@ -134,7 +134,7 @@ final class Expectation
|
|||||||
/**
|
/**
|
||||||
* Dump the expectation value when the result of the condition is truthy.
|
* Dump the expectation value when the result of the condition is truthy.
|
||||||
*
|
*
|
||||||
* @param (\Closure(TValue): bool)|bool $condition
|
* @param (Closure(TValue): bool)|bool $condition
|
||||||
* @return self<TValue>
|
* @return self<TValue>
|
||||||
*/
|
*/
|
||||||
public function ddWhen(Closure|bool $condition, mixed ...$arguments): Expectation
|
public function ddWhen(Closure|bool $condition, mixed ...$arguments): Expectation
|
||||||
@ -151,7 +151,7 @@ final class Expectation
|
|||||||
/**
|
/**
|
||||||
* Dump the expectation value when the result of the condition is falsy.
|
* Dump the expectation value when the result of the condition is falsy.
|
||||||
*
|
*
|
||||||
* @param (\Closure(TValue): bool)|bool $condition
|
* @param (Closure(TValue): bool)|bool $condition
|
||||||
* @return self<TValue>
|
* @return self<TValue>
|
||||||
*/
|
*/
|
||||||
public function ddUnless(Closure|bool $condition, mixed ...$arguments): Expectation
|
public function ddUnless(Closure|bool $condition, mixed ...$arguments): Expectation
|
||||||
@ -535,7 +535,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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',
|
'to be final',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -548,7 +548,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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',
|
'to be readonly',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -561,7 +561,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isTrait(),
|
||||||
'to be trait',
|
'to be trait',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -582,7 +582,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isAbstract(),
|
||||||
'to be abstract',
|
'to be abstract',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -599,7 +599,7 @@ final class Expectation
|
|||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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)),
|
sprintf("to have method '%s'", implode("', '", $methods)),
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -670,7 +670,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isEnum(),
|
||||||
'to be enum',
|
'to be enum',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -712,7 +712,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isInterface(),
|
||||||
'to be interface',
|
'to be interface',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -733,7 +733,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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),
|
sprintf("to extend '%s'", $class),
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -773,6 +773,10 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
function (ObjectDescription $object) use ($traits): bool {
|
function (ObjectDescription $object) use ($traits): bool {
|
||||||
foreach ($traits as $trait) {
|
foreach ($traits as $trait) {
|
||||||
|
if (isset($object->reflectionClass) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
|
if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -792,7 +796,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [],
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getInterfaceNames() === [],
|
||||||
'to implement nothing',
|
'to implement nothing',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -809,7 +813,8 @@ final class Expectation
|
|||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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()) === [],
|
&& array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [],
|
||||||
"to only implement '".implode("', '", $interfaces)."'",
|
"to only implement '".implode("', '", $interfaces)."'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
@ -823,7 +828,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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}'",
|
"to have prefix '{$prefix}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -836,7 +841,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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}'",
|
"to have suffix '{$suffix}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -855,7 +860,7 @@ final class Expectation
|
|||||||
$this,
|
$this,
|
||||||
function (ObjectDescription $object) use ($interfaces): bool {
|
function (ObjectDescription $object) use ($interfaces): bool {
|
||||||
foreach ($interfaces as $interface) {
|
foreach ($interfaces as $interface) {
|
||||||
if (! $object->reflectionClass->implementsInterface($interface)) {
|
if (! isset($object->reflectionClass) || ! $object->reflectionClass->implementsInterface($interface)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -928,7 +933,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->hasMethod('__invoke'),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod('__invoke'),
|
||||||
'to be invokable',
|
'to be invokable',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||||
);
|
);
|
||||||
@ -1037,7 +1042,7 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$this,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) !== [],
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getAttributes($attribute) !== [],
|
||||||
"to have attribute '{$attribute}'",
|
"to have attribute '{$attribute}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -1066,7 +1071,8 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this,
|
$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
|
&& (new ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|
||||||
&& (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line
|
&& (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line
|
||||||
'to be '.$backingType.' backed enum',
|
'to be '.$backingType.' backed enum',
|
||||||
|
|||||||
@ -74,7 +74,10 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toUse(array|string $targets): ArchExpectation
|
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),
|
fn () => $this->throwExpectationFailedException('toUse', $target),
|
||||||
), is_string($targets) ? [$targets] : $targets));
|
), is_string($targets) ? [$targets] : $targets));
|
||||||
}
|
}
|
||||||
@ -84,8 +87,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
|
public function toHaveFileSystemPermissions(string $permissions): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) !== $permissions,
|
fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) !== $permissions,
|
||||||
sprintf('permissions not to be [%s]', $permissions),
|
sprintf('permissions not to be [%s]', $permissions),
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||||
@ -105,8 +111,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHaveMethodsDocumented(): ArchExpectation
|
public function toHaveMethodsDocumented(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||||
|| array_filter(
|
|| array_filter(
|
||||||
Reflection::getMethodsFromReflectionClass($object->reflectionClass),
|
Reflection::getMethodsFromReflectionClass($object->reflectionClass),
|
||||||
@ -124,8 +133,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHavePropertiesDocumented(): ArchExpectation
|
public function toHavePropertiesDocumented(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||||
|| array_filter(
|
|| array_filter(
|
||||||
Reflection::getPropertiesFromReflectionClass($object->reflectionClass),
|
Reflection::getPropertiesFromReflectionClass($object->reflectionClass),
|
||||||
@ -144,8 +156,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toUseStrictTypes(): ArchExpectation
|
public function toUseStrictTypes(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
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)),
|
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',
|
'not to use strict types',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),
|
||||||
@ -157,8 +172,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toUseStrictEquality(): ArchExpectation
|
public function toUseStrictEquality(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
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), ' !== '),
|
fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' === ') && ! str_contains((string) file_get_contents($object->path), ' !== '),
|
||||||
'to use strict equality',
|
'to use strict equality',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, ' === ') || str_contains($line, ' !== ')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, ' === ') || str_contains($line, ' !== ')),
|
||||||
@ -170,9 +188,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeFinal(): ArchExpectation
|
public function toBeFinal(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && ! $object->reflectionClass->isFinal(),
|
fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isFinal()),
|
||||||
'not to be final',
|
'not to be final',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -183,9 +204,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeReadonly(): ArchExpectation
|
public function toBeReadonly(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
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) === false || ! $object->reflectionClass->isReadOnly()) && assert(true), // @phpstan-ignore-line
|
||||||
'not to be readonly',
|
'not to be readonly',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -196,9 +220,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeTrait(): ArchExpectation
|
public function toBeTrait(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isTrait(),
|
||||||
'not to be trait',
|
'not to be trait',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -217,9 +244,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeAbstract(): ArchExpectation
|
public function toBeAbstract(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isAbstract(),
|
||||||
'not to be abstract',
|
'not to be abstract',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -234,11 +264,14 @@ final readonly class OppositeExpectation
|
|||||||
{
|
{
|
||||||
$methods = is_array($method) ? $method : [$method];
|
$methods = is_array($method) ? $method : [$method];
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => array_filter(
|
fn (ObjectDescription $object): bool => array_filter(
|
||||||
$methods,
|
$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),
|
'to not have methods: '.implode(', ', $methods),
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
@ -266,8 +299,11 @@ final readonly class OppositeExpectation
|
|||||||
|
|
||||||
$state = new stdClass;
|
$state = new stdClass;
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||||
$reflectionMethods = isset($object->reflectionClass)
|
$reflectionMethods = isset($object->reflectionClass)
|
||||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)
|
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)
|
||||||
@ -286,7 +322,7 @@ final readonly class OppositeExpectation
|
|||||||
$methods === []
|
$methods === []
|
||||||
? 'not to have public methods'
|
? 'not to have public methods'
|
||||||
: sprintf("not to have public methods besides '%s'", implode("', '", $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;
|
$state = new stdClass;
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||||
$reflectionMethods = isset($object->reflectionClass)
|
$reflectionMethods = isset($object->reflectionClass)
|
||||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)
|
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)
|
||||||
@ -329,7 +368,7 @@ final readonly class OppositeExpectation
|
|||||||
$methods === []
|
$methods === []
|
||||||
? 'not to have protected methods'
|
? 'not to have protected methods'
|
||||||
: sprintf("not to have protected methods besides '%s'", implode("', '", $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;
|
$state = new stdClass;
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
function (ObjectDescription $object) use ($methods, &$state): bool {
|
function (ObjectDescription $object) use ($methods, &$state): bool {
|
||||||
$reflectionMethods = isset($object->reflectionClass)
|
$reflectionMethods = isset($object->reflectionClass)
|
||||||
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)
|
? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)
|
||||||
@ -372,7 +414,7 @@ final readonly class OppositeExpectation
|
|||||||
$methods === []
|
$methods === []
|
||||||
? 'not to have private methods'
|
? 'not to have private methods'
|
||||||
: sprintf("not to have private methods besides '%s'", implode("', '", $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
|
public function toBeEnum(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isEnum(),
|
||||||
'not to be enum',
|
'not to be enum',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -410,8 +455,11 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeClass(): ArchExpectation
|
public function toBeClass(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! class_exists($object->name),
|
fn (ObjectDescription $object): bool => ! class_exists($object->name),
|
||||||
'not to be class',
|
'not to be class',
|
||||||
FileLineFinder::where(fn (string $line): bool => true),
|
FileLineFinder::where(fn (string $line): bool => true),
|
||||||
@ -431,9 +479,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeInterface(): ArchExpectation
|
public function toBeInterface(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isInterface(),
|
||||||
'not to be interface',
|
'not to be interface',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -452,9 +503,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toExtend(string $class): ArchExpectation
|
public function toExtend(string $class): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isSubclassOf($class),
|
||||||
sprintf("not to extend '%s'", $class),
|
sprintf("not to extend '%s'", $class),
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -465,9 +519,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toExtendNothing(): ArchExpectation
|
public function toExtendNothing(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false,
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getParentClass() !== false,
|
||||||
'to extend a class',
|
'to extend a class',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, '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];
|
$traits = is_array($traits) ? $traits : [$traits];
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
function (ObjectDescription $object) use ($traits): bool {
|
function (ObjectDescription $object) use ($traits): bool {
|
||||||
foreach ($traits as $trait) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,11 +575,14 @@ final readonly class OppositeExpectation
|
|||||||
{
|
{
|
||||||
$interfaces = is_array($interfaces) ? $interfaces : [$interfaces];
|
$interfaces = is_array($interfaces) ? $interfaces : [$interfaces];
|
||||||
|
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
function (ObjectDescription $object) use ($interfaces): bool {
|
function (ObjectDescription $object) use ($interfaces): bool {
|
||||||
foreach ($interfaces as $interface) {
|
foreach ($interfaces as $interface) {
|
||||||
if ($object->reflectionClass->implementsInterface($interface)) {
|
if (isset($object->reflectionClass) && $object->reflectionClass->implementsInterface($interface)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -536,9 +599,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toImplementNothing(): ArchExpectation
|
public function toImplementNothing(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [],
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getInterfaceNames() !== [],
|
||||||
'to implement an interface',
|
'to implement an interface',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -557,9 +623,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHavePrefix(string $prefix): ArchExpectation
|
public function toHavePrefix(string $prefix): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_starts_with($object->reflectionClass->getShortName(), $prefix),
|
||||||
"not to have prefix '{$prefix}'",
|
"not to have prefix '{$prefix}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -570,9 +639,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHaveSuffix(string $suffix): ArchExpectation
|
public function toHaveSuffix(string $suffix): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! str_ends_with($object->reflectionClass->getName(), $suffix),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_ends_with($object->reflectionClass->getName(), $suffix),
|
||||||
"not to have suffix '{$suffix}'",
|
"not to have suffix '{$suffix}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),
|
||||||
);
|
);
|
||||||
@ -599,7 +671,10 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeUsed(): ArchExpectation
|
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
|
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),
|
fn () => $this->throwExpectationFailedException('toBeUsedIn', $target),
|
||||||
), is_string($targets) ? [$targets] : $targets));
|
), is_string($targets) ? [$targets] : $targets));
|
||||||
}
|
}
|
||||||
@ -632,9 +710,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toBeInvokable(): ArchExpectation
|
public function toBeInvokable(): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->hasMethod('__invoke'),
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->hasMethod('__invoke'),
|
||||||
'to not be invokable',
|
'to not be invokable',
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||||
);
|
);
|
||||||
@ -645,9 +726,12 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
public function toHaveAttribute(string $attribute): ArchExpectation
|
public function toHaveAttribute(string $attribute): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => $object->reflectionClass->getAttributes($attribute) === [],
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getAttributes($attribute) === [],
|
||||||
"to not have attribute '{$attribute}'",
|
"to not have attribute '{$attribute}'",
|
||||||
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))
|
||||||
);
|
);
|
||||||
@ -737,9 +821,13 @@ final readonly class OppositeExpectation
|
|||||||
*/
|
*/
|
||||||
private function toBeBackedEnum(string $backingType): ArchExpectation
|
private function toBeBackedEnum(string $backingType): ArchExpectation
|
||||||
{
|
{
|
||||||
|
/** @var Expectation<array<int, string>|string> $original */
|
||||||
|
$original = $this->original;
|
||||||
|
|
||||||
return Targeted::make(
|
return Targeted::make(
|
||||||
$this->original,
|
$original,
|
||||||
fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum()
|
fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false
|
||||||
|
|| ! $object->reflectionClass->isEnum()
|
||||||
|| ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|
|| ! (new \ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line
|
||||||
|| (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line
|
|| (string) (new \ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line
|
||||||
'not to be '.$backingType.' backed enum',
|
'not to be '.$backingType.' backed enum',
|
||||||
|
|||||||
@ -17,6 +17,7 @@ use Pest\Factories\Concerns\HigherOrderable;
|
|||||||
use Pest\Support\Reflection;
|
use Pest\Support\Reflection;
|
||||||
use Pest\Support\Str;
|
use Pest\Support\Str;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
|
use PHPUnit\Framework\Attributes\TestDox;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
@ -135,7 +136,7 @@ final class TestCaseFactory
|
|||||||
|
|
||||||
$this->attributes = [
|
$this->attributes = [
|
||||||
new Attribute(
|
new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\TestDox::class,
|
TestDox::class,
|
||||||
[$this->filename],
|
[$this->filename],
|
||||||
),
|
),
|
||||||
...$this->attributes,
|
...$this->attributes,
|
||||||
|
|||||||
@ -13,6 +13,9 @@ use Pest\Support\Str;
|
|||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
use PHPUnit\Framework\Assert;
|
use PHPUnit\Framework\Assert;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
|
use PHPUnit\Framework\Attributes\Depends;
|
||||||
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
|
use PHPUnit\Framework\Attributes\TestDox;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,7 +158,7 @@ final class TestCaseMethodFactory
|
|||||||
assert($testCase instanceof TestCaseFactory);
|
assert($testCase instanceof TestCaseFactory);
|
||||||
$method = $this;
|
$method = $this;
|
||||||
|
|
||||||
return function (...$arguments) use ($testCase, $method, $closure): mixed { // @phpstan-ignore-line
|
return function (...$arguments) use ($testCase, $method, $closure): mixed {
|
||||||
/* @var TestCase $this */
|
/* @var TestCase $this */
|
||||||
$testCase->proxies->proxy($this);
|
$testCase->proxies->proxy($this);
|
||||||
$method->proxies->proxy($this);
|
$method->proxies->proxy($this);
|
||||||
@ -192,11 +195,11 @@ final class TestCaseMethodFactory
|
|||||||
|
|
||||||
$this->attributes = [
|
$this->attributes = [
|
||||||
new Attribute(
|
new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\Test::class,
|
Test::class,
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
new Attribute(
|
new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\TestDox::class,
|
TestDox::class,
|
||||||
[str_replace('*/', '{@*}', $this->description)],
|
[str_replace('*/', '{@*}', $this->description)],
|
||||||
),
|
),
|
||||||
...$this->attributes,
|
...$this->attributes,
|
||||||
@ -206,7 +209,7 @@ final class TestCaseMethodFactory
|
|||||||
$depend = Str::evaluable($this->describing === [] ? $depend : Str::describe($this->describing, $depend));
|
$depend = Str::evaluable($this->describing === [] ? $depend : Str::describe($this->describing, $depend));
|
||||||
|
|
||||||
$this->attributes[] = new Attribute(
|
$this->attributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\Depends::class,
|
Depends::class,
|
||||||
[$depend],
|
[$depend],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,7 +136,7 @@ if (! function_exists('test')) {
|
|||||||
*/
|
*/
|
||||||
function test(?string $description = null, ?Closure $closure = null): HigherOrderTapProxy|TestCall
|
function test(?string $description = null, ?Closure $closure = null): HigherOrderTapProxy|TestCall
|
||||||
{
|
{
|
||||||
if ($description === null && TestSuite::getInstance()->test instanceof \PHPUnit\Framework\TestCase) {
|
if ($description === null && TestSuite::getInstance()->test instanceof TestCase) {
|
||||||
return new HigherOrderTapProxy(TestSuite::getInstance()->test);
|
return new HigherOrderTapProxy(TestSuite::getInstance()->test);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ if (! function_exists('covers')) {
|
|||||||
|
|
||||||
/** @var MutationTestRunner $runner */
|
/** @var MutationTestRunner $runner */
|
||||||
$runner = Container::getInstance()->get(MutationTestRunner::class);
|
$runner = Container::getInstance()->get(MutationTestRunner::class);
|
||||||
/** @var \Pest\Mutate\Repositories\ConfigurationRepository $configurationRepository */
|
/** @var ConfigurationRepository $configurationRepository */
|
||||||
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
||||||
$everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;
|
$everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;
|
||||||
$classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;
|
$classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;
|
||||||
@ -259,7 +259,7 @@ if (! function_exists('mutates')) {
|
|||||||
|
|
||||||
/** @var MutationTestRunner $runner */
|
/** @var MutationTestRunner $runner */
|
||||||
$runner = Container::getInstance()->get(MutationTestRunner::class);
|
$runner = Container::getInstance()->get(MutationTestRunner::class);
|
||||||
/** @var \Pest\Mutate\Repositories\ConfigurationRepository $configurationRepository */
|
/** @var ConfigurationRepository $configurationRepository */
|
||||||
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
$configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);
|
||||||
$everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;
|
$everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;
|
||||||
$classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;
|
$classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ use Pest\Support\Str;
|
|||||||
use PHPUnit\Event\Code\Test;
|
use PHPUnit\Event\Code\Test;
|
||||||
use PHPUnit\Event\Code\TestMethod;
|
use PHPUnit\Event\Code\TestMethod;
|
||||||
use PHPUnit\Event\Code\Throwable;
|
use PHPUnit\Event\Code\Throwable;
|
||||||
|
use PHPUnit\Event\Test\AfterLastTestMethodErrored;
|
||||||
use PHPUnit\Event\Test\BeforeFirstTestMethodErrored;
|
use PHPUnit\Event\Test\BeforeFirstTestMethodErrored;
|
||||||
use PHPUnit\Event\Test\ConsideredRisky;
|
use PHPUnit\Event\Test\ConsideredRisky;
|
||||||
use PHPUnit\Event\Test\Errored;
|
use PHPUnit\Event\Test\Errored;
|
||||||
@ -150,7 +151,7 @@ final readonly class Converter
|
|||||||
{
|
{
|
||||||
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
|
if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {
|
||||||
$firstTest = $this->getFirstTest($testSuite);
|
$firstTest = $this->getFirstTest($testSuite);
|
||||||
if ($firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
|
if ($firstTest instanceof TestMethod) {
|
||||||
return $this->getTestMethodNameWithoutDatasetSuffix($firstTest);
|
return $this->getTestMethodNameWithoutDatasetSuffix($firstTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +179,7 @@ final readonly class Converter
|
|||||||
public function getTestSuiteLocation(TestSuite $testSuite): ?string
|
public function getTestSuiteLocation(TestSuite $testSuite): ?string
|
||||||
{
|
{
|
||||||
$firstTest = $this->getFirstTest($testSuite);
|
$firstTest = $this->getFirstTest($testSuite);
|
||||||
if (! $firstTest instanceof \PHPUnit\Event\Code\TestMethod) {
|
if (! $firstTest instanceof TestMethod) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$path = $firstTest->testDox()->prettifiedClassName();
|
$path = $firstTest->testDox()->prettifiedClassName();
|
||||||
@ -254,8 +255,9 @@ final readonly class Converter
|
|||||||
$numberOfNotPassedTests = count(
|
$numberOfNotPassedTests = count(
|
||||||
array_unique(
|
array_unique(
|
||||||
array_map(
|
array_map(
|
||||||
function (BeforeFirstTestMethodErrored|Errored|Failed|Skipped|ConsideredRisky|MarkedIncomplete $event): string {
|
function (AfterLastTestMethodErrored|BeforeFirstTestMethodErrored|Errored|Failed|Skipped|ConsideredRisky|MarkedIncomplete $event): string {
|
||||||
if ($event instanceof BeforeFirstTestMethodErrored) {
|
if ($event instanceof BeforeFirstTestMethodErrored
|
||||||
|
|| $event instanceof AfterLastTestMethodErrored) {
|
||||||
return $event->testClassName();
|
return $event->testClassName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -200,7 +200,7 @@ final class TeamCityLogger
|
|||||||
|
|
||||||
public function testFinished(Finished $event): void
|
public function testFinished(Finished $event): void
|
||||||
{
|
{
|
||||||
if (! $this->time instanceof \PHPUnit\Event\Telemetry\HRTime) {
|
if (! $this->time instanceof HRTime) {
|
||||||
throw ShouldNotHappen::fromMessage('Start time has not been set.');
|
throw ShouldNotHappen::fromMessage('Start time has not been set.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,6 @@ final class TeamCityLogger
|
|||||||
$reflector = new ReflectionClass($telemetry);
|
$reflector = new ReflectionClass($telemetry);
|
||||||
|
|
||||||
$property = $reflector->getProperty('current');
|
$property = $reflector->getProperty('current');
|
||||||
$property->setAccessible(true);
|
|
||||||
$snapshot = $property->getValue($telemetry);
|
$snapshot = $property->getValue($telemetry);
|
||||||
assert($snapshot instanceof Snapshot);
|
assert($snapshot instanceof Snapshot);
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ use Closure;
|
|||||||
use Countable;
|
use Countable;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use Error;
|
use Error;
|
||||||
|
use Illuminate\Testing\TestResponse;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use JsonSerializable;
|
use JsonSerializable;
|
||||||
use Pest\Exceptions\InvalidExpectationValue;
|
use Pest\Exceptions\InvalidExpectationValue;
|
||||||
@ -183,7 +184,6 @@ final class Expectation
|
|||||||
{
|
{
|
||||||
foreach ($needles as $needle) {
|
foreach ($needles as $needle) {
|
||||||
if (is_string($this->value)) {
|
if (is_string($this->value)) {
|
||||||
// @phpstan-ignore-next-line
|
|
||||||
Assert::assertStringContainsString((string) $needle, $this->value);
|
Assert::assertStringContainsString((string) $needle, $this->value);
|
||||||
} else {
|
} else {
|
||||||
if (! is_iterable($this->value)) {
|
if (! is_iterable($this->value)) {
|
||||||
@ -847,7 +847,7 @@ final class Expectation
|
|||||||
is_object($this->value) && method_exists($this->value, 'toSnapshot') => $this->value->toSnapshot(),
|
is_object($this->value) && method_exists($this->value, 'toSnapshot') => $this->value->toSnapshot(),
|
||||||
is_object($this->value) && method_exists($this->value, '__toString') => $this->value->__toString(),
|
is_object($this->value) && method_exists($this->value, '__toString') => $this->value->__toString(),
|
||||||
is_object($this->value) && method_exists($this->value, 'toString') => $this->value->toString(),
|
is_object($this->value) && method_exists($this->value, 'toString') => $this->value->toString(),
|
||||||
$this->value instanceof \Illuminate\Testing\TestResponse => $this->value->getContent(), // @phpstan-ignore-line
|
$this->value instanceof TestResponse => $this->value->getContent(), // @phpstan-ignore-line
|
||||||
is_array($this->value) => json_encode($this->value, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
is_array($this->value) => json_encode($this->value, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
||||||
$this->value instanceof Traversable => json_encode(iterator_to_array($this->value), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
$this->value instanceof Traversable => json_encode(iterator_to_array($this->value), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
||||||
$this->value instanceof JsonSerializable => json_encode($this->value->jsonSerialize(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
$this->value instanceof JsonSerializable => json_encode($this->value->jsonSerialize(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),
|
||||||
@ -988,7 +988,7 @@ final class Expectation
|
|||||||
*/
|
*/
|
||||||
private function export(mixed $value): string
|
private function export(mixed $value): string
|
||||||
{
|
{
|
||||||
if (! $this->exporter instanceof \Pest\Support\Exporter) {
|
if (! $this->exporter instanceof Exporter) {
|
||||||
$this->exporter = Exporter::default();
|
$this->exporter = Exporter::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ final readonly class Panic
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$output = Container::getInstance()->get(OutputInterface::class);
|
$output = Container::getInstance()->get(OutputInterface::class);
|
||||||
} catch (Throwable) { // @phpstan-ignore-line
|
} catch (Throwable) {
|
||||||
$output = new ConsoleOutput;
|
$output = new ConsoleOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ final class AfterEachCall
|
|||||||
|
|
||||||
$afterEachTestCase = ChainableClosure::boundWhen(
|
$afterEachTestCase = ChainableClosure::boundWhen(
|
||||||
fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),
|
fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),
|
||||||
ChainableClosure::bound(fn () => $proxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
ChainableClosure::bound(fn () => $proxies->chain($this), $this->closure)->bindTo($this, self::class),
|
||||||
)->bindTo($this, self::class);
|
)->bindTo($this, self::class);
|
||||||
|
|
||||||
assert($afterEachTestCase instanceof Closure);
|
assert($afterEachTestCase instanceof Closure);
|
||||||
|
|||||||
@ -79,7 +79,7 @@ final class BeforeEachCall
|
|||||||
|
|
||||||
$beforeEachTestCase = ChainableClosure::boundWhen(
|
$beforeEachTestCase = ChainableClosure::boundWhen(
|
||||||
fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),
|
fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),
|
||||||
ChainableClosure::bound(fn () => $testCaseProxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
ChainableClosure::bound(fn () => $testCaseProxies->chain($this), $this->closure)->bindTo($this, self::class),
|
||||||
)->bindTo($this, self::class);
|
)->bindTo($this, self::class);
|
||||||
|
|
||||||
assert($beforeEachTestCase instanceof Closure);
|
assert($beforeEachTestCase instanceof Closure);
|
||||||
|
|||||||
@ -72,13 +72,13 @@ final class DescribeCall
|
|||||||
{
|
{
|
||||||
$filename = Backtrace::file();
|
$filename = Backtrace::file();
|
||||||
|
|
||||||
if (! $this->currentBeforeEachCall instanceof \Pest\PendingCalls\BeforeEachCall) {
|
if (! $this->currentBeforeEachCall instanceof BeforeEachCall) {
|
||||||
$this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);
|
$this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);
|
||||||
|
|
||||||
$this->currentBeforeEachCall->describing[] = $this->description;
|
$this->currentBeforeEachCall->describing[] = $this->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->currentBeforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line
|
$this->currentBeforeEachCall->{$name}(...$arguments);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,11 @@ use Pest\Support\NullClosure;
|
|||||||
use Pest\Support\Str;
|
use Pest\Support\Str;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
use PHPUnit\Framework\AssertionFailedError;
|
use PHPUnit\Framework\AssertionFailedError;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversFunction;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversNothing;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversTrait;
|
||||||
|
use PHPUnit\Framework\Attributes\Group;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,7 +186,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
* Runs the current test multiple times with
|
* Runs the current test multiple times with
|
||||||
* each item of the given `iterable`.
|
* each item of the given `iterable`.
|
||||||
*
|
*
|
||||||
* @param array<\Closure|iterable<int|string, mixed>|string> $data
|
* @param array<Closure|iterable<int|string, mixed>|string> $data
|
||||||
*/
|
*/
|
||||||
public function with(Closure|iterable|string ...$data): self
|
public function with(Closure|iterable|string ...$data): self
|
||||||
{
|
{
|
||||||
@ -211,7 +216,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
{
|
{
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
$this->testCaseMethod->attributes[] = new Attribute(
|
$this->testCaseMethod->attributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\Group::class,
|
Group::class,
|
||||||
[$group],
|
[$group],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -224,7 +229,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
*/
|
*/
|
||||||
public function only(): self
|
public function only(): self
|
||||||
{
|
{
|
||||||
Only::enable($this, ...func_get_args()); // @phpstan-ignore-line
|
Only::enable($this, ...func_get_args());
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -549,7 +554,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
{
|
{
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$this->testCaseFactoryAttributes[] = new Attribute(
|
$this->testCaseFactoryAttributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\CoversClass::class,
|
CoversClass::class,
|
||||||
[$class],
|
[$class],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -572,7 +577,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
{
|
{
|
||||||
foreach ($traits as $trait) {
|
foreach ($traits as $trait) {
|
||||||
$this->testCaseFactoryAttributes[] = new Attribute(
|
$this->testCaseFactoryAttributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\CoversTrait::class,
|
CoversTrait::class,
|
||||||
[$trait],
|
[$trait],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -595,7 +600,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
{
|
{
|
||||||
foreach ($functions as $function) {
|
foreach ($functions as $function) {
|
||||||
$this->testCaseFactoryAttributes[] = new Attribute(
|
$this->testCaseFactoryAttributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\CoversFunction::class,
|
CoversFunction::class,
|
||||||
[$function],
|
[$function],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -609,7 +614,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
public function coversNothing(): self
|
public function coversNothing(): self
|
||||||
{
|
{
|
||||||
$this->testCaseMethod->attributes[] = new Attribute(
|
$this->testCaseMethod->attributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\CoversNothing::class,
|
CoversNothing::class,
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ namespace Pest;
|
|||||||
|
|
||||||
function version(): string
|
function version(): string
|
||||||
{
|
{
|
||||||
return '3.6.0';
|
return '3.8.6';
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDirectory(string $file = ''): string
|
function testDirectory(string $file = ''): string
|
||||||
|
|||||||
@ -37,6 +37,11 @@ final class Coverage implements AddsOutput, HandlesArguments
|
|||||||
*/
|
*/
|
||||||
public bool $coverage = false;
|
public bool $coverage = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether it should show the coverage or not.
|
||||||
|
*/
|
||||||
|
public bool $compact = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum coverage.
|
* The minimum coverage.
|
||||||
*/
|
*/
|
||||||
@ -124,6 +129,10 @@ final class Coverage implements AddsOutput, HandlesArguments
|
|||||||
$this->coverageExactly = (float) $exactlyOption;
|
$this->coverageExactly = (float) $exactlyOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['COLLISION_PRINTER_COMPACT'] ?? false) {
|
||||||
|
$this->compact = true;
|
||||||
|
}
|
||||||
|
|
||||||
return $originals;
|
return $originals;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +153,7 @@ final class Coverage implements AddsOutput, HandlesArguments
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$coverage = \Pest\Support\Coverage::report($this->output);
|
$coverage = \Pest\Support\Coverage::report($this->output, $this->compact);
|
||||||
$exitCode = (int) ($coverage < $this->coverageMin);
|
$exitCode = (int) ($coverage < $this->coverageMin);
|
||||||
|
|
||||||
if ($exitCode === 0 && $this->coverageExactly !== null) {
|
if ($exitCode === 0 && $this->coverageExactly !== null) {
|
||||||
|
|||||||
@ -119,6 +119,6 @@ final readonly class Init implements HandlesArguments
|
|||||||
*/
|
*/
|
||||||
private function isLaravelInstalled(): bool
|
private function isLaravelInstalled(): bool
|
||||||
{
|
{
|
||||||
return InstalledVersions::isInstalled('laravel/laravel');
|
return InstalledVersions::isInstalled('laravel/framework');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ namespace Pest\Plugins\Parallel\Handlers;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use Composer\InstalledVersions;
|
use Composer\InstalledVersions;
|
||||||
use Illuminate\Testing\ParallelRunner;
|
use Illuminate\Testing\ParallelRunner;
|
||||||
|
use Orchestra\Testbench\TestCase;
|
||||||
use ParaTest\Options;
|
use ParaTest\Options;
|
||||||
use ParaTest\RunnerInterface;
|
use ParaTest\RunnerInterface;
|
||||||
use Pest\Contracts\Plugins\HandlesArguments;
|
use Pest\Contracts\Plugins\HandlesArguments;
|
||||||
@ -39,13 +40,13 @@ final class Laravel implements HandlesArguments
|
|||||||
* Executes the given closure when running Laravel.
|
* Executes the given closure when running Laravel.
|
||||||
*
|
*
|
||||||
* @param array<int, string> $arguments
|
* @param array<int, string> $arguments
|
||||||
* @param CLosure(array<int, string>): array<int, string> $closure
|
* @param Closure(array<int, string>): array<int, string> $closure
|
||||||
* @return array<int, string>
|
* @return array<int, string>
|
||||||
*/
|
*/
|
||||||
private function whenUsingLaravel(array $arguments, Closure $closure): array
|
private function whenUsingLaravel(array $arguments, Closure $closure): array
|
||||||
{
|
{
|
||||||
$isLaravelApplication = InstalledVersions::isInstalled('laravel/framework', false);
|
$isLaravelApplication = InstalledVersions::isInstalled('laravel/framework', false);
|
||||||
$isLaravelPackage = class_exists(\Orchestra\Testbench\TestCase::class);
|
$isLaravelPackage = class_exists(TestCase::class);
|
||||||
|
|
||||||
if ($isLaravelApplication && ! $isLaravelPackage) {
|
if ($isLaravelApplication && ! $isLaravelPackage) {
|
||||||
return $closure($arguments);
|
return $closure($arguments);
|
||||||
|
|||||||
@ -19,6 +19,7 @@ use Pest\TestSuite;
|
|||||||
use PHPUnit\Event\Facade as EventFacade;
|
use PHPUnit\Event\Facade as EventFacade;
|
||||||
use PHPUnit\Event\TestRunner\WarningTriggered;
|
use PHPUnit\Event\TestRunner\WarningTriggered;
|
||||||
use PHPUnit\Runner\CodeCoverage;
|
use PHPUnit\Runner\CodeCoverage;
|
||||||
|
use PHPUnit\Runner\ResultCache\DefaultResultCache;
|
||||||
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
|
use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade;
|
||||||
use PHPUnit\TestRunner\TestResult\TestResult;
|
use PHPUnit\TestRunner\TestResult\TestResult;
|
||||||
use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry;
|
use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry;
|
||||||
@ -79,7 +80,10 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
private array $unexpectedOutputFiles = [];
|
private array $unexpectedOutputFiles = [];
|
||||||
|
|
||||||
/** @var list<SplFileInfo> */
|
/** @var list<SplFileInfo> */
|
||||||
private array $testresultFiles = [];
|
private array $resultCacheFiles = [];
|
||||||
|
|
||||||
|
/** @var list<SplFileInfo> */
|
||||||
|
private array $testResultFiles = [];
|
||||||
|
|
||||||
/** @var list<SplFileInfo> */
|
/** @var list<SplFileInfo> */
|
||||||
private array $coverageFiles = [];
|
private array $coverageFiles = [];
|
||||||
@ -264,7 +268,8 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
$this->batches[$token] = 0;
|
$this->batches[$token] = 0;
|
||||||
|
|
||||||
$this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;
|
$this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;
|
||||||
$this->testresultFiles[] = $worker->testresultFile;
|
$this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;
|
||||||
|
$this->testResultFiles[] = $worker->testResultFile;
|
||||||
|
|
||||||
if (isset($worker->junitFile)) {
|
if (isset($worker->junitFile)) {
|
||||||
$this->junitFiles[] = $worker->junitFile;
|
$this->junitFiles[] = $worker->junitFile;
|
||||||
@ -298,12 +303,12 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
|
|
||||||
private function complete(TestResult $testResultSum): int
|
private function complete(TestResult $testResultSum): int
|
||||||
{
|
{
|
||||||
foreach ($this->testresultFiles as $testresultFile) {
|
foreach ($this->testResultFiles as $testResultFile) {
|
||||||
if (! $testresultFile->isFile()) {
|
if (! $testResultFile->isFile()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$contents = file_get_contents($testresultFile->getPathname());
|
$contents = file_get_contents($testResultFile->getPathname());
|
||||||
assert($contents !== false);
|
assert($contents !== false);
|
||||||
$testResult = unserialize($contents);
|
$testResult = unserialize($contents);
|
||||||
assert($testResult instanceof TestResult);
|
assert($testResult instanceof TestResult);
|
||||||
@ -360,9 +365,20 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
$testResultSum->phpNotices(),
|
$testResultSum->phpNotices(),
|
||||||
$testResultSum->phpWarnings(),
|
$testResultSum->phpWarnings(),
|
||||||
$testResultSum->numberOfIssuesIgnoredByBaseline(),
|
$testResultSum->numberOfIssuesIgnoredByBaseline(),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($this->options->configuration->cacheResult()) {
|
||||||
|
$resultCacheSum = new DefaultResultCache($this->options->configuration->testResultCacheFile());
|
||||||
|
foreach ($this->resultCacheFiles as $resultCacheFile) {
|
||||||
|
$resultCache = new DefaultResultCache($resultCacheFile->getPathname());
|
||||||
|
$resultCache->load();
|
||||||
|
|
||||||
|
$resultCacheSum->mergeWith($resultCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
$resultCacheSum->persist();
|
||||||
|
}
|
||||||
|
|
||||||
$this->printer->printResults(
|
$this->printer->printResults(
|
||||||
$testResultSum,
|
$testResultSum,
|
||||||
$this->teamcityFiles,
|
$this->teamcityFiles,
|
||||||
@ -375,7 +391,7 @@ final class WrapperRunner implements RunnerInterface
|
|||||||
$exitcode = Result::exitCode($this->options->configuration, $testResultSum);
|
$exitcode = Result::exitCode($this->options->configuration, $testResultSum);
|
||||||
|
|
||||||
$this->clearFiles($this->unexpectedOutputFiles);
|
$this->clearFiles($this->unexpectedOutputFiles);
|
||||||
$this->clearFiles($this->testresultFiles);
|
$this->clearFiles($this->testResultFiles);
|
||||||
$this->clearFiles($this->coverageFiles);
|
$this->clearFiles($this->coverageFiles);
|
||||||
$this->clearFiles($this->junitFiles);
|
$this->clearFiles($this->junitFiles);
|
||||||
$this->clearFiles($this->teamcityFiles);
|
$this->clearFiles($this->teamcityFiles);
|
||||||
|
|||||||
@ -71,7 +71,7 @@ final class DatasetsRepository
|
|||||||
*
|
*
|
||||||
* @throws ShouldNotHappen
|
* @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];
|
$dataset = self::$withs[$filename.self::SEPARATOR.$description];
|
||||||
|
|
||||||
@ -110,7 +110,6 @@ final class DatasetsRepository
|
|||||||
foreach ($datasetCombination as $datasetCombinationElement) {
|
foreach ($datasetCombination as $datasetCombinationElement) {
|
||||||
$partialDescriptions[] = $datasetCombinationElement['label'];
|
$partialDescriptions[] = $datasetCombinationElement['label'];
|
||||||
|
|
||||||
// @phpstan-ignore-next-line
|
|
||||||
$values = array_merge($values, $datasetCombinationElement['values']);
|
$values = array_merge($values, $datasetCombinationElement['values']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +200,7 @@ final class DatasetsRepository
|
|||||||
throw new DatasetDoesNotExist($name);
|
throw new DatasetDoesNotExist($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $matchingDatasets[$closestScopeDatasetKey];
|
return $matchingDatasets[$closestScopeDatasetKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,6 @@ final class DatasetsRepository
|
|||||||
$result = $tmp;
|
$result = $tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @phpstan-ignore-next-line
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,8 @@ final class SnapshotRepository
|
|||||||
* Creates a snapshot repository instance.
|
* Creates a snapshot repository instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
readonly private string $testsPath,
|
private readonly string $testsPath,
|
||||||
readonly private string $snapshotsPath,
|
private readonly string $snapshotsPath,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -40,7 +40,7 @@ final class Result
|
|||||||
*/
|
*/
|
||||||
public static function exitCode(Configuration $configuration, TestResult $result): int
|
public static function exitCode(Configuration $configuration, TestResult $result): int
|
||||||
{
|
{
|
||||||
if ($result->wasSuccessfulIgnoringPhpunitWarnings()) {
|
if ($result->wasSuccessful()) {
|
||||||
if ($configuration->failOnWarning()) {
|
if ($configuration->failOnWarning()) {
|
||||||
$warnings = $result->numberOfTestsWithTestTriggeredPhpunitWarningEvents()
|
$warnings = $result->numberOfTestsWithTestTriggeredPhpunitWarningEvents()
|
||||||
+ count($result->warnings())
|
+ count($result->warnings())
|
||||||
@ -60,7 +60,7 @@ final class Result
|
|||||||
return self::FAILURE_EXIT;
|
return self::FAILURE_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($result->wasSuccessfulIgnoringPhpunitWarnings()) {
|
if ($result->wasSuccessful()) {
|
||||||
if ($configuration->failOnRisky() && $result->hasTestConsideredRiskyEvents()) {
|
if ($configuration->failOnRisky() && $result->hasTestConsideredRiskyEvents()) {
|
||||||
$returnCode = self::FAILURE_EXIT;
|
$returnCode = self::FAILURE_EXIT;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,14 +23,12 @@ final class EnsureIgnorableTestCasesAreIgnored implements StartedSubscriber
|
|||||||
{
|
{
|
||||||
$reflection = new ReflectionClass(Facade::class);
|
$reflection = new ReflectionClass(Facade::class);
|
||||||
$property = $reflection->getProperty('collector');
|
$property = $reflection->getProperty('collector');
|
||||||
$property->setAccessible(true);
|
|
||||||
$collector = $property->getValue();
|
$collector = $property->getValue();
|
||||||
|
|
||||||
assert($collector instanceof Collector);
|
assert($collector instanceof Collector);
|
||||||
|
|
||||||
$reflection = new ReflectionClass($collector);
|
$reflection = new ReflectionClass($collector);
|
||||||
$property = $reflection->getProperty('testRunnerTriggeredWarningEvents');
|
$property = $reflection->getProperty('testRunnerTriggeredWarningEvents');
|
||||||
$property->setAccessible(true);
|
|
||||||
|
|
||||||
/** @var array<int, WarningTriggered> $testRunnerTriggeredWarningEvents */
|
/** @var array<int, WarningTriggered> $testRunnerTriggeredWarningEvents */
|
||||||
$testRunnerTriggeredWarningEvents = $property->getValue($collector);
|
$testRunnerTriggeredWarningEvents = $property->getValue($collector);
|
||||||
|
|||||||
@ -15,18 +15,18 @@ final class Closure
|
|||||||
/**
|
/**
|
||||||
* Binds the given closure to the given "this".
|
* Binds the given closure to the given "this".
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @throws ShouldNotHappen
|
* @throws ShouldNotHappen
|
||||||
*/
|
*/
|
||||||
public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure
|
public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure
|
||||||
{
|
{
|
||||||
if (! $closure instanceof \Closure) {
|
if (! $closure instanceof BaseClosure) {
|
||||||
throw ShouldNotHappen::fromMessage('Could not bind null closure.');
|
throw ShouldNotHappen::fromMessage('Could not bind null closure.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$closure = BaseClosure::bind($closure, $newThis, $newScope);
|
$closure = BaseClosure::bind($closure, $newThis, $newScope);
|
||||||
|
|
||||||
if (! $closure instanceof \Closure) {
|
if (! $closure instanceof BaseClosure) {
|
||||||
throw ShouldNotHappen::fromMessage('Could not bind closure.');
|
throw ShouldNotHappen::fromMessage('Could not bind closure.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ final class Container
|
|||||||
*/
|
*/
|
||||||
public static function getInstance(): self
|
public static function getInstance(): self
|
||||||
{
|
{
|
||||||
if (! self::$instance instanceof \Pest\Support\Container) {
|
if (! self::$instance instanceof Container) {
|
||||||
self::$instance = new self;
|
self::$instance = new self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,7 @@ final class Coverage
|
|||||||
* Reports the code coverage report to the
|
* Reports the code coverage report to the
|
||||||
* console and returns the result in float.
|
* console and returns the result in float.
|
||||||
*/
|
*/
|
||||||
public static function report(OutputInterface $output): float
|
public static function report(OutputInterface $output, bool $compact = false): float
|
||||||
{
|
{
|
||||||
if (! file_exists($reportPath = self::getPath())) {
|
if (! file_exists($reportPath = self::getPath())) {
|
||||||
if (self::usingXdebug()) {
|
if (self::usingXdebug()) {
|
||||||
@ -113,6 +113,10 @@ final class Coverage
|
|||||||
? '100.0'
|
? '100.0'
|
||||||
: number_format($file->percentageOfExecutedLines()->asFloat(), 1, '.', '');
|
: number_format($file->percentageOfExecutedLines()->asFloat(), 1, '.', '');
|
||||||
|
|
||||||
|
if ($percentage === '100.0' && $compact) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$uncoveredLines = '';
|
$uncoveredLines = '';
|
||||||
|
|
||||||
$percentageOfExecutedLinesAsString = $file->percentageOfExecutedLines()->asString();
|
$percentageOfExecutedLinesAsString = $file->percentageOfExecutedLines()->asString();
|
||||||
|
|||||||
@ -66,6 +66,7 @@ final readonly class Exporter
|
|||||||
|
|
||||||
$result[] = $context->contains($data[$key]) !== false
|
$result[] = $context->contains($data[$key]) !== false
|
||||||
? '*RECURSION*'
|
? '*RECURSION*'
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
: sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context));
|
: sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,7 @@ final readonly class HigherOrderCallables
|
|||||||
*/
|
*/
|
||||||
public function and(mixed $value): Expectation
|
public function and(mixed $value): Expectation
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $this->expect($value);
|
return $this->expect($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,14 +50,13 @@ final class HigherOrderMessage
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->hasHigherOrderCallable()) {
|
if ($this->hasHigherOrderCallable()) {
|
||||||
/* @phpstan-ignore-next-line */
|
|
||||||
return (new HigherOrderCallables($target))->{$this->name}(...$this->arguments);
|
return (new HigherOrderCallables($target))->{$this->name}(...$this->arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return is_array($this->arguments)
|
return is_array($this->arguments)
|
||||||
? Reflection::call($target, $this->name, $this->arguments)
|
? Reflection::call($target, $this->name, $this->arguments)
|
||||||
: $target->{$this->name}; /* @phpstan-ignore-line */
|
: $target->{$this->name};
|
||||||
} catch (Throwable $throwable) {
|
} catch (Throwable $throwable) {
|
||||||
Reflection::setPropertyValue($throwable, 'file', $this->filename);
|
Reflection::setPropertyValue($throwable, 'file', $this->filename);
|
||||||
Reflection::setPropertyValue($throwable, 'line', $this->line);
|
Reflection::setPropertyValue($throwable, 'line', $this->line);
|
||||||
@ -65,7 +64,6 @@ final class HigherOrderMessage
|
|||||||
if ($throwable->getMessage() === $this->getUndefinedMethodMessage($target, $this->name)) {
|
if ($throwable->getMessage() === $this->getUndefinedMethodMessage($target, $this->name)) {
|
||||||
/** @var ReflectionClass<TValue> $reflection */
|
/** @var ReflectionClass<TValue> $reflection */
|
||||||
$reflection = new ReflectionClass($target);
|
$reflection = new ReflectionClass($target);
|
||||||
/* @phpstan-ignore-next-line */
|
|
||||||
$reflection = $reflection->getParentClass() ?: $reflection;
|
$reflection = $reflection->getParentClass() ?: $reflection;
|
||||||
Reflection::setPropertyValue($throwable, 'message', sprintf('Call to undefined method %s::%s()', $reflection->getName(), $this->name));
|
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
|
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, sprintf('%s::%s()', $target::class, $methodName));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(self::UNDEFINED_METHOD, $methodName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,6 @@ final class HigherOrderMessageCollection
|
|||||||
public function chain(object $target): void
|
public function chain(object $target): void
|
||||||
{
|
{
|
||||||
foreach ($this->messages as $message) {
|
foreach ($this->messages as $message) {
|
||||||
// @phpstan-ignore-next-line
|
|
||||||
$target = $message->call($target) ?? $target;
|
$target = $message->call($target) ?? $target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ final class HigherOrderTapProxy
|
|||||||
*/
|
*/
|
||||||
public function __set(string $property, mixed $value): void
|
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)
|
public function __get(string $property)
|
||||||
{
|
{
|
||||||
if (property_exists($this->target, $property)) {
|
if (property_exists($this->target, $property)) {
|
||||||
return $this->target->{$property}; // @phpstan-ignore-line
|
return $this->target->{$property};
|
||||||
}
|
}
|
||||||
|
|
||||||
$className = (new ReflectionClass($this->target))->getName();
|
$className = (new ReflectionClass($this->target))->getName();
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use Closure;
|
|||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Pest\Exceptions\ShouldNotHappen;
|
use Pest\Exceptions\ShouldNotHappen;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use ReflectionFunction;
|
use ReflectionFunction;
|
||||||
@ -34,8 +35,6 @@ final class Reflection
|
|||||||
try {
|
try {
|
||||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||||
|
|
||||||
$reflectionMethod->setAccessible(true);
|
|
||||||
|
|
||||||
return $reflectionMethod->invoke($object, ...$args);
|
return $reflectionMethod->invoke($object, ...$args);
|
||||||
} catch (ReflectionException $exception) {
|
} catch (ReflectionException $exception) {
|
||||||
if (method_exists($object, '__call')) {
|
if (method_exists($object, '__call')) {
|
||||||
@ -68,7 +67,7 @@ final class Reflection
|
|||||||
{
|
{
|
||||||
$test = TestSuite::getInstance()->test;
|
$test = TestSuite::getInstance()->test;
|
||||||
|
|
||||||
if (! $test instanceof \PHPUnit\Framework\TestCase) {
|
if (! $test instanceof TestCase) {
|
||||||
return self::bindCallable($callable);
|
return self::bindCallable($callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +112,6 @@ final class Reflection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$reflectionProperty->setAccessible(true);
|
|
||||||
|
|
||||||
return $reflectionProperty->getValue($object);
|
return $reflectionProperty->getValue($object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,8 +141,6 @@ final class Reflection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$reflectionProperty->setAccessible(true);
|
|
||||||
$reflectionProperty->setValue($object, $value);
|
$reflectionProperty->setValue($object, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +222,7 @@ final class Reflection
|
|||||||
{
|
{
|
||||||
$getProperties = fn (ReflectionClass $reflectionClass): array => array_filter(
|
$getProperties = fn (ReflectionClass $reflectionClass): array => array_filter(
|
||||||
array_map(
|
array_map(
|
||||||
fn (ReflectionProperty $property): \ReflectionProperty => $property,
|
fn (ReflectionProperty $property): ReflectionProperty => $property,
|
||||||
$reflectionClass->getProperties(),
|
$reflectionClass->getProperties(),
|
||||||
), fn (ReflectionProperty $property): bool => $property->getDeclaringClass()->getName() === $reflectionClass->getName(),
|
), fn (ReflectionProperty $property): bool => $property->getDeclaringClass()->getName() === $reflectionClass->getName(),
|
||||||
);
|
);
|
||||||
@ -262,7 +257,7 @@ final class Reflection
|
|||||||
{
|
{
|
||||||
$getMethods = fn (ReflectionClass $reflectionClass): array => array_filter(
|
$getMethods = fn (ReflectionClass $reflectionClass): array => array_filter(
|
||||||
array_map(
|
array_map(
|
||||||
fn (ReflectionMethod $method): \ReflectionMethod => $method,
|
fn (ReflectionMethod $method): ReflectionMethod => $method,
|
||||||
$reflectionClass->getMethods($filter),
|
$reflectionClass->getMethods($filter),
|
||||||
), fn (ReflectionMethod $method): bool => $method->getDeclaringClass()->getName() === $reflectionClass->getName(),
|
), fn (ReflectionMethod $method): bool => $method->getDeclaringClass()->getName() === $reflectionClass->getName(),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -30,6 +30,7 @@ final class StateGenerator
|
|||||||
$testResultEvent->throwable()
|
$testResultEvent->throwable()
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
$state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));
|
$state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,33 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<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"
|
bootstrap="vendor/autoload.php"
|
||||||
colors="true"
|
colors="true"
|
||||||
>
|
>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="Unit">
|
<testsuite name="Unit">
|
||||||
<directory suffix="Test.php">./tests/Unit</directory>
|
<directory>tests/Unit</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="Feature">
|
<testsuite name="Feature">
|
||||||
<directory suffix="Test.php">./tests/Feature</directory>
|
<directory>tests/Feature</directory>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
<source>
|
||||||
|
<include>
|
||||||
|
<directory>app</directory>
|
||||||
|
</include>
|
||||||
|
</source>
|
||||||
<php>
|
<php>
|
||||||
<env name="APP_ENV" value="testing"/>
|
<env name="APP_ENV" value="testing"/>
|
||||||
|
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
||||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
<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_CONNECTION" value="sqlite"/> -->
|
||||||
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
||||||
<env name="MAIL_MAILER" value="array"/>
|
<env name="MAIL_MAILER" value="array"/>
|
||||||
|
<env name="PULSE_ENABLED" value="false"/>
|
||||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||||
<env name="SESSION_DRIVER" value="array"/>
|
<env name="SESSION_DRIVER" value="array"/>
|
||||||
<env name="TELESCOPE_ENABLED" value="false"/>
|
<env name="TELESCOPE_ENABLED" value="false"/>
|
||||||
</php>
|
</php>
|
||||||
<source>
|
|
||||||
<include>
|
|
||||||
<directory suffix=".php">./app</directory>
|
|
||||||
</include>
|
|
||||||
</source>
|
|
||||||
</phpunit>
|
</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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<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"
|
bootstrap="vendor/autoload.php"
|
||||||
colors="true"
|
colors="true"
|
||||||
>
|
>
|
||||||
@ -11,8 +11,8 @@
|
|||||||
</testsuites>
|
</testsuites>
|
||||||
<source>
|
<source>
|
||||||
<include>
|
<include>
|
||||||
<directory suffix=".php">./app</directory>
|
<directory>app</directory>
|
||||||
<directory suffix=".php">./src</directory>
|
<directory>src</directory>
|
||||||
</include>
|
</include>
|
||||||
</source>
|
</source>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
Pest Testing Framework 3.5.2.
|
Pest Testing Framework 3.8.6.
|
||||||
|
|
||||||
USAGE: pest <file> [options]
|
USAGE: pest <file> [options]
|
||||||
|
|
||||||
@ -53,7 +53,7 @@
|
|||||||
--disallow-test-output ................. Be strict about output during tests
|
--disallow-test-output ................. Be strict about output during tests
|
||||||
--enforce-time-limit ................. Enforce time limit based on test size
|
--enforce-time-limit ................. Enforce time limit based on test size
|
||||||
--default-time-limit [sec] Timeout in seconds for tests that have no declared 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-defect ... Stop after first error, failure, warning, or risky test
|
||||||
--stop-on-error ..................................... Stop after first error
|
--stop-on-error ..................................... Stop after first error
|
||||||
--stop-on-failure ................................. Stop after first failure
|
--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-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-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-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-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-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-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
|
--cache-result ............................ Write test results to cache file
|
||||||
--do-not-cache-result .............. Do not 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
|
--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-errors ............. Display details for errors triggered by tests
|
||||||
--display-notices ........... Display details for notices triggered by tests
|
--display-notices ........... Display details for notices triggered by tests
|
||||||
--display-warnings ......... Display details for warnings 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
|
--reverse-list .............................. Print defects in reverse order
|
||||||
--teamcity . Replace default progress and result output with TeamCity format
|
--teamcity . Replace default progress and result output with TeamCity format
|
||||||
--testdox ................ Replace default result output with TestDox format
|
--testdox ................ Replace default result output with TestDox format
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
Pest Testing Framework 3.5.2.
|
Pest Testing Framework 3.8.6.
|
||||||
|
|
||||||
|
|||||||
@ -1428,16 +1428,6 @@
|
|||||||
PASS Tests\Hooks\BeforeEachTest
|
PASS Tests\Hooks\BeforeEachTest
|
||||||
✓ global beforeEach execution order
|
✓ 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
|
PASS Tests\PHPUnit\CustomAffixes\InvalidTestName
|
||||||
✓ it runs file names like @#$%^&()-_=+.php
|
✓ it runs file names like @#$%^&()-_=+.php
|
||||||
|
|
||||||
@ -1491,6 +1481,16 @@
|
|||||||
PASS Tests\Playground
|
PASS Tests\Playground
|
||||||
✓ basic
|
✓ basic
|
||||||
|
|
||||||
|
PASS Tests\Plugins\Coverage
|
||||||
|
✓ compute comparable coverage with (0, 0)
|
||||||
|
✓ compute comparable coverage with (0.5, 0.5)
|
||||||
|
✓ compute comparable coverage with (1.0, 1.0)
|
||||||
|
✓ compute comparable coverage with (32.51, 32.5)
|
||||||
|
✓ compute comparable coverage with (32.12312321312312, 32.1)
|
||||||
|
✓ compute comparable coverage with (32.53333333333333, 32.5)
|
||||||
|
✓ compute comparable coverage with (32.57777771232132, 32.5)
|
||||||
|
✓ compute comparable coverage with (100.0, 100.0)
|
||||||
|
|
||||||
PASS Tests\Plugins\Traits
|
PASS Tests\Plugins\Traits
|
||||||
✓ it allows global uses
|
✓ it allows global uses
|
||||||
✓ it allows multiple global uses registered in the same path
|
✓ it allows multiple global uses registered in the same path
|
||||||
@ -1698,4 +1698,4 @@
|
|||||||
WARN Tests\Visual\Version
|
WARN Tests\Visual\Version
|
||||||
- visual snapshot of help command output
|
- visual snapshot of help command output
|
||||||
|
|
||||||
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 38 todos, 24 skipped, 1142 passed (2720 assertions)
|
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 38 todos, 33 skipped, 1144 passed (2736 assertions)
|
||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Pest\Plugin;
|
||||||
|
|
||||||
trait PluginTrait
|
trait PluginTrait
|
||||||
{
|
{
|
||||||
public function assertPluginTraitGotRegistered(): void
|
public function assertPluginTraitGotRegistered(): void
|
||||||
@ -16,8 +18,8 @@ trait SecondPluginTrait
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pest\Plugin::uses(PluginTrait::class);
|
Plugin::uses(PluginTrait::class);
|
||||||
Pest\Plugin::uses(SecondPluginTrait::class);
|
Plugin::uses(SecondPluginTrait::class);
|
||||||
|
|
||||||
function _assertThat()
|
function _assertThat()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$foo = new \stdClass;
|
$foo = new stdClass;
|
||||||
$foo->bar = 0;
|
$foo->bar = 0;
|
||||||
|
|
||||||
beforeAll(function () use ($foo) {
|
beforeAll(function () use ($foo) {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ it('adds coverage if --coverage exist', function () {
|
|||||||
$arguments = $plugin->handleArguments(['--coverage']);
|
$arguments = $plugin->handleArguments(['--coverage']);
|
||||||
expect($arguments)->toEqual(['--coverage-php', Coverage::getPath()])
|
expect($arguments)->toEqual(['--coverage-php', Coverage::getPath()])
|
||||||
->and($plugin->coverage)->toBeTrue();
|
->and($plugin->coverage)->toBeTrue();
|
||||||
})->skip(! \Pest\Support\Coverage::isAvailable() || ! function_exists('xdebug_info') || ! in_array('coverage', xdebug_info('mode'), true), 'Coverage is not available');
|
})->skip(! Coverage::isAvailable() || ! function_exists('xdebug_info') || ! in_array('coverage', xdebug_info('mode'), true), 'Coverage is not available');
|
||||||
|
|
||||||
it('adds coverage if --min exist', function () {
|
it('adds coverage if --min exist', function () {
|
||||||
$plugin = new CoveragePlugin(new ConsoleOutput);
|
$plugin = new CoveragePlugin(new ConsoleOutput);
|
||||||
|
|||||||
@ -39,7 +39,7 @@ it('allows to call underlying protected/private methods', function () {
|
|||||||
|
|
||||||
it('throws error if method do not exist', function () {
|
it('throws error if method do not exist', function () {
|
||||||
test()->foo();
|
test()->foo();
|
||||||
})->throws(\ReflectionException::class, 'Call to undefined method PHPUnit\Framework\TestCase::foo()');
|
})->throws(ReflectionException::class, 'Call to undefined method PHPUnit\Framework\TestCase::foo()');
|
||||||
|
|
||||||
it('can forward unexpected calls to any global function')->_assertThat();
|
it('can forward unexpected calls to any global function')->_assertThat();
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \PHPUnit\Framework\TestCase
|
* @return TestCase
|
||||||
*/
|
*/
|
||||||
function myAssertTrue($value)
|
function myAssertTrue($value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,8 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class MyCustomClassTest extends PHPUnit\Framework\TestCase
|
class MyCustomClassTest extends TestCase
|
||||||
{
|
{
|
||||||
public function assertTrueIsTrue()
|
public function assertTrueIsTrue()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
pest()->use(Tests\CustomTestCase\CustomTestCase::class)->in(__DIR__);
|
use Tests\CustomTestCase\CustomTestCase;
|
||||||
|
|
||||||
|
pest()->use(CustomTestCase::class)->in(__DIR__);
|
||||||
|
|
||||||
test('closure was bound to CustomTestCase', function () {
|
test('closure was bound to CustomTestCase', function () {
|
||||||
$this->assertCustomTrue();
|
$this->assertCustomTrue();
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
trait MyCustomTrait
|
trait MyCustomTrait
|
||||||
{
|
{
|
||||||
public function assertFalseIsFalse()
|
public function assertFalseIsFalse()
|
||||||
@ -8,7 +10,7 @@ trait MyCustomTrait
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MyCustomClass extends PHPUnit\Framework\TestCase
|
abstract class MyCustomClass extends TestCase
|
||||||
{
|
{
|
||||||
public function assertTrueIsTrue()
|
public function assertTrueIsTrue()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use Pest\Plugins\Coverage;
|
|||||||
use Symfony\Component\Console\Output\NullOutput;
|
use Symfony\Component\Console\Output\NullOutput;
|
||||||
|
|
||||||
test('compute comparable coverage', function (float $givenValue, float $expectedValue) {
|
test('compute comparable coverage', function (float $givenValue, float $expectedValue) {
|
||||||
$output = new NullOutput();
|
$output = new NullOutput;
|
||||||
|
|
||||||
$plugin = new Coverage($output);
|
$plugin = new Coverage($output);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Pest\Configuration\Printer;
|
||||||
|
|
||||||
it('creates a printer instance', function () {
|
it('creates a printer instance', function () {
|
||||||
$theme = pest()->printer();
|
$theme = pest()->printer();
|
||||||
|
|
||||||
expect($theme)->toBeInstanceOf(Pest\Configuration\Printer::class);
|
expect($theme)->toBeInstanceOf(Printer::class);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
test('collision', function (array $arguments) {
|
test('collision', function (array $arguments) {
|
||||||
$output = function () use ($arguments) {
|
$output = function () use ($arguments) {
|
||||||
$process = (new Symfony\Component\Process\Process(
|
$process = (new Process(
|
||||||
array_merge(['php', 'bin/pest', 'tests/Fixtures/CollisionTest.php'], $arguments),
|
array_merge(['php', 'bin/pest', 'tests/Fixtures/CollisionTest.php'], $arguments),
|
||||||
null,
|
null,
|
||||||
['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true', 'COLLISION_TEST' => true]
|
['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true', 'COLLISION_TEST' => true]
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
test('visual snapshot of help command output', function () {
|
test('visual snapshot of help command output', function () {
|
||||||
$output = function () {
|
$output = function () {
|
||||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest', '--help'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));
|
$process = (new Process(['php', 'bin/pest', '--help'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));
|
||||||
|
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ $run = function () {
|
|||||||
|
|
||||||
test('parallel', function () use ($run) {
|
test('parallel', function () use ($run) {
|
||||||
expect($run('--exclude-group=integration'))
|
expect($run('--exclude-group=integration'))
|
||||||
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 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');
|
->toContain('Parallel: 3 processes');
|
||||||
})->skipOnWindows();
|
})->skipOnWindows();
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
test('visual snapshot of test suite on success', function () {
|
test('visual snapshot of test suite on success', function () {
|
||||||
$testsPath = dirname(__DIR__);
|
$testsPath = dirname(__DIR__);
|
||||||
$snapshot = implode(DIRECTORY_SEPARATOR, [
|
$snapshot = implode(DIRECTORY_SEPARATOR, [
|
||||||
@ -9,7 +11,7 @@ test('visual snapshot of test suite on success', function () {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$output = function () use ($testsPath) {
|
$output = function () use ($testsPath) {
|
||||||
$process = (new Symfony\Component\Process\Process(
|
$process = (new Process(
|
||||||
['php', 'bin/pest'],
|
['php', 'bin/pest'],
|
||||||
dirname($testsPath),
|
dirname($testsPath),
|
||||||
['EXCLUDE' => 'integration', '--exclude-group' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0, 'COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],
|
['EXCLUDE' => 'integration', '--exclude-group' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0, 'COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
function normalize_windows_os_output(string $text): string
|
function normalize_windows_os_output(string $text): string
|
||||||
{
|
{
|
||||||
$text = str_replace('\r', '', $text);
|
$text = str_replace('\r', '', $text);
|
||||||
@ -17,7 +19,7 @@ test('visual snapshot of team city', function (string $testFile) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$output = function () use ($testsPath) {
|
$output = function () use ($testsPath) {
|
||||||
$process = (new Symfony\Component\Process\Process(
|
$process = (new Process(
|
||||||
['php', 'bin/pest', '--teamcity', $testsPath],
|
['php', 'bin/pest', '--teamcity', $testsPath],
|
||||||
dirname(__DIR__, levels: 2),
|
dirname(__DIR__, levels: 2),
|
||||||
[
|
[
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
test('visual snapshot of help command output', function () {
|
test('visual snapshot of help command output', function () {
|
||||||
$output = function () {
|
$output = function () {
|
||||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest', '--version'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));
|
$process = (new Process(['php', 'bin/pest', '--version'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));
|
||||||
|
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user