Skip to content

[Feature]: Better Intellisense for PestPHP #524

@ace-of-aces

Description

@ace-of-aces

Feature Description

Hey!

What causes a lot of friction for me currently as a Laravel dev in an environment with VS Code, PHP and Laravel is the subpar DX when it comes to writing tests with PestPHP.
I'd really like to improve this, meaning that I'd want to contribute this feature.

Note

I'm only focussing on Intelephense as an LSP here, as that's what I'm using and is the most commonly used PHP LSP in VS Code, but most of this should apply to other LSPs as well.

Technical context

I think the currently insufficient LSP support for Pest is mainly due to the magic mapping of the $this variable in the function-only API of Pest.

Intelephense did not provide any autocompletion or error detection for the $this variable in Pest test cases until recently. In version 1.15, they added support for the @param-closure-this PHPDoc tag, which is used inside Pest's function declarations, so Intelephense can actually resolve the $this variable inside of test cases.

While this is great, there's an issue with it in Laravel projects: The TestCase class inside of Pest itself is just the PHPUnit TestCase class. In Laravel projects, we're typically using Laravel's enriched TestCase, and in most setups even a user-defined TestCase which extends the one from the framework.

This mismatch leads to lots of "Undefined method" errors in test files by default:

Image

When users don't want to ignore those errors, they currently have to manually resolve them, which can be achieved in two ways:

  1. Tedious inline type hints in every single test case:
test('guests are redirected to the login page', function () {
    /** @var Tests\TestCase $this */ // <----- This
    $response = $this->get(route('dashboard'));
    $response->assertRedirect(route('login'));
});
  1. Through an IDE helper file, like this one I created based on this comment by the creator of Intelephense.

The second approach is obviously more scalable.

So while what I described so far is my main pain point, there's another Pest API which isn't supported by the LSP by default, and that's Custom Expectations.

For example, when a user has defined a custom expectation:

// Pest.php
expect()->extend('toBeOne', function () {
    return $this->toBe(1);
});

Just like with the test functions, this can be hinted to the LSP via an IDE helper file:

<?php

namespace Pest {
    class Expectation
    {
        public function toBeOne() {}
    }
}

My feature suggestion

So to lift this pain from developers, I'd love to have this handled via this extension.

Fortunately there's already the existing infrastructure in place to generate helpers, like the vendor/_laravel_ide_/_facade.php file. I'd suggest generating additional helpers mentioned above for Pest.

So, if you would be open to this addition, I'd love to hear some feedback on:

  • how deep and accurate this should go (just basic static helpers or parsing custom expectations and providing them etc.)
  • if and how this should be user-configurable or auto-discovered (e.g. when tests/Pest.php exists or when Pest is detected in composer.json)
  • how exactly the helpers should look like (e.g. with @see tags to the actual implementation?)

I would happily do what it takes for this and start working on a PR! 😊

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions