alies-dev/psalm-plugin-pest
Psalm plugin for Pest
Makes Psalm understand Pest test files.
$thisin test closures. Pest binds everytest(),it(),beforeEach()andafterEach()closure to a TestCase, so$this->useror$this->actingAs()is valid code. Pest documents that binding only as@param-closure-this TestCall, which Psalm 6.19+ reads literally: every$this->...in a test becomesUndefinedThisPropertyFetchorUndefinedMethodonTestCall, plus aMixed*cascade. The plugin binds$thisto the class Pest actually uses.- Pest's public API. Pest marks the classes behind
expect()->toBe(),uses()->in(),pest()->extend()andtest()->group()as@internal. The plugin stops reportingInternalMethodon them. Pest classes outside that API keep reporting.
Installation
composer require --dev alies-dev/psalm-plugin-pest
vendor/bin/psalm-plugin enable alies-dev/psalm-plugin-pest
Requirements: PHP 8.3+ (Pest 4's floor), Psalm 6.19+ or 7, Pest 4. Your test directory must be part of <projectFiles>.
How the TestCase is resolved
For each test file, first match wins:
- The class passed to
uses(...)orpest()->extend(...)in the test file itself. - The class assigned to the file's directory through
uses(...)->in(...)orpest()->extend(...)->in(...)intests/Pest.php, or in any other file Pest loads at boot:tests/Helpers.php,tests/Expectations.php, thetests/Helpers/andtests/Expectations/trees, everyDatasets.php, and every file under aDatasets/directory.in()accepts string literals, globs,__DIR__and__DIR__ . '/Feature'. PHPUnit\Framework\TestCase, Pest's default, for files insidetests/.
Traits passed to uses() never decide the class. The files are parsed, never executed.
When the answer is uncertain the plugin keeps Pest's own TestCall binding rather than guess.
Known limitations
tests/Pest.phpis looked up next to your Psalm config. A custom test directory (Pest's--test-directory) is not detected, and its tests keep Pest's binding.- A test file outside
tests/(for example a monorepo package with its own suite) keeps Pest's binding. - A boot file the plugin cannot read statically disables resolution for the whole suite. That covers a variable argument, a call inside a condition or a closure, an
include, a top-levelreturnorexit, an aliaseduse function uses, and a symlinked file. uses()->in()written in one test file to configure other files is ignored.- Analyzing a single test file on its own declines when its TestCase class was not scanned; full project runs are unaffected.
- Properties a test assigns dynamically (
$this->user = ...inbeforeEach()) are reported, because Psalm now sees the real TestCase. Declare them on the TestCase. - Psalm 7.0.0-beta22 has no
@param-closure-thissupport, so there$thisin a test closure is stillInvalidScope. Binding activates automatically on a Psalm 7 release that carries it (vimeo/psalm master does). TheInternalMethodrelief works on every supported version. - Pest 5 is untested. The plugin keys on Pest's
@param-closure-this TestCalltag and class names, and does nothing if those change.
License
MIT, see LICENSE.
Related Packages
sikessem/devtools
๐งช Tools needed for PHP and Laravel project development and automation.
6,003
1
actions
analyze-code
code-analyzer
code-inpector
collision
dd
debug
debugbar
debugger
dev
dev-tools
devtools
die-dump
dump
fake
faker
ide-helper
ignition
inspect-code
larastan
laravel
laravel-debugbar
laravel-devtools
laravel-test-tools
laravel-testing-tools
laravel-tools
lint
mock
mockery
pest
php
phpstan
phpunit
pint
psalm
ray
rector
refactor
sigui
siguici
sikessem
test
test-automation
test-tools
testing
testing-tools
var-dump
var-dumper
web-tools
webtools
jakehenshall/pest-plugin-wordpress
The most comprehensive WordPress testing framework built on Pest PHP v4. Include...
6
1
odinns/phpstan-pest-this
PHPStan extensions to infer Pest closure $this type from test file mappings.
2,838
1