24e0ab5745c1a403f6ad7811a2109d6aa78a156d
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Functional / SiteHandling / PlainRequestTest.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
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\Core\Error\Http\PageNotFoundException;
18 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
19 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataMapFactory;
20 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
21 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
22 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
23
24 /**
25 * Test case for frontend requests without having site handling configured
26 */
27 class PlainRequestTest extends AbstractRequestTest
28 {
29 /**
30 * @var ActionService
31 */
32 private $actionService;
33
34 /**
35 * @var string
36 */
37 private $siteTitle = 'A Company that Manufactures Everything Inc';
38
39 /**
40 * @var InternalRequestContext
41 */
42 private $internalRequestContext;
43
44 protected function setUp()
45 {
46 parent::setUp();
47
48 // these settings are forwarded to the frontend sub-request as well
49 $this->internalRequestContext = (new InternalRequestContext())
50 ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
51
52 $this->setUpBackendUserFromFixture(1);
53 $this->actionService = new ActionService();
54
55 $scenarioFile = __DIR__ . '/Fixtures/scenario.yaml';
56 $factory = DataMapFactory::fromYamlFile($scenarioFile);
57 $this->actionService->invoke(
58 $factory->getDataMap(),
59 [],
60 $factory->getSuggestedIds()
61 );
62
63 $this->setUpFrontendRootPage(
64 101,
65 [
66 'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
67 'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
68 ],
69 [
70 'title' => 'ACME Root',
71 'sitetitle' => $this->siteTitle,
72 ]
73 );
74 }
75
76 protected function tearDown()
77 {
78 unset(
79 $this->actionService,
80 $this->internalRequestContext
81 );
82 parent::tearDown();
83 }
84
85 /**
86 * @return array
87 */
88 public function requestsAreRedirectedDataProvider(): array
89 {
90 $domainPaths = [
91 '/',
92 'http://localhost/',
93 'https://localhost/',
94 'http://website.local/',
95 'https://website.local/',
96 ];
97
98 $queries = [
99 '?',
100 '?id=101',
101 '?id=acme-root'
102 ];
103
104 return $this->wrapInArray(
105 $this->keysFromValues(
106 $this->meltStrings([$domainPaths, $queries])
107 )
108 );
109 }
110
111 /**
112 * @param string $uri
113 *
114 * @test
115 * @dataProvider requestsAreRedirectedDataProvider
116 */
117 public function requestsAreRedirected(string $uri)
118 {
119 $expectedStatusCode = 307;
120 $expectedHeaders = ['location' => ['index.php?id=acme-first']];
121
122 $response = $this->executeFrontendRequest(
123 new InternalRequest($uri),
124 $this->internalRequestContext
125 );
126 static::assertSame($expectedStatusCode, $response->getStatusCode());
127 static::assertSame($expectedHeaders, $response->getHeaders());
128 }
129
130 /**
131 * @return array
132 */
133 public function pageIsRenderedDataProvider(): array
134 {
135 $domainPaths = [
136 '/',
137 'http://localhost/',
138 'https://localhost/',
139 'http://website.local/',
140 'https://website.local/',
141 ];
142
143 $queries = [
144 '?id=102',
145 '?id=acme-first',
146 ];
147
148 $languageQueries = [
149 '',
150 '&L=0',
151 '&L=1',
152 '&L=2',
153 ];
154
155 return array_map(
156 function (string $uri) {
157 if (strpos($uri, '&L=1') !== false) {
158 $expectedPageTitle = 'FR: Welcome';
159 } elseif (strpos($uri, '&L=2') !== false) {
160 $expectedPageTitle = 'FR-CA: Welcome';
161 } else {
162 $expectedPageTitle = 'EN: Welcome';
163 }
164 return [$uri, $expectedPageTitle];
165 },
166 $this->keysFromValues(
167 $this->meltStrings([$domainPaths, $queries, $languageQueries])
168 )
169 );
170 }
171
172 /**
173 * @param string $uri
174 * @param string $expectedPageTitle
175 *
176 * @test
177 * @dataProvider pageIsRenderedDataProvider
178 */
179 public function pageIsRendered(string $uri, string $expectedPageTitle)
180 {
181 $response = $this->executeFrontendRequest(
182 new InternalRequest($uri),
183 $this->internalRequestContext
184 );
185 $responseStructure = ResponseContent::fromString(
186 (string)$response->getBody()
187 );
188
189 static::assertSame(
190 200,
191 $response->getStatusCode()
192 );
193 static::assertSame(
194 $this->siteTitle,
195 $responseStructure->getScopePath('template/sitetitle')
196 );
197 static::assertSame(
198 $expectedPageTitle,
199 $responseStructure->getScopePath('page/title')
200 );
201 }
202
203 /**
204 * @return array
205 */
206 public function pageRenderingStopsWithInvalidCacheHashDataProvider(): array
207 {
208 $domainPaths = [
209 '/',
210 'http://localhost/',
211 'https://localhost/',
212 'http://website.local/',
213 'https://website.local/',
214 ];
215
216 $queries = [
217 '?',
218 '?id=101',
219 '?id=acme-root',
220 '?id=102',
221 '?id=acme-first',
222 ];
223
224 $customQueries = [
225 '&testing[value]=1',
226 '&testing[value]=1&cHash=',
227 '&testing[value]=1&cHash=WRONG',
228 ];
229
230 return $this->wrapInArray(
231 $this->keysFromValues(
232 $this->meltStrings([$domainPaths, $queries, $customQueries])
233 )
234 );
235 }
236
237 /**
238 * @param string $uri
239 *
240 * @test
241 * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
242 * @todo In TYPO3 v8 this seemed to be rendered, without throwing that exception
243 */
244 public function pageRequestThrowsExceptionWithInvalidCacheHash(string $uri)
245 {
246 $this->expectExceptionCode(1518472189);
247 $this->expectException(PageNotFoundException::class);
248
249 $this->executeFrontendRequest(
250 new InternalRequest($uri),
251 $this->internalRequestContext
252 );
253 }
254
255 /**
256 * @param string $uri
257 *
258 * @test
259 * @dataProvider pageRenderingStopsWithInvalidCacheHashDataProvider
260 */
261 public function pageRequestSendsNotFoundResponseWithInvalidCacheHash(string $uri)
262 {
263 $response = $this->executeFrontendRequest(
264 new InternalRequest($uri),
265 $this->internalRequestContext->withMergedGlobalSettings([
266 'TYPO3_CONF_VARS' => [
267 'FE' => [
268 'pageNotFound_handling' => 'READFILE:typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/PageError.txt',
269 ]
270 ]
271 ])
272 );
273
274 static::assertSame(
275 404,
276 $response->getStatusCode()
277 );
278 static::assertThat(
279 (string)$response->getBody(),
280 static::logicalOr(
281 static::stringContains('reason: Request parameters could not be validated (&amp;cHash empty)'),
282 static::stringContains('reason: Request parameters could not be validated (&amp;cHash comparison failed)')
283 )
284 );
285 }
286
287 /**
288 * @return array
289 */
290 public function pageIsRenderedWithValidCacheHashDataProvider(): array
291 {
292 $domainPaths = [
293 '/',
294 'http://localhost/',
295 'https://localhost/',
296 'http://website.local/',
297 'https://website.local/',
298 ];
299
300 // cHash has been calculated with encryption key set to
301 // '4408d27a916d51e624b69af3554f516dbab61037a9f7b9fd6f81b4d3bedeccb6'
302 $queries = [
303 // @todo Currently fails since cHash is verified after(!) redirect to page 102
304 // '?&cHash=814ea11ad629c7e24cfd031cea2779f4&id=101',
305 // '?&cHash=814ea11ad629c7e24cfd031cea2779f4id=acme-root',
306 '?&cHash=126d2980c12f4759fed1bb7429db2dff&id=102',
307 '?&cHash=126d2980c12f4759fed1bb7429db2dff&id=acme-first',
308 ];
309
310 $customQueries = [
311 '&testing[value]=1',
312 ];
313
314 $dataSet = $this->wrapInArray(
315 $this->keysFromValues(
316 $this->meltStrings([$domainPaths, $queries, $customQueries])
317 )
318 );
319
320 return $dataSet;
321 }
322
323 /**
324 * @param string $uri
325 *
326 * @test
327 * @dataProvider pageIsRenderedWithValidCacheHashDataProvider
328 */
329 public function pageIsRenderedWithValidCacheHash($uri)
330 {
331 $response = $this->executeFrontendRequest(
332 new InternalRequest($uri),
333 $this->internalRequestContext
334 );
335 $responseStructure = ResponseContent::fromString(
336 (string)$response->getBody()
337 );
338 static::assertSame(
339 '1',
340 $responseStructure->getScopePath('getpost/testing.value')
341 );
342 }
343 }