EventDispatcherTest   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 581
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 241
dl 0
loc 581
rs 10
c 0
b 0
f 0
wmc 28

26 Methods

Rating   Name   Duplication   Size   Complexity  
A testEventLogWithSpecifiedEvents() 0 25 1
A getEventFileConfigPath() 0 8 2
A testEventCreation() 0 8 1
A testTriggerEventWithError() 0 26 1
A testAddListenerForNoneExistingKey() 0 17 1
A configDataProvider() 0 14 1
A testEventLogWithGivenEvents() 0 21 1
A testGetConfiguration() 0 19 1
A testTriggerWithStopPropagation() 0 21 1
A testTriggerNoneExistingEvent() 0 7 1
A triggerError() 0 3 1
A testGetInvalidEventObject() 0 13 1
A clearLog() 0 6 2
A triggerStop() 0 4 1
A testEventLogWithExternalObjects() 0 21 1
A testEnableAndDisableEventLog() 0 17 1
A setUp() 0 5 1
A tearDown() 0 3 1
A testTriggerMultipleEvents() 0 38 1
A testSetEventDispatcherConfiguration() 0 56 1
A trigger() 0 3 1
A testEventLog() 0 21 1
A testTryToLoadConfigWithIncorrectType() 0 9 1
A testTryToLoadConfigFromMissingFile() 0 8 1
A testTriggerEvent() 0 19 1
A testAddListenerAndTriggerEvent() 0 25 1
1
<?php
2
3
/**
4
 * test Event Dispatcher class
5
 *
6
 * @package     BlueEvent
7
 * @subpackage  Test
8
 * @author      Michał Adamiak    <[email protected]>
9
 * @copyright   chajr/bluetree
10
 */
