Completed
Push — master ( 13785c...b6ad57 )
by Ross
12s
created

InterfaceTypehintHandler::interfaced()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace League\Tactician\Bundle\Tests\DependencyInjection\HandlerMapping;
5
6
use DateTime;
7
use League\Tactician\Bundle\DependencyInjection\HandlerMapping\Routing;
8
use League\Tactician\Bundle\DependencyInjection\HandlerMapping\TypeHintMapping;
9
use League\Tactician\Bundle\DependencyInjection\InvalidCommandBusId;
10
use League\Tactician\Bundle\Tests\Fake\FakeCommand;
11
use League\Tactician\Bundle\Tests\Fake\OtherFakeCommand;
12
use PHPUnit\Framework\TestCase;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Definition;
15
16
final class TypeHintMappingTest extends TestCase
17
{
18
    public function test_will_skip_definitions_without_auto_tag()
19
    {
20
        $builder = new ContainerBuilder();
21
        $builder
22
            ->setDefinition('some.handler', new Definition(InvokeHandler::class))
23
            ->addTag('tactician.handler', ['foo' => 'bar']);
24
25
        $routing = (new TypeHintMapping())->build($builder, new Routing(['default']));
26
27
        $this->assertEquals([], $routing->commandToServiceMapping('default'));
28
    }
29
30
    public function test_will_resolve_parameters_in_handler_class()
31
    {
32
        $builder = new ContainerBuilder();
33
        $builder->setParameter('handler_class', InvokeHandler::class);
34
        $builder
35
            ->setDefinition('some.handler', new Definition('%handler_class%'))
36
            ->addTag('tactician.handler', ['typehints' => true]);
37
38
        $routing = (new TypeHintMapping())->build($builder, new Routing(['default']));
39
40
        $this->assertEquals([FakeCommand::class => 'some.handler'], $routing->commandToServiceMapping('default'));
41
    }
42
43
    /**
44
     * @dataProvider simpleTestCases
45
     */
46
    public function test_standard(string $handlerFQCN, array $expectedMapping)
47
    {
48
        $builder = new ContainerBuilder();
49
        $builder
50
            ->setDefinition('some.handler', new Definition($handlerFQCN))
51
            ->addTag('tactician.handler', ['typehints' => true]);
52
53
        $routing = (new TypeHintMapping())->build($builder, new Routing(['default']));
54
55
        $this->assertEquals($expectedMapping, $routing->commandToServiceMapping('default'));
56
    }
57
58
    public function simpleTestCases()
59
    {
60
        return [
61
            'can read __invoke magic method type hint' => [
62
                InvokeHandler::class,
63
                [FakeCommand::class => 'some.handler']
64
            ],
65
            'takes unary methods but not those with multiple parameters' => [
66
                BasicHandler::class,
67
                [FakeCommand::class => 'some.handler', OtherFakeCommand::class => 'some.handler']
68
            ],
69
            'can not exclude built-in objects unfortunately' => [
70
                DateTimeHandler::class,
71
                [DateTime::class => 'some.handler']
72
            ],
73
            'will skip methods with no typehint' => [NoTypehintHandler::class, []],
74
            'will skip methods with an interface typehint' => [InterfaceTypehintHandler::class, []],
75
            'will not try to map scalar typehints' => [ScalarHandler::class, []],
76
            'will not use protected or private methods' => [ProtectedMethodHandler::class, []],
77
            'will not use constructor method' => [ConstructorHandler::class, []],
78
            'will not use static methods' => [StaticHandler::class, []],
79
            'will not use abstract methods' => [AbstractHandler::class, []],
80
            'will not use variadic methods' => [VariadicHandler::class, []]
81
        ];
82
    }
83
84
    public function test_can_bind_to_specific_bus()
85
    {
86
        $builder = new ContainerBuilder();
87
        $builder
88
            ->setDefinition('first.handler', new Definition(BasicHandler::class))
89
            ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.a']);
90
91
        $builder
92
            ->setDefinition('second.handler', new Definition(DateTimeHandler::class))
93
            ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.b']);
94
95
        $routing = (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b']));
96
97
        $this->assertEquals(
98
            [
99
                FakeCommand::class => 'first.handler',
100
                OtherFakeCommand::class => 'first.handler'
101
            ],
102
            $routing->commandToServiceMapping('bus.a')
103
        );
104
        $this->assertEquals(
105
            [DateTime::class => 'second.handler'],
106
            $routing->commandToServiceMapping('bus.b')
107
        );
108
    }
109
110
    public function test_can_bind_to_multiple_buses()
111
    {
112
        $builder = new ContainerBuilder();
113
        $builder
114
            ->setDefinition('first.handler', new Definition(BasicHandler::class))
115
            ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.a'])
116
            ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.b']);
117
118
        $routing = (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b']));
119
120
        $expected = [
121
            FakeCommand::class => 'first.handler',
122
            OtherFakeCommand::class => 'first.handler',
123
        ];
124
125
        $this->assertEquals($expected, $routing->commandToServiceMapping('bus.a'));
126
        $this->assertEquals($expected, $routing->commandToServiceMapping('bus.b'));
127
    }
128
129
    public function test_will_error_when_given_invalid_bus()
130
    {
131
        $this->expectException(InvalidCommandBusId::class);
132
133
        $builder = new ContainerBuilder();
134
        $builder
135
            ->setDefinition('first.handler', new Definition(BasicHandler::class))
136
            ->addTag('tactician.handler', ['typehints' => true, 'bus' => 'bus.does.not.exist.mwhahahaha']);
137
138
        (new TypeHintMapping())->build($builder, new Routing(['bus.a', 'bus.b']));
139
    }
140
}
141
142
class BasicHandler
143
{
144
    public function handle(FakeCommand $command)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
145
    {
146
    }
147
148
    public function run(OtherFakeCommand $command)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
149
    {
150
    }
151
152
    public function notACommand(FakeCommand $cmdA, OtherFakeCommand $cmdB)
0 ignored issues
show
Unused Code introduced by
The parameter $cmdA is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $cmdB is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
153
    {
154
    }
155
}
156
157
class VariadicHandler
158
{
159
    public function handle(FakeCommand ...$commands)
0 ignored issues
show
Unused Code introduced by
The parameter $commands is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
160
    {
161
    }
162
}
163
164
class DateTimeHandler
165
{
166
    public function handle(DateTime $command)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
167
    {
168
    }
169
}
170
171
class StaticHandler
172
{
173
    public static function handle(FakeCommand $command)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
    {
175
    }
176
}
177
178
abstract class AbstractHandler
179
{
180
    abstract public function handle(FakeCommand $command);
181
}
182
183
class ScalarHandler
184
{
185
    public function handle(string $someString)
0 ignored issues
show
Unused Code introduced by
The parameter $someString is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
    {
187
    }
188
189
    public function execute(int $foobar)
0 ignored issues
show
Unused Code introduced by
The parameter $foobar is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
190
    {
191
    }
192
193
    public function that(callable $thing)
0 ignored issues
show
Unused Code introduced by
The parameter $thing is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
    {
195
    }
196
}
197
198
interface ServiceInterface {
199
200
}
201
202
class InterfaceTypehintHandler
203
{
204
    public function interfaced(ServiceInterface $foo)
0 ignored issues
show
Unused Code introduced by
The parameter $foo is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
205
    {
206
    }
207
}
208
209
class NoTypehintHandler
210
{
211
    public function handle($foo)
0 ignored issues
show
Unused Code introduced by
The parameter $foo is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
212
    {
213
    }
214
}
215
216
class InvokeHandler
217
{
218
    public function __invoke(FakeCommand $command)
219
    {
220
    }
221
}
222
223
224
class ProtectedMethodHandler
225
{
226
    protected function handle(FakeCommand $command)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
227
    {
228
    }
229
230
    private function execute(OtherFakeCommand $command)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
231
    {
232
    }
233
}
234
235
class ConstructorHandler
236
{
237
    public function __construct(SomeDependency $dependency)
0 ignored issues
show
Unused Code introduced by
The parameter $dependency is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
238
    {
239
    }
240
}
241
242
class SomeDependency
243
{
244
}
245