Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
61 / 61
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10pest()->group('integration');
11
12use DI\Container;
13use Phexium\Plugin\CommandBus\Adapter\SyncCommandBus;
14use Phexium\Plugin\Logger\Adapter\NullLogger;
15use Tests\Phexium\Fake\Application\Command\Command as FakeCommand;
16use Tests\Phexium\Fake\Application\Command\CommandAlternative as FakeCommandAlternative;
17use Tests\Phexium\Fake\Application\Command\Handler as FakeHandler;
18use Tests\Phexium\Fake\Application\Command\InvalidCommandHandler as FakeInvalidCommandHandler;
19use Tests\Phexium\Fake\Application\Command\OrphanCommand as FakeOrphanCommand;
20use Tests\Phexium\Fake\Plugin\Logger\Logger as FakeLogger;
21
22describe('Dispatching', function (): void {
23    it('dispatches command to auto-discovered handler', function (): void {
24        $container = new Container();
25        $logger = new NullLogger();
26
27        $handler = new FakeHandler();
28        $container->set(FakeHandler::class, $handler);
29
30        $commandBus = new SyncCommandBus($container, $logger);
31
32        $command = new FakeCommand();
33        $commandBus->dispatch($command);
34
35        expect($handler->handled)->toBeTrue();
36    });
37
38    it('invokes handler on each dispatch', function (): void {
39        $container = new Container();
40        $logger = new NullLogger();
41
42        $handler = new FakeHandler();
43        $container->set(FakeHandler::class, $handler);
44
45        $commandBus = new SyncCommandBus($container, $logger);
46
47        $command = new FakeCommand();
48        $commandBus->dispatch($command);
49        $commandBus->dispatch($command);
50
51        expect($handler->handled)->toBeTrue()
52            ->and($handler->handleCount)->toBe(2)
53        ;
54    });
55});
56
57describe('Error handling', function (): void {
58    it('throws exception for non-existent handler', function (): void {
59        $container = new Container();
60        $logger = new NullLogger();
61
62        $commandBus = new SyncCommandBus($container, $logger);
63
64        $command = new FakeOrphanCommand();
65
66        expect(fn () => $commandBus->dispatch($command))
67            ->toThrow(InvalidArgumentException::class, 'Handler not found for command')
68        ;
69    });
70
71    it('throws exception for invalid handler', function (): void {
72        $container = new Container();
73        $container->set(FakeInvalidCommandHandler::class, new FakeInvalidCommandHandler());
74
75        $logger = new NullLogger();
76
77        $commandBus = new SyncCommandBus($container, $logger);
78
79        $command = new FakeCommandAlternative();
80
81        expect(fn () => $commandBus->dispatch($command))
82            ->toThrow(InvalidArgumentException::class, 'CommandHandlerInterface')
83        ;
84    });
85});
86
87describe('Logging', function (): void {
88    it('logs command dispatch with context', function (): void {
89        $container = new Container();
90        $logger = new FakeLogger();
91
92        $handler = new FakeHandler();
93        $container->set(FakeHandler::class, $handler);
94
95        $commandBus = new SyncCommandBus($container, $logger);
96
97        $command = new FakeCommand();
98        $commandBus->dispatch($command);
99
100        expect($logger->hasLog('debug', 'CommandBus: Dispatching command', [
101            'command' => FakeCommand::class,
102        ]))->toBeTrue();
103    });
104});