Passed
Push — master ( a624d4...6f2d98 )
by Alexander
01:22
created

ProviderTest.php$0 ➔ __construct()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
cc 1
rs 10
1
<?php
2
3
namespace Yiisoft\EventDispatcher\Tests\Provider;
4
5
use PHPUnit\Framework\TestCase;
6
use Yiisoft\EventDispatcher\Provider\AbstractProviderConfigurator;
7
use Yiisoft\EventDispatcher\Provider\Provider;
8
use Yiisoft\EventDispatcher\Tests\Event\ClassItself;
9
use Yiisoft\EventDispatcher\Tests\Event\Event;
10
use Yiisoft\EventDispatcher\Tests\Event\ParentClass;
11
use Yiisoft\EventDispatcher\Tests\Event\ParentInterface;
12
use Yiisoft\EventDispatcher\Tests\Event\ClassInterface;
13
use Yiisoft\EventDispatcher\Tests\Listener\Invokable;
14
use Yiisoft\EventDispatcher\Tests\Listener\NonStatic;
15
use Yiisoft\EventDispatcher\Tests\Listener\WithStaticMethod;
16
17
final class ProviderTest extends TestCase
18
{
19
    public function testAttachCallableArray(): void
20
    {
21
        $provider = new Provider();
22
        $providerConfigurator = $this->getProviderConfigurator($provider);
23
        $providerConfigurator->attach([WithStaticMethod::class, 'handle']);
24
25
        $listeners = $provider->getListenersForEvent(new Event());
26
        $this->assertCount(1, $listeners);
27
    }
28
29
    public function testAttachCallableFunction(): void
30
    {
31
        $provider = new Provider();
32
        $providerConfigurator = $this->getProviderConfigurator($provider);
33
        $providerConfigurator->attach('Yiisoft\EventDispatcher\Tests\Provider\handle');
34
35
        $listeners = $provider->getListenersForEvent(new Event());
36
        $this->assertCount(1, $listeners);
37
    }
38
39
    public function testAttachClosure(): void
40
    {
41
        $provider = new Provider();
42
        $providerConfigurator = $this->getProviderConfigurator($provider);
43
        $providerConfigurator->attach(function (Event $event) {
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

43
        $providerConfigurator->attach(function (/** @scrutinizer ignore-unused */ Event $event) {

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

Loading history...
44
            // do nothing
45
        });
46
47
        $listeners = $provider->getListenersForEvent(new Event());
48
        $this->assertCount(1, $listeners);
49
    }
50
51
    public function testAttachCallableObject(): void
52
    {
53
        $provider = new Provider();
54
        $providerConfigurator = $this->getProviderConfigurator($provider);
55
        $providerConfigurator->attach([new NonStatic(), 'handle']);
56
57
        $listeners = $provider->getListenersForEvent(new Event());
58
        $this->assertCount(1, $listeners);
59
    }
60
61
    public function testInvokable(): void
62
    {
63
        $provider = new Provider();
64
        $providerConfigurator = $this->getProviderConfigurator($provider);
65
        $providerConfigurator->attach(new Invokable());
66
67
        $listeners = $provider->getListenersForEvent(new Event());
68
        $this->assertCount(1, $listeners);
69
    }
70
71
    public function testListenersForClassHierarchyAreReturned(): void
72
    {
73
        $provider = new Provider();
74
        $providerConfigurator = $this->getProviderConfigurator($provider);
75
76
        $providerConfigurator->attach(function (ParentInterface $parentInterface) {
77
            $parentInterface->register('parent interface');
78
        });
79
        $providerConfigurator->attach(function (ParentClass $parentClass) {
80
            $parentClass->register('parent class');
81
        });
82
        $providerConfigurator->attach(function (ClassInterface $classInterface) {
83
            $classInterface->register('class interface');
84
        });
85
        $providerConfigurator->attach(function (ClassItself $classItself) {
86
            $classItself->register('class itself');
87
        });
88
89
        $event = new ClassItself();
90
        foreach ($provider->getListenersForEvent($event) as $listener) {
91
            $listener($event);
92
        }
93
94
        $classHierarchyHandlers = array_slice($event->registered(), 0, 2);
95
        $interfaceHandlers = array_slice($event->registered(), 2);
96
97
        $this->assertEquals(
98
            [
99
                'class itself',
100
                'parent class'
101
            ],
102
            $classHierarchyHandlers
103
        );
104
105
        $this->assertContains('class interface', $interfaceHandlers);
106
        $this->assertContains('parent interface', $interfaceHandlers);
107
    }
108
109
    public function testListenerWithNoParameterThrowsException(): void
110
    {
111
        $provider = new Provider();
112
        $providerConfigurator = $this->getProviderConfigurator($provider);
113
114
        $this->expectException(\InvalidArgumentException::class);
115
        $this->expectExceptionMessage('Listeners must declare an object type they can accept.');
116
117
        $providerConfigurator->attach(fn () => null);
118
    }
119
120
    public function testListenerForEventIsReturned(): void
121
    {
122
        $provider = new Provider();
123
        $providerConfigurator = $this->getProviderConfigurator($provider);
124
125
        $listener = fn () => null;
126
127
        $providerConfigurator->attach($listener, Event::class);
128
129
        $listeners = $provider->getListenersForEvent(new Event());
130
131
        $listeners = \iterator_to_array($listeners, false);
132
        $this->assertCount(1, $listeners);
133
        $this->assertContains($listener, $listeners);
134
    }
135
136
    public function testDetachListenersForEventAreDetached(): void
137
    {
138
        $provider = new Provider();
139
        $providerConfigurator = $this->getProviderConfigurator($provider);
140
141
        $providerConfigurator->attach(fn () => null, Event::class);
142
        $providerConfigurator->detach(Event::class);
143
144
        $listeners = $provider->getListenersForEvent(new Event());
145
146
        $this->assertCount(0, $listeners);
147
    }
148
149
    private function getProviderConfigurator(Provider $provider)
150
    {
151
        return new class($provider) extends AbstractProviderConfigurator {
152
            private Provider $provider;
153
154
            public function __construct(Provider $provider)
155
            {
156
                $this->provider = $provider;
157
            }
158
159
            public function attach(callable $listener, string $eventClassName = ''): void
160
            {
161
                $this->provider->attach($listener, $eventClassName);
162
            }
163
164
            public function detach(string $eventClassName): void
165
            {
166
                $this->provider->detach($eventClassName);
167
            }
168
        };
169
    }
170
}
171
172
function handle(Event $event): void
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

172
function handle(/** @scrutinizer ignore-unused */ Event $event): void

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

Loading history...
173
{
174
    // do nothing
175
}
176