‪TYPO3CMS  10.4
HrefLangGeneratorTest.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 
22 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
23 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
24 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
25 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
26 
27 class ‪HrefLangGeneratorTest extends FunctionalTestCase
28 {
30 
34  protected ‪$coreExtensionsToLoad = [
35  'core',
36  'frontend',
37  'seo'
38  ];
39 
43  protected const ‪LANGUAGE_PRESETS = [
44  'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8', 'iso' => 'en', 'hrefLang' => 'en-US', 'direction' => ''],
45  'DE' => ['id' => 1, 'title' => 'German', 'locale' => 'de_DE.UTF8', 'iso' => 'de', 'hrefLang' => 'de-DE', 'direction' => ''],
46  'DE-CH' => ['id' => 2, 'title' => 'Swiss German', 'locale' => 'de_CH.UTF8', 'iso' => 'de', 'hrefLang' => 'de-CH', 'direction' => ''],
47  'NL' => ['id' => 3, 'title' => 'Dutch', 'locale' => 'nl_NL.UTF8', 'iso' => 'nl', 'hrefLang' => 'nl-NL', 'direction' => ''],
48  'FR' => ['id' => 4, 'title' => 'French', 'locale' => 'fr_FR.UTF8', 'iso' => 'fr', 'hrefLang' => 'fr-FR', 'direction' => ''],
49  'DK' => ['id' => 5, 'title' => 'Danish', 'locale' => 'da_DK.UTF8', 'iso' => 'da', 'hrefLang' => 'da-DK', 'direction' => ''],
50  ];
51 
52  public static function ‪setUpBeforeClass(): void
53  {
54  parent::setUpBeforeClass();
55  static::initializeDatabaseSnapshot();
56  }
57 
58  public static function ‪tearDownAfterClass(): void
59  {
60  static::destroyDatabaseSnapshot();
61  parent::tearDownAfterClass();
62  }
63 
64  protected function ‪setUp(): void
65  {
66  parent::setUp();
67 
69  'acme-com',
70  $this->‪buildSiteConfiguration(1000, 'https://acme.com/'),
71  [
72  $this->‪buildDefaultLanguageConfiguration('EN', '/'),
73  $this->‪buildLanguageConfiguration('DE', '/de'),
74  $this->‪buildLanguageConfiguration('DE-CH', '/de-ch', ['DE'], 'fallback'),
75  $this->‪buildLanguageConfiguration('NL', '/nl'),
76  $this->‪buildLanguageConfiguration('FR', '/fr'),
77  $this->‪buildLanguageConfiguration('DK', '/dk', ['EN'], 'free'),
78  ]
79  );
80 
81  $this->‪setUpDatabaseWithYamlPayload(__DIR__ . '/../Fixtures/HrefLangScenario.yml');
82  }
83 
88  public function ‪checkHrefLangOutput(string $url, array $expectedTags, array $notExpectedTags): void
89  {
90  $this->setUpFrontendRootPage(
91  1000,
92  ['typo3/sysext/seo/Tests/Functional/Fixtures/HrefLang.typoscript']
93  );
94 
95  $response = $this->executeFrontendRequest(
96  new InternalRequest($url)
97  );
98  $stream = $response->getBody();
99  $stream->rewind();
100  $content = $stream->getContents();
101 
102  foreach ($expectedTags as $expectedTag) {
103  self::assertStringContainsString($expectedTag, $content);
104  }
105 
106  foreach ($notExpectedTags as $notExpectedTag) {
107  self::assertStringNotContainsString($notExpectedTag, $content);
108  }
109  }
110 
114  public function ‪checkHrefLangOutputDataProvider(): array
115  {
116  return [
117  'No translation available, so only hreflang tags expected for default language and fallback languages' => [
118  'https://acme.com/',
119  [
120  '<link rel="alternate" hreflang="en-US" href="https://acme.com/"/>',
121  '<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/"/>',
122  ],
123  [
124  '<link rel="alternate" hreflang="de-DE"'
125  ]
126  ],
127  'English page, with German translation' => [
128  'https://acme.com/hello',
129  [
130  '<link rel="alternate" hreflang="en-US" href="https://acme.com/hello"/>',
131  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/willkommen"/>',
132  '<link rel="alternate" hreflang="x-default" href="https://acme.com/hello"/>',
133  ],
134  []
135  ],
136  'German page, with English translation and English default' => [
137  'https://acme.com/de/willkommen',
138  [
139  '<link rel="alternate" hreflang="en-US" href="https://acme.com/hello"/>',
140  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/willkommen"/>',
141  '<link rel="alternate" hreflang="x-default" href="https://acme.com/hello"/>',
142  ],
143  []
144  ],
145  'English page, with German and Dutch translation, without Dutch hreflang config' => [
146  'https://acme.com/hello',
147  [
148  '<link rel="alternate" hreflang="en-US" href="https://acme.com/hello"/>',
149  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/willkommen"/>',
150  '<link rel="alternate" hreflang="x-default" href="https://acme.com/hello"/>',
151  ],
152  [
153  '<link rel="alternate" hreflang="en-US" href="https://acme.com/nl/welkom"/>',
154  '<link rel="alternate" hreflang="" href="https://acme.com/nl/welkom"/>',
155  ]
156  ],
157  'Dutch page, with German and English translation, without Dutch hreflang config' => [
158  'https://acme.com/hello',
159  [
160  '<link rel="alternate" hreflang="en-US" href="https://acme.com/hello"/>',
161  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/willkommen"/>',
162  '<link rel="alternate" hreflang="x-default" href="https://acme.com/hello"/>',
163  ],
164  [
165  '<link rel="alternate" hreflang="en-US" href="https://acme.com/nl/welkom"/>',
166  '<link rel="alternate" hreflang="" href="https://acme.com/nl/welkom"/>',
167  ]
168  ],
169  'English page with canonical' => [
170  'https://acme.com/contact',
171  [
172  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/kontakt"/>',
173  '<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/kontakt"/>',
174  ],
175  [
176  '<link rel="alternate" hreflang="en-US" href="https://acme.com/contact"/>',
177  '<link rel="alternate" hreflang="x-default" href="https://acme.com/contact"/>',
178  ]
179  ],
180  'Swiss german page with canonical' => [
181  'https://acme.com/de-ch/uber',
182  [
183  '<link rel="alternate" hreflang="en-US" href="https://acme.com/about"/>',
184  '<link rel="alternate" hreflang="x-default" href="https://acme.com/about"/>',
185  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/uber"/>',
186  ],
187  [
188  '<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/uber"/>',
189  ]
190  ],
191  'Swiss german page with fallback to German, without content' => [
192  'https://acme.com/de-ch/produkte',
193  [
194  '<link rel="alternate" hreflang="en-US" href="https://acme.com/products"/>',
195  '<link rel="alternate" hreflang="x-default" href="https://acme.com/products"/>',
196  '<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/produkte"/>',
197  '<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/produkte"/>',
198  ],
199  []
200  ],
201  'Languages with fallback should have hreflang even when page record is not translated, strict languages without translations shouldnt' => [
202  'https://acme.com/hello',
203  [
204  '<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/willkommen"/>',
205  ],
206  [
207  '<link rel="alternate" hreflang="fr-FR"',
208 
209  ]
210  ],
211  'Languages with fallback type free should not have hreflang when page record is not translated' => [
212  'https://acme.com/no-translation',
213  [],
214  [
215  '<link rel="alternate" hreflang="',
216  ],
217  ],
218  ];
219  }
220 
225  protected function ‪setUpDatabaseWithYamlPayload(string $pathToYamlFile): void
226  {
227  $this->withDatabaseSnapshot(function () use ($pathToYamlFile) {
228  $backendUser = $this->setUpBackendUserFromFixture(1);
230 
231  $factory = DataHandlerFactory::fromYamlFile($pathToYamlFile);
232  $writer = DataHandlerWriter::withBackendUser($backendUser);
233  $writer->invokeFactory($factory);
234  static::failIfArrayIsNotEmpty(
235  $writer->getErrors()
236  );
237  });
238  }
239 
243  protected static function ‪failIfArrayIsNotEmpty(array $items): void
244  {
245  if (empty($items)) {
246  return;
247  }
248 
249  self::fail(
250  'Array was not empty as expected, but contained these items:' . LF
251  . '* ' . implode(LF . '* ', $items)
252  );
253  }
254 }
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\LANGUAGE_PRESETS
‪const LANGUAGE_PRESETS
Definition: HrefLangGeneratorTest.php:41
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest
Definition: HrefLangGeneratorTest.php:28
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait
Definition: SiteBasedTestTrait.php:36
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang
Definition: HrefLangGeneratorTest.php:18
‪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\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\checkHrefLangOutput
‪checkHrefLangOutput(string $url, array $expectedTags, array $notExpectedTags)
Definition: HrefLangGeneratorTest.php:86
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\writeSiteConfiguration
‪writeSiteConfiguration(string $identifier, array $site=[], array $languages=[], array $errorHandling=[])
Definition: SiteBasedTestTrait.php:58
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\failIfArrayIsNotEmpty
‪static failIfArrayIsNotEmpty(array $items)
Definition: HrefLangGeneratorTest.php:241
‪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\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\setUpBeforeClass
‪static setUpBeforeClass()
Definition: HrefLangGeneratorTest.php:50
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\checkHrefLangOutputDataProvider
‪array checkHrefLangOutputDataProvider()
Definition: HrefLangGeneratorTest.php:112
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\setUpDatabaseWithYamlPayload
‪setUpDatabaseWithYamlPayload(string $pathToYamlFile)
Definition: HrefLangGeneratorTest.php:223
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\tearDownAfterClass
‪static tearDownAfterClass()
Definition: HrefLangGeneratorTest.php:56
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\setUp
‪setUp()
Definition: HrefLangGeneratorTest.php:62
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:66
‪TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait\buildSiteConfiguration
‪array buildSiteConfiguration(int $rootPageId, string $base='')
Definition: SiteBasedTestTrait.php:109
‪TYPO3\CMS\Seo\Tests\Functional\HrefLang\HrefLangGeneratorTest\$coreExtensionsToLoad
‪string[] $coreExtensionsToLoad
Definition: HrefLangGeneratorTest.php:32