‪TYPO3CMS  10.4
MountPointTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
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 
19 
21 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
22 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
23 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
24 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
25 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
26 
64 {
68  private ‪$siteTitle = 'A Company that Manufactures Board Games and Everything Inc';
69 
74 
75  public static function ‪setUpBeforeClass(): void
76  {
77  parent::setUpBeforeClass();
78  static::initializeDatabaseSnapshot();
79  }
80 
81  public static function ‪tearDownAfterClass(): void
82  {
83  static::destroyDatabaseSnapshot();
84  parent::tearDownAfterClass();
85  }
86 
87  protected function ‪setUp(): void
88  {
89  parent::setUp();
90 
91  // these settings are forwarded to the frontend sub-request as well
92  $this->internalRequestContext = (new InternalRequestContext())
93  ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
94 
96  'main',
97  $this->‪buildSiteConfiguration(1000, 'https://acme.com/'),
98  [
99  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
100  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
101  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
102  ]
103  );
105  'acme-canada',
106  $this->‪buildSiteConfiguration(2000, 'https://acme.ca/'),
107  [
108  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
109  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
110  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
111  ]
112  );
114  'acme-us',
115  $this->‪buildSiteConfiguration(3000, 'https://acme.us/'),
116  [
117  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
118  $this->‪buildLanguageConfiguration('ES', '/es/', ['ES']),
119  ]
120  );
122  'archive-acme-com',
123  $this->‪buildSiteConfiguration(10000, 'https://archive.acme.com/'),
124  [
125  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
126  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
127  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN'])
128  ]
129  );
130  $this->withDatabaseSnapshot(function () {
131  $this->‪setUpDatabase();
132  });
133  }
134 
135  protected function ‪setUpDatabase()
136  {
137  $backendUser = $this->setUpBackendUserFromFixture(1);
139 
140  $scenarioFile = __DIR__ . '/Fixtures/MountPointScenario.yaml';
141  $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
142  $writer = DataHandlerWriter::withBackendUser($backendUser);
143  $writer->invokeFactory($factory);
144  static::failIfArrayIsNotEmpty(
145  $writer->getErrors()
146  );
147 
148  $this->setUpFrontendRootPage(
149  1000,
150  [
151  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
152  ],
153  [
154  'title' => 'ACME Global',
155  'sitetitle' => $this->siteTitle,
156  ]
157  );
158  $this->setUpFrontendRootPage(
159  2000,
160  [
161  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
162  ],
163  [
164  'title' => 'ACME Canada',
165  'sitetitle' => $this->siteTitle,
166  ]
167  );
168  $this->setUpFrontendRootPage(
169  3000,
170  [
171  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
172  ],
173  [
174  'title' => 'ACME US',
175  'sitetitle' => $this->siteTitle,
176  ]
177  );
178  $this->setUpFrontendRootPage(
179  10000,
180  [
181  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript',
182  ],
183  [
184  'title' => 'ACME Archive',
185  'sitetitle' => $this->siteTitle,
186  ]
187  );
188  }
189 
190  protected function ‪tearDown(): void
191  {
192  unset($this->internalRequestContext);
193  parent::tearDown();
194  }
195 
199  public function ‪hierarchicalMenuIsGeneratedDataProvider(): array
200  {
201  $siteMapOfMainPage = [
202  ['title' => 'EN: Welcome', 'link' => '/welcome'],
203  [
204  'title' => 'EN: Features',
205  'link' => '/features',
206  'children' => [
207  [
208  'title' => 'EN: Frontend Editing',
209  'link' => '/features/frontend-editing/',
210  ],
211  ],
212  ],
213  [
214  'title' => 'EN: Products',
215  'link' => '/products',
216  'children' => [
217  [
218  'title' => 'EN: Toys',
219  'link' => '/products/toys',
220  ],
221  [
222  'title' => 'EN: Card Games',
223  'link' => '/products/card-games',
224  ],
225  [
226  'title' => 'EN: Board Games',
227  'link' => '/products/board-games',
228  'children' => [
229  [
230  'title' => 'EN: Monopoly',
231  'link' => '/products/monopoly',
232  ],
233  [
234  'title' => 'EN: Catan',
235  'link' => '/products/board-games/catan',
236  ],
237  [
238  'title' => 'EN: Risk',
239  'link' => '/risk',
240  ],
241  ]
242  ],
243  [
244  'title' => 'Archived Products',
245  'link' => '/products/archive',
246  'children' => [
247  [
248  'title' => 'EN: Games of the 1980s',
249  'link' => '/products/archive/games-of-the-1980s',
250  ],
251  [
252  'title' => 'EN: Games of the 1990s',
253  'link' => '/products/archive/games-of-the-1990s',
254  ],
255  [
256  'title' => 'Uno - The famous classic',
257  'link' => '/products/archive/uno',
258  ],
259  ],
260  ],
261  ],
262  ],
263  [
264  'title' => 'See our Archives',
265  'link' => '/archive',
266  'children' => [
267  [
268  'title' => 'EN: Archived Products',
269  'link' => '/archive/products',
270  'children' => [
271  [
272  'title' => 'EN: Games of the 1980s',
273  'link' => '/archive/products/games-of-the-1980s',
274  ],
275  [
276  'title' => 'EN: Games of the 1990s',
277  'link' => '/archive/products/games-of-the-1990s',
278  ],
279  [
280  'title' => 'Uno - The famous classic',
281  'link' => '/archive/uno',
282  ],
283  ],
284  ],
285  [
286  'title' => 'EN: Archived News',
287  'link' => '/archive/news',
288  'children' => [
289  [
290  'title' => 'EN: Whats new in 2020',
291  'link' => '/archive/news/latest-releases-2020',
292  ],
293  [
294  'title' => 'EN: Whats new in 2019',
295  'link' => '/archive/news/latest-releases-2019',
296  ],
297  ]
298  ]
299  ],
300  ],
301  ['title' => 'About us', 'link' => '/about'],
302  ['title' => 'Page not found', 'link' => '/404'],
303  // Link gets resolved to other site + shortcut to first page
304  ['title' => 'ACME in Canada', 'link' => 'https://acme.ca/news/'],
305  ];
306  $siteMapOfCanadianPage = [
307  [
308  'title' => 'News of Canada',
309  'link' => '/news/',
310  'children' => [
311  [
312  'title' => 'New Games in Canada 2020',
313  'link' => '/news/games-in-canada-2020',
314  ],
315  [
316  'title' => 'New Games in Canada 2019',
317  'link' => '/slug-with-a-mistake-which-never-changed/games-in-canada-2019',
318  ],
319  ]
320  ],
321  [
322  'title' => 'Products',
323  'link' => '/products',
324  'children' => [
325  [
326  'title' => 'EN: Toys',
327  'link' => '/products/toys',
328  ],
329  [
330  'title' => 'EN: Card Games',
331  'link' => '/products/card-games',
332  ],
333  [
334  'title' => 'EN: Board Games',
335  'link' => '/products/board-games',
336  'children' => [
337  [
338  'title' => 'EN: Monopoly',
339  'link' => '/products/monopoly',
340  ],
341  [
342  'title' => 'EN: Catan',
343  'link' => '/products/board-games/catan',
344  ],
345  [
346  'title' => 'EN: Risk',
347  'link' => '/products/risk',
348  ],
349  ]
350  ],
351  [
352  'title' => 'Archived Products',
353  'link' => '/products/archive',
354  'children' => [
355  [
356  'title' => 'EN: Games of the 1980s',
357  'link' => '/products/archive/games-of-the-1980s',
358  ],
359  [
360  'title' => 'EN: Games of the 1990s',
361  'link' => '/products/archive/games-of-the-1990s',
362  ],
363  [
364  'title' => 'Uno - The famous classic',
365  // Perfect example that the first two slugs are the slugs from the MountPoint Pages
366  'link' => '/products/archive/uno',
367  ],
368  ],
369  ],
370  ],
371  ],
372  [
373  'title' => 'All News',
374  'link' => '/all-news',
375  'children' => [
376  [
377  'title' => 'News of Canada',
378  // slash is added because ID 2100 has a trailing slash
379  'link' => '/all-news/canada/',
380  'children' => [
381  [
382  'title' => 'New Games in Canada 2020',
383  // Example where the slug of the MountPoint page is added
384  // And the "common" prefix of the mounted page - "/news" is removed
385  // Frmo the slug of the main page
386  'link' => '/all-news/canada/games-in-canada-2020',
387  ],
388  [
389  'title' => 'New Games in Canada 2019',
390  // no common prefix, but the original slug was added
391  'link' => '/all-news/canada/slug-with-a-mistake-which-never-changed/games-in-canada-2019',
392  ],
393  ]
394  ],
395  [
396  'title' => 'Archived News',
397  'link' => '/all-news/archive',
398  'children' => [
399  [
400  'title' => 'EN: Whats new in 2020',
401  'link' => '/all-news/archive/latest-releases-2020',
402  ],
403  [
404  'title' => 'EN: Whats new in 2019',
405  'link' => '/all-news/archive/latest-releases-2019',
406  ],
407  ]
408  ],
409  ]
410  ],
411  ['title' => 'Link To Our Worldwide Site', 'link' => 'https://acme.com/welcome'],
412  ];
413  return [
414  'ACME Global' => [
415  'https://acme.com/welcome',
416  $siteMapOfMainPage
417  ],
418  'ACME Canada First Subpage in EN' => [
419  'https://acme.ca/all-news',
420  $siteMapOfCanadianPage
421  ],
422  'ACME Canada Subpage of mounted Products page' => [
423  'https://acme.ca/products/risk',
424  $siteMapOfCanadianPage
425  ]
426  ];
427  }
428 
436  public function ‪hierarchicalMenuIsGenerated(string $accessedUrl, array $expectation)
437  {
438  $response = $this->executeFrontendRequest(
439  (new InternalRequest($accessedUrl))
440  ->withInstructions([
441  $this->createHierarchicalMenuProcessorInstruction([
442  'levels' => 3,
443  'entryLevel' => 0,
444  'expandAll' => 1,
445  'includeSpacer' => 1,
446  'titleField' => 'title',
447  ])
448  ]),
449  $this->internalRequestContext
450  );
451 
452  $json = json_decode((string)$response->getBody(), true);
453  $json = $this->filterMenu($json);
454 
455  self::assertSame($expectation, $json);
456  }
457 
459  {
460  return [
461  'regular page on global site' => [
462  'https://acme.com/welcome',
463  1000,
464  1100,
465  null
466  ],
467  'mountpoint to a different site with same slug on global site' => [
468  'https://acme.com/products/archive',
469  1000,
470  1340,
471  '10100-1340'
472  ],
473  'subpage of mountpoint to a different site with same slug on global site' => [
474  'https://acme.com/products/archive/uno',
475  1000,
476  10130,
477  '10100-1340'
478  ],
479  'subpage of mountpoint to a different site on global site' => [
480  'https://acme.com/archive/products/games-of-the-1980s',
481  1000,
482  10110,
483  '10000-1400'
484  ],
485  ];
486  }
487 
496  public function ‪requestsResolvePageIdAndMountPointParameter(string $uri, int $rootPageId, int $expectedPageId, ?string $expectedMountPointParameter)
497  {
498  $this->setUpFrontendRootPage(
499  $rootPageId,
500  [
501  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkRequest.typoscript',
502  ],
503  [
504  'title' => 'ACME Root',
505  'sitetitle' => $this->siteTitle,
506  ]
507  );
508  $response = $this->executeFrontendRequest(
509  (new InternalRequest($uri)),
510  $this->internalRequestContext
511  );
512  $responseData = json_decode((string)$response->getBody(), true);
513  self::assertSame(200, $response->getStatusCode());
514  self::assertSame($expectedPageId, $responseData['pageId']);
515  self::assertSame($expectedMountPointParameter, $responseData['dynamicArguments']['MP'] ?? null);
516  }
517 
522  {
523  return [
524  'Show content of MountPoint Page' => [
525  'https://acme.ca/all-news/archive',
526  'Content of MountPoint Page'
527  ],
528  'Show content of Mounted Page' => [
529  'https://acme.ca/all-news/canada',
530  'See a list of all games distributed in canada'
531  ],
532  'Show content of Mounted Page for second site' => [
533  'https://acme.us/all-news/us',
534  'See a list of all games distributed in the US'
535  ],
536  ];
537  }
538 
551  public function ‪mountPointPagesShowContentAsConfigured(string $uri, string $expected)
552  {
553  $this->setUpFrontendRootPage(
554  2000,
555  [
556  'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
557  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
558  ],
559  [
560  'title' => 'ACME Root',
561  'sitetitle' => $this->siteTitle,
562  ]
563  );
564  $this->setUpFrontendRootPage(
565  3000,
566  [
567  'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
568  'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
569  ],
570  [
571  'title' => 'ACME Root',
572  'sitetitle' => $this->siteTitle,
573  ]
574  );
575  $response = $this->executeFrontendRequest(
576  (new InternalRequest($uri)),
577  $this->internalRequestContext
578  );
579  self::assertSame(200, $response->getStatusCode());
580  $responseStructure = ResponseContent::fromString(
581  (string)$response->getBody()
582  );
583  $responseRecords = $responseStructure->getSection('Default')->getRecords();
584  $firstContent = null;
585  // Find tt_content element
586  foreach ($responseRecords as $identifier => $record) {
587  if (strpos($identifier, 'tt_content:') === 0) {
588  $firstContent = $record;
589  break;
590  }
591  }
592  if ($expected) {
593  self::assertStringContainsString($expected, $firstContent['header'] ?? '');
594  } else {
595  self::assertEmpty($firstContent);
596  }
597  }
598 }
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\tearDownAfterClass
‪static tearDownAfterClass()
Definition: MountPointTest.php:79
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\hierarchicalMenuIsGeneratedDataProvider
‪array hierarchicalMenuIsGeneratedDataProvider()
Definition: MountPointTest.php:197
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\hierarchicalMenuIsGenerated
‪hierarchicalMenuIsGenerated(string $accessedUrl, array $expectation)
Definition: MountPointTest.php:434
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildLanguageConfiguration
‪array buildLanguageConfiguration(string $identifier, string $base, array $fallbackIdentifiers=[], string $fallbackType=null)
Definition: SiteBasedTestTrait.php:142
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\$siteTitle
‪string $siteTitle
Definition: MountPointTest.php:67
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\$internalRequestContext
‪InternalRequestContext $internalRequestContext
Definition: MountPointTest.php:71
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\setUpDatabase
‪setUpDatabase()
Definition: MountPointTest.php:133
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\writeSiteConfiguration
‪writeSiteConfiguration(string $identifier, array $site=[], array $languages=[], array $errorHandling=[])
Definition: SiteBasedTestTrait.php:58
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\AbstractTestCase
Definition: AbstractTestCase.php:29
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\mountPointPagesShowContentAsConfigured
‪mountPointPagesShowContentAsConfigured(string $uri, string $expected)
Definition: MountPointTest.php:549
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest
Definition: MountPointTest.php:64
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\setUp
‪setUp()
Definition: MountPointTest.php:85
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildDefaultLanguageConfiguration
‪array buildDefaultLanguageConfiguration(string $identifier, string $base)
Definition: SiteBasedTestTrait.php:124
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static initializeLanguageObject()
Definition: Bootstrap.php:617
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\tearDown
‪tearDown()
Definition: MountPointTest.php:188
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling
Definition: AbstractTestCase.php:18
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\requestsResolvePageIdAndMountPointParameter
‪requestsResolvePageIdAndMountPointParameter(string $uri, int $rootPageId, int $expectedPageId, ?string $expectedMountPointParameter)
Definition: MountPointTest.php:494
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:66
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\setUpBeforeClass
‪static setUpBeforeClass()
Definition: MountPointTest.php:73
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildSiteConfiguration
‪array buildSiteConfiguration(int $rootPageId, string $base='')
Definition: SiteBasedTestTrait.php:109
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\requestsResolvePageIdAndMountPointParameterDataProvider
‪requestsResolvePageIdAndMountPointParameterDataProvider()
Definition: MountPointTest.php:456
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\mountPointPagesShowContentAsConfiguredDataProvider
‪array mountPointPagesShowContentAsConfiguredDataProvider()
Definition: MountPointTest.php:519