Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12345 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
 */
197
	public function testDispatch() {
198
		$manager = new CakeEventManager();
199
		$listener = $this->getMock('CakeEventTestListener');
200
		$anotherListener = $this->getMock('CakeEventTestListener');
201
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
202
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
203
		$event = new CakeEvent('fake.event');
204
 
205
		$listener->expects($this->once())->method('listenerFunction')->with($event);
206
		$anotherListener->expects($this->once())->method('listenerFunction')->with($event);
207
		$manager->dispatch($event);
208
	}
209
 
210
/**
211
 * Tests event dispatching using event key name
212
 *
213
 * @return void
214
 */
215
	public function testDispatchWithKeyName() {
216
		$manager = new CakeEventManager();
217
		$listener = new CakeEventTestListener();
218
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
219
		$event = 'fake.event';
220
		$manager->dispatch($event);
221
 
222
		$expected = array('listenerFunction');
223
		$this->assertEquals($expected, $listener->callStack);
224
	}
225
 
226
/**
227
 * Tests event dispatching with a return value
228
 *
229
 * @return void
230
 */
231
	public function testDispatchReturnValue() {
232
		$this->skipIf(
233
			version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
234
			'These tests fail in PHPUnit 3.6'
235
		);
236
		$manager = new CakeEventManager();
237
		$listener = $this->getMock('CakeEventTestListener');
238
		$anotherListener = $this->getMock('CakeEventTestListener');
239
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
240
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
241
		$event = new CakeEvent('fake.event');
242
 
243
		$listener->expects($this->at(0))->method('listenerFunction')
244
			->with($event)
245
			->will($this->returnValue('something special'));
246
		$anotherListener->expects($this->at(0))
247
			->method('listenerFunction')
248
			->with($event);
249
		$manager->dispatch($event);
250
		$this->assertEquals('something special', $event->result);
251
	}
252
 
253
/**
254
 * Tests that returning false in a callback stops the event
255
 *
256
 * @return void
257
 */
258
	public function testDispatchFalseStopsEvent() {
259
		$this->skipIf(
260
			version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
261
			'These tests fail in PHPUnit 3.6'
262
		);
263
 
264
		$manager = new CakeEventManager();
265
		$listener = $this->getMock('CakeEventTestListener');
266
		$anotherListener = $this->getMock('CakeEventTestListener');
267
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
268
		$manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
269
		$event = new CakeEvent('fake.event');
270
 
271
		$listener->expects($this->at(0))->method('listenerFunction')
272
			->with($event)
273
			->will($this->returnValue(false));
274
		$anotherListener->expects($this->never())
275
			->method('listenerFunction');
276
		$manager->dispatch($event);
277
		$this->assertTrue($event->isStopped());
278
	}
279
 
280
/**
281
 * Tests event dispatching using priorities
282
 *
283
 * @return void
284
 */
285
	public function testDispatchPrioritized() {
286
		$manager = new CakeEventManager();
287
		$listener = new CakeEventTestListener();
288
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
289
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
290
		$event = new CakeEvent('fake.event');
291
		$manager->dispatch($event);
292
 
293
		$expected = array('secondListenerFunction', 'listenerFunction');
294
		$this->assertEquals($expected, $listener->callStack);
295
	}
296
 
297
/**
298
 * Tests event dispatching with passed params
299
 *
300
 * @return void
301
 */
302
	public function testDispatchPassingParams() {
303
		$manager = new CakeEventManager();
304
		$listener = $this->getMock('CakeEventTestListener');
305
		$anotherListener = $this->getMock('CakeEventTestListener');
306
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
307
		$manager->attach(array($anotherListener, 'secondListenerFunction'), 'fake.event', array('passParams' => true));
308
		$event = new CakeEvent('fake.event', $this, array('some' => 'data'));
309
 
310
		$listener->expects($this->once())->method('listenerFunction')->with($event);
311
		$anotherListener->expects($this->once())->method('secondListenerFunction')->with('data');
312
		$manager->dispatch($event);
313
	}
