‪TYPO3CMS  ‪main
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 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
23 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
24 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
25 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
26 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
27 
65 {
66  protected function ‪setUp(): void
67  {
68  parent::setUp();
69 
71  'main',
72  $this->‪buildSiteConfiguration(1000, 'https://acme.com/'),
73  [
74  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
75  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
76  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
77  ]
78  );
80  'acme-canada',
81  $this->‪buildSiteConfiguration(2000, 'https://acme.ca/'),
82  [
83  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
84  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
85  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
86  ]
87  );
89  'acme-us',
90  $this->‪buildSiteConfiguration(3000, 'https://acme.us/'),
91  [
92  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
93  $this->‪buildLanguageConfiguration('ES', '/es/', ['ES']),
94  ]
95  );
97  'archive-acme-com',
98  $this->‪buildSiteConfiguration(10000, 'https://archive.acme.com/'),
99  [
100  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
101  $this->‪buildLanguageConfiguration('FR', '/fr/', ['EN']),
102  $this->‪buildLanguageConfiguration('FR-CA', '/fr-ca/', ['FR', 'EN']),
103  ]
104  );
105  $this->withDatabaseSnapshot(function () {
106  $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
107  $backendUser = $this->setUpBackendUser(1);
108  ‪$GLOBALS['LANG'] = $this->get(LanguageServiceFactory::class)->createFromUserPreferences($backendUser);
109  $scenarioFile = __DIR__ . '/Fixtures/MountPointScenario.yaml';
110  $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
111  $writer = DataHandlerWriter::withBackendUser($backendUser);
112  $writer->invokeFactory($factory);
113  static::failIfArrayIsNotEmpty($writer->getErrors());
114  $this->setUpFrontendRootPage(1000, ['EXT:frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript'], ['title' => 'ACME Global']);
115  $this->setUpFrontendRootPage(2000, ['EXT:frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript'], ['title' => 'ACME Canada']);
116  $this->setUpFrontendRootPage(3000, ['EXT:frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript'], ['title' => 'ACME US']);
117  $this->setUpFrontendRootPage(10000, ['EXT:frontend/Tests/Functional/SiteHandling/Fixtures/LinkGenerator.typoscript'], ['title' => 'ACME Archive']);
118  });
119  }
120 
121  public static function ‪hierarchicalMenuIsGeneratedDataProvider(): array
122  {
123  $siteMapOfMainPage = [
124  ['title' => 'EN: Welcome', 'link' => '/welcome'],
125  [
126  'title' => 'EN: Features',
127  'link' => '/features',
128  'children' => [
129  [
130  'title' => 'EN: Frontend Editing',
131  'link' => '/features/frontend-editing/',
132  ],
133  ],
134  ],
135  [
136  'title' => 'EN: Products',
137  'link' => '/products',
138  'children' => [
139  [
140  'title' => 'EN: Toys',
141  'link' => '/products/toys',
142  ],
143  [
144  'title' => 'EN: Card Games',
145  'link' => '/products/card-games',
146  ],
147  [
148  'title' => 'EN: Board Games',
149  'link' => '/products/board-games',
150  'children' => [
151  [
152  'title' => 'EN: Monopoly',
153  'link' => '/products/monopoly',
154  ],
155  [
156  'title' => 'EN: Catan',
157  'link' => '/products/board-games/catan',
158  ],
159  [
160  'title' => 'EN: Risk',
161  'link' => '/risk',
162  ],
163  ],
164  ],
165  [
166  'title' => 'Archived Products',
167  'link' => '/products/archive',
168  'children' => [
169  [
170  'title' => 'EN: Games of the 1980s',
171  'link' => '/products/archive/games-of-the-1980s',
172  ],
173  [
174  'title' => 'EN: Games of the 1990s',
175  'link' => '/products/archive/games-of-the-1990s',
176  ],
177  [
178  'title' => 'Uno - The famous classic',
179  'link' => '/products/archive/uno',
180  ],
181  ],
182  ],
183  ],
184  ],
185  [
186  'title' => 'See our Archives',
187  'link' => '/archive',
188  'children' => [
189  [
190  'title' => 'EN: Archived Products',
191  'link' => '/archive/products',
192  'children' => [
193  [
194  'title' => 'EN: Games of the 1980s',
195  'link' => '/archive/products/games-of-the-1980s',
196  ],
197  [
198  'title' => 'EN: Games of the 1990s',
199  'link' => '/archive/products/games-of-the-1990s',
200  ],
201  [
202  'title' => 'Uno - The famous classic',
203  'link' => '/archive/uno',
204  ],
205  ],
206  ],
207  [
208  'title' => 'EN: Archived News',
209  'link' => '/archive/news',
210  'children' => [
211  [
212  'title' => 'EN: Whats new in 2020',
213  'link' => '/archive/news/latest-releases-2020',
214  ],
215  [
216  'title' => 'EN: Whats new in 2019',
217  'link' => '/archive/news/latest-releases-2019',
218  ],
219  ],
220  ],
221  ],
222  ],
223  ['title' => 'About us', 'link' => '/about'],
224  ['title' => 'Page not found', 'link' => '/404'],
225  // Link gets resolved to other site + shortcut to first page
226  ['title' => 'ACME in Canada', 'link' => 'https://acme.ca/news/'],
227  ];
228  $siteMapOfCanadianPage = [
229  [
230  'title' => 'News of Canada',
231  'link' => '/news/',
232  'children' => [
233  [
234  'title' => 'New Games in Canada 2020',
235  'link' => '/news/games-in-canada-2020',
236  ],
237  [
238  'title' => 'New Games in Canada 2019',
239  'link' => '/slug-with-a-mistake-which-never-changed/games-in-canada-2019',
240  ],
241  ],
242  ],
243  [
244  'title' => 'Products',
245  'link' => '/products',
246  'children' => [
247  [
248  'title' => 'EN: Toys',
249  'link' => '/products/toys',
250  ],
251  [
252  'title' => 'EN: Card Games',
253  'link' => '/products/card-games',
254  ],
255  [
256  'title' => 'EN: Board Games',
257  'link' => '/products/board-games',
258  'children' => [
259  [
260  'title' => 'EN: Monopoly',
261  'link' => '/products/monopoly',
262  ],
263  [
264  'title' => 'EN: Catan',
265  'link' => '/products/board-games/catan',
266  ],
267  [
268  'title' => 'EN: Risk',
269  'link' => '/products/risk',
270  ],
271  ],
272  ],
273  [
274  'title' => 'Archived Products',
275  'link' => '/products/archive',
276  'children' => [
277  [
278  'title' => 'EN: Games of the 1980s',
279  'link' => '/products/archive/games-of-the-1980s',
280  ],
281  [
282  'title' => 'EN: Games of the 1990s',
283  'link' => '/products/archive/games-of-the-1990s',
284  ],
285  [
286  'title' => 'Uno - The famous classic',
287  // Perfect example that the first two slugs are the slugs from the MountPoint Pages
288  'link' => '/products/archive/uno',
289  ],
290  ],
291  ],
292  ],
293  ],
294  [
295  'title' => 'All News',
296  'link' => '/all-news',
297  'children' => [
298  [
299  'title' => 'News of Canada',
300  // slash is added because ID 2100 has a trailing slash
301  'link' => '/all-news/canada/',
302  'children' => [
303  [
304  'title' => 'New Games in Canada 2020',
305  // Example where the slug of the MountPoint page is added
306  // And the "common" prefix of the mounted page - "/news" is removed
307  // Frmo the slug of the main page
308  'link' => '/all-news/canada/games-in-canada-2020',
309  ],
310  [
311  'title' => 'New Games in Canada 2019',
312  // no common prefix, but the original slug was added
313  'link' => '/all-news/canada/slug-with-a-mistake-which-never-changed/games-in-canada-2019',
314  ],
315  ],
316  ],
317  [
318  'title' => 'Archived News',
319  'link' => '/all-news/archive',
320  'children' => [
321  [
322  'title' => 'EN: Whats new in 2020',
323  'link' => '/all-news/archive/latest-releases-2020',
324  ],
325  [
326  'title' => 'EN: Whats new in 2019',
327  'link' => '/all-news/archive/latest-releases-2019',
328  ],
329  ],
330  ],
331  ],
332  ],
333  ['title' => 'Link To Our Worldwide Site', 'link' => 'https://acme.com/welcome'],
334  ];
335  return [
336  'ACME Global' => [
337  'https://acme.com/welcome',
338  $siteMapOfMainPage,
339  ],
340  'ACME Canada First Subpage in EN' => [
341  'https://acme.ca/all-news',
342  $siteMapOfCanadianPage,
343  ],
344  'ACME Canada Subpage of mounted Products page' => [
345  'https://acme.ca/products/risk',
346  $siteMapOfCanadianPage,
347  ],
348  ];
349  }
350 
351  #[DataProvider('hierarchicalMenuIsGeneratedDataProvider')]
352  #[Test]
353  public function ‪hierarchicalMenuIsGenerated(string $accessedUrl, array $expectation): void
354  {
355  $response = $this->executeFrontendSubRequest(
356  (new InternalRequest($accessedUrl))
357  ->withInstructions([
358  $this->createHierarchicalMenuProcessorInstruction([
359  'levels' => 3,
360  'entryLevel' => 0,
361  'expandAll' => 1,
362  'includeSpacer' => 1,
363  'titleField' => 'title',
364  ]),
365  ])
366  );
367 
368  $json = json_decode((string)$response->getBody(), true);
369  $json = $this->filterMenu($json);
370 
371  self::assertSame($expectation, $json);
372  }
373 
375  {
376  return [
377  'regular page on global site' => [
378  'https://acme.com/welcome',
379  1000,
380  1100,
381  null,
382  ],
383  'mountpoint to a different site with same slug on global site' => [
384  'https://acme.com/products/archive',
385  1000,
386  1340,
387  '10100-1340',
388  ],
389  'subpage of mountpoint to a different site with same slug on global site' => [
390  'https://acme.com/products/archive/uno',
391  1000,
392  10130,
393  '10100-1340',
394  ],
395  'subpage of mountpoint to a different site on global site' => [
396  'https://acme.com/archive/products/games-of-the-1980s',
397  1000,
398  10110,
399  '10000-1400',
400  ],
401  ];
402  }
403 
404  #[DataProvider('requestsResolvePageIdAndMountPointParameterDataProvider')]
405  #[Test]
406  public function ‪requestsResolvePageIdAndMountPointParameter(string $uri, int $rootPageId, int $expectedPageId, ?string $expectedMountPointParameter): void
407  {
408  $this->setUpFrontendRootPage(
409  $rootPageId,
410  [
411  'EXT:frontend/Tests/Functional/SiteHandling/Fixtures/LinkRequest.typoscript',
412  ],
413  [
414  'title' => 'ACME Root',
415  ]
416  );
417  $response = $this->executeFrontendSubRequest((new InternalRequest($uri)));
418  $responseData = json_decode((string)$response->getBody(), true);
419  self::assertSame(200, $response->getStatusCode());
420  self::assertSame($expectedPageId, $responseData['pageId']);
421  self::assertSame($expectedMountPointParameter, $responseData['dynamicArguments']['MP'] ?? null);
422  }
423 
425  {
426  return [
427  'Show content of MountPoint Page' => [
428  'https://acme.ca/all-news/archive',
429  'Content of MountPoint Page',
430  ],
431  'Show content of Mounted Page' => [
432  'https://acme.ca/all-news/canada',
433  'See a list of all games distributed in canada',
434  ],
435  'Show content of Mounted Page for second site' => [
436  'https://acme.us/all-news/us',
437  'See a list of all games distributed in the US',
438  ],
439  ];
440  }
441 
447  #[DataProvider('mountPointPagesShowContentAsConfiguredDataProvider')]
448  #[Test]
449  public function ‪mountPointPagesShowContentAsConfigured(string $uri, string $expected): void
450  {
451  $this->setUpFrontendRootPage(
452  2000,
453  [
454  'EXT:core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
455  'EXT:frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
456  ],
457  [
458  'title' => 'ACME Root',
459  ]
460  );
461  $this->setUpFrontendRootPage(
462  3000,
463  [
464  'EXT:core/Tests/Functional/Fixtures/Frontend/JsonRenderer.typoscript',
465  'EXT:frontend/Tests/Functional/SiteHandling/Fixtures/JsonRenderer.typoscript',
466  ],
467  [
468  'title' => 'ACME Root',
469  ]
470  );
471  $response = $this->executeFrontendSubRequest((new InternalRequest($uri)));
472  self::assertSame(200, $response->getStatusCode());
473  $responseStructure = ResponseContent::fromString(
474  (string)$response->getBody()
475  );
476  $responseRecords = $responseStructure->getSection('Default')->getRecords();
477  $firstContent = null;
478  // Find tt_content element
479  foreach ($responseRecords as ‪$identifier => ‪$record) {
480  if (str_starts_with(‪$identifier, 'tt_content:')) {
481  $firstContent = ‪$record;
482  break;
483  }
484  }
485  if ($expected) {
486  self::assertStringContainsString($expected, $firstContent['header'] ?? '');
487  } else {
488  self::assertEmpty($firstContent);
489  }
490  }
491 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildLanguageConfiguration
‪buildLanguageConfiguration(string $identifier, string $base, array $fallbackIdentifiers=[], string $fallbackType=null)
Definition: SiteBasedTestTrait.php:116
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\mountPointPagesShowContentAsConfiguredDataProvider
‪static mountPointPagesShowContentAsConfiguredDataProvider()
Definition: MountPointTest.php:424
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\hierarchicalMenuIsGenerated
‪hierarchicalMenuIsGenerated(string $accessedUrl, array $expectation)
Definition: MountPointTest.php:353
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\writeSiteConfiguration
‪writeSiteConfiguration(string $identifier, array $site=[], array $languages=[], array $errorHandling=[])
Definition: SiteBasedTestTrait.php:50
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\AbstractTestCase
Definition: AbstractTestCase.php:29
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildSiteConfiguration
‪buildSiteConfiguration(int $rootPageId, string $base='')
Definition: SiteBasedTestTrait.php:96
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\requestsResolvePageIdAndMountPointParameterDataProvider
‪static requestsResolvePageIdAndMountPointParameterDataProvider()
Definition: MountPointTest.php:374
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\mountPointPagesShowContentAsConfigured
‪mountPointPagesShowContentAsConfigured(string $uri, string $expected)
Definition: MountPointTest.php:449
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest
Definition: MountPointTest.php:65
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\setUp
‪setUp()
Definition: MountPointTest.php:66
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\hierarchicalMenuIsGeneratedDataProvider
‪static hierarchicalMenuIsGeneratedDataProvider()
Definition: MountPointTest.php:121
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling
Definition: AbstractTestCase.php:18
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildDefaultLanguageConfiguration
‪buildDefaultLanguageConfiguration(string $identifier, string $base)
Definition: SiteBasedTestTrait.php:106
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Frontend\Tests\Functional\SiteHandling\MountPointTest\requestsResolvePageIdAndMountPointParameter
‪requestsResolvePageIdAndMountPointParameter(string $uri, int $rootPageId, int $expectedPageId, ?string $expectedMountPointParameter)
Definition: MountPointTest.php:406
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37