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