11
namespace BlueEventTest;
12
13
use BlueEvent\Event\Base\Interfaces\EventInterface;
14
use BlueEvent\Event\Base\EventDispatcher;
15
use PHPUnit\Framework\TestCase;
16
17
class EventDispatcherTest extends TestCase
18
{
19
    /**
20
     * name of test event log file
21
     */
22
    const EVENT_LOG_NAME = '/debug.log';
23
24
    /**
25
     * store information that even was triggered
26
     *
27
     * @var bool
28
     */
29
    public static $eventTriggered = 0;
30
31
    /**
32
     * store generated log file path
33
     *
34
     * @var string
35
     */
36
    protected $logPath;
37
38
    /**
39
     * actions launched before test starts
40
     */
41
    protected function setUp(): void
42
    {
43
        $this->logPath = __DIR__ . '/log';
44
45
        $this->clearLog();
46
    }
47
48
    /**
49
     * test event initialize
50
     *
51
     * @param array $options
52
     * @dataProvider configDataProvider
53
     */
54
    public function testEventCreation($options)
55
    {
56
        $instance = new EventDispatcher;
57
        $this->assertInstanceOf('BlueEvent\Event\Base\EventDispatcher', $instance);
58
        $this->assertFalse($instance->hasErrors());
59
60
        $instance = new EventDispatcher($options);
61
        $this->assertEquals($options['events'], $instance->getEventConfiguration());
62
    }
63
64
    /**
65
     * test read configuration
66
     *
67
     * @param array $options
68
     * @dataProvider configDataProvider
69
     */
70
    public function testSetEventDispatcherConfiguration($options)
71
    {
72
        $eventDispatcher = new EventDispatcher;
73
        $eventDispatcher->setEventConfiguration($options['events']);
74
75
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
76
77
        $eventDispatcher->setEventConfiguration([
78
            'test_event_code' => [
79
                'listeners' => [
80
                    'newListener'
81
                ]
82
            ]
83
        ]);
84
85
        $options['events']['test_event_code']['listeners'][] = 'newListener';
86
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
87
88
        unset($options['events']['test_event_code']['listeners'][3]);
89
90
        $eventDispatcher   = new EventDispatcher;
91
        $eventDispatcher->readEventConfiguration(
92
            $this->getEventFileConfigPath('array'),
93
            'array'
94
        );
95
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
96
97
        $eventDispatcher   = new EventDispatcher;
98
        $eventDispatcher->readEventConfiguration(
99
            $this->getEventFileConfigPath('json'),
100
            'json'
101
        );
102
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
103
104
        $eventDispatcher   = new EventDispatcher;
105
        $eventDispatcher->readEventConfiguration(
106
            $this->getEventFileConfigPath('ini'),
107
            'ini'
108
        );
109
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
110
111
        $eventDispatcher = new EventDispatcher(
112
            [
113
                'from_file' => $this->getEventFileConfigPath('xml'),
114
                'type'      => 'xml'
115
            ]
116
        );
117
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
118
119
        $eventDispatcher = new EventDispatcher(
120
            [
121
                'from_file' => $this->getEventFileConfigPath('yaml'),
122
                'type'      => 'yaml'
123
            ]
124
        );
125
        $this->assertEquals($options['events'], $eventDispatcher->getEventConfiguration());
126
    }
127
128
    /**
129
     * check for error if configuration file don't exists
130
     */
131
    public function testTryToLoadConfigFromMissingFile(): void
132
    {
133
        $this->expectException(\InvalidArgumentException::class);
134
        $eventDispatcher = new EventDispatcher();
135
136
        $eventDispatcher->readEventConfiguration(
137
            $this->getEventFileConfigPath('txt'),
138
            'txt'
139
        );
140
    }
141
142
    public function testTryToLoadConfigWithIncorrectType(): void
143
    {
144
        $this->expectExceptionMessage("Incorrect configuration type: incorrect");
145
        $this->expectException(\InvalidArgumentException::class);
146
        $eventDispatcher = new EventDispatcher();
147
148
        $eventDispatcher->readEventConfiguration(
149
            $this->getEventFileConfigPath('incorrect'),
150
            'incorrect'
151
        );
152
    }
153
154
    /**
155
     * test that event is called correctly
156
     */
157
    public function testTriggerEvent()
158
    {
159
        $instance = new EventDispatcher;
160
        $instance->setEventConfiguration([
161
            'test_event' => [
162
                'object'    => 'BlueEvent\Event\BaseEvent',
163
                'listeners' => [
164
                    'BlueEventTest\EventDispatcherTest::trigger',
165
                    function ($event) {
166
                        /** @var $event \BlueEvent\Event\BaseEvent */
167
                        self::$eventTriggered += $event->getEventParameters()['value'];
168
                    }
169
                ]
170
            ],
171
        ]);
172
173
        $instance->triggerEvent('test_event', ['value' => 2]);
174
175
        $this->assertEquals(3, self::$eventTriggered);
176
    }
177
178
    public function testTriggerNoneExistingEvent()
179
    {
180
        $instance = new EventDispatcher;
181
182
        $instance->triggerEvent('test_event', ['value' => 2]);
183
184
        $this->assertEquals(3, self::$eventTriggered);
185
    }
186
187
    /**
188
     * test trigger event with stop propagation before next listener
189
     */
190
    public function testTriggerWithStopPropagation()
191
    {
192
        $instance = new EventDispatcher;
193
        $instance->setEventConfiguration([
194
            'test_event' => [
195
                'object'    => 'BlueEvent\Event\BaseEvent',
196
                'listeners' => [
197
                    'BlueEventTest\EventDispatcherTest::triggerStop',
198
                    function ($event) {
199
                        /** @var $event \BlueEvent\Event\BaseEvent */
200
                        self::$eventTriggered += $event->getEventParameters()['value'];
201
                    }
202
                ]
203
            ],
204
        ]);
205
206
        $this->assertEquals(3, self::$eventTriggered);
207
208
        $instance->triggerEvent('test_event', ['value' => 2]);
209
210
        $this->assertEquals(4, self::$eventTriggered);
211
    }
212
213
    public function testAddListenerForNoneExistingKey()
214
    {
215
        $instance = new EventDispatcher;
216
217
        $instance->addEventListener(
218
            'test_event',
219
            [
220
                function ($event) {
221
                    /** @var $event \BlueEvent\Event\BaseEvent */
222
                    self::$eventTriggered += $event->getEventParameters()['value'];
223
                }
224
            ]
225
        );
226
227
        $instance->triggerEvent('test_event', ['value' => 2]);
228
229
        $this->assertEquals(8, self::$eventTriggered);
230
    }
231
232
    /**
233
     * test dynamically add new listener or listeners for given event name
234
     */
235
    public function testAddListenerAndTriggerEvent()
236
    {
237
        $instance = new EventDispatcher;
238
        $instance->setEventConfiguration([
239
            'test_event' => [
240
                'object'    => 'BlueEvent\Event\BaseEvent',
241
                'listeners' => [
242
                    'BlueEventTest\EventDispatcherTest::trigger'
243
                ]
244
            ],
245
        ]);
246
247
        $instance->addEventListener(
248
            'test_event',
249
            [
250
                function ($event) {
251
                    /** @var $event \BlueEvent\Event\BaseEvent */
252
                    self::$eventTriggered += $event->getEventParameters()['value'];
253
                }
254
            ]
255
        );
256
257
        $instance->triggerEvent('test_event', ['value' => 2]);
258
259
        $this->assertEquals(11, self::$eventTriggered);
260
    }
261
262
    /**
263
     * test trigger event with exception
264
     */
265
    public function testTriggerEventWithError()
266
    {
267
        $instance = new EventDispatcher;
268
        $instance->setEventConfiguration([
269
            'test_event' => [
270
                'object'    => 'BlueEvent\Event\BaseEvent',
271
                'listeners' => [
272
                    'BlueEventTest\EventDispatcherTest::triggerError',
273
                ]
274
            ],
275
        ]);
276
277
        $this->assertFalse($instance->hasErrors());
278
        $this->assertEquals([], $instance->getErrors());
279
280
        $instance->triggerEvent('test_event');
281
282
        $this->assertTrue($instance->hasErrors());
283
        $this->assertEquals(
284
            'Test error',
285
            $instance->getErrors()[0]['message']
286
        );
287
288
        $instance->clearErrors();
289
        $this->assertFalse($instance->hasErrors());
290
        $this->assertEquals([], $instance->getErrors());
291
    }
292
293
    /**
294
     * check for error if invalid object was declared as listener
295
     */
296
    public function testGetInvalidEventObject(): void
297
    {
298
        $this->expectException(\LogicException::class);
299
        $instance = new EventDispatcher();
300
301
        $instance->setEventConfiguration([
302
            'invalid_object_event' => [
303
                'object'    => InvalidEventObject::class,
304
                'listeners' => []
305
            ],
306
        ]);
307
308
        $instance->triggerEvent('invalid_object_event');
309
    }
310
311
    /**
312
     * test that event log can be enabled/disabled
313
     */
314
    public function testGetConfiguration()
315
    {
316
        $instance = new EventDispatcher;
317
318
        $this->assertEquals(
319
            [
320
                'type' => 'array',
321
                'log_events' => false,
322
                'log_all_events' => true,
323
                'from_file' => false,
324
                'log_object' => false,
325
                'log_config' => [
326
                    'log_path' => './log',
327
                    'level' => 'debug',
328
                    'storage' => \SimpleLog\Storage\File::class,
329
                ],
330
                'events' => [],
331
            ],
332
            $instance->getConfiguration()
333
        );
334
    }
335
336
    /**
337
     * test that event log can be enabled/disabled
338
     */
339
    public function testEnableAndDisableEventLog()
340
    {
341
        $instance = new EventDispatcher;
342
343
        $this->assertFalse($instance->getConfiguration('log_events'));
344
        $instance->setEventLog(false);
345
        $this->assertFalse($instance->getConfiguration('log_events'));
346
        $instance->setEventLog(true);
347
        $this->assertTrue($instance->getConfiguration('log_events'));
348
349
        $instance = new EventDispatcher([
350
            'log_events' => true
351
        ]);
352
353
        $this->assertTrue($instance->getConfiguration('log_events'));
354
        $instance->setEventLog(false);
355
        $this->assertFalse($instance->getConfiguration('log_events'));
356
    }
357
358
    /**
359
     * test that log file was created correctly
360
     */
361
    public function testEventLog(): void
362
    {
363
        $instance = new EventDispatcher([
364
            'log_events' => true,
365
            'log_config' => ['log_path' => $this->logPath],
366
        ]);
367
        $instance->setEventConfiguration([
368
            'test_event' => [
369
                'object'    => 'BlueEvent\Event\BaseEvent',
370
                'listeners' => [
371
                    [__CLASS__, 'trigger'],
372
                    'BlueEventTest\EventDispatcherTest::triggerError',
373
                    function () {
374
                    }
375
                ]
376
            ],
377
        ]);
378
379
        $this->assertFileDoesNotExist($this->logPath . self::EVENT_LOG_NAME);
380
        $instance->triggerEvent('test_event');
381
        $this->assertFileExists($this->logPath . self::EVENT_LOG_NAME);
382
    }
383
384
    /**
385
     * check calling additional log object and listener as array
386
     */
387
    public function testEventLogWithExternalObjects()
388
    {
389
        $instance = new EventDispatcher([
390
            'log_all_events'    => true,
391
            'log_path'          =>  $this->logPath,
392
            'log_object'        => new \SimpleLog\Log,
393
        ]);
394
395
        $instance->setEventLog(true);
396
397
        $instance->setEventConfiguration([
398
            'test_event' => [
399
                'object'    => 'BlueEvent\Event\BaseEvent',
400
                'listeners' => [
401
                    [new self, 'trigger']
402
                ]
403
            ],
404
        ]);
405
406
        $instance->triggerEvent('test_event');
407
        $this->assertFileExists($this->logPath);
408
    }
409
410
    /**
411
     * test log event with direct given all events
412
     */
413
    public function testEventLogWithGivenEvents()
414
    {
415
        $instance = new EventDispatcher([
416
            'log_path' =>  $this->logPath
417
        ]);
418
419
        $instance->setEventLog(true)->logAllEvents();
420
421
        $this->assertTrue($instance->getConfiguration('log_all_events'));
422
423
        $instance->setEventConfiguration([
424
            'test_event' => [
425
                'object'    => 'BlueEvent\Event\BaseEvent',
426
                'listeners' => [
427
                    'BlueEventTest\EventDispatcherTest::trigger',
428
                ]
429
            ],
430
        ]);
431
432
        $instance->triggerEvent('test_event');
433
        $this->assertFileExists($this->logPath);
434
    }
435
436
437
    /**
438
     * test log event with direct given specified event key
439
     */
440
    public function testEventLogWithSpecifiedEvents()
441
    {
442
        $instance = new EventDispatcher([
443
            'log_path'          =>  $this->logPath,
444
            'log_all_events'    => false
445
        ]);
446
447
        $instance->setEventLog(true);
448
        $instance->logEvent(['test_event']);
449
450
        $instance->setEventConfiguration([
451
            'test_event' => [
452
                'object'    => 'BlueEvent\Event\BaseEvent',
453
                'listeners' => [
454
                    'BlueEventTest\EventDispatcherTest::trigger',
455
                ]
456
            ],
457
        ]);
458
459
        $this->assertEquals(
460
            ['test_event'],
461
            $instance->getAllEventsToLog()
462
        );
463
        $instance->triggerEvent('test_event');
464
        $this->assertFileExists($this->logPath);
465
    }
466
467
    /**
468
     * config data for test
469
     *
470
     * @return array
471
     */
472
    public function configDataProvider()
473
    {
474
        return [
475
            [
476
                'options' => [
477
                    'type'      => 'array',
478
                    'from_file' => false,
479
                    'events' => [
480
                        'test_event_code' => [
481
                            'object'    => 'BlueEvent\Event\BaseEvent',
482
                            'listeners' => [
483
                                'ClassOne::method',
484
                                'ClassSecond::method',
485
                                'someFunction',
486
                            ]
487
                        ]
488
                    ],
489
                ]
490
            ]
491
        ];
492
    }
493
494
    /**
495
     * config data for test from file
496
     *
497
     * @param string $type
498
     * @return string
499
     */
500
    public function getEventFileConfigPath($type)
501
    {
502
        $extension = $type;
503
        if ($type === 'array') {
504
            $extension = 'php';
505
        }
506
507
        return __DIR__ . '/Config/testConfig/config.' . $extension;
508
    }
509
510
    /**
511
     * method to test event triggering
512
     */
513
    public static function trigger()
514
    {
515
        self::$eventTriggered++;
516
    }
517
518
    /**
519
     * method to test event triggering
520
     *
521
     * @throws \Exception
522
     */
523
    public static function triggerError()
524
    {
525
        throw new \Exception('Test error');
526
    }
527
528
    /**
529
     * method to test event triggering
530
     *
531
     * @param EventInterface $event
532
     */
533
    public static function triggerStop(EventInterface $event)
534
    {
535
        $event->stopPropagation();
536
        self::$eventTriggered++;
537
    }
538
539
    /**
540
     * test that event is called correctly
541
     */
542
    public function testTriggerMultipleEvents()
543
    {
544
        $testData = [];
545
        $instance = new EventDispatcher(['events' => [
546
            'test_event' => [
547
                'object'    => 'BlueEvent\Event\BaseEvent',
548
                'listeners' => [
549
                    function ($event) use (&$testData) {
550
                        /** @var $event \BlueEvent\Event\BaseEvent */
551
                        $testData['test_event'] = $event->getEventParameters();
552
                    }
553
                ]
554
            ],
555
            'test_event_other' => [
556
                'object'    => 'BlueEvent\Event\BaseEvent',
557
                'listeners' => [
558
                    function ($event) use (&$testData) {
559
                        /** @var $event \BlueEvent\Event\BaseEvent */
560
                        $testData['test_event_other'] = $event->getEventParameters();
561
                    }
562
                ]
563
            ],
564
        ]]);
565
566
        $instance->triggerEvent('test_event', ['value' => 2]);
567
568
        $this->assertArrayHasKey('test_event', $testData);
569
        $this->assertEquals(
570
            ['value' => 2],
571
            $testData['test_event']
572
        );
573
574
        $instance->triggerEvent('test_event_other', ['value' => 5]);
575
576
        $this->assertArrayHasKey('test_event_other', $testData);
577
        $this->assertEquals(
578
            ['value' => 5],
579
            $testData['test_event_other']
580
        );
581
    }
582
583
    protected function clearLog()
584
    {
585
        $logFile = $this->logPath . self::EVENT_LOG_NAME;
586
587
        if (file_exists($logFile)) {
588
            unlink($logFile);
589
        }
590
    }
591
592
    /**
593
     * actions launched after test was finished
594
     */
595
    protected function tearDown(): void
596
    {
597
        $this->clearLog();
598
    }
599
}
600