Issues (27)

spec/Application/EventDispatcherSpec.php (5 issues)

1
<?php
2
3
/**
4
 * This file is part of slick/event package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace spec\Slick\Event\Application;
11
12
use PhpSpec\Exception\Example\FailureException;
13
use Psr\EventDispatcher\ListenerProviderInterface;
14
use Psr\EventDispatcher\StoppableEventInterface;
15
use Slick\Event\Application\EventDispatcher;
16
use PhpSpec\ObjectBehavior;
17
use Slick\Event\Event;
18
use Slick\Event\EventDispatcher as SlickEventDispatcher;
19
use Slick\Event\EventGenerator;
20
use Slick\Event\EventListener;
21
22
/**
23
 * EventDispatcherSpec specs
24
 *
25
 * @package spec\Slick\Event\Application
26
 */
27
class EventDispatcherSpec extends ObjectBehavior
28
{
29
    function it_is_initializable()
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
30
    {
31
        $this->shouldHaveType(EventDispatcher::class);
32
    }
33
34
    function its_an_event_dispatcher()
35
    {
36
        $this->shouldBeAnInstanceOf(SlickEventDispatcher::class);
37
    }
38
39
    function it_can_add_an_event_callable()
40
    {
41
        $call = function (object $eventObject) {
42
            $eventObject->foo = 'baz';
43
            return $eventObject;
44
        };
45
46
        $this->addListener('*', $call);
0 ignored issues
show
The method addListener() does not exist on spec\Slick\Event\Application\EventDispatcherSpec. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

46
        $this->/** @scrutinizer ignore-call */ 
47
               addListener('*', $call);
Loading history...
47
        $eventDispatched = (object)['foo' => 'bar'];
48
        $this->dispatch($eventDispatched)->shouldBe($eventDispatched);
0 ignored issues
show
The method dispatch() does not exist on spec\Slick\Event\Application\EventDispatcherSpec. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

48
        $this->/** @scrutinizer ignore-call */ 
49
               dispatch($eventDispatched)->shouldBe($eventDispatched);
Loading history...
49
        if ($eventDispatched->foo === 'bar') {
50
            throw new FailureException(
51
                "Expected callable to be called, but it wasn't..."
52
            );
53
        }
54
    }
55
56
    function it_can_add_event_listeners(EventListener $listener)
57
    {
58
        $this->addListener('*', $listener);
59
        $eventDispatched = (object)['foo' => 'bar'];
60
        $listener->handle($eventDispatched)
61
            ->willReturnArgument(0)
62
            ->shouldBeCalled();
63
        $this->dispatch($eventDispatched);
64
    }
65
66
    function it_handles_event_priority()
67
    {
68
        $event = new PriorityEvent();
69
        $listener1 = new PriorityListener();
70
        $listener2 = new PriorityListener();
71
        $this->addListener('*', $listener1, EventDispatcher::P_LOW);
72
        $this->addListener('*', $listener2);
73
        $this->dispatch($event)->called()->shouldBe([$listener2, $listener1]);
74
    }
75
76
    function it_match_events_by_its_names()
77
    {
78
        $event = new PriorityEvent();
79
        $listener1 = new PriorityListener();
80
        $listener2 = new PriorityListener();
81
        $this->addListener(\stdClass::class, $listener1, EventDispatcher::P_LOW);
82
        $this->addListener(PriorityEvent::class, $listener2);
83
        $this->dispatch($event)->called()->shouldBe([$listener2]);
84
    }
85
86
    function it_match_all_with_asterisk(EventListener $listener1, EventListener $listener2)
87
    {
88
        $this->addListener('*', $listener1);
89
        $this->addListener(PriorityEvent::class, $listener2);
90
91
        $event = (object)[];
92
        $listener1->handle($event)->willReturnArgument(0)->shouldBeCalled();
93
        $listener2->handle($event)->shouldNotBeCalled();
94
95
        $this->dispatch($event);
96
    }
97
98
    function it_can_place_asterisk_in_any_place_in_pattern(EventListener $listener)
99
    {
100
        $event = new PriorityEvent();
101
        $listener->handle($event)->willReturnArgument(0)->shouldBeCalled();
102
103
        $this->addListener('*Event', $listener);
104
        $this->dispatch($event);
105
    }
106
107
    function it_stops_the_dispatch_when_stoppable_event_is_active(
108
        StoppableEventInterface $event,
109
        EventListener $listener1,
110
        EventListener $listener2
111
    )
112
    {
113
        $event->isPropagationStopped()->willReturn(true);
114
        $listener1->handle($event)->willReturnArgument(0)->shouldBeCalled();
115
        $listener2->handle($event)->shouldNotBeCalled();
116
117
        $this->addListener('*', $listener1);
118
        $this->addListener('*', $listener2);
119
        $this->dispatch($event);
120
    }
121
122
    function it_handles_event_listener_providers(
123
        ListenerProviderInterface $listenerProvider,
124
        EventListener $listener,
125
        Event $event
126
    ) {
127
        $listenerProvider->getListenersForEvent($event)->willReturn([$listener]);
128
        $listener->handle($event)->willReturnArgument(0)->shouldBeCalled();
129
        $this->addListener('*', $listenerProvider);
130
        $this->dispatch($event);
131
    }
132
133
    function it_can_dispatch_events_form_a_generator(
134
        EventGenerator $generator,
135
        Event $event,
136
        EventListener $listener
137
    ) {
138
        $listener->handle($event)->willReturnArgument(0)->shouldBeCalled();
139
        $generator->releaseEvents()->willReturn([$event]);
140
        $this->addListener('*', $listener);
141
        $this->dispatchEventsFrom($generator);
0 ignored issues
show
The method dispatchEventsFrom() does not exist on spec\Slick\Event\Application\EventDispatcherSpec. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

141
        $this->/** @scrutinizer ignore-call */ 
142
               dispatchEventsFrom($generator);
Loading history...
142
    }
143
144
    function it_holds_dispatch_calls_for_after_dispatch_is_over(Event $event1, Event $event2)
145
    {
146
        $this->shouldBeAnInstanceOf(EventGenerator::class);
147
        $dispatcher = $this;
148
        $calls = [];
149
        $listener = function (object $event) use ($dispatcher, $event2, &$calls) {
150
            static $count;
151
            if (!$count) {
152
                $count = 0;
153
            }
154
155
            if ($count < 1) {
156
                $count++;
157
                $dispatcher->dispatch($event2);
158
            }
159
160
            $calls[] = $event;
161
162
            return $event;
163
        };
164
        $this->addListener('*', $listener);
165
        $this->dispatch($event1)->shouldBe($event1);
166
        $expected = [$event1->getWrappedObject(), $event2->getWrappedObject()];
0 ignored issues
show
The method getWrappedObject() does not exist on Slick\Event\Event. ( Ignorable by Annotation )

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

166
        $expected = [$event1->/** @scrutinizer ignore-call */ getWrappedObject(), $event2->getWrappedObject()];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
168
        if ($calls !== $expected) {
169
            throw new FailureException(
170
                "Late dispatch was processed before the origin has finished, it shouldn't..."
171
            );
172
        }
173
    }
174
}
175
176
class PriorityEvent
177
{
178
179
    protected $called = [];
180
181
    /**
182
     * call
183
     *
184
     * @param EventListener $listener
185
     */
186
    public function call(EventListener $listener): void
187
    {
188
        $this->called[] = $listener;
189
    }
190
191
    public function called(): array
192
    {
193
        return $this->called;
194
    }
195
}
196
197
class PriorityListener implements EventListener
198
{
199
200
    /**
201
     * Handles provided event
202
     *
203
     * @param Object|PriorityEvent $event
204
     */
205
    public function handle(object $event): object
206
    {
207
        $event->call($this);
208
        return $event;
209
    }
210
}
211