From 920083b3c69079a415f795f858c7b2b437d8aa69 Mon Sep 17 00:00:00 2001 From: Funky Waddle Date: Wed, 25 Feb 2026 00:33:21 -0600 Subject: [PATCH] Milestone 6: Testing Helpers & Verification --- src/EventAssertions.php | 70 ++++++++++++++++++++++++++ src/EventCollector.php | 67 ++++++++++++++++++++++++ tests/Unit/EventTestingHelpersTest.php | 42 ++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 src/EventAssertions.php create mode 100644 src/EventCollector.php create mode 100644 tests/Unit/EventTestingHelpersTest.php diff --git a/src/EventAssertions.php b/src/EventAssertions.php new file mode 100644 index 0000000..a93cc83 --- /dev/null +++ b/src/EventAssertions.php @@ -0,0 +1,70 @@ +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." + ); + } +} diff --git a/src/EventCollector.php b/src/EventCollector.php new file mode 100644 index 0000000..802a3cb --- /dev/null +++ b/src/EventCollector.php @@ -0,0 +1,67 @@ + 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 + */ + public function getEvents(): array + { + return $this->events; + } + + /** + * Clears the collected events. + * + * @return void + */ + public function clear(): void + { + $this->events = []; + } +} diff --git a/tests/Unit/EventTestingHelpersTest.php b/tests/Unit/EventTestingHelpersTest.php new file mode 100644 index 0000000..1f7ba35 --- /dev/null +++ b/tests/Unit/EventTestingHelpersTest.php @@ -0,0 +1,42 @@ +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'); + } +}