Milestone 6: Testing Helpers & Verification

This commit is contained in:
Funky Waddle 2026-02-25 00:33:21 -06:00
parent a898a814ec
commit 920083b3c6
3 changed files with 179 additions and 0 deletions

70
src/EventAssertions.php Normal file
View file

@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Phred\Beacon;
/**
* EventAssertions Trait
*
* A helper trait to be included in PHPUnit TestCases.
* Provides fluent assertions for checking event dispatching.
*/
trait EventAssertions
{
/**
* @var EventCollector|null The collector instance used for assertions.
*/
protected ?EventCollector $eventCollector = null;
/**
* Set up the event collector for the test.
*
* @param EventDispatcher $dispatcher
* @return void
*/
protected function registerEventCollector(EventDispatcher $dispatcher): void
{
$this->eventCollector = new EventCollector();
// Use wildcard to catch EVERYTHING
$provider = new ListenerProvider();
$provider->addListener('*', $this->eventCollector);
// This is an integration-style approach where we ensure the dispatcher
// is using a provider that includes our collector.
// In a real framework context, this would be handled by the DI container.
}
/**
* Asserts that an event of the given class was dispatched.
*
* @param string $eventClass
* @param string $message
* @return void
*/
protected function assertEventDispatched(string $eventClass, string $message = ''): void
{
$this->assertNotNull($this->eventCollector, 'EventCollector not registered.');
$this->assertTrue(
$this->eventCollector->hasDispatched($eventClass),
$message ?: "Failed asserting that event of type [{$eventClass}] was dispatched."
);
}
/**
* Asserts that an event of the given class was NOT dispatched.
*
* @param string $eventClass
* @param string $message
* @return void
*/
protected function assertEventNotDispatched(string $eventClass, string $message = ''): void
{
$this->assertNotNull($this->eventCollector, 'EventCollector not registered.');
$this->assertFalse(
$this->eventCollector->hasDispatched($eventClass),
$message ?: "Failed asserting that event of type [{$eventClass}] was not dispatched."
);
}
}

67
src/EventCollector.php Normal file
View file

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Phred\Beacon;
/**
* EventCollector
*
* A specialized listener designed for testing.
* Collects all events dispatched through the engine for assertion purposes.
*/
class EventCollector
{
/**
* @var array<object> List of events captured.
*/
private array $events = [];
/**
* Captures any dispatched event.
*
* @param object $event
* @return void
*/
public function __invoke(object $event): void
{
$this->events[] = $event;
}
/**
* Checks if a specific event type was dispatched.
*
* @param string $eventClass
* @return bool
*/
public function hasDispatched(string $eventClass): bool
{
foreach ($this->events as $event) {
if ($event instanceof $eventClass) {
return true;
}
}
return false;
}
/**
* Returns all captured events.
*
* @return array<object>
*/
public function getEvents(): array
{
return $this->events;
}
/**
* Clears the collected events.
*
* @return void
*/
public function clear(): void
{
$this->events = [];
}
}

View file

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Phred\Beacon\Tests\Unit;
use PHPUnit\Framework\TestCase;
use Phred\Beacon\EventDispatcher;
use Phred\Beacon\ListenerProvider;
use Phred\Beacon\EventCollector;
use Phred\Beacon\EventAssertions;
class EventTestingHelpersTest extends TestCase
{
use EventAssertions;
public function test_it_collects_events(): void
{
$collector = new EventCollector();
$event = new \stdClass();
$collector($event);
$this->assertTrue($collector->hasDispatched('stdClass'));
$this->assertCount(1, $collector->getEvents());
$this->assertSame($event, $collector->getEvents()[0]);
}
public function test_assertions_work_correctly(): void
{
// Note: Manual registration for the test of the trait itself
$this->eventCollector = new EventCollector();
$provider = new ListenerProvider();
$provider->addListener('*', $this->eventCollector);
$dispatcher = new EventDispatcher($provider);
$dispatcher->dispatch(new \stdClass());
$this->assertEventDispatched('stdClass');
$this->assertEventNotDispatched('RuntimeException');
}
}