Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 1
<?php
2
/**
3
 * CakePHP : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright	  Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link		  http://cakephp.org CakePHP Project
12
 * @package		  Cake.Test.Case.Event
13
 * @since		  CakePHP v 2.1
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16
 
17
App::uses('CakeEvent', 'Event');
18
App::uses('CakeEventManager', 'Event');
19
App::uses('CakeEventListener', 'Event');
20
 
21
/**
22
 * Mock class used to test event dispatching
23
 *
24
 * @package Cake.Test.Case.Event
25
 */
26
class CakeEventTestListener {
27
 
28
	public $callStack = array();
29
 
30
/**
31
 * Test function to be used in event dispatching
32
 *
33
 * @return void
34
 */
35
	public function listenerFunction() {
36
		$this->callStack[] = __FUNCTION__;
37
	}
38
 
39
/**
40
 * Test function to be used in event dispatching
41
 *
42
 * @return void
43
 */
44
	public function secondListenerFunction() {
45
		$this->callStack[] = __FUNCTION__;
46
	}
47
 
48
/**
49
 * Auxiliary function to help in stopPropagation testing
50
 *
51
 * @param CakeEvent $event
52
 * @return void
53
 */
54
	public function stopListener($event) {
55
		$event->stopPropagation();
56
	}
57
 
58
}
59
 
60
/**
61
 * Mock used for testing the subscriber objects
62
 *
63
 * @package Cake.Test.Case.Event
64
 */
65
class CustomTestEventListener extends CakeEventTestListener implements CakeEventListener {
66
 
67
	public function implementedEvents() {
68
		return array(
69
			'fake.event' => 'listenerFunction',
70
			'another.event' => array('callable' => 'secondListenerFunction', 'passParams' => true),
71
			'multiple.handlers' => array(
72
				array('callable' => 'listenerFunction'),
73
				array('callable' => 'thirdListenerFunction')
74
			)
75
		);
76
	}
77
 
78
/**
79
 * Test function to be used in event dispatching
80
 *
81
 * @return void
82
 */
83
	public function thirdListenerFunction() {
84
		$this->callStack[] = __FUNCTION__;
85
	}
86
 
87
}
88
 
89
/**
90
 * Tests the CakeEventManager class functionality
91
 *
92
 */
