[BUGFIX] EXT:form - handle boolean finisher options
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Tests / Unit / Domain / Finishers / AbstractFinisherTest.php
1 <?php
2 namespace TYPO3\CMS\Form\Tests\Unit\Domain\Finishers;
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 Prophecy\Argument;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19 use TYPO3\CMS\Extbase\Object\ObjectManager;
20 use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
21 use TYPO3\CMS\Form\Domain\Finishers\FinisherContext;
22 use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;
23 use TYPO3\CMS\Form\Service\TranslationService;
24
25 /**
26 * Test case
27 */
28 class AbstractFinisherTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
29 {
30 /**
31 * @var array A backup of registered singleton instances
32 */
33 protected $singletonInstances = [];
34
35 /**
36 * Set up
37 */
38 public function setUp()
39 {
40 $this->singletonInstances = GeneralUtility::getSingletonInstances();
41 }
42
43 /**
44 * Tear down
45 */
46 public function tearDown()
47 {
48 GeneralUtility::resetSingletonInstances($this->singletonInstances);
49 parent::tearDown();
50 }
51
52 /**
53 * @test
54 */
55 public function parseOptionReturnsNullIfOptionNameIsTranslation()
56 {
57 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
58 AbstractFinisher::class,
59 [],
60 '',
61 false
62 );
63
64 $this->assertNull($mockAbstractFinisher->_call('parseOption', 'translation'));
65 }
66
67 /**
68 * @test
69 */
70 public function parseOptionReturnsNullIfOptionNameNotExistsWithinOptions()
71 {
72 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
73 AbstractFinisher::class,
74 [],
75 '',
76 false
77 );
78
79 $mockAbstractFinisher->_set('options', []);
80
81 $this->assertNull($mockAbstractFinisher->_call('parseOption', 'foo'));
82 }
83
84 /**
85 * @test
86 */
87 public function parseOptionReturnsNullIfOptionNameNotExistsWithinDefaultOptions()
88 {
89 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
90 AbstractFinisher::class,
91 [],
92 '',
93 false
94 );
95
96 $mockAbstractFinisher->_set('options', []);
97
98 $this->assertNull($mockAbstractFinisher->_call('parseOption', 'foo'));
99 }
100
101 /**
102 * @test
103 */
104 public function parseOptionReturnsArrayOptionValuesAsArray()
105 {
106 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
107 AbstractFinisher::class,
108 [],
109 '',
110 false
111 );
112
113 $mockAbstractFinisher->_set('options', [
114 'foo' => ['bar', 'foobar']
115 ]);
116
117 $expected = ['bar', 'foobar'];
118
119 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo'));
120 }
121
122 /**
123 * @test
124 */
125 public function parseOptionReturnsBoolOptionValuesAsBool()
126 {
127 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
128 AbstractFinisher::class,
129 [],
130 '',
131 false
132 );
133
134 $mockAbstractFinisher->_set('options', [
135 'foo1' => false,
136 ]);
137
138 $expected = false;
139
140 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'foo1'));
141 }
142
143 /**
144 * @test
145 */
146 public function parseOptionReturnsValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsAString()
147 {
148 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
149 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
150
151 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
152 'translateFinisherOption'
153 ], [], '', false);
154
155 $mockTranslationService
156 ->expects($this->any())
157 ->method('translateFinisherOption')
158 ->willReturnArgument(3);
159
160 $objectMangerProphecy
161 ->get(TranslationService::class)
162 ->willReturn($mockTranslationService);
163
164 $expected = 'element-value';
165 $elementIdentifier = 'element-identifier-1';
166
167 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
168 AbstractFinisher::class,
169 [],
170 '',
171 false
172 );
173
174 $mockAbstractFinisher->_set('options', [
175 'subject' => '{' . $elementIdentifier . '}'
176 ]);
177
178 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
179
180 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
181 $formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
182 $formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn($expected);
183
184 $finisherContextProphecy->getFormRuntime(Argument::cetera())
185 ->willReturn($formRuntimeProphecy->reveal());
186
187 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
188
189 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
190 }
191
192 /**
193 * @test
194 */
195 public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceAFormElementIdentifierWhoseValueIsNotAString()
196 {
197 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
198 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
199
200 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
201 'translateFinisherOption'
202 ], [], '', false);
203
204 $mockTranslationService
205 ->expects($this->any())
206 ->method('translateFinisherOption')
207 ->willReturnArgument(3);
208
209 $objectMangerProphecy
210 ->get(TranslationService::class)
211 ->willReturn($mockTranslationService);
212
213 $elementIdentifier = 'element-identifier-1';
214 $expected = '{' . $elementIdentifier . '}';
215
216 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
217 AbstractFinisher::class,
218 [],
219 '',
220 false
221 );
222
223 $mockAbstractFinisher->_set('options', [
224 'subject' => '{' . $elementIdentifier . '}'
225 ]);
226
227 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
228
229 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
230 $formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
231 $formElementValue = new \DateTime;
232 $formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn($formElementValue);
233
234 $finisherContextProphecy->getFormRuntime(Argument::cetera())
235 ->willReturn($formRuntimeProphecy->reveal());
236
237 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
238
239 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
240 }
241
242 /**
243 * @test
244 */
245 public function parseOptionReturnsNoReplacedValueFromFormRuntimeIfOptionNameReferenceANonExistingFormElement()
246 {
247 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
248 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
249
250 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
251 'translateFinisherOption'
252 ], [], '', false);
253
254 $mockTranslationService
255 ->expects($this->any())
256 ->method('translateFinisherOption')
257 ->willReturnArgument(3);
258
259 $objectMangerProphecy
260 ->get(TranslationService::class)
261 ->willReturn($mockTranslationService);
262
263 $elementIdentifier = 'element-identifier-1';
264
265 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
266 AbstractFinisher::class,
267 [],
268 '',
269 false
270 );
271
272 $mockAbstractFinisher->_set('options', [
273 'subject' => '{' . $elementIdentifier . '}'
274 ]);
275
276 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
277
278 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
279 $formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
280 $formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(false);
281
282 $finisherContextProphecy->getFormRuntime(Argument::cetera())
283 ->willReturn($formRuntimeProphecy->reveal());
284
285 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
286
287 $expected = '{' . $elementIdentifier . '}';
288 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
289 }
290
291 /**
292 * @test
293 */
294 public function parseOptionReturnsDefaultOptionValueIfOptionNameNotExistsWithinOptionsButWithinDefaultOptions()
295 {
296 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
297 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
298
299 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
300 'translateFinisherOption'
301 ], [], '', false);
302
303 $mockTranslationService
304 ->expects($this->any())
305 ->method('translateFinisherOption')
306 ->willReturnArgument(3);
307
308 $objectMangerProphecy
309 ->get(TranslationService::class)
310 ->willReturn($mockTranslationService);
311
312 $expected = 'defaultValue';
313
314 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
315 AbstractFinisher::class,
316 [],
317 '',
318 false
319 );
320
321 $mockAbstractFinisher->_set('options', []);
322 $mockAbstractFinisher->_set('defaultOptions', [
323 'subject' => $expected
324 ]);
325
326 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
327
328 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
329 $formRuntimeProphecy->offsetExists(Argument::cetera())->willReturn(true);
330 $formRuntimeProphecy->offsetGet(Argument::cetera())->willReturn(false);
331
332 $finisherContextProphecy->getFormRuntime(Argument::cetera())
333 ->willReturn($formRuntimeProphecy->reveal());
334
335 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
336
337 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
338 }
339
340 /**
341 * @test
342 */
343 public function parseOptionReturnsDefaultOptionValueIfOptionValueIsAFormElementReferenceAndTheFormElementValueIsEmpty()
344 {
345 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
346 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
347
348 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
349 'translateFinisherOption'
350 ], [], '', false);
351
352 $mockTranslationService
353 ->expects($this->any())
354 ->method('translateFinisherOption')
355 ->willReturnArgument(3);
356
357 $objectMangerProphecy
358 ->get(TranslationService::class)
359 ->willReturn($mockTranslationService);
360
361 $elementIdentifier = 'element-identifier-1';
362 $expected = 'defaultValue';
363
364 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
365 AbstractFinisher::class,
366 [],
367 '',
368 false
369 );
370
371 $mockAbstractFinisher->_set('options', [
372 'subject' => '{' . $elementIdentifier . '}'
373 ]);
374 $mockAbstractFinisher->_set('defaultOptions', [
375 'subject' => $expected
376 ]);
377
378 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
379
380 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
381 $formRuntimeProphecy->offsetExists(Argument::exact($elementIdentifier))->willReturn(true);
382 $formRuntimeProphecy->offsetGet(Argument::exact($elementIdentifier))->willReturn('');
383
384 $finisherContextProphecy->getFormRuntime(Argument::cetera())
385 ->willReturn($formRuntimeProphecy->reveal());
386
387 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
388
389 $this->assertSame($expected, $mockAbstractFinisher->_call('parseOption', 'subject'));
390 }
391
392 /**
393 * @test
394 */
395 public function parseOptionReturnsTimestampIfOptionValueIsATimestampRequestTrigger()
396 {
397 $objectMangerProphecy = $this->prophesize(ObjectManager::class);
398 GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal());
399
400 $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [
401 'translateFinisherOption'
402 ], [], '', false);
403
404 $mockTranslationService
405 ->expects($this->any())
406 ->method('translateFinisherOption')
407 ->willReturnArgument(3);
408
409 $objectMangerProphecy
410 ->get(TranslationService::class)
411 ->willReturn($mockTranslationService);
412
413 $mockAbstractFinisher = $this->getAccessibleMockForAbstractClass(
414 AbstractFinisher::class,
415 [],
416 '',
417 false
418 );
419
420 $mockAbstractFinisher->_set('options', [
421 'crdate' => '{__currentTimestamp}'
422 ]);
423
424 $finisherContextProphecy = $this->prophesize(FinisherContext::class);
425
426 $formRuntimeProphecy = $this->prophesize(FormRuntime::class);
427
428 $finisherContextProphecy->getFormRuntime(Argument::cetera())
429 ->willReturn($formRuntimeProphecy->reveal());
430
431 $mockAbstractFinisher->_set('finisherContext', $finisherContextProphecy->reveal());
432
433 $expected = '#^([0-9]{10})$#';
434 $this->assertEquals(1, preg_match($expected, $mockAbstractFinisher->_call('parseOption', 'crdate')));
435 }
436 }