Completed
Push — master ( 6cb3bb...ba31e6 )
by Frank
01:21 queued 18s
created

src/EventDispatcherTest.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Event;
6
7
use PHPUnit\Framework\TestCase;
8
use Psr\EventDispatcher\ListenerProviderInterface;
9
use stdClass;
10
11
class EventDispatcherTest extends TestCase
12
{
13
    /**
14
     * @test
15
     */
16 View Code Duplication
    public function listening_to_a_plain_object_event(): void
17
    {
18
        $dispatcher = new EventDispatcher();
19
        $listenerSpy = new ListenerSpy();
20
        $event = new stdClass;
21
22
        $dispatcher->subscribeTo(stdClass::class, $listenerSpy);
23
        $dispatcher->dispatch($event);
24
25
        $this->assertTrue($listenerSpy->wasCalledWith($event));
26
    }
27
28
    /**
29
     * @test
30
     */
31
    public function dispatching_returns_the_event_object(): void
32
    {
33
        $event = new stdClass();
34
        $dispatcher = new  EventDispatcher();
35
36
        $returnedEvent = $dispatcher->dispatch($event);
0 ignored issues
show
$event is of type object<stdClass>, but the function expects a object<League\Event\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
37
38
        $this->assertSame($event, $returnedEvent);
39
    }
40
41
    /**
42
     * @test
43
     */
44
    public function listening_to_a_named_event(): void
45
    {
46
        $dispatcher = new EventDispatcher();
47
        $listenerSpy = new ListenerSpy();
48
        $event = new StubNamedEvent('event.name');
49
50
        $dispatcher->subscribeTo('event.name', $listenerSpy);
51
        $dispatcher->dispatch($event);
52
53
        $this->assertTrue($listenerSpy->wasCalledWith($event));
54
    }
55
56
    /**
57
     * @test
58
     */
59
    public function listening_to_a_named_event_ignores_other_names(): void
60
    {
61
        $dispatcher = new EventDispatcher();
62
        $listenerSpy = new ListenerSpy();
63
        $dispatcher->subscribeTo('event.name', $listenerSpy);
64
        $dispatcher->dispatch(new StubNamedEvent('event.name'));
65
        $dispatcher->dispatch(new StubNamedEvent('other.event.name'));
66
67
        $this->assertEquals(1, $listenerSpy->numberOfTimeCalled());
68
    }
69
70
    /**
71
     * @test
72
     */
73 View Code Duplication
    public function it_uses_a_provided_listener_provider(): void
74
    {
75
        $listenerSpy = new ListenerSpy();
76
        $provider = new PrioritizedListenerCollection();
77
        $provider->subscribeTo(stdClass::class, $listenerSpy);
78
        $dispatcher = new EventDispatcher($provider);
79
        $event = new stdClass();
80
81
        $dispatcher->dispatch($event);
82
83
        $this->assertTrue($listenerSpy->wasCalledWith($event));
84
    }
85
86
    /**
87
     * @test
88
     */
89 View Code Duplication
    public function it_only_keeps_notifying_handlers_when_the_event_propagation_is_not_stopped(): void
90
    {
91
        $dispatcher = new EventDispatcher();
92
        $listenerSpy = new ListenerSpy();
93
        $event = new StubStoppableEvent();
94
95
        $dispatcher->subscribeTo(
96
            StubStoppableEvent::class,
97
            function (StubStoppableEvent $event) {
98
                $event->stopPropagation();
99
            }
100
        );
101
        $dispatcher->subscribeTo(StubStoppableEvent::class, $listenerSpy);
102
        $dispatcher->dispatch($event);
103
104
        $this->assertFalse($listenerSpy->wasCalledWith($event));
105
    }
106
107
    /**
108
     * @test
109
     */
110
    public function it_calls_one_time_listeners_one_time(): void
111
    {
112
        $normalListener = new ListenerSpy();
113
        $oneTimeListener = new ListenerSpy();
114
115
        $dispatcher = new EventDispatcher();
116
        $dispatcher->subscribeTo(stdClass::class, $normalListener);
117
        $dispatcher->subscribeOnceTo(stdClass::class, $oneTimeListener);
118
119
        $dispatcher->dispatch(new stdClass());
120
        $dispatcher->dispatch(new stdClass());
121
        $dispatcher->dispatch(new stdClass());
122
123
        $this->assertEquals(1, $oneTimeListener->numberOfTimeCalled());
124
        $this->assertEquals(3, $normalListener->numberOfTimeCalled());
125
    }
126
127
    /**
128
     * @test
129
     * @dataProvider dpScenariosCausingSubscribingFailure
130
     */
131
    public function subscribing_does_not_work_when_the_underlying_provider_does_not_allow_subscribing(callable $scenario
132
    ): void {
133
        $provider = new class() implements ListenerProviderInterface {
134
            public function getListenersForEvent(object $event): iterable
135
            {
136
                return [];
137
            }
138
        };
139
        $dispatcher = new EventDispatcher($provider);
140
141
        $this->expectExceptionObject(
142
            UnableToSubscribeListener::becauseTheListenerProviderDoesNotAcceptListeners($provider)
143
        );
144
145
        $scenario($dispatcher);
146
    }
147
148
    public function dpScenariosCausingSubscribingFailure(): iterable
149
    {
150
        yield "subscribing" => [
151
            function (EventDispatcher $dispatcher) {
152
                $dispatcher->subscribeTo(
153
                    'event',
154
                    function () {
155
                    }
156
                );
157
            },
158
        ];
159
160
        yield "subscribing once" => [
161
            function (EventDispatcher $dispatcher) {
162
                $dispatcher->subscribeOnceTo(
163
                    'event',
164
                    function () {
165
                    }
166
                );
167
            },
168
        ];
169
170
        yield "subscribing from subscriber" => [
171
            function (EventDispatcher $dispatcher) {
172
                $dispatcher->subscribeListenersFrom(
173
                    new class () implements ListenerSubscriber {
174
                        public function subscribeListeners(ListenerAcceptor $acceptor): void
175
                        {
176
                        }
177
                    }
178
                );
179
            },
180
        ];
181
    }
182
183
    /**
184
     * @test
185
     */
186
    public function listeners_are_prioritized(): void
187
    {
188
        $dispatcher = new EventDispatcher();
189
        $event = new StubMutableEvent('Hi!');
190
        $append = static function (string $value) {
191
            return static function (StubMutableEvent $event) use ($value) {
192
                $event->append(' ' . $value);
193
            };
194
        };
195
        $appendHello = $append('Hello,');
196
        $appendWorld = $append('World!');
197
        $appendGoodBye = $append('Good bye!');
198
        $dispatcher->subscribeTo(StubMutableEvent::class, $appendWorld, 0);
199
        $dispatcher->subscribeTo(StubMutableEvent::class, $appendHello, 10);
200
        $dispatcher->subscribeTo(StubMutableEvent::class, $appendGoodBye, -10);
201
202
        $dispatcher->dispatch($event);
203
204
        $this->assertEquals('Hi! Hello, World! Good bye!', $event->value());
205
    }
206
207
    /**
208
     * @test
209
     */
210
    public function events_from_an_event_generator_can_be_dispatched(): void
211
    {
212
        $dispatcher = new EventDispatcher();
213
        $listener = new ListenerSpy();
214
        $dispatcher->subscribeTo(stdClass::class, $listener);
215
216
        $eventGenerator = new class () implements EventGenerator {
217
            use EventGeneratorBehavior {
218
                recordEvent as public;
219
            }
220
        };
221
        $eventGenerator->recordEvent(new stdClass());
222
        $eventGenerator->recordEvent(new stdClass());
223
        $eventGenerator->recordEvent(new stdClass());
224
        $dispatcher->dispatchGeneratedEvents($eventGenerator);
225
226
        $this->assertEquals(3, $listener->numberOfTimeCalled());
227
    }
228
229
    /**
230
     * @test
231
     */
232
    public function listeners_can_be_subscribed_through_a_subscriber(): void
233
    {
234
        $subscriber = new class () implements ListenerSubscriber {
235
            public function subscribeListeners(ListenerAcceptor $acceptor): void
236
            {
237
                $acceptor->subscribeTo(
238
                    StubMutableEvent::class,
239
                    function (StubMutableEvent $event) {
240
                        $event->append(' mutated');
241
                    }
242
                );
243
            }
244
        };
245
        $dispatcher = new EventDispatcher();
246
        $dispatcher->subscribeListenersFrom($subscriber);
247
        $event = new StubMutableEvent('this is');
248
        $dispatcher->dispatch($event);
249
250
        $this->assertEquals('this is mutated', $event->value());
251
    }
252
}
253