93
class CakeEventManagerTest extends CakeTestCase {
94
 
95
/**
96
 * Tests the attach() method for a single event key in multiple queues
97
 *
98
 * @return void
99
 */
100
	public function testAttachListeners() {
101
		$manager = new CakeEventManager();
102
		$manager->attach('fakeFunction', 'fake.event');
103
		$expected = array(
104
			array('callable' => 'fakeFunction', 'passParams' => false)
105
		);
106
		$this->assertEquals($expected, $manager->listeners('fake.event'));
107
 
108
		$manager->attach('fakeFunction2', 'fake.event');
109
		$expected[] = array('callable' => 'fakeFunction2', 'passParams' => false);
110
		$this->assertEquals($expected, $manager->listeners('fake.event'));
111
 
112
		$manager->attach('inQ5', 'fake.event', array('priority' => 5));
113
		$manager->attach('inQ1', 'fake.event', array('priority' => 1));
114
		$manager->attach('otherInQ5', 'fake.event', array('priority' => 5));
115
 
116
		$expected = array_merge(
117
			array(
118
				array('callable' => 'inQ1', 'passParams' => false),
119
				array('callable' => 'inQ5', 'passParams' => false),
120
				array('callable' => 'otherInQ5', 'passParams' => false)
121
			),
122
			$expected
123
		);
124
		$this->assertEquals($expected, $manager->listeners('fake.event'));
125
	}
126
 
127
/**
128
 * Tests the attach() method for multiple event key in multiple queues
129
 *
130
 * @return void
131
 */
132
	public function testAttachMultipleEventKeys() {
133
		$manager = new CakeEventManager();
134
		$manager->attach('fakeFunction', 'fake.event');
135
		$manager->attach('fakeFunction2', 'another.event');
136
		$manager->attach('fakeFunction3', 'another.event', array('priority' => 1, 'passParams' => true));
137
		$expected = array(
138
			array('callable' => 'fakeFunction', 'passParams' => false)
139
		);
140
		$this->assertEquals($expected, $manager->listeners('fake.event'));
141
 
142
		$expected = array(
143
			array('callable' => 'fakeFunction3', 'passParams' => true),
144
			array('callable' => 'fakeFunction2', 'passParams' => false)
145
		);
146
		$this->assertEquals($expected, $manager->listeners('another.event'));
147
	}
148
 
149
/**
150
 * Tests detaching an event from a event key queue
151
 *
152
 * @return void
153
 */
154
	public function testDetach() {
155
		$manager = new CakeEventManager();
156
		$manager->attach(array('AClass', 'aMethod'), 'fake.event');
157
		$manager->attach(array('AClass', 'anotherMethod'), 'another.event');
158
		$manager->attach('fakeFunction', 'another.event', array('priority' => 1));
159
 
160
		$manager->detach(array('AClass', 'aMethod'), 'fake.event');
161
		$this->assertEquals(array(), $manager->listeners('fake.event'));
162
 
163
		$manager->detach(array('AClass', 'anotherMethod'), 'another.event');
164
		$expected = array(
165
			array('callable' => 'fakeFunction', 'passParams' => false)
166
		);
167
		$this->assertEquals($expected, $manager->listeners('another.event'));
168
 
169
		$manager->detach('fakeFunction', 'another.event');
170
		$this->assertEquals(array(), $manager->listeners('another.event'));
171
	}
172
 
173
/**
174
 * Tests detaching an event from all event queues
175
 *
176
 * @return void
177
 */
178
	public function testDetachFromAll() {
179
		$manager = new CakeEventManager();
180
		$manager->attach(array('AClass', 'aMethod'), 'fake.event');
181
		$manager->attach(array('AClass', 'aMethod'), 'another.event');
182
		$manager->attach('fakeFunction', 'another.event', array('priority' => 1));
183
 
184
		$manager->detach(array('AClass', 'aMethod'));
185
		$expected = array(
186
			array('callable' => 'fakeFunction', 'passParams' => false)
187
		);
188
		$this->assertEquals($expected, $manager->listeners('another.event'));
189
		$this->assertEquals(array(), $manager->listeners('fake.event'));
190
	}
191
 
192
/**
193
 * Tests event dispatching
194
 *
195
 * @return void
196
 * @triggers fake.event
197
 */
198
	public function testDispatch() {
199
		$manager = new CakeEventManager();
200
		$listener = $this->getMock('CakeEventTestListener');
201
		$anotherListener = $this->getMock('CakeEventTestListener');
202
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
203
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
204
		$event = new CakeEvent('fake.event');
205
 
206
		$listener->expects($this->once())->method('listenerFunction')->with($event);
207
		$anotherListener->expects($this->once())->method('listenerFunction')->with($event);
208
		$manager->dispatch($event);
209
	}
210
 
211
/**
212
 * Tests event dispatching using event key name
213
 *
214
 * @return void
215
 */
216
	public function testDispatchWithKeyName() {
217
		$manager = new CakeEventManager();
218
		$listener = new CakeEventTestListener();
219
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
220
		$event = 'fake.event';
221
		$manager->dispatch($event);
222
 
223
		$expected = array('listenerFunction');
224
		$this->assertEquals($expected, $listener->callStack);
225
	}
226
 
227
/**
228
 * Tests event dispatching with a return value
229
 *
230
 * @return void
231
 * @triggers fake.event
232
 */
233
	public function testDispatchReturnValue() {
234
		$this->skipIf(
235
			version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
236
			'These tests fail in PHPUnit 3.6'
237
		);
238
		$manager = new CakeEventManager();
239
		$listener = $this->getMock('CakeEventTestListener');
240
		$anotherListener = $this->getMock('CakeEventTestListener');
241
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
242
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
243
		$event = new CakeEvent('fake.event');
244
 
245
		$listener->expects($this->at(0))->method('listenerFunction')
246
			->with($event)
247
			->will($this->returnValue('something special'));
248
		$anotherListener->expects($this->at(0))
249
			->method('listenerFunction')
250
			->with($event);
251
		$manager->dispatch($event);
252
		$this->assertEquals('something special', $event->result);
253
	}
254
 
255
/**
256
 * Tests that returning false in a callback stops the event
257
 *
258
 * @return void
259
 * @triggers fake.event
260
 */
261
	public function testDispatchFalseStopsEvent() {
262
		$this->skipIf(
263
			version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
264
			'These tests fail in PHPUnit 3.6'
265
		);
266
 
267
		$manager = new CakeEventManager();
268
		$listener = $this->getMock('CakeEventTestListener');
269
		$anotherListener = $this->getMock('CakeEventTestListener');
270
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
271
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
272
		$event = new CakeEvent('fake.event');
273
 
274
		$listener->expects($this->at(0))->method('listenerFunction')
275
			->with($event)
276
			->will($this->returnValue(false));
277
		$anotherListener->expects($this->never())
278
			->method('listenerFunction');
279
		$manager->dispatch($event);
280
		$this->assertTrue($event->isStopped());
281
	}
282
 
283
/**
284
 * Tests event dispatching using priorities
285
 *
286
 * @return void
287
 * @triggers fake.event
288
 */
289
	public function testDispatchPrioritized() {
290
		$manager = new CakeEventManager();
291
		$listener = new CakeEventTestListener();
292
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
293
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
294
		$event = new CakeEvent('fake.event');
295
		$manager->dispatch($event);
296
 
297
		$expected = array('secondListenerFunction', 'listenerFunction');
298
		$this->assertEquals($expected, $listener->callStack);
299
	}
300
 
301
/**
302
 * Tests event dispatching with passed params
303
 *
304
 * @return void
305
 * @triggers fake.event $this, array('some' => 'data')
306
 */
307
	public function testDispatchPassingParams() {
308
		$manager = new CakeEventManager();
309
		$listener = $this->getMock('CakeEventTestListener');
310
		$anotherListener = $this->getMock('CakeEventTestListener');
311
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
312
		$manager->attach(array($anotherListener, 'secondListenerFunction'), 'fake.event', array('passParams' => true));
313
		$event = new CakeEvent('fake.event', $this, array('some' => 'data'));
314
 
315
		$listener->expects($this->once())->method('listenerFunction')->with($event);
316
		$anotherListener->expects($this->once())->method('secondListenerFunction')->with('data');
317
		$manager->dispatch($event);
318
	}
319
 
320
/**
321
 * Tests subscribing a listener object and firing the events it subscribed to
322
 *
323
 * @return void
324
 * @triggers fake.event
325
 * @triggers another.event $this, array('some' => 'data')
326
 * @triggers multiple.handlers
327
 */
328
	public function testAttachSubscriber() {
329
		$manager = new CakeEventManager();
330
		$listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction'));
331
		$manager->attach($listener);
332
		$event = new CakeEvent('fake.event');
333
 
334
		$manager->dispatch($event);
335
 
336
		$expected = array('listenerFunction');
337
		$this->assertEquals($expected, $listener->callStack);
338
 
339
		$listener->expects($this->at(0))->method('secondListenerFunction')->with('data');
340
		$event = new CakeEvent('another.event', $this, array('some' => 'data'));
341
		$manager->dispatch($event);
342
 
343
		$manager = new CakeEventManager();
344
		$listener = $this->getMock('CustomTestEventListener', array('listenerFunction', 'thirdListenerFunction'));
345
		$manager->attach($listener);
346
		$event = new CakeEvent('multiple.handlers');
347
		$listener->expects($this->once())->method('listenerFunction')->with($event);
348
		$listener->expects($this->once())->method('thirdListenerFunction')->with($event);
349
		$manager->dispatch($event);
350
	}
351
 
352
/**
353
 * Tests subscribing a listener object and firing the events it subscribed to
354
 *
355
 * @return void
356
 */
357
	public function testDetachSubscriber() {
358
		$manager = new CakeEventManager();
359
		$listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction'));
360
		$manager->attach($listener);
361
		$expected = array(
362
			array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => true)
363
		);
364
		$this->assertEquals($expected, $manager->listeners('another.event'));
365
		$expected = array(
366
			array('callable' => array($listener, 'listenerFunction'), 'passParams' => false)
367
		);
368
		$this->assertEquals($expected, $manager->listeners('fake.event'));
369
		$manager->detach($listener);
370
		$this->assertEquals(array(), $manager->listeners('fake.event'));
371
		$this->assertEquals(array(), $manager->listeners('another.event'));
372
	}
373
 
374
/**
375
 * Tests that it is possible to get/set the manager singleton
376
 *
377
 * @return void
378
 */
379
	public function testGlobalDispatcherGetter() {
380
		$this->assertInstanceOf('CakeEventManager', CakeEventManager::instance());
381
		$manager = new CakeEventManager();
382
 
383
		CakeEventManager::instance($manager);
384
		$this->assertSame($manager, CakeEventManager::instance());
385
	}
386
 
387
/**
388
 * Tests that the global event manager gets the event too from any other manager
389
 *
390
 * @return void
391
 * @triggers fake.event
392
 */
393
	public function testDispatchWithGlobal() {
394
		$generalManager = $this->getMock('CakeEventManager', array('prioritisedListeners'));
395
		$manager = new CakeEventManager();
396
		$event = new CakeEvent('fake.event');
397
		CakeEventManager::instance($generalManager);
398
 
399
		$generalManager->expects($this->once())->method('prioritisedListeners')->with('fake.event');
400
		$manager->dispatch($event);
401
		CakeEventManager::instance(new CakeEventManager());
402
	}
403
 
404
/**
405
 * Tests that stopping an event will not notify the rest of the listeners
406
 *
407
 * @return void
408
 * @triggers fake.event
409
 */
410
	public function testStopPropagation() {
411
		$generalManager = $this->getMock('CakeEventManager');
412
		$manager = new CakeEventManager();
413
		$listener = new CakeEventTestListener();
414
 
415
		CakeEventManager::instance($generalManager);
416
		$generalManager->expects($this->any())
417
				->method('prioritisedListeners')
418
				->with('fake.event')
419
				->will($this->returnValue(array()));
420
 
421
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
422
		$manager->attach(array($listener, 'stopListener'), 'fake.event', array('priority' => 8));
423
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
424
		$event = new CakeEvent('fake.event');
425
		$manager->dispatch($event);
426
 
427
		$expected = array('secondListenerFunction');
428
		$this->assertEquals($expected, $listener->callStack);
429
		CakeEventManager::instance(new CakeEventManager());
430
	}
