Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Peststan Laravel Package

mrpunyapal/peststan

PHPStan extension for Pest PHP. Adds generic typing for expect(), type-narrowing assertions, type-safe and() chaining, correct $this binding in test closures, and accurate return types for Pest functions. Supports Pest 3–5 on PHP 8.2+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev mrpunyapal/peststan
    

    If using phpstan/extension-installer, no further config is needed. Otherwise, add to phpstan.neon:

    includes:
        - vendor/mrpunyapal/peststan/extension.neon
    
  2. First Use Case: Run PHPStan on your test directory:

    vendor/bin/phpstan analyse tests
    

    PestStan will now provide type hints for expect() calls and $this binding in test closures.


Implementation Patterns

Core Workflow: Type-Safe Testing

  1. Expectation Chaining:

    expect($user)
        ->toBeInstanceOf(User::class)
        ->and($user->posts)
        ->toHaveCount(3);
    
    • PHPStan tracks the narrowed type (User) through assertions.
  2. Dynamic Property Inference:

    beforeEach(function () {
        $this->user = User::factory()->create(); // PestStan infers type as `User`
    });
    
  3. TestCase Integration:

    // tests/Pest.php
    uses(Tests\TestCase::class)->in('Feature');
    
    // tests/Feature/UserTest.php
    it('uses TestCase methods', function () {
        $this->assertDatabaseHas('users', ['email' => 'test@example.com']);
        // PHPStan knows $this is Tests\TestCase
    });
    

Advanced Patterns

  1. Custom TestCase Helpers:

    // tests/Pest.php
    uses(CustomTestCase::class)->in('Unit');
    
    // CustomTestCase.php
    public function customHelper() { ... }
    
    // Test file
    it('uses custom helper')->customHelper(); // Works in TestCall chains
    
  2. Architecture Testing:

    expect('App\Models')
        ->toExtend('Illuminate\Database\Eloquent\Model')
        ->ignoring('App\Models\Legacy');
    
  3. Rule-Based Refactoring: Use PestStan’s static analysis rules to catch issues early:

    // Catches empty test closures
    it('forgot assertions'); // Triggers `pest.test.emptyClosure`
    

Gotchas and Tips

Common Pitfalls

  1. $this in beforeAll():

    beforeAll(function () {
        $this->db = new Database(); // ❌ Error: $this unavailable
    });
    

    Fix: Use beforeEach() instead.

  2. Union Types in Dynamic Properties:

    beforeEach(function () {
        $this->item = new Post(); // Type: Post
    });
    beforeEach(function () {
        $this->item = new Comment(); // Type: Post|Comment
    });
    

    Tip: PestStan unionizes types across hooks.

  3. Static Closures:

    it('fails', static function () { ... }); // ❌ Error: `pest.test.staticClosure`
    

Debugging Tips

  1. Manual TestCase Override: If auto-detection fails, force it in phpstan.neon:

    parameters:
        peststan:
            testCaseClass: App\Testing\CustomTestCase
    
  2. Ignoring Rules: Suppress specific rules inline:

    /** @phpstan-ignore pest.expectation.impossible */
    expect(42)->toBeString(); // Ignores redundant assertion
    
  3. Extension Paths: Ensure Pest.php files are in PHPStan’s paths:

    parameters:
        peststan:
            pestConfigFiles:
                - tests/Pest.php
    

Extension Points

  1. Custom Assertions: Extend ExpectationTypeNarrower to support new expect() methods.

  2. Rule Customization: Add new static analysis rules by extending PestDiagnosticIdentifiers.

  3. Pest Version Compatibility: Check src/Analysis/PestVersionResolver.php to ensure support for your Pest version.


```markdown
### Pro Tips for Daily Use
- **Leverage `and()` for Complex Chains**:
  ```php
  expect($user)
      ->toBeInstanceOf(User::class)
      ->and($user->posts)
      ->toHaveCount(3)
      ->each(fn ($post) => expect($post)->toBePublished());

PHPStan tracks types through each step.

  • Use toBeInstanceOf for Polymorphism:

    expect($entity)->toBeInstanceOf(Post::class | Comment::class);
    

    PestStan handles union types in assertions.

  • Architecture Testing: Validate class relationships without runtime checks:

    expect('App\Services')->toBeInvokable();
    
  • Rule-Based CI Checks: Add PestStan rules to your CI baseline to enforce test quality:

    # phpstan.neon
    parameters:
        level: 8
        ignoreErrors:
            - identifier: pest.test.emptyClosure
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky