Completed
Branch develop (343ae8)
by Michał
02:22
created

EventDispatcherTest::clearLog()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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