431
 
432
/**
433
 * Tests event dispatching using priorities
434
 *
435
 * @return void
436
 * @triggers fake.event
437
 */
438
	public function testDispatchPrioritizedWithGlobal() {
439
		$generalManager = $this->getMock('CakeEventManager');
440
		$manager = new CakeEventManager();
441
		$listener = new CustomTestEventListener();
442
		$event = new CakeEvent('fake.event');
443
 
444
		CakeEventManager::instance($generalManager);
445
		$generalManager->expects($this->any())
446
				->method('prioritisedListeners')
447
				->with('fake.event')
448
				->will($this->returnValue(
449
					array(11 => array(
450
						array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => false)
451
					))
452
				));
453
 
454
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
455
		$manager->attach(array($listener, 'thirdListenerFunction'), 'fake.event', array('priority' => 15));
456
 
457
		$manager->dispatch($event);
458
 
459
		$expected = array('listenerFunction', 'secondListenerFunction', 'thirdListenerFunction');
460
		$this->assertEquals($expected, $listener->callStack);
461
		CakeEventManager::instance(new CakeEventManager());
462
	}
463
 
464
/**
465
 * Tests event dispatching using priorities
466
 *
467
 * @return void
468
 * @triggers fake.event
469
 */
470
	public function testDispatchGlobalBeforeLocal() {
471
		$generalManager = $this->getMock('CakeEventManager');
472
		$manager = new CakeEventManager();
473
		$listener = new CustomTestEventListener();
474
		$event = new CakeEvent('fake.event');
475
 
476
		CakeEventManager::instance($generalManager);
477
		$generalManager->expects($this->any())
478
				->method('prioritisedListeners')
479
				->with('fake.event')
480
				->will($this->returnValue(
481
					array(10 => array(
482
						array('callable' => array($listener, 'listenerFunction'), 'passParams' => false)
483
					))
484
				));
485
 
486
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event');
487
 
488
		$manager->dispatch($event);
489
 
490
		$expected = array('listenerFunction', 'secondListenerFunction');
491
		$this->assertEquals($expected, $listener->callStack);
492
		CakeEventManager::instance(new CakeEventManager());
493
	}
494
 
495
/**
496
 * test callback
497
 */
498
	public function onMyEvent($event) {
499
		$event->data['callback'] = 'ok';
500
	}
501
 
502
/**
503
 * Tests events dispatched by a local manager can be handled by
504
 * handler registered in the global event manager
505
 * @triggers my_event $manager
506
 */
507
	public function testDispatchLocalHandledByGlobal() {
508
		$callback = array($this, 'onMyEvent');
509
		CakeEventManager::instance()->attach($callback, 'my_event');
510
		$manager = new CakeEventManager();
511
		$event = new CakeEvent('my_event', $manager);
512
		$manager->dispatch($event);
513
		$this->assertEquals('ok', $event->data['callback']);
514
	}
515
 
516
/**
517
 * Test that events are dispatched properly when there are global and local
518
 * listeners at the same priority.
519
 *
520
 * @return void
521
 * @triggers fake.event $this
522
 */
523
	public function testDispatchWithGlobalAndLocalEvents() {
524
		$listener = new CustomTestEventListener();
525
		CakeEventManager::instance()->attach($listener);
526
		$listener2 = new CakeEventTestListener();
527
		$manager = new CakeEventManager();
528
		$manager->attach(array($listener2, 'listenerFunction'), 'fake.event');
529
 
530
		$manager->dispatch(new CakeEvent('fake.event', $this));
531
		$this->assertEquals(array('listenerFunction'), $listener->callStack);
532
		$this->assertEquals(array('listenerFunction'), $listener2->callStack);
533
	}
534
 
535
}