From 1296ac11ed946399109eecfd3225d3219b04ad28 Mon Sep 17 00:00:00 2001 From: Mario Lubenka Date: Mon, 24 Oct 2022 15:30:02 +0200 Subject: [PATCH] [TASK] Remove dependencies to Core testing classes Classes from TYPO3 core testing namespace are not available when the package is installed via Composer and causes local tests to fail. The classes used are added and used to our namespace. Fixes: #3376 --- .../Fixtures/Frontend/PhpError.php | 69 ++++ Tests/Integration/IntegrationTest.php | 1 - Tests/Integration/SiteBasedTestTrait.php | 307 ++++++++++++++++++ 3 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 Tests/Integration/Fixtures/Frontend/PhpError.php create mode 100644 Tests/Integration/SiteBasedTestTrait.php diff --git a/Tests/Integration/Fixtures/Frontend/PhpError.php b/Tests/Integration/Fixtures/Frontend/PhpError.php new file mode 100644 index 0000000000..114af58c6f --- /dev/null +++ b/Tests/Integration/Fixtures/Frontend/PhpError.php @@ -0,0 +1,69 @@ +statusCode = $statusCode; + $this->configuration = $configuration; + } + + /** + * @param ServerRequestInterface $request + * @param string $message + * @param array $reasons + * @return ResponseInterface + */ + public function handlePageError( + ServerRequestInterface $request, + string $message, + array $reasons = [] + ): ResponseInterface { + $data = [ + 'uri' => (string)$request->getUri(), + 'message' => $message, + 'reasons' => $reasons, + ]; + return new JsonResponse($data, $this->statusCode); + } +} diff --git a/Tests/Integration/IntegrationTest.php b/Tests/Integration/IntegrationTest.php index 80e2dcbe88..e1773b3d68 100644 --- a/Tests/Integration/IntegrationTest.php +++ b/Tests/Integration/IntegrationTest.php @@ -46,7 +46,6 @@ use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait; use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; diff --git a/Tests/Integration/SiteBasedTestTrait.php b/Tests/Integration/SiteBasedTestTrait.php new file mode 100644 index 0000000000..abfa259bed --- /dev/null +++ b/Tests/Integration/SiteBasedTestTrait.php @@ -0,0 +1,307 @@ +instancePath . '/typo3conf/sites/', + $this->get('cache.core') + ); + + try { + // ensure no previous site configuration influences the test + GeneralUtility::rmdir($this->instancePath . '/typo3conf/sites/' . $identifier, true); + $siteConfiguration->write($identifier, $configuration); + } catch (\Exception $exception) { + $this->markTestSkipped($exception->getMessage()); + } + } + + /** + * @param string $identifier + * @param array $overrides + */ + protected function mergeSiteConfiguration( + string $identifier, + array $overrides + ): void { + $siteConfiguration = new SiteConfiguration( + $this->instancePath . '/typo3conf/sites/', + $this->get('cache.core') + ); + $configuration = $siteConfiguration->load($identifier); + $configuration = array_merge($configuration, $overrides); + try { + $siteConfiguration->write($identifier, $configuration); + } catch (\Exception $exception) { + $this->markTestSkipped($exception->getMessage()); + } + } + + /** + * @param int $rootPageId + * @param string $base + * @return array + */ + protected function buildSiteConfiguration( + int $rootPageId, + string $base = '' + ): array { + return [ + 'rootPageId' => $rootPageId, + 'base' => $base, + ]; + } + + /** + * @param string $identifier + * @param string $base + * @return array + */ + protected function buildDefaultLanguageConfiguration( + string $identifier, + string $base + ): array { + $configuration = $this->buildLanguageConfiguration($identifier, $base); + $configuration['typo3Language'] = 'default'; + $configuration['flag'] = 'global'; + unset($configuration['fallbackType'], $configuration['fallbacks']); + return $configuration; + } + + /** + * @param string $identifier + * @param string $base + * @param array $fallbackIdentifiers + * @param string $fallbackType + * @return array + */ + protected function buildLanguageConfiguration( + string $identifier, + string $base, + array $fallbackIdentifiers = [], + string $fallbackType = null + ): array { + $preset = $this->resolveLanguagePreset($identifier); + + $configuration = [ + 'languageId' => $preset['id'], + 'title' => $preset['title'], + 'navigationTitle' => $preset['title'], + 'base' => $base, + 'locale' => $preset['locale'], + 'iso-639-1' => $preset['iso'] ?? '', + 'hreflang' => $preset['hrefLang'] ?? '', + 'direction' => $preset['direction'] ?? '', + 'typo3Language' => $preset['iso'] ?? '', + 'flag' => $preset['iso'] ?? '', + 'fallbackType' => $fallbackType ?? (empty($fallbackIdentifiers) ? 'strict' : 'fallback'), + ]; + + if (!empty($fallbackIdentifiers)) { + $fallbackIds = array_map( + function (string $fallbackIdentifier) { + $preset = $this->resolveLanguagePreset($fallbackIdentifier); + return $preset['id']; + }, + $fallbackIdentifiers + ); + $configuration['fallbackType'] = $fallbackType ?? 'fallback'; + $configuration['fallbacks'] = implode(',', $fallbackIds); + } + + return $configuration; + } + + /** + * @param string $handler + * @param array $codes + * @return array + */ + protected function buildErrorHandlingConfiguration( + string $handler, + array $codes + ): array { + if ($handler === 'Page') { + // This implies you cannot test both 404 and 403 in the same test. + // Fixing that requires much deeper changes to the testing harness, + // as the structure here is only a portion of the config array structure. + if (in_array(404, $codes, true)) { + $baseConfiguration = [ + 'errorContentSource' => 't3://page?uid=404', + ]; + } elseif (in_array(403, $codes, true)) { + $baseConfiguration = [ + 'errorContentSource' => 't3://page?uid=403', + ]; + } + } elseif ($handler === 'Fluid') { + $baseConfiguration = [ + 'errorFluidTemplate' => 'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/FluidError.html', + 'errorFluidTemplatesRootPath' => '', + 'errorFluidLayoutsRootPath' => '', + 'errorFluidPartialsRootPath' => '', + ]; + } elseif ($handler === 'PHP') { + $baseConfiguration = [ + 'errorPhpClassFQCN' => PhpError::class, + ]; + } else { + throw new \LogicException( + sprintf('Invalid handler "%s"', $handler), + 1533894782 + ); + } + + $baseConfiguration['errorHandler'] = $handler; + + return array_map( + static function (int $code) use ($baseConfiguration) { + $baseConfiguration['errorCode'] = $code; + return $baseConfiguration; + }, + $codes + ); + } + + /** + * @param string $identifier + * @return mixed + */ + protected function resolveLanguagePreset(string $identifier) + { + if (!isset(static::LANGUAGE_PRESETS[$identifier])) { + throw new \LogicException( + sprintf('Undefined preset identifier "%s"', $identifier), + 1533893665 + ); + } + return static::LANGUAGE_PRESETS[$identifier]; + } + + /** + * @param InternalRequest $request + * @param AbstractInstruction ...$instructions + * @return InternalRequest + * + * @todo Instruction handling should be part of Testing Framework (multiple instructions per identifier, merge in interface) + */ + protected function applyInstructions(InternalRequest $request, AbstractInstruction ...$instructions): InternalRequest + { + $modifiedInstructions = []; + + foreach ($instructions as $instruction) { + $identifier = $instruction->getIdentifier(); + if (isset($modifiedInstructions[$identifier]) || $request->getInstruction($identifier) !== null) { + $modifiedInstructions[$identifier] = $this->mergeInstruction( + $modifiedInstructions[$identifier] ?? $request->getInstruction($identifier), + $instruction + ); + } else { + $modifiedInstructions[$identifier] = $instruction; + } + } + + return $request->withInstructions($modifiedInstructions); + } + + /** + * @param AbstractInstruction $current + * @param AbstractInstruction $other + * @return AbstractInstruction + */ + protected function mergeInstruction(AbstractInstruction $current, AbstractInstruction $other): AbstractInstruction + { + if (get_class($current) !== get_class($other)) { + throw new \LogicException('Cannot merge different instruction types', 1565863174); + } + + if ($current instanceof TypoScriptInstruction) { + /** @var TypoScriptInstruction $other */ + $typoScript = array_replace_recursive( + $current->getTypoScript() ?? [], + $other->getTypoScript() ?? [] + ); + $constants = array_replace_recursive( + $current->getConstants() ?? [], + $other->getConstants() ?? [] + ); + if ($typoScript !== []) { + $current = $current->withTypoScript($typoScript); + } + if ($constants !== []) { + $current = $current->withConstants($constants); + } + return $current; + } + + if ($current instanceof ArrayValueInstruction) { + /** @var ArrayValueInstruction $other */ + $array = array_merge_recursive($current->getArray(), $other->getArray()); + return $current->withArray($array); + } + + return $current; + } +}