314
 
315
/**
316
 * Tests subscribing a listener object and firing the events it subscribed to
317
 *
318
 * @return void
319
 */
320
	public function testAttachSubscriber() {
321
		$manager = new CakeEventManager();
322
		$listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction'));
323
		$manager->attach($listener);
324
		$event = new CakeEvent('fake.event');
325
 
326
		$manager->dispatch($event);
327
 
328
		$expected = array('listenerFunction');
329
		$this->assertEquals($expected, $listener->callStack);
330
 
331
		$listener->expects($this->at(0))->method('secondListenerFunction')->with('data');
332
		$event = new CakeEvent('another.event', $this, array('some' => 'data'));
333
		$manager->dispatch($event);
334
 
335
		$manager = new CakeEventManager();
336
		$listener = $this->getMock('CustomTestEventListener', array('listenerFunction', 'thirdListenerFunction'));
337
		$manager->attach($listener);
338
		$event = new CakeEvent('multiple.handlers');
339
		$listener->expects($this->once())->method('listenerFunction')->with($event);
340
		$listener->expects($this->once())->method('thirdListenerFunction')->with($event);
341
		$manager->dispatch($event);
342
	}
343
 
344
/**
345
 * Tests subscribing a listener object and firing the events it subscribed to
346
 *
347
 * @return void
348
 */
349
	public function testDetachSubscriber() {
350
		$manager = new CakeEventManager();
351
		$listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction'));
352
		$manager->attach($listener);
353
		$expected = array(
354
			array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => true)
355
		);
356
		$this->assertEquals($expected, $manager->listeners('another.event'));
357
		$expected = array(
358
			array('callable' => array($listener, 'listenerFunction'), 'passParams' => false)
359
		);
360
		$this->assertEquals($expected, $manager->listeners('fake.event'));
361
		$manager->detach($listener);
362
		$this->assertEquals(array(), $manager->listeners('fake.event'));
363
		$this->assertEquals(array(), $manager->listeners('another.event'));
364
	}
365
 
366
/**
367
 * Tests that it is possible to get/set the manager singleton
368
 *
369
 * @return void
370
 */
371
	public function testGlobalDispatcherGetter() {
372
		$this->assertInstanceOf('CakeEventManager', CakeEventManager::instance());
373
		$manager = new CakeEventManager();
374
 
375
		CakeEventManager::instance($manager);
376
		$this->assertSame($manager, CakeEventManager::instance());
377
	}
378
 
379
/**
380
 * Tests that the global event manager gets the event too from any other manager
381
 *
382
 * @return void
383
 */
384
	public function testDispatchWithGlobal() {
385
		$generalManager = $this->getMock('CakeEventManager', array('prioritisedListeners'));
386
		$manager = new CakeEventManager();
387
		$event = new CakeEvent('fake.event');
388
		CakeEventManager::instance($generalManager);
389
 
390
		$generalManager->expects($this->once())->method('prioritisedListeners')->with('fake.event');
391
		$manager->dispatch($event);
392
		CakeEventManager::instance(new CakeEventManager());
393
	}
394
 
395
/**
396
 * Tests that stopping an event will not notify the rest of the listeners
397
 *
398
 * @return void
399
 */
400
	public function testStopPropagation() {
401
		$generalManager = $this->getMock('CakeEventManager');
402
		$manager = new CakeEventManager();
403
		$listener = new CakeEventTestListener();
404
 
405
		CakeEventManager::instance($generalManager);
406
		$generalManager->expects($this->any())
407
				->method('prioritisedListeners')
408
				->with('fake.event')
409
				->will($this->returnValue(array()));
410
 
411
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
412
		$manager->attach(array($listener, 'stopListener'), 'fake.event', array('priority' => 8));
413
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
414
		$event = new CakeEvent('fake.event');
415
		$manager->dispatch($event);
416
 
417
		$expected = array('secondListenerFunction');
418
		$this->assertEquals($expected, $listener->callStack);
419
		CakeEventManager::instance(new CakeEventManager());
420
	}
