2 namespace TYPO3\CMS\Extbase\Tests\Unit\SignalSlot
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
20 class DispatcherTest
extends \TYPO3\CMS\Core\Tests\UnitTestCase
{
23 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher|\PHPUnit_Framework_MockObject_MockObject|\Tx_Phpunit_Interface_AccessibleObject
25 protected $signalSlotDispatcher;
27 public function setUp() {
28 $accessibleClassName = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher', array('dummy'));
29 $this->signalSlotDispatcher
= new $accessibleClassName();
35 public function connectAllowsForConnectingASlotWithASignal() {
36 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
37 $mockSlot = $this->getMock('ClassB', array('someSlotMethod'));
38 $this->signalSlotDispatcher
->connect(get_class($mockSignal), 'emitSomeSignal', get_class($mockSlot), 'someSlotMethod', TRUE);
39 $expectedSlots = array(
40 array('class' => get_class($mockSlot), 'method' => 'someSlotMethod', 'object' => NULL, 'passSignalInformation' => TRUE)
42 $this->assertSame($expectedSlots, $this->signalSlotDispatcher
->getSlots(get_class($mockSignal), 'emitSomeSignal'));
48 public function connectAlsoAcceptsObjectsInPlaceOfTheClassName() {
49 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
50 $mockSlot = $this->getMock('ClassB', array('someSlotMethod'));
51 $this->signalSlotDispatcher
->connect(get_class($mockSignal), 'emitSomeSignal', $mockSlot, 'someSlotMethod', TRUE);
52 $expectedSlots = array(
53 array('class' => NULL, 'method' => 'someSlotMethod', 'object' => $mockSlot, 'passSignalInformation' => TRUE)
55 $this->assertSame($expectedSlots, $this->signalSlotDispatcher
->getSlots(get_class($mockSignal), 'emitSomeSignal'));
61 public function connectAlsoAcceptsClosuresActingAsASlot() {
62 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
63 $mockSlot = function () {
65 $this->signalSlotDispatcher
->connect(get_class($mockSignal), 'emitSomeSignal', $mockSlot, 'foo', TRUE);
66 $expectedSlots = array(
67 array('class' => NULL, 'method' => '__invoke', 'object' => $mockSlot, 'passSignalInformation' => TRUE)
69 $this->assertSame($expectedSlots, $this->signalSlotDispatcher
->getSlots(get_class($mockSignal), 'emitSomeSignal'));
75 public function dispatchPassesTheSignalArgumentsToTheSlotMethod() {
77 $mockSlot = function () use (&$arguments) {
78 ($arguments = func_get_args());
80 $this->signalSlotDispatcher
->connect('Foo', 'bar', $mockSlot, NULL, FALSE);
81 $this->signalSlotDispatcher
->dispatch('Foo', 'bar', array('bar', 'quux'));
82 $this->assertSame(array('bar', 'quux'), $arguments);
88 public function dispatchRetrievesSlotInstanceFromTheObjectManagerIfOnlyAClassNameWasSpecified() {
89 $slotClassName = uniqid('Mock_');
90 eval('class ' . $slotClassName . ' { function slot($foo, $baz) { $this->arguments = array($foo, $baz); } }');
91 $mockSlot = new $slotClassName();
92 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
93 $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
94 $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
95 $this->signalSlotDispatcher
->_set('objectManager', $mockObjectManager);
96 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
97 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $slotClassName, 'slot', FALSE);
98 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
99 $this->assertSame($mockSlot->arguments
, array('bar', 'quux'));
105 public function dispatchHandsOverArgumentsReturnedByAFormerSlot() {
106 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
108 $firstMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
109 $firstMockSlot->expects($this->once())
111 ->will($this->returnCallback(
112 function($foo, $baz) {
113 return array('modified_' . $foo, 'modified_' . $baz);}
116 $secondMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
117 $secondMockSlot->expects($this->once())
119 ->with('modified_bar', 'modified_quux');
122 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $firstMockSlot, 'slot', FALSE);
123 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $secondMockSlot, 'slot', FALSE);
125 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
131 public function dispatchHandsOverArgumentsReturnedByAFormerSlotWithoutInterferingWithSignalSlotInformation() {
132 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
134 $firstMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
135 $firstMockSlot->expects($this->once())
137 ->will($this->returnCallback(
138 function($foo, $baz) {
139 return array('modified_' . $foo, 'modified_' . $baz);}
142 $secondMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
143 $secondMockSlot->expects($this->once())
145 ->with('modified_bar', 'modified_quux');
147 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $firstMockSlot, 'slot');
148 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $secondMockSlot, 'slot');
150 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
156 public function dispatchHandsOverFormerArgumentsIfPreviousSlotDoesNotReturnAnything() {
157 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
159 $firstMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
160 $firstMockSlot->expects($this->once())
162 ->will($this->returnCallback(
163 function($foo, $baz) {
164 return array('modified_' . $foo, 'modified_' . $baz);}
167 $secondMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
168 $secondMockSlot->expects($this->once())
171 $thirdMockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
172 $thirdMockSlot->expects($this->once())
174 ->with('modified_bar', 'modified_quux');
177 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $firstMockSlot, 'slot');
178 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $secondMockSlot, 'slot');
179 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $thirdMockSlot, 'slot');
181 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
186 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
188 public function dispatchThrowsAnExceptionIfTheSlotReturnsNonArray() {
189 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
191 $mockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
192 $mockSlot->expects($this->once())
194 ->will($this->returnCallback(
199 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $mockSlot, 'slot', FALSE);
200 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
205 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
207 public function dispatchThrowsAnExceptionIfTheSlotReturnsDifferentNumberOfItems() {
208 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
210 $mockSlot = $this->getMock('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\SlotFixture');
211 $mockSlot->expects($this->once())
213 ->will($this->returnCallback(
215 return array(1, 2, 3);}
218 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $mockSlot, 'slot', FALSE);
219 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
224 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
226 public function dispatchThrowsAnExceptionIfTheSpecifiedClassOfASlotIsUnknown() {
227 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
228 $mockObjectManager->expects($this->once())->method('isRegistered')->with('NonExistingClassName')->will($this->returnValue(FALSE));
229 $this->signalSlotDispatcher
->_set('objectManager', $mockObjectManager);
230 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
231 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', 'NonExistingClassName', 'slot', TRUE);
232 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array());
237 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
239 public function dispatchThrowsAnExceptionIfTheSpecifiedSlotMethodDoesNotExist() {
240 $slotClassName = uniqid('Mock_');
241 eval('class ' . $slotClassName . ' { function slot($foo, $baz) { $this->arguments = array($foo, $baz); } }');
242 $mockSlot = new $slotClassName();
243 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
244 $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
245 $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
246 $this->signalSlotDispatcher
->_set('objectManager', $mockObjectManager);
247 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
248 $this->signalSlotDispatcher
->connect('Foo', 'emitBar', $slotClassName, 'unknownMethodName', TRUE);
249 $this->signalSlotDispatcher
->dispatch('Foo', 'emitBar', array('bar', 'quux'));
250 $this->assertSame($mockSlot->arguments
, array('bar', 'quux'));
256 public function dispatchPassesFirstArgumentContainingSlotInformationIfTheConnectionStatesSo() {
257 $arguments = array();
258 $mockSlot = function () use (&$arguments) {
259 ($arguments = func_get_args());
261 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
262 $this->signalSlotDispatcher
->connect('SignalClassName', 'methodName', $mockSlot, NULL, TRUE);
263 $this->signalSlotDispatcher
->_set('objectManager', $mockObjectManager);
264 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
265 $this->signalSlotDispatcher
->dispatch('SignalClassName', 'methodName', array('bar', 'quux'));
266 $this->assertSame(array('bar', 'quux', 'SignalClassName::methodName'), $arguments);
271 * @expectedException \InvalidArgumentException
272 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
274 public function connectThrowsInvalidArgumentExceptionIfSlotMethodNameIsEmptyAndSlotClassNameIsNoClosure() {
275 $this->signalSlotDispatcher
->connect('ClassA', 'emitSomeSignal', 'ClassB', '');
280 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
282 public function dispatchReturnsEmptyArrayIfSignalNameAndOrSignalClassNameIsNotRegistered() {
283 $this->assertSame(array(), $this->signalSlotDispatcher
->dispatch('ClassA', 'someNotRegisteredSignalName'));
289 public function dispatchReturnsEmptyArrayIfSignalDoesNotProvideAnyArguments() {
290 $this->assertSame(array(), $this->signalSlotDispatcher
->dispatch('ClassA', 'emitSomeSignal'));
296 public function dispatchReturnsArgumentsArrayAsIsIfSignalIsNotRegistered() {
302 $this->assertSame($arguments, $this->signalSlotDispatcher
->dispatch('ClassA', 'emitSomeSignal', $arguments));
307 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
308 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
310 public function dispatchThrowsInvalidSlotExceptionIfObjectManagerOfSignalSlotDispatcherIsNotSet() {
311 $this->signalSlotDispatcher
->_set('isInitialized', TRUE);
312 $this->signalSlotDispatcher
->_set('objectManager', NULL);
313 $this->signalSlotDispatcher
->_set('slots', array('ClassA' => array('emitSomeSignal' => array(array()))));
315 $this->assertSame(NULL, $this->signalSlotDispatcher
->dispatch('ClassA', 'emitSomeSignal'));