[Bug]: pest --init detects laravel/framework in plain php application when Herd is installed
What Happened
I set up a simple plain php application with pest (see below for bash setup and resulting composer.json). Then I ran vendor/bin/pest --init.
The generated code is for laravel (contains use Illuminate\Foundation\Testing\TestCase as BaseTestCase;) and does not work.
$ vendor/bin/pest
Error
Class "Illuminate\Foundation\Testing\TestCase" not found
at tests/TestCase.php:7
3▕ namespace Tests;
4▕
5▕ use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
6▕
➜ 7▕ abstract class TestCase extends BaseTestCase
8▕ {
9▕ //
10▕ }
11▕
+2 vendor frames
3 [internal]:0
Composer\Autoload\ClassLoader::loadClass("Tests\TestCase")
+2 vendor frames
6 tests/Pest.php:16
Pest\PendingCalls\UsesCall::__destruct()
I expect pest not to detect laravel, and instead use the stubs for PhpUnit (use PHPUnit\Framework\TestCase as BaseTestCase;)
How to Reproduce
I have Laravel Herd installed (v1.20.3) on a Mac, using php 8.4.8 and composer 2.8.9.
Setup bash:
$ composer init --name=thomas/test --require-dev=pestphp/pest:^3.8 --autoload=src --no-interaction
Writing ./composer.json
PSR-4 autoloading configured. Use "namespace Thomas\Test;" in src
Include the Composer autoloader with: require 'vendor/autoload.php';
$ composer install
...
Do you trust "pestphp/pest-plugin" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] y
...
$ vendor/bin/pest --init
Resulting composer.json:
{
"name": "thomas/test",
"require-dev": {
"pestphp/pest": "^3.8"
},
"autoload": {
"psr-4": {
"Thomas\\Test\\": "src"
}
},
"require": {},
"config": {
"allow-plugins": {
"pestphp/pest-plugin": true
}
}
}
Sample Repository
No response
Pest Version
3.8.2
PHP Version
8.4.8
Operation System
macOS
Notes
I set up a test script to dig into the problem:
$ composer require composer-runtime-api
$ cat src/info.php
<?php
require_once 'vendor/autoload.php';
use Composer\InstalledVersions;
var_dump(InstalledVersions::isInstalled('laravel/framework'));
var_dump(InstalledVersions::getInstallPath('laravel/framework'));
$ php src/info.php
bool(true)
string(101) "phar:///Applications/Herd.app/Contents/Resources/valet/dump.phar/vendor/composer/../laravel/framework"
This clearly shows that InstalledVersions::isInstalled gives the wrong result. It seems not to be limited to local dependencies.
However, adding false as the second parameter ($includeDevRequirements), yields the expected result for me:
var_dump(InstalledVersions::isInstalled('laravel/framework', false));
// output:
// bool(false)
// string(101) "phar:///Applications/Herd.app/Contents/Resources/valet/dump.phar/vendor/composer/../laravel/framework"
So, maybe this could be fixed here, by adding a second boolean parameter: https://github.com/pestphp/pest/blob/3.x/src/Plugins/Init.php#L122
However, this would most likely not be an actual fix. I think the base problem is a missing composer php API to ignore global requirements when querying installed packages.