[BUGFIX] Notice free FormEngine testing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / NodeFactoryTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form;
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 TYPO3\CMS\Backend\Form\Element\SelectSingleElement;
18 use TYPO3\CMS\Backend\Form\Element\SelectTreeElement;
19 use TYPO3\CMS\Backend\Form\Element\UnknownElement;
20 use TYPO3\CMS\Backend\Form\Exception;
21 use TYPO3\CMS\Backend\Form\NodeFactory;
22 use TYPO3\CMS\Backend\Form\NodeInterface;
23 use TYPO3\CMS\Backend\Form\NodeResolverInterface;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
26
27 /**
28 * Test case
29 */
30 class NodeFactoryTest extends UnitTestCase
31 {
32 /**
33 * @test
34 */
35 public function constructThrowsExceptionIfOverrideMissesNodeNameKey()
36 {
37 $this->expectException(Exception::class);
38 $this->expectExceptionCode(1432207533);
39 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
40 1433089391 => [
41 'class' => 'foo',
42 'priority' => 23,
43 ],
44 ];
45 new NodeFactory();
46 }
47
48 /**
49 * @test
50 */
51 public function constructThrowsExceptionIfOverrideMissesPriorityKey()
52 {
53 $this->expectException(Exception::class);
54 $this->expectExceptionCode(1432207533);
55 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
56 1433089393 => [
57 'nodeName' => 'foo',
58 'class' => 'bar',
59 ],
60 ];
61 new NodeFactory();
62 }
63
64 /**
65 * @test
66 */
67 public function constructThrowsExceptionIfOverrideMissesClassKey()
68 {
69 $this->expectException(Exception::class);
70 $this->expectExceptionCode(1432207533);
71 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
72 1433089392 => [
73 'nodeName' => 'foo',
74 'priority' => 23,
75 ],
76 ];
77 new NodeFactory();
78 }
79
80 /**
81 * @test
82 */
83 public function constructThrowsExceptionIfOverridePriorityIsLowerThanZero()
84 {
85 $this->expectException(Exception::class);
86 $this->expectExceptionCode(1432223531);
87 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
88 1433089394 => [
89 'nodeName' => 'foo',
90 'class' => 'bar',
91 'priority' => -23,
92 ],
93 ];
94 new NodeFactory();
95 }
96 /**
97 * @test
98 */
99 public function constructThrowsExceptionIfOverridePriorityIsHigherThanHundred()
100 {
101 $this->expectException(Exception::class);
102 $this->expectExceptionCode(1432223531);
103 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
104 1433089395 => [
105 'nodeName' => 'foo',
106 'class' => 'bar',
107 'priority' => 142,
108 ],
109 ];
110 new NodeFactory();
111 }
112
113 /**
114 * @test
115 */
116 public function constructorThrowsExceptionIfOverrideTwoNodesWithSamePriorityAndSameNodeNameAreRegistered()
117 {
118 $this->expectException(Exception::class);
119 $this->expectExceptionCode(1432223893);
120 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
121 1433089396 => [
122 'nodeName' => 'foo',
123 'priority' => 20,
124 'class' => 'fooClass',
125 ],
126 1433089397 => [
127 'nodeName' => 'foo',
128 'priority' => 20,
129 'class' => 'barClass',
130 ],
131 ];
132 new NodeFactory();
133 }
134
135 /**
136 * @test
137 */
138 public function constructThrowsExceptionIfResolverMissesNodeNameKey()
139 {
140 $this->expectException(Exception::class);
141 $this->expectExceptionCode(1433155522);
142 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
143 1433154905 => [
144 'class' => 'foo',
145 'priority' => 23,
146 ],
147 ];
148 new NodeFactory();
149 }
150
151 /**
152 * @test
153 */
154 public function constructThrowsExceptionIfResolverMissesPriorityKey()
155 {
156 $this->expectException(Exception::class);
157 $this->expectExceptionCode(1433155522);
158 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
159 1433154905 => [
160 'nodeName' => 'foo',
161 'class' => 'bar',
162 ],
163 ];
164 new NodeFactory();
165 }
166
167 /**
168 * @test
169 */
170 public function constructThrowsExceptionIfResolverMissesClassKey()
171 {
172 $this->expectException(Exception::class);
173 $this->expectExceptionCode(1433155522);
174 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
175 1433154906 => [
176 'nodeName' => 'foo',
177 'priority' => 23,
178 ],
179 ];
180 new NodeFactory();
181 }
182
183 /**
184 * @test
185 */
186 public function constructThrowsExceptionIfResolverPriorityIsLowerThanZero()
187 {
188 $this->expectException(Exception::class);
189 $this->expectExceptionCode(1433155563);
190 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
191 1433154907 => [
192 'nodeName' => 'foo',
193 'class' => 'bar',
194 'priority' => -23,
195 ],
196 ];
197 new NodeFactory();
198 }
199 /**
200 * @test
201 */
202 public function constructThrowsExceptionIfResolverPriorityIsHigherThanHundred()
203 {
204 $this->expectException(Exception::class);
205 $this->expectExceptionCode(1433155563);
206 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
207 1433154908 => [
208 'nodeName' => 'foo',
209 'class' => 'bar',
210 'priority' => 142,
211 ],
212 ];
213 new NodeFactory();
214 }
215
216 /**
217 * @test
218 */
219 public function constructorThrowsExceptionIfResolverTwoNodesWithSamePriorityAndSameNodeNameAreRegistered()
220 {
221 $this->expectException(Exception::class);
222 $this->expectExceptionCode(1433155705);
223 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
224 1433154909 => [
225 'nodeName' => 'foo',
226 'priority' => 20,
227 'class' => 'fooClass',
228 ],
229 1433154910 => [
230 'nodeName' => 'foo',
231 'priority' => 20,
232 'class' => 'barClass',
233 ],
234 ];
235 new NodeFactory();
236 }
237
238 /**
239 * @test
240 */
241 public function constructorThrowsNoExceptionIfResolverWithSamePriorityButDifferentNodeNameAreRegistered()
242 {
243 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
244 1433154909 => [
245 'nodeName' => 'foo',
246 'priority' => 20,
247 'class' => 'fooClass',
248 ],
249 1433154910 => [
250 'nodeName' => 'bar',
251 'priority' => 20,
252 'class' => 'barClass',
253 ],
254 ];
255 new NodeFactory();
256 }
257
258 /**
259 * @test
260 */
261 public function createThrowsExceptionIfRenderTypeIsNotGiven()
262 {
263 $this->expectException(Exception::class);
264 $this->expectExceptionCode(1431452406);
265 $subject = new NodeFactory();
266 $subject->create([]);
267 }
268
269 /**
270 * @test
271 */
272 public function createThrowsExceptionIfNodeDoesNotImplementNodeInterface()
273 {
274 $this->expectException(Exception::class);
275 $this->expectExceptionCode(1431872546);
276 $mockNode = new \stdClass();
277 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
278 $mockSubject = $this->getMockBuilder(NodeFactory::class)
279 ->setMethods(['instantiate'])
280 ->disableOriginalConstructor()
281 ->getMock();
282 $mockSubject->expects($this->once())->method('instantiate')->will($this->returnValue($mockNode));
283 $mockSubject->create(['renderType' => 'foo']);
284 }
285
286 /**
287 * @test
288 */
289 public function createReturnsInstanceOfUnknownElementIfTypeIsNotRegistered()
290 {
291 $unknownElementProphecy = $this->prophesize(UnknownElement::class);
292 $unknownElementRevelation = $unknownElementProphecy->reveal();
293 GeneralUtility::addInstance(UnknownElement::class, $unknownElementRevelation);
294 $subject = new NodeFactory();
295 $this->assertSame($unknownElementRevelation, $subject->create(['renderType' => 'foo']));
296 }
297
298 /**
299 * @test
300 */
301 public function createReturnsInstanceOfSelectTreeElementIfNeeded()
302 {
303 $data = [
304 'type' => 'select',
305 'renderType' => 'selectTree',
306 ];
307 $selectTreeElementProphecy = $this->prophesize(SelectTreeElement::class);
308 $selectTreeElementRevelation = $selectTreeElementProphecy->reveal();
309 GeneralUtility::addInstance(SelectTreeElement::class, $selectTreeElementRevelation);
310 $subject = new NodeFactory();
311 $this->assertSame($selectTreeElementRevelation, $subject->create($data));
312 }
313
314 /**
315 * @test
316 */
317 public function createReturnsInstanceOfSelectSingleElementIfNeeded()
318 {
319 $data = [
320 'type' => 'select',
321 'renderType' => 'selectSingle',
322 'parameterArray' => [
323 'fieldConf' => [
324 'config' => [],
325 ],
326 ],
327 ];
328 $subject = new NodeFactory();
329 $selectSingleElementProphecy = $this->prophesize(SelectSingleElement::class);
330 $selectSingleElementRevelation = $selectSingleElementProphecy->reveal();
331 GeneralUtility::addInstance(SelectSingleElement::class, $selectSingleElementRevelation);
332 $this->assertSame($selectSingleElementRevelation, $subject->create($data));
333 }
334
335 /**
336 * @test
337 */
338 public function createInstantiatesNewRegisteredElement()
339 {
340 $data = ['renderType' => 'foo'];
341 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
342 [
343 'nodeName' => 'foo',
344 'priority' => 20,
345 'class' => \stdClass::class,
346 ],
347 ];
348 $mockNode = $this->createMock(NodeInterface::class);
349 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
350 $mockSubject = $this->getMockBuilder(NodeFactory::class)
351 ->setMethods(['instantiate'])
352 ->getMock();
353 $mockSubject->expects($this->once())->method('instantiate')->with('stdClass')->will($this->returnValue($mockNode));
354 $mockSubject->create($data);
355 }
356
357 /**
358 * @test
359 */
360 public function createInstantiatesElementRegisteredWithHigherPriorityWithOneGivenOrder()
361 {
362 $data = ['renderType' => 'foo'];
363 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
364 1433089467 => [
365 'nodeName' => 'foo',
366 'priority' => 20,
367 'class' => 'foo1Class',
368 ],
369 1433089468 => [
370 'nodeName' => 'foo',
371 'priority' => 30,
372 'class' => 'foo2Class',
373 ],
374 ];
375 $mockNode = $this->createMock(NodeInterface::class);
376 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
377 $mockSubject = $this->getMockBuilder(NodeFactory::class)
378 ->setMethods(['instantiate'])
379 ->getMock();
380 $mockSubject->expects($this->once())->method('instantiate')->with('foo2Class')->will($this->returnValue($mockNode));
381 $mockSubject->create($data);
382 }
383
384 /**
385 * @test
386 */
387 public function createInstantiatesElementRegisteredWithHigherPriorityWithOtherGivenOrder()
388 {
389 $data = ['renderType' => 'foo'];
390 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
391 1433089469 => [
392 'nodeName' => 'foo',
393 'priority' => 30,
394 'class' => 'foo2Class',
395 ],
396 1433089470 => [
397 'nodeName' => 'foo',
398 'priority' => 20,
399 'class' => 'foo1Class',
400 ],
401 ];
402 $mockNode = $this->createMock(NodeInterface::class);
403 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
404 $mockSubject = $this->getMockBuilder(NodeFactory::class)
405 ->setMethods(['instantiate'])
406 ->getMock();
407 $mockSubject->expects($this->once())->method('instantiate')->with('foo2Class')->will($this->returnValue($mockNode));
408 $mockSubject->create($data);
409 }
410
411 /**
412 * @test
413 */
414 public function createThrowsExceptionIfResolverDoesNotImplementNodeResolverInterface()
415 {
416 $this->expectException(Exception::class);
417 $this->expectExceptionCode(1433157422);
418 $data = ['renderType' => 'foo'];
419 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
420 1433156887 => [
421 'nodeName' => 'foo',
422 'priority' => 10,
423 'class' => 'fooClass',
424 ],
425 ];
426 $mockResolver = $this->getMockBuilder(\stdClass::class)->getMock();
427
428 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
429 $mockSubject = $this->getMockBuilder(NodeFactory::class)
430 ->setMethods(['instantiate'])
431 ->getMock();
432 $mockSubject->expects($this->at(0))->method('instantiate')->will($this->returnValue($mockResolver));
433 $mockSubject->create($data);
434 }
435
436 /**
437 * @test
438 */
439 public function createInstantiatesResolverWithHighestPriorityFirstWithOneGivenOrder()
440 {
441 $data = ['renderType' => 'foo'];
442 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
443 [
444 'nodeName' => 'foo',
445 'priority' => 20,
446 'class' => \stdClass::class,
447 ],
448 ];
449 $mockNode = $this->createMock(NodeInterface::class);
450
451 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
452 1433156887 => [
453 'nodeName' => 'foo',
454 'priority' => 10,
455 'class' => 'foo1Class',
456 ],
457 1433156888 => [
458 'nodeName' => 'foo',
459 'priority' => 30,
460 'class' => 'foo2Class',
461 ],
462 ];
463 $mockResolver1 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
464 $mockResolver2 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
465
466 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
467 $mockSubject = $this->getMockBuilder(NodeFactory::class)
468 ->setMethods(['instantiate'])
469 ->getMock();
470 $mockSubject->expects($this->at(0))->method('instantiate')->with('foo2Class')->will($this->returnValue($mockResolver2));
471 $mockSubject->expects($this->at(1))->method('instantiate')->with('foo1Class')->will($this->returnValue($mockResolver1));
472 $mockSubject->expects($this->at(2))->method('instantiate')->will($this->returnValue($mockNode));
473 $mockSubject->create($data);
474 }
475
476 /**
477 * @test
478 */
479 public function createInstantiatesResolverWithHighestPriorityFirstWithOtherGivenOrder()
480 {
481 $data = ['renderType' => 'foo'];
482 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
483 [
484 'nodeName' => 'foo',
485 'priority' => 20,
486 'class' => \stdClass::class,
487 ],
488 ];
489 $mockNode = $this->createMock(NodeInterface::class);
490
491 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
492 1433156887 => [
493 'nodeName' => 'foo',
494 'priority' => 30,
495 'class' => 'foo1Class',
496 ],
497 1433156888 => [
498 'nodeName' => 'foo',
499 'priority' => 10,
500 'class' => 'foo2Class',
501 ],
502 ];
503 $mockResolver1 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
504 $mockResolver2 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
505
506 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
507 $mockSubject = $this->getMockBuilder(NodeFactory::class)
508 ->setMethods(['instantiate'])
509 ->getMock();
510 $mockSubject->expects($this->at(0))->method('instantiate')->with('foo1Class')->will($this->returnValue($mockResolver1));
511 $mockSubject->expects($this->at(1))->method('instantiate')->with('foo2Class')->will($this->returnValue($mockResolver2));
512 $mockSubject->expects($this->at(2))->method('instantiate')->will($this->returnValue($mockNode));
513 $mockSubject->create($data);
514 }
515
516 /**
517 * @test
518 */
519 public function createInstantiatesNodeClassReturnedByResolver()
520 {
521 $data = ['renderType' => 'foo'];
522 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
523 [
524 'nodeName' => 'foo',
525 'priority' => 20,
526 'class' => \stdClass::class,
527 ],
528 ];
529 $mockNode = $this->createMock(NodeInterface::class);
530
531 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
532 1433156887 => [
533 'nodeName' => 'foo',
534 'priority' => 30,
535 'class' => 'foo1Class',
536 ],
537 ];
538 $mockResolver1 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
539 $mockResolver1->expects($this->once())->method('resolve')->will($this->returnValue('fooNodeClass'));
540
541 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
542 $mockSubject = $this->getMockBuilder(NodeFactory::class)
543 ->setMethods(['instantiate'])
544 ->getMock();
545 $mockSubject->expects($this->at(0))->method('instantiate')->will($this->returnValue($mockResolver1));
546 $mockSubject->expects($this->at(1))->method('instantiate')->with('fooNodeClass')->will($this->returnValue($mockNode));
547 $mockSubject->create($data);
548 }
549
550 /**
551 * @test
552 */
553 public function createDoesNotCallSecondResolverWithLowerPriorityIfFirstResolverReturnedClassName()
554 {
555 $data = ['renderType' => 'foo'];
556 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'] = [
557 [
558 'nodeName' => 'foo',
559 'priority' => 20,
560 'class' => \stdClass::class,
561 ],
562 ];
563 $mockNode = $this->createMock(NodeInterface::class);
564
565 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeResolver'] = [
566 1433156887 => [
567 'nodeName' => 'foo',
568 'priority' => 30,
569 'class' => 'foo1Class',
570 ],
571 1433156888 => [
572 'nodeName' => 'foo',
573 'priority' => 10,
574 'class' => 'foo2Class',
575 ],
576 ];
577 $mockResolver1 = $this->getMockBuilder(NodeResolverInterface::class)->getMock();
578 $mockResolver1->expects($this->once())->method('resolve')->will($this->returnValue('fooNodeClass'));
579
580 /** @var NodeFactory|\PHPUnit_Framework_MockObject_MockObject $mockSubject */
581 $mockSubject = $this->getMockBuilder(NodeFactory::class)
582 ->setMethods(['instantiate'])
583 ->getMock();
584 $mockSubject->expects($this->at(0))->method('instantiate')->with('foo1Class')->will($this->returnValue($mockResolver1));
585 $mockSubject->expects($this->at(1))->method('instantiate')->with('fooNodeClass')->will($this->returnValue($mockNode));
586 $mockSubject->create($data);
587 }
588 }