fix(scheduler): skip test directories in ScheduledActionScanner
Test files inside module Tests/ directories (e.g. app/Mod/Lem/Tests/) extend Tests\TestCase which isn't available in production without dev dependencies. The scanner now skips /Tests/ directories and *Test.php files, and wraps class_exists() in try/catch for defence in depth. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
7db3637985
commit
d02f4361e3
3 changed files with 59 additions and 1 deletions
|
|
@ -52,9 +52,26 @@ class ScheduledActionScanner
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip test directories — test files extend base classes
|
||||||
|
// that aren't available without dev dependencies.
|
||||||
|
// Convention: module test dirs use capital "Tests/" (e.g. app/Mod/Lem/Tests/).
|
||||||
|
if (preg_match('#[/\\\\]Tests[/\\\\]#', $file->getPathname())
|
||||||
|
|| str_ends_with($file->getBasename(), 'Test.php')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$class = $this->classFromFile($file->getPathname());
|
$class = $this->classFromFile($file->getPathname());
|
||||||
|
|
||||||
if ($class === null || ! class_exists($class)) {
|
if ($class === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (! class_exists($class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} catch (\Throwable) {
|
||||||
|
// Class may reference unavailable dependencies (e.g. dev-only)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,4 +70,21 @@ class ScheduledActionScannerTest extends TestCase
|
||||||
$results = $this->scanner->scan(['/nonexistent/path']);
|
$results = $this->scanner->scan(['/nonexistent/path']);
|
||||||
$this->assertEmpty($results);
|
$this->assertEmpty($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_scan_skips_test_directories(): void
|
||||||
|
{
|
||||||
|
$results = $this->scanner->scan([
|
||||||
|
dirname(__DIR__).'/Fixtures/Mod/Scheduled',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// FakeScheduledTest is inside a Tests/ directory and should be skipped
|
||||||
|
$classes = array_keys($results);
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
$this->assertStringNotContainsString('FakeScheduledTest', $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// But real actions are still discovered
|
||||||
|
$this->assertArrayHasKey(EveryMinuteAction::class, $results);
|
||||||
|
$this->assertArrayHasKey(DailyAction::class, $results);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
tests/Fixtures/Mod/Scheduled/Tests/FakeScheduledTest.php
Normal file
24
tests/Fixtures/Mod/Scheduled/Tests/FakeScheduledTest.php
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Core\Tests\Fixtures\Mod\Scheduled\Tests;
|
||||||
|
|
||||||
|
use Core\Actions\Action;
|
||||||
|
use Core\Actions\Scheduled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file lives inside a Tests/ directory to verify that the
|
||||||
|
* scanner skips test directories. Despite having #[Scheduled],
|
||||||
|
* it should never be discovered.
|
||||||
|
*/
|
||||||
|
#[Scheduled(frequency: 'everyMinute')]
|
||||||
|
class FakeScheduledTest
|
||||||
|
{
|
||||||
|
use Action;
|
||||||
|
|
||||||
|
public function handle(): string
|
||||||
|
{
|
||||||
|
return 'should-not-be-discovered';
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue