969ff9d023bead8235492a7cb841d41b808846ef
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / SignalSlot / DispatcherTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\SignalSlot;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * Testcase for the Signal Dispatcher Class
32 *
33 * @author Felix Oertel <f@oer.tel>
34 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
35 */
36 class DispatcherTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
37
38 /**
39 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher|\PHPUnit_Framework_MockObject_MockObject|\Tx_Phpunit_Interface_AccessibleObject
40 */
41 protected $signalSlotDispatcher;
42
43 public function setUp() {
44 $accessibleClassName = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher', array('dummy'));
45 $this->signalSlotDispatcher = new $accessibleClassName();
46 }
47
48 /**
49 * @test
50 * @author Felix Oertel <f@oer.tel>
51 */
52 public function connectAllowsForConnectingASlotWithASignal() {
53 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
54 $mockSlot = $this->getMock('ClassB', array('someSlotMethod'));
55 $this->signalSlotDispatcher->connect(get_class($mockSignal), 'emitSomeSignal', get_class($mockSlot), 'someSlotMethod', TRUE);
56 $expectedSlots = array(
57 array('class' => get_class($mockSlot), 'method' => 'someSlotMethod', 'object' => NULL, 'passSignalInformation' => TRUE)
58 );
59 $this->assertSame($expectedSlots, $this->signalSlotDispatcher->getSlots(get_class($mockSignal), 'emitSomeSignal'));
60 }
61
62 /**
63 * @test
64 * @author Felix Oertel <f@oer.tel>
65 */
66 public function connectAlsoAcceptsObjectsInPlaceOfTheClassName() {
67 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
68 $mockSlot = $this->getMock('ClassB', array('someSlotMethod'));
69 $this->signalSlotDispatcher->connect(get_class($mockSignal), 'emitSomeSignal', $mockSlot, 'someSlotMethod', TRUE);
70 $expectedSlots = array(
71 array('class' => NULL, 'method' => 'someSlotMethod', 'object' => $mockSlot, 'passSignalInformation' => TRUE)
72 );
73 $this->assertSame($expectedSlots, $this->signalSlotDispatcher->getSlots(get_class($mockSignal), 'emitSomeSignal'));
74 }
75
76 /**
77 * @test
78 * @author Felix Oertel <f@oer.tel>
79 */
80 public function connectAlsoAcceptsClosuresActingAsASlot() {
81 $mockSignal = $this->getMock('ClassA', array('emitSomeSignal'));
82 $mockSlot = function () {
83 };
84 $this->signalSlotDispatcher->connect(get_class($mockSignal), 'emitSomeSignal', $mockSlot, 'foo', TRUE);
85 $expectedSlots = array(
86 array('class' => NULL, 'method' => '__invoke', 'object' => $mockSlot, 'passSignalInformation' => TRUE)
87 );
88 $this->assertSame($expectedSlots, $this->signalSlotDispatcher->getSlots(get_class($mockSignal), 'emitSomeSignal'));
89 }
90
91 /**
92 * @test
93 * @author Felix Oertel <f@oer.tel>
94 */
95 public function dispatchPassesTheSignalArgumentsToTheSlotMethod() {
96 $arguments = array();
97 $mockSlot = function () use (&$arguments) {
98 ($arguments = func_get_args());
99 };
100 $this->signalSlotDispatcher->connect('Foo', 'bar', $mockSlot, NULL, FALSE);
101 $this->signalSlotDispatcher->dispatch('Foo', 'bar', array('foo' => 'bar', 'baz' => 'quux'));
102 $this->assertSame(array('bar', 'quux'), $arguments);
103 }
104
105 /**
106 * @test
107 * @author Felix Oertel <f@oer.tel>
108 */
109 public function dispatchRetrievesSlotInstanceFromTheObjectManagerIfOnlyAClassNameWasSpecified() {
110 $slotClassName = uniqid('Mock_');
111 eval('class ' . $slotClassName . ' { function slot($foo, $baz) { $this->arguments = array($foo, $baz); } }');
112 $mockSlot = new $slotClassName();
113 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
114 $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
115 $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
116 $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
117 $this->signalSlotDispatcher->_set('isInitialized', TRUE);
118 $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'slot', FALSE);
119 $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array('foo' => 'bar', 'baz' => 'quux'));
120 $this->assertSame($mockSlot->arguments, array('bar', 'quux'));
121 }
122
123 /**
124 * @test
125 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
126 * @author Felix Oertel <f@oer.tel>
127 */
128 public function dispatchThrowsAnExceptionIfTheSpecifiedClassOfASlotIsUnknown() {
129 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
130 $mockObjectManager->expects($this->once())->method('isRegistered')->with('NonExistingClassName')->will($this->returnValue(FALSE));
131 $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
132 $this->signalSlotDispatcher->_set('isInitialized', TRUE);
133 $this->signalSlotDispatcher->connect('Foo', 'emitBar', 'NonExistingClassName', 'slot', TRUE);
134 $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array());
135 }
136
137 /**
138 * @test
139 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
140 * @author Felix Oertel <f@oer.tel>
141 */
142 public function dispatchThrowsAnExceptionIfTheSpecifiedSlotMethodDoesNotExist() {
143 $slotClassName = uniqid('Mock_');
144 eval('class ' . $slotClassName . ' { function slot($foo, $baz) { $this->arguments = array($foo, $baz); } }');
145 $mockSlot = new $slotClassName();
146 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
147 $mockObjectManager->expects($this->once())->method('isRegistered')->with($slotClassName)->will($this->returnValue(TRUE));
148 $mockObjectManager->expects($this->once())->method('get')->with($slotClassName)->will($this->returnValue($mockSlot));
149 $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
150 $this->signalSlotDispatcher->_set('isInitialized', TRUE);
151 $this->signalSlotDispatcher->connect('Foo', 'emitBar', $slotClassName, 'unknownMethodName', TRUE);
152 $this->signalSlotDispatcher->dispatch('Foo', 'emitBar', array('foo' => 'bar', 'baz' => 'quux'));
153 $this->assertSame($mockSlot->arguments, array('bar', 'quux'));
154 }
155
156 /**
157 * @test
158 * @author Felix Oertel <f@oer.tel>
159 */
160 public function dispatchPassesFirstArgumentContainingSlotInformationIfTheConnectionStatesSo() {
161 $arguments = array();
162 $mockSlot = function () use (&$arguments) {
163 ($arguments = func_get_args());
164 };
165 $mockObjectManager = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\ObjectManagerInterface');
166 $this->signalSlotDispatcher->connect('SignalClassName', 'methodName', $mockSlot, NULL, TRUE);
167 $this->signalSlotDispatcher->_set('objectManager', $mockObjectManager);
168 $this->signalSlotDispatcher->_set('isInitialized', TRUE);
169 $this->signalSlotDispatcher->dispatch('SignalClassName', 'methodName', array('foo' => 'bar', 'baz' => 'quux'));
170 $this->assertSame(array('bar', 'quux', 'SignalClassName::methodName'), $arguments);
171 }
172
173 /**
174 * @test
175 * @expectedException \InvalidArgumentException
176 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
177 */
178 public function connectThrowsInvalidArgumentExceptionIfSlotMethodNameIsEmptyAndSlotClassNameIsNoClosure() {
179 $this->signalSlotDispatcher->connect('ClassA', 'emitSomeSignal', 'ClassB', '');
180 }
181
182 /**
183 * @test
184 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
185 */
186 public function dispatchReturnsVoidIfSignalNameAndOrSignalClassNameIsNotRegistered() {
187 $this->assertSame(NULL, $this->signalSlotDispatcher->dispatch('ClassA', 'emitSomeSignal'));
188 }
189
190 /**
191 * @test
192 * @expectedException \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
193 * @author Alexander Schnitzler <alex.schnitzler@typovision.de>
194 */
195 public function dispatchThrowsInvalidSlotExceptionIfObjectManagerOfSignalSlotDispatcherIsNotSet() {
196 $this->signalSlotDispatcher->_set('isInitialized', TRUE);
197 $this->signalSlotDispatcher->_set('objectManager', NULL);
198 $this->signalSlotDispatcher->_set('slots', array('ClassA' => array('emitSomeSignal' => array(array()))));
199
200 $this->assertSame(NULL, $this->signalSlotDispatcher->dispatch('ClassA', 'emitSomeSignal'));
201 }
202 }
203
204 ?>