[BUGFIX] Notice free FormEngine testing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaSelectTreeItemsTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
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.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Doctrine\DBAL\Driver\Statement;
18 use Prophecy\Argument;
19 use Prophecy\Prophecy\ObjectProphecy;
20 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectTreeItems;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\Database\Connection;
23 use TYPO3\CMS\Core\Database\ConnectionPool;
24 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
25 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
26 use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer;
27 use TYPO3\CMS\Core\Localization\LanguageService;
28 use TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider;
29 use TYPO3\CMS\Core\Tree\TableConfiguration\TableConfigurationTree;
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
32
33 /**
34 * Tests for the TcaSelectTreeItems provider.
35 *
36 * This test only covers the renderTree() method. All other methods are covered by TcaSelectItemsTest
37 *
38 * @see TcaSelecItemsTest
39 */
40 class TcaSelectTreeItemsTest extends UnitTestCase
41 {
42 /**
43 * @var array A backup of registered singleton instances
44 */
45 protected $singletonInstances = [];
46
47 /**
48 * Initializes the mock object.
49 */
50 public function setUp()
51 {
52 $this->singletonInstances = GeneralUtility::getSingletonInstances();
53 }
54
55 protected function tearDown()
56 {
57 GeneralUtility::purgeInstances();
58 GeneralUtility::resetSingletonInstances($this->singletonInstances);
59 parent::tearDown();
60 }
61
62 /**
63 * Setup a mock database connection with expectations for
64 * the testsuite.
65 */
66 protected function mockDatabaseConnection()
67 {
68 $connectionProphet = $this->prophesize(Connection::class);
69 $connectionProphet->quote(Argument::cetera())->will(function ($arguments) {
70 return "'" . $arguments[0] . "'";
71 });
72 $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
73 return '`' . $arguments[0] . '`';
74 });
75
76 /** @var Statement|ObjectProphecy $statementProphet */
77 $statementProphet = $this->prophesize(Statement::class);
78 $statementProphet->fetch()->shouldBeCalled();
79
80 $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class);
81 $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal());
82 $restrictionProphet->add(Argument::cetera())->willReturn($restrictionProphet->reveal());
83
84 $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
85 $queryBuilderProphet->expr()->willReturn(
86 GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
87 );
88 $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal());
89 $queryBuilderProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
90 return '`' . $arguments[0] . '`';
91 });
92
93 $connectionPoolProphet = $this->prophesize(ConnectionPool::class);
94 $connectionPoolProphet->getConnectionForTable('foreignTable')
95 ->willReturn($connectionProphet->reveal());
96 $connectionPoolProphet->getQueryBuilderForTable('foreignTable')
97 ->shouldBeCalled()
98 ->willReturn($queryBuilderProphet->reveal());
99
100 $queryBuilderProphet->select('foreignTable.uid')
101 ->shouldBeCalled()
102 ->willReturn($queryBuilderProphet->reveal());
103 $queryBuilderProphet->from('foreignTable')
104 ->shouldBeCalled()
105 ->willReturn($queryBuilderProphet->reveal());
106 $queryBuilderProphet->from('pages')
107 ->shouldBeCalled()
108 ->willReturn($queryBuilderProphet->reveal());
109 $queryBuilderProphet->where('')
110 ->shouldBeCalled()
111 ->willReturn($queryBuilderProphet->reveal());
112 $queryBuilderProphet->andWhere(' 1=1')
113 ->shouldBeCalled()
114 ->willReturn($queryBuilderProphet->reveal());
115 $queryBuilderProphet->andWhere('`pages.uid` = `foreignTable.pid`')
116 ->shouldBeCalled()
117 ->willReturn($queryBuilderProphet->reveal());
118 $queryBuilderProphet->execute()
119 ->shouldBeCalled()
120 ->willReturn($statementProphet->reveal());
121
122 // Two instances are needed due to the push/pop behavior of addInstance()
123 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
124 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
125 }
126
127 /**
128 * @test
129 */
130 public function addDataAddsTreeConfigurationForExtJs()
131 {
132 $GLOBALS['TCA']['foreignTable'] = [];
133
134 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
135 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
136 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
137 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
138
139 $languageService = $this->prophesize(LanguageService::class);
140 $GLOBALS['LANG'] = $languageService->reveal();
141 $languageService->sL(Argument::cetera())->willReturnArgument(0);
142
143 $this->mockDatabaseConnection();
144
145 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
146 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
147 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
148
149 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
150 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
151 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
152 $tableConfigurationTreeProphecy->setDataProvider(Argument::cetera())->shouldBeCalled();
153 $tableConfigurationTreeProphecy->setNodeRenderer(Argument::cetera())->shouldBeCalled();
154 $tableConfigurationTreeProphecy->render()->shouldBeCalled()->willReturn(['fake', 'tree', 'data']);
155
156 $input = [
157 'tableName' => 'aTable',
158 'effectivePid' => 42,
159 'databaseRow' => [
160 'uid' => 5,
161 'aField' => '1'
162 ],
163 'processedTca' => [
164 'columns' => [
165 'aField' => [
166 'config' => [
167 'type' => 'select',
168 'renderType' => 'selectTree',
169 'treeConfig' => [
170 'childrenField' => 'childrenField'
171 ],
172 'foreign_table' => 'foreignTable',
173 'items' => [],
174 'maxitems' => 1
175 ],
176 ],
177 ],
178 ],
179 'selectTreeCompileItems' => true,
180 ];
181
182 $expected = $input;
183 $expected['databaseRow']['aField'] = ['1'];
184 $expected['processedTca']['columns']['aField']['config']['items'] = [
185 'fake', 'tree', 'data',
186 ];
187 $this->assertEquals($expected, (new TcaSelectTreeItems)->addData($input));
188 }
189
190 /**
191 * @test
192 */
193 public function addDataHandsPageTsConfigSettingsOverToTableConfigurationTree()
194 {
195 $GLOBALS['TCA']['foreignTable'] = [];
196
197 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
198 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
199 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
200 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
201
202 $languageService = $this->prophesize(LanguageService::class);
203 $GLOBALS['LANG'] = $languageService->reveal();
204 $languageService->sL(Argument::cetera())->willReturnArgument(0);
205
206 $this->mockDatabaseConnection();
207
208 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
209 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
210 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
211
212 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
213 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
214 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
215 $tableConfigurationTreeProphecy->render()->willReturn([]);
216 $tableConfigurationTreeProphecy->setDataProvider(Argument::cetera())->shouldBeCalled();
217 $tableConfigurationTreeProphecy->setNodeRenderer(Argument::cetera())->shouldBeCalled();
218
219 $input = [
220 'tableName' => 'aTable',
221 'effectivePid' => 42,
222 'databaseRow' => [
223 'uid' => 5,
224 'aField' => '1'
225 ],
226 'processedTca' => [
227 'columns' => [
228 'aField' => [
229 'config' => [
230 'type' => 'select',
231 'renderType' => 'selectTree',
232 'treeConfig' => [
233 'childrenField' => 'childrenField'
234 ],
235 'foreign_table' => 'foreignTable',
236 'items' => [],
237 'maxitems' => 1
238 ],
239 ],
240 ],
241 ],
242 'pageTsConfig' => [
243 'TCEFORM.' => [
244 'aTable.' => [
245 'aField.' => [
246 'config.' => [
247 'treeConfig.' => [
248 'rootUid' => '42',
249 'appearance.' => [
250 'expandAll' => 1,
251 'maxLevels' => 4,
252 'nonSelectableLevels' => '0,1',
253 ],
254 ],
255 ],
256 ],
257 ],
258 ],
259 ],
260 'selectTreeCompileItems' => true,
261 ];
262
263 (new TcaSelectTreeItems)->addData($input);
264
265 $treeDataProviderProphecy->setRootUid(42)->shouldHaveBeenCalled();
266 $treeDataProviderProphecy->setExpandAll(true)->shouldHaveBeenCalled();
267 $treeDataProviderProphecy->setLevelMaximum(4)->shouldHaveBeenCalled();
268 $treeDataProviderProphecy->setNonSelectableLevelList('0,1')->shouldHaveBeenCalled();
269 }
270 }