diff --git a/src/Console/OutputStyle.php b/src/Console/OutputStyle.php index 8e5ad0a5f..69070ca3d 100644 --- a/src/Console/OutputStyle.php +++ b/src/Console/OutputStyle.php @@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Throwable; +use function array_keys; +use function array_values; use function sprintf; final class OutputStyle extends SymfonyStyle @@ -18,25 +20,34 @@ final class OutputStyle extends SymfonyStyle public function message(EventSerializer $serializer, Message $message): void { $event = $message->event(); - $data = $serializer->serialize($event, [Encoder::OPTION_PRETTY_PRINT => true]); + + try { + $data = $serializer->serialize($event, [Encoder::OPTION_PRETTY_PRINT => true]); + } catch (Throwable $error) { + $this->error( + sprintf( + 'Error while serializing event "%s": %s', + $message->event()::class, + $error->getMessage(), + ), + ); + + if ($this->isVeryVerbose()) { + $this->throwable($error); + } + + return; + } $this->title($data->name); - $this->horizontalTable([ - 'eventClass', - 'aggregateName', - 'aggregateId', - 'playhead', - 'recordedOn', - ], [ - [ - $event::class, - $message->aggregateName(), - $message->aggregateId(), - $message->playhead(), - $message->recordedOn()->format(DateTimeInterface::ATOM), - ], - ]); + $headers = $message->headers(); + + if (isset($headers['recordedOn']) && $headers['recordedOn'] instanceof DateTimeInterface) { + $headers['recordedOn'] = $headers['recordedOn']->format(DateTimeInterface::ATOM); + } + + $this->horizontalTable(array_keys($headers), [array_values($headers)]); $this->block($data->payload); } diff --git a/tests/Unit/Console/OutputStyleTest.php b/tests/Unit/Console/OutputStyleTest.php index 4b6dc6df0..d2a29f02c 100644 --- a/tests/Unit/Console/OutputStyleTest.php +++ b/tests/Unit/Console/OutputStyleTest.php @@ -15,6 +15,7 @@ use Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileId; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; +use RuntimeException; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; @@ -23,7 +24,7 @@ final class OutputStyleTest extends TestCase { use ProphecyTrait; - public function testWrite(): void + public function testMessage(): void { $input = new ArrayInput([]); $output = new BufferedOutput(); @@ -52,8 +53,38 @@ public function testWrite(): void $content = $output->fetch(); self::assertStringContainsString('profile.created', $content); - self::assertStringContainsString('Patchlevel\EventSourcing\Tests\Unit\Fixture\ProfileCreated', $content); - self::assertStringContainsString('Patchlevel\EventSourcing\Tests\Unit\Fixture\Profile', $content); + self::assertStringContainsString('profile', $content); self::assertStringContainsString('{"id":"1","email":"foo@bar.com"}', $content); } + + public function testMessageWithError(): void + { + $input = new ArrayInput([]); + $output = new BufferedOutput(); + + $event = new ProfileCreated( + ProfileId::fromString('1'), + Email::fromString('foo@bar.com'), + ); + + $serializer = $this->prophesize(EventSerializer::class); + $serializer + ->serialize($event, [Encoder::OPTION_PRETTY_PRINT => true]) + ->willThrow(new RuntimeException('Unknown Error')); + + $message = Message::create($event) + ->withAggregateName('profile') + ->withAggregateId('1') + ->withPlayhead(1) + ->withRecordedOn(new DateTimeImmutable()); + + $console = new OutputStyle($input, $output); + + $console->message($serializer->reveal(), $message); + + $content = $output->fetch(); + + self::assertStringContainsString('Unknown Error', $content); + self::assertStringContainsString(ProfileCreated::class, $content); + } }