134 lines
3.8 KiB
PHP
134 lines
3.8 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace Phred\Beacon\Tests\Integration;
|
||
|
|
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
use Phred\Beacon\AsEventListener;
|
||
|
|
use Phred\Beacon\AsSubscriber;
|
||
|
|
use Phred\Beacon\EventDispatcher;
|
||
|
|
use Phred\Beacon\ListenerDiscovery;
|
||
|
|
use Phred\Beacon\ListenerProvider;
|
||
|
|
use Phred\BeaconContracts\SubscriberInterface;
|
||
|
|
use Psr\Container\ContainerInterface;
|
||
|
|
|
||
|
|
class DiscoveryIntegrationTest extends TestCase
|
||
|
|
{
|
||
|
|
private string $tempDir;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
$this->tempDir = sys_get_temp_dir() . '/beacon_discovery_test_' . uniqid();
|
||
|
|
mkdir($this->tempDir);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function tearDown(): void
|
||
|
|
{
|
||
|
|
$this->removeDir($this->tempDir);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_it_discovers_attributed_listeners(): void
|
||
|
|
{
|
||
|
|
$this->createTestClass('TestListener', <<<'PHP'
|
||
|
|
namespace Phred\Discovery;
|
||
|
|
use Phred\Beacon\AsEventListener;
|
||
|
|
class TestListener {
|
||
|
|
#[AsEventListener(event: 'stdClass', priority: 10)]
|
||
|
|
public function onEvent($event): void { $event->called = true; }
|
||
|
|
}
|
||
|
|
PHP
|
||
|
|
);
|
||
|
|
|
||
|
|
$provider = new ListenerProvider();
|
||
|
|
$discovery = new ListenerDiscovery([$this->tempDir]);
|
||
|
|
$discovery->discover($provider);
|
||
|
|
|
||
|
|
$dispatcher = new EventDispatcher($provider);
|
||
|
|
$event = new \stdClass();
|
||
|
|
$event->called = false;
|
||
|
|
|
||
|
|
$dispatcher->dispatch($event);
|
||
|
|
|
||
|
|
$this->assertTrue($event->called);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_it_discovers_subscribers(): void
|
||
|
|
{
|
||
|
|
$this->createTestClass('TestSubscriber', <<<'PHP'
|
||
|
|
namespace Phred\Discovery;
|
||
|
|
use Phred\Beacon\AsSubscriber;
|
||
|
|
use Phred\BeaconContracts\SubscriberInterface;
|
||
|
|
#[AsSubscriber]
|
||
|
|
class TestSubscriber implements SubscriberInterface {
|
||
|
|
public static function getSubscribedEvents(): array {
|
||
|
|
return ['stdClass' => 'onEvent'];
|
||
|
|
}
|
||
|
|
public function onEvent($event): void { $event->sub_called = true; }
|
||
|
|
}
|
||
|
|
PHP
|
||
|
|
);
|
||
|
|
|
||
|
|
$provider = new ListenerProvider();
|
||
|
|
$discovery = new ListenerDiscovery([$this->tempDir]);
|
||
|
|
$discovery->discover($provider);
|
||
|
|
|
||
|
|
$dispatcher = new EventDispatcher($provider);
|
||
|
|
$event = new \stdClass();
|
||
|
|
$event->sub_called = false;
|
||
|
|
|
||
|
|
$dispatcher->dispatch($event);
|
||
|
|
|
||
|
|
$this->assertTrue($event->sub_called);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_lazy_loading_via_container(): void
|
||
|
|
{
|
||
|
|
$this->createTestClass('LazyListener', <<<'PHP'
|
||
|
|
namespace Phred\Discovery;
|
||
|
|
use Phred\Beacon\AsEventListener;
|
||
|
|
class LazyListener {
|
||
|
|
#[AsEventListener(event: 'stdClass')]
|
||
|
|
public function __invoke($event): void { $event->lazy_called = true; }
|
||
|
|
}
|
||
|
|
PHP
|
||
|
|
);
|
||
|
|
|
||
|
|
$container = $this->createMock(ContainerInterface::class);
|
||
|
|
$container->expects($this->once())
|
||
|
|
->method('get')
|
||
|
|
->with('Phred\Discovery\LazyListener')
|
||
|
|
->willReturn(new class {
|
||
|
|
public function __invoke($event) { $event->lazy_called = true; }
|
||
|
|
});
|
||
|
|
|
||
|
|
$provider = new ListenerProvider($container);
|
||
|
|
$discovery = new ListenerDiscovery([$this->tempDir]);
|
||
|
|
$discovery->discover($provider);
|
||
|
|
|
||
|
|
$dispatcher = new EventDispatcher($provider);
|
||
|
|
$event = new \stdClass();
|
||
|
|
$event->lazy_called = false;
|
||
|
|
|
||
|
|
$dispatcher->dispatch($event);
|
||
|
|
|
||
|
|
$this->assertTrue($event->lazy_called);
|
||
|
|
}
|
||
|
|
|
||
|
|
private function createTestClass(string $name, string $content): void
|
||
|
|
{
|
||
|
|
file_put_contents($this->tempDir . '/' . $name . '.php', "<?php\n" . $content);
|
||
|
|
require_once $this->tempDir . '/' . $name . '.php';
|
||
|
|
}
|
||
|
|
|
||
|
|
private function removeDir(string $dir): void
|
||
|
|
{
|
||
|
|
$files = array_diff(scandir($dir), ['.', '..']);
|
||
|
|
foreach ($files as $file) {
|
||
|
|
$path = $dir . '/' . $file;
|
||
|
|
is_dir($path) ? $this->removeDir($path) : unlink($path);
|
||
|
|
}
|
||
|
|
rmdir($dir);
|
||
|
|
}
|
||
|
|
}
|