[TASK] typo3/testing-framework now flushes runtime caches
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / Typolink / AbstractTypolinkBuilderTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\Unit\Typolink;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use Psr\Log\LoggerInterface;
19 use TYPO3\CMS\Core\Log\LogManager;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
22 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
23 use TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder;
24 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
25
26 /**
27 * Test case
28 */
29 class AbstractTypolinkBuilderTest extends UnitTestCase
30 {
31 /**
32 * @var bool Reset singletons created by subject
33 */
34 protected $resetSingletonInstances = true;
35
36 /**
37 * @var \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController|\TYPO3\TestingFramework\Core\AccessibleObjectInterface
38 */
39 protected $frontendControllerMock;
40
41 /**
42 * Set up
43 */
44 protected function setUp()
45 {
46 $this->createMockedLoggerAndLogManager();
47
48 $this->frontendControllerMock = $this->getAccessibleMock(
49 TypoScriptFrontendController::class,
50 ['dummy'],
51 [],
52 '',
53 false
54 );
55 $GLOBALS['TSFE'] = $this->frontendControllerMock;
56 }
57
58 //////////////////////
59 // Utility functions
60 //////////////////////
61
62 /**
63 * Avoid logging to the file system (file writer is currently the only configured writer)
64 */
65 protected function createMockedLoggerAndLogManager()
66 {
67 $logManagerMock = $this->getMockBuilder(LogManager::class)->getMock();
68 $loggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock();
69 $logManagerMock->expects($this->any())
70 ->method('getLogger')
71 ->willReturn($loggerMock);
72 GeneralUtility::setSingletonInstance(LogManager::class, $logManagerMock);
73 }
74
75 /**
76 * @return array The test data for forceAbsoluteUrlReturnsAbsoluteUrl
77 */
78 public function forceAbsoluteUrlReturnsCorrectAbsoluteUrlDataProvider()
79 {
80 return [
81 'Missing forceAbsoluteUrl leaves URL untouched' => [
82 'foo',
83 'foo',
84 []
85 ],
86 'Absolute URL stays unchanged' => [
87 'http://example.org/',
88 'http://example.org/',
89 [
90 'forceAbsoluteUrl' => '1'
91 ]
92 ],
93 'Absolute URL stays unchanged 2' => [
94 'http://example.org/resource.html',
95 'http://example.org/resource.html',
96 [
97 'forceAbsoluteUrl' => '1'
98 ]
99 ],
100 'Scheme and host w/o ending slash stays unchanged' => [
101 'http://example.org',
102 'http://example.org',
103 [
104 'forceAbsoluteUrl' => '1'
105 ]
106 ],
107 'Scheme can be forced' => [
108 'typo3://example.org',
109 'http://example.org',
110 [
111 'forceAbsoluteUrl' => '1',
112 'forceAbsoluteUrl.' => [
113 'scheme' => 'typo3'
114 ]
115 ]
116 ],
117 'Relative path old-style' => [
118 'http://localhost/fileadmin/dummy.txt',
119 '/fileadmin/dummy.txt',
120 [
121 'forceAbsoluteUrl' => '1',
122 ]
123 ],
124 'Relative path' => [
125 'http://localhost/fileadmin/dummy.txt',
126 'fileadmin/dummy.txt',
127 [
128 'forceAbsoluteUrl' => '1',
129 ]
130 ],
131 'Scheme can be forced with pseudo-relative path' => [
132 'typo3://localhost/fileadmin/dummy.txt',
133 '/fileadmin/dummy.txt',
134 [
135 'forceAbsoluteUrl' => '1',
136 'forceAbsoluteUrl.' => [
137 'scheme' => 'typo3'
138 ]
139 ]
140 ],
141 'Hostname only is not treated as valid absolute URL' => [
142 'http://localhost/example.org',
143 'example.org',
144 [
145 'forceAbsoluteUrl' => '1'
146 ]
147 ],
148 'Scheme and host is added to local file path' => [
149 'typo3://localhost/fileadmin/my.pdf',
150 'fileadmin/my.pdf',
151 [
152 'forceAbsoluteUrl' => '1',
153 'forceAbsoluteUrl.' => [
154 'scheme' => 'typo3'
155 ]
156 ]
157 ]
158 ];
159 }
160
161 /**
162 * @param string $expected The expected URL
163 * @param string $url The URL to parse and manipulate
164 * @param array $configuration The configuration array
165 * @test
166 * @dataProvider forceAbsoluteUrlReturnsCorrectAbsoluteUrlDataProvider
167 */
168 public function forceAbsoluteUrlReturnsCorrectAbsoluteUrl($expected, $url, array $configuration)
169 {
170 $contentObjectRendererProphecy = $this->prophesize(ContentObjectRenderer::class);
171 $subject = $this->getAccessibleMock(
172 AbstractTypolinkBuilder::class,
173 ['build'],
174 [$contentObjectRendererProphecy->reveal()],
175 '',
176 false
177 );
178 // Force hostname
179 $_SERVER['HTTP_HOST'] = 'localhost';
180 $_SERVER['SCRIPT_NAME'] = '/typo3/index.php';
181 $GLOBALS['TSFE']->absRefPrefix = '';
182
183 $this->assertEquals($expected, $subject->_call('forceAbsoluteUrl', $url, $configuration));
184 }
185
186 /**
187 * @test
188 */
189 public function forceAbsoluteUrlReturnsCorrectAbsoluteUrlWithSubfolder()
190 {
191 $contentObjectRendererProphecy = $this->prophesize(ContentObjectRenderer::class);
192 $subject = $this->getAccessibleMock(
193 AbstractTypolinkBuilder::class,
194 ['build'],
195 [$contentObjectRendererProphecy->reveal()],
196 '',
197 false
198 );
199 // Force hostname
200 $_SERVER['HTTP_HOST'] = 'localhost';
201 $_SERVER['SCRIPT_NAME'] = '/subfolder/typo3/index.php';
202
203 $expected = 'http://localhost/subfolder/fileadmin/my.pdf';
204 $url = 'fileadmin/my.pdf';
205 $configuration = [
206 'forceAbsoluteUrl' => '1'
207 ];
208
209 $this->assertEquals($expected, $subject->_call('forceAbsoluteUrl', $url, $configuration));
210 }
211
212 /**
213 * Data provider for resolveTargetAttribute
214 *
215 * @return array [[$expected, $conf, $name, $respectFrameSetOption, $fallbackTarget],]
216 */
217 public function resolveTargetAttributeDataProvider(): array
218 {
219 $targetName = $this->getUniqueId('name_');
220 $target = $this->getUniqueId('target_');
221 $fallback = $this->getUniqueId('fallback_');
222 return [
223 'Take target from $conf, if $conf[$targetName] is set.' =>
224 [
225 $target,
226 [$targetName => $target], // $targetName is set
227 $targetName,
228 true,
229 $fallback,
230 'other doctype'
231 ],
232 'Else from fallback, if not $respectFrameSetOption ...' =>
233 [
234 $fallback,
235 [],
236 $targetName,
237 false, // $respectFrameSetOption false
238 $fallback,
239 'other doctype'
240 ],
241 ' ... or no doctype ... ' =>
242 [
243 $fallback,
244 [],
245 $targetName,
246 true,
247 $fallback,
248 null // no $doctype
249 ],
250 ' ... or doctype xhtml_trans... ' =>
251 [
252 $fallback,
253 [],
254 $targetName,
255 true,
256 $fallback,
257 'xhtml_trans'
258 ],
259 ' ... or doctype xhtml_basic... ' =>
260 [
261 $fallback,
262 [],
263 $targetName,
264 true,
265 $fallback,
266 'xhtml_basic'
267 ],
268 ' ... or doctype html5... ' =>
269 [
270 $fallback,
271 [],
272 $targetName,
273 true,
274 $fallback,
275 'html5'
276 ],
277 ' If all hopes fail, an empty string is returned. ' =>
278 [
279 '',
280 [],
281 $targetName,
282 true,
283 $fallback,
284 'other doctype'
285 ],
286 'It finally applies stdWrap' =>
287 [
288 'wrap_target',
289 [$targetName . '.' =>
290 [ 'ifEmpty' => 'wrap_target' ]
291 ],
292 $targetName,
293 true,
294 $fallback,
295 'other doctype'
296 ],
297 ];
298 }
299
300 /**
301 * @test
302 * @dataProvider resolveTargetAttributeDataProvider
303 * @param string $expected
304 * @param array $conf
305 * @param string $name
306 * @param bool $respectFrameSetOption
307 * @param string $fallbackTarget
308 * @param string|null $doctype
309 */
310 public function canResolveTheTargetAttribute(
311 string $expected,
312 array $conf,
313 string $name,
314 bool $respectFrameSetOption,
315 string $fallbackTarget,
316 $doctype
317 ) {
318 $this->frontendControllerMock->config =
319 ['config' => [ 'doctype' => $doctype]];
320 $renderer = GeneralUtility::makeInstance(ContentObjectRenderer::class);
321 $subject = $this->getMockBuilder(AbstractTypolinkBuilder::class)
322 ->setConstructorArgs([$renderer])
323 ->setMethods(['build'])
324 ->getMock();
325 $actual = $this->callInaccessibleMethod(
326 $subject,
327 'resolveTargetAttribute',
328 $conf,
329 $name,
330 $respectFrameSetOption,
331 $fallbackTarget
332 );
333 $this->assertEquals($expected, $actual);
334 }
335 }