421
 
422
/**
423
 * Tests event dispatching using priorities
424
 *
425
 * @return void
426
 */
427
	public function testDispatchPrioritizedWithGlobal() {
428
		$generalManager = $this->getMock('CakeEventManager');
429
		$manager = new CakeEventManager();
430
		$listener = new CustomTestEventListener();
431
		$event = new CakeEvent('fake.event');
432
 
433
		CakeEventManager::instance($generalManager);
434
		$generalManager->expects($this->any())
435
				->method('prioritisedListeners')
436
				->with('fake.event')
437
				->will($this->returnValue(
438
					array(11 => array(
439
						array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => false)
440
					))
441
				));
442
 
443
		$manager->attach(array($listener, 'listenerFunction'), 'fake.event');
444
		$manager->attach(array($listener, 'thirdListenerFunction'), 'fake.event', array('priority' => 15));
445
 
446
		$manager->dispatch($event);
447
 
448
		$expected = array('listenerFunction', 'secondListenerFunction', 'thirdListenerFunction');
449
		$this->assertEquals($expected, $listener->callStack);
450
		CakeEventManager::instance(new CakeEventManager());
451
	}
452
 
453
/**
454
 * Tests event dispatching using priorities
455
 *
456
 * @return void
457
 */
458
	public function testDispatchGlobalBeforeLocal() {
459
		$generalManager = $this->getMock('CakeEventManager');
460
		$manager = new CakeEventManager();
461
		$listener = new CustomTestEventListener();
462
		$event = new CakeEvent('fake.event');
463
 
464
		CakeEventManager::instance($generalManager);
465
		$generalManager->expects($this->any())
466
				->method('prioritisedListeners')
467
				->with('fake.event')
468
				->will($this->returnValue(
469
					array(10 => array(
470
						array('callable' => array($listener, 'listenerFunction'), 'passParams' => false)
471
					))
472
				));
473
 
474
		$manager->attach(array($listener, 'secondListenerFunction'), 'fake.event');
475
 
476
		$manager->dispatch($event);
477
 
478
		$expected = array('listenerFunction', 'secondListenerFunction');
479
		$this->assertEquals($expected, $listener->callStack);
480
		CakeEventManager::instance(new CakeEventManager());
481
	}
482
 
483
/**
484
 * test callback
485
 */
486
	public function onMyEvent($event) {
487
		$event->data['callback'] = 'ok';
488
	}
489
 
490
/**
491
 * Tests events dispatched by a local manager can be handled by
492
 * handler registered in the global event manager
493
 */
494
	public function testDispatchLocalHandledByGlobal() {
495
		$callback = array($this, 'onMyEvent');
496
		CakeEventManager::instance()->attach($callback, 'my_event');
497
		$manager = new CakeEventManager();
498
		$event = new CakeEvent('my_event', $manager);
499
		$manager->dispatch($event);
500
		$this->assertEquals('ok', $event->data['callback']);
501
	}
502
 
503
/**
504
 * Test that events are dispatched properly when there are global and local
505
 * listeners at the same priority.
506
 *
507
 * @return void
508
 */
509
	public function testDispatchWithGlobalAndLocalEvents() {
510
		$listener = new CustomTestEventListener();
511
		CakeEventManager::instance()->attach($listener);
512
		$listener2 = new CakeEventTestListener();
513
		$manager = new CakeEventManager();
514
		$manager->attach(array($listener2, 'listenerFunction'), 'fake.event');
515
 
516
		$manager->dispatch(new CakeEvent('fake.event', $this));
517
		$this->assertEquals(array('listenerFunction'), $listener->callStack);
518
		$this->assertEquals(array('listenerFunction'), $listener2->callStack);
519
	}
520
 
521
}