From f03af432ca87cc7945c0247efd2cd82b19461a82 Mon Sep 17 00:00:00 2001
From: Nikita Hovratov <nikita.h@live.de>
Date: Tue, 25 Oct 2022 13:51:05 +0200
Subject: [PATCH] [TASK] Convert FluidTemplateContentObjectTest to functional
 tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Resolves: #98724
Resolves: #98728
Releases: main
Change-Id: Id046c240ae4e9d3017dc4b8503e23fd8a6a9b4b8
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/76258
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Oliver Klee <typo3-coding@oliverklee.de>
Tested-by: Nikita Hovratov <nikita.h@live.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Nikita Hovratov <nikita.h@live.de>
---
 composer.json                                 |    1 +
 .../ContentObject/Fixtures/pages.csv          |    3 +
 .../FluidTemplateContentObjectTest.php        |  521 +++++--
 .../Classes/ContentObjectCurrentValue.php     |   29 +
 .../TypoScript/assets.typoscript              |    6 +
 .../TypoScript/current.typoscript             |    6 +
 .../Configuration/TypoScript/data.typoscript  |    6 +
 .../Configuration/TypoScript/file.typoscript  |    5 +
 .../fluid_template_stdwrap.typoscript         |   10 +
 .../TypoScript/format.typoscript              |    9 +
 .../TypoScript/format_stdwrap.typoscript      |   11 +
 .../TypoScript/layout_root_path.typoscript    |    9 +
 ...ut_root_path_and_paths_fallback.typoscript |   13 +
 .../layout_root_path_stdwrap.typoscript       |   10 +
 .../layout_root_paths_fallback.typoscript     |   13 +
 .../layout_root_paths_stdwrap.typoscript      |   12 +
 .../nested_fluid_template.typoscript          |   17 +
 ...sted_fluid_template_with_layout.typoscript |   26 +
 .../TypoScript/partial.typoscript             |    9 +
 ...al_root_path_and_paths_fallback.typoscript |   13 +
 .../partial_root_paths_fallback.typoscript    |   12 +
 .../partial_root_paths_stdwrap.typoscript     |   10 +
 .../TypoScript/partial_stdwrap.typoscript     |   10 +
 .../TypoScript/settings.typoscript            |   12 +
 .../TypoScript/template.typoscript            |    6 +
 .../TypoScript/template_name.typoscript       |    8 +
 .../template_name_stdwrap.typoscript          |    9 +
 .../template_rootpaths_stdwrap.typoscript     |   11 +
 .../TypoScript/variables.typoscript           |   14 +
 .../variables_reserved_current.typoscript     |   14 +
 .../variables_reserved_data.typoscript        |   14 +
 .../Private/FoobarLayouts/Foobar.html         |    1 +
 .../Private/FoobarPartials/Foobar.html        |    1 +
 .../Private/FoobarTemplates/Foobar.html       |    1 +
 .../Private/FoobarTemplates/Foobar.xml        |    4 +
 .../LayoutOverrides/Layouts/Default.html      |    2 +
 .../Private/Layouts/AlternativeLayout.html    |    2 +
 .../Resources/Private/Layouts/Default.html    |    2 +
 .../PartialOverrides/Partials/Component.html  |    1 +
 .../Resources/Private/Partials/Component.html |    1 +
 .../Templates/AlternativeTemplate.html        |    4 +
 .../Resources/Private/Templates/Main.html     |    4 +
 .../Resources/Private/Templates/Settings.html |    1 +
 .../Private/Templates/Variables.html          |    1 +
 .../Private/Templates/WithPartial.html        |    1 +
 .../Resources/Public/Icons/Extension.svg      |    1 +
 .../test_fluid_template/composer.json         |   16 +
 .../test_fluid_template/ext_emconf.php        |   18 +
 .../test_fluid_template/ext_localconf.php     |    5 +
 .../FluidTemplateContentObjectTest.php        | 1373 -----------------
 50 files changed, 826 insertions(+), 1462 deletions(-)
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/pages.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/ContentObjectCurrentValue.php
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/assets.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/current.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/data.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/file.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/fluid_template_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_and_paths_fallback.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_fallback.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template_with_layout.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_path_and_paths_fallback.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_fallback.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/settings.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_rootpaths_stdwrap.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_current.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_data.typoscript
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarLayouts/Foobar.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarPartials/Foobar.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.xml
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/LayoutOverrides/Layouts/Default.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/AlternativeLayout.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/Default.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/PartialOverrides/Partials/Component.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Partials/Component.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/AlternativeTemplate.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Main.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Settings.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Variables.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/WithPartial.html
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Public/Icons/Extension.svg
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/composer.json
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_emconf.php
 create mode 100644 typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_localconf.php
 delete mode 100644 typo3/sysext/frontend/Tests/Unit/ContentObject/FluidTemplateContentObjectTest.php

diff --git a/composer.json b/composer.json
index 490ff15b8799..4bb8264e6905 100644
--- a/composer.json
+++ b/composer.json
@@ -291,6 +291,7 @@
 			"TYPO3\\CMS\\Recycler\\Tests\\": "typo3/sysext/recycler/Tests/",
 			"TYPO3\\CMS\\T3editor\\Tests\\": "typo3/sysext/t3editor/Tests/",
 			"TYPO3\\CMS\\Tstemplate\\Tests\\": "typo3/sysext/tstemplate/Tests/",
+			"TYPO3Tests\\TestFluidTemplate\\": "typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/",
 			"TYPO3Tests\\TestLogger\\": "typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_logger/Classes/",
 			"TYPO3Tests\\TestTyposcriptAstFunctionEvent\\": "typo3/sysext/core/Tests/Functional/Fixtures/Extensions/test_typoscript_ast_function_event/Classes/"
 		},
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/pages.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/pages.csv
new file mode 100644
index 000000000000..7e4527aaae95
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/pages.csv
@@ -0,0 +1,3 @@
+pages
+,uid,pid,title
+,1,0,FluidTemplateContentObjectTest
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php b/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
index 492112ce12ea..b4f030d03415 100644
--- a/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/FluidTemplateContentObjectTest.php
@@ -17,106 +17,449 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Frontend\Tests\Functional\ContentObject;
 
-use Prophecy\PhpUnit\ProphecyTrait;
-use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Frontend\ContentObject\ContentObjectFactory;
-use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
 class FluidTemplateContentObjectTest extends FunctionalTestCase
 {
-    use ProphecyTrait;
+    use SiteBasedTestTrait;
 
-    protected bool $initializeDatabase = false;
+    protected const LANGUAGE_PRESETS = [];
+    protected const ROOT_PAGE_ID = 1;
 
     protected array $testExtensionsToLoad = [
-        'typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test',
+        'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template',
     ];
 
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->importCSVDataSet('typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/pages.csv');
+        $this->writeSiteConfiguration(
+            'fluid_template',
+            $this->buildSiteConfiguration(self::ROOT_PAGE_ID, '/'),
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function renderWorksWithNestedFluidTemplate(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('ABC', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function renderWorksWithNestedFluidTemplateWithLayouts(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template_with_layout.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('Default Layout', $responseBody);
+        self::assertStringContainsString('LayoutOverride', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function stdWrapAppliesForTemplateRootPaths(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_rootpaths_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Foobar', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function optionFileIsUsedAsTemplate(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/file.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Foobar', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function optionTemplateIsUsedAsCObjTemplate(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('My fluid template', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function optionTemplateNameIsUsedAsHtmlFileInTemplateRootPaths(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Foobar', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function stdWrapIsAppliedOnOptionTemplateName(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Foobar', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function layoutIsFoundInLayoutRootPath(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('Alternative Layout', $responseBody);
+        self::assertStringContainsString('Alternative Template', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function layoutRootPathHasStdWrapSupport(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('Alternative Layout', $responseBody);
+        self::assertStringContainsString('Alternative Template', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function layoutRootPathsHasStdWrapSupport(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('Alternative Layout', $responseBody);
+        self::assertStringContainsString('Alternative Template', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function fallbacksForLayoutRootPathsAreApplied(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_fallback.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('LayoutOverride', $responseBody);
+        self::assertStringContainsString('Main Template', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function fallbacksForLayoutRootPathAreAppendedToLayoutRootPath(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_and_paths_fallback.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('LayoutOverride', $responseBody);
+        self::assertStringContainsString('Main Template', $responseBody);
+    }
+
+    /**
+     * @test
+     */
+    public function partialsInPartialRootPathAreFound(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Template with Partial', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function partialRootPathHasStdWrapSupport(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Template with Partial', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function partialRootPathsHasStdWrapSupport(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Template with Partial', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function fallbacksForPartialRootPathsAreApplied(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_fallback.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Template with Partial Override', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function fallbacksForPartialRootPathAreAppendedToPartialRootPath(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_path_and_paths_fallback.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Template with Partial Override', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function formatOverridesDefaultHtmlSuffix(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('FoobarXML', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function stdWrapIsAppliedOnOptionFormat(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('FoobarXML', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function settingsAreAssignedToTheView(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/settings.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('I am coming from the settings', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function renderThrowsExceptionForReservedVariableNameData(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_data.typoscript',
+            ]
+        );
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionCode(1288095720);
+        $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+    }
+
+    /**
+     * @test
+     */
+    public function renderThrowsExceptionForReservedVariableNameCurrent(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_current.typoscript',
+            ]
+        );
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionCode(1288095720);
+        $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+    }
+
+    /**
+     * @test
+     */
+    public function cObjectIsAppliedOnVariables(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('I am coming from the variables', (string)$response->getBody());
+    }
+
     /**
      * @test
      */
-    public function renderWorksWithNestedFluidtemplate(): void
-    {
-        $tsfe = $this->createMock(TypoScriptFrontendController::class);
-        $GLOBALS['TSFE'] = $tsfe;
-
-        $configuration = [
-            '10' => 'FLUIDTEMPLATE',
-            '10.' => [
-                'template' => 'TEXT',
-                'template.' => [
-                    'value' => 'A{anotherFluidTemplate}C',
-                ],
-                'variables.' => [
-                    'anotherFluidTemplate' => 'FLUIDTEMPLATE',
-                    'anotherFluidTemplate.' => [
-                        'template' => 'TEXT',
-                        'template.' => [
-                            'value' => 'B',
-                        ],
-                    ],
-                ],
-            ],
-        ];
-        $expectedResult = 'ABC';
-
-        $contentObjectRenderer = new ContentObjectRenderer($tsfe);
-        $contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
-        $fluidTemplateContentObject = $this->get(ContentObjectFactory::class)->getContentObject(
-            'COA',
-            $this->prophesize(ServerRequestInterface::class)->reveal(),
-            $contentObjectRenderer
-        );
-        $result = $fluidTemplateContentObject->render($configuration);
-
-        self::assertEquals($expectedResult, $result);
-    }
-
-    /**
-     * @test
-     */
-    public function renderWorksWithNestedFluidtemplateWithLayouts(): void
-    {
-        $tsfe = $this->createMock(TypoScriptFrontendController::class);
-        $GLOBALS['TSFE'] = $tsfe;
-
-        $configuration = [
-            '10' => 'FLUIDTEMPLATE',
-            '10.' => [
-                'template' => 'TEXT',
-                'template.' => [
-                    'value' => '<f:layout name="BaseLayout"/><f:section name="main"><f:format.raw>{anotherFluidTemplate}</f:format.raw></f:section>',
-                ],
-                'layoutRootPaths.' => [
-                    '0' => 'EXT:fluid_test/Resources/Private/Layouts',
-                ],
-                'variables.' => [
-                    'anotherFluidTemplate' => 'FLUIDTEMPLATE',
-                    'anotherFluidTemplate.' => [
-                        'template' => 'TEXT',
-                        'template.' => [
-                            'value' => '<f:layout name="BaseLayout"/><f:section name="main"></f:section>',
-                        ],
-                        'layoutRootPaths.' => [
-                            '0' => 'EXT:fluid_test/Resources/Private/LayoutOverride/Layouts',
-                        ],
-                    ],
-                ],
-            ],
-        ];
-        $expectedResult = 'DefaultLayoutLayoutOverride';
-
-        $contentObjectRenderer = new ContentObjectRenderer($tsfe);
-        $contentObjectRenderer->setRequest($this->prophesize(ServerRequestInterface::class)->reveal());
-        $fluidTemplateContentObject = $this->get(ContentObjectFactory::class)->getContentObject(
-            'COA',
-            $this->prophesize(ServerRequestInterface::class)->reveal(),
-            $contentObjectRenderer
-        );
-        $result = preg_replace('/\s+/', '', strip_tags($fluidTemplateContentObject->render($configuration)));
-
-        self::assertEquals($expectedResult, $result);
+    public function contentObjectRendererDataIsAvailableInView(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/data.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('FluidTemplateContentObjectTest', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function renderAssignsContentObjectRendererCurrentValueToView(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/current.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('My current value', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function stdWrapIsAppliedOnOverallFluidTemplate(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/fluid_template_stdwrap.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('1+1=2', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function renderFluidTemplateAssetsIntoPageRendererRendersAndAttachesAssets(): void
+    {
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/assets.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        $responseBody = (string)$response->getBody();
+        self::assertStringContainsString('Foo Header' . "\n" . '</head>', $responseBody);
+        self::assertStringContainsString('Foo Footer' . "\n" . '</body>', $responseBody);
     }
 }
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/ContentObjectCurrentValue.php b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/ContentObjectCurrentValue.php
new file mode 100644
index 000000000000..bda4c934862e
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Classes/ContentObjectCurrentValue.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3Tests\TestFluidTemplate;
+
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectPostInitHookInterface;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+
+class ContentObjectCurrentValue implements ContentObjectPostInitHookInterface
+{
+    public function postProcessContentObjectInitialization(ContentObjectRenderer &$parentObject)
+    {
+        $parentObject->setCurrentVal('My current value');
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/assets.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/assets.typoscript
new file mode 100644
index 000000000000..b65123c400da
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/assets.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template.value = <f:section name="HeaderAssets">Foo Header</f:section><f:section name="FooterAssets">Foo Footer</f:section>
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/current.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/current.typoscript
new file mode 100644
index 000000000000..8c7704c3bbee
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/current.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template.value = {current}
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/data.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/data.typoscript
new file mode 100644
index 000000000000..a04625d62659
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/data.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template.value = {data.title}
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/file.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/file.typoscript
new file mode 100644
index 000000000000..db91bbba2cb6
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/file.typoscript
@@ -0,0 +1,5 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  file = EXT:test_fluid_template/Resources/Private/FoobarTemplates/Foobar.html
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/fluid_template_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/fluid_template_stdwrap.typoscript
new file mode 100644
index 000000000000..fb9d00416770
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/fluid_template_stdwrap.typoscript
@@ -0,0 +1,10 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template.value = 1+1=
+
+  stdWrap {
+    wrap = |2
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format.typoscript
new file mode 100644
index 000000000000..a6ee82238ebc
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format.typoscript
@@ -0,0 +1,9 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Foobar
+  format = xml
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/FoobarTemplates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format_stdwrap.typoscript
new file mode 100644
index 000000000000..171d8d2853e3
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/format_stdwrap.typoscript
@@ -0,0 +1,11 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Foobar
+  format = ml
+  format.prepend = TEXT
+  format.prepend.value = x
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/FoobarTemplates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path.typoscript
new file mode 100644
index 000000000000..abb8142b4c7a
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path.typoscript
@@ -0,0 +1,9 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = AlternativeTemplate
+  layoutRootPath = EXT:test_fluid_template/Resources/Private/Layouts
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_and_paths_fallback.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_and_paths_fallback.typoscript
new file mode 100644
index 000000000000..e8f2c8f132e2
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_and_paths_fallback.typoscript
@@ -0,0 +1,13 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Main
+  layoutRootPath = EXT:test_fluid_template/Resources/Private/FoobarLayouts
+  layoutRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private
+    10 = EXT:test_fluid_template/Resources/Private/LayoutOverrides/Layouts
+  }
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_stdwrap.typoscript
new file mode 100644
index 000000000000..b4c8c5e6872a
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_path_stdwrap.typoscript
@@ -0,0 +1,10 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = AlternativeTemplate
+  layoutRootPath = EXT:test_fluid_template/Resources/Private/
+  layoutRootPath.wrap = |Layouts
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_fallback.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_fallback.typoscript
new file mode 100644
index 000000000000..a881e590c6e9
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_fallback.typoscript
@@ -0,0 +1,13 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Main
+  layoutRootPath =
+  layoutRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private
+    10 = EXT:test_fluid_template/Resources/Private/LayoutOverrides/Layouts
+  }
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_stdwrap.typoscript
new file mode 100644
index 000000000000..6f7b36585905
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/layout_root_paths_stdwrap.typoscript
@@ -0,0 +1,12 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = AlternativeTemplate
+  layoutRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private/
+    0.wrap = |Layouts
+  }
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template.typoscript
new file mode 100644
index 000000000000..2ae0451aec61
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template.typoscript
@@ -0,0 +1,17 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template {
+    value = A{anotherFluidTemplate}C
+  }
+  variables {
+    anotherFluidTemplate = FLUIDTEMPLATE
+    anotherFluidTemplate {
+      template = TEXT
+      template {
+        value = B
+      }
+    }
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template_with_layout.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template_with_layout.typoscript
new file mode 100644
index 000000000000..59ccef113f6a
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/nested_fluid_template_with_layout.typoscript
@@ -0,0 +1,26 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template {
+    value = <f:layout/><f:section name="Main"><f:format.raw>{anotherFluidTemplate}</f:format.raw></f:section>
+  }
+
+  layoutRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private/Layouts
+  }
+
+  variables {
+    anotherFluidTemplate = FLUIDTEMPLATE
+    anotherFluidTemplate {
+      template = TEXT
+      template {
+        value = <f:layout/><f:section name="Main"></f:section>
+      }
+
+      layoutRootPaths {
+        0 = EXT:test_fluid_template/Resources/Private/LayoutOverrides/Layouts
+      }
+    }
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial.typoscript
new file mode 100644
index 000000000000..da160c3c5592
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial.typoscript
@@ -0,0 +1,9 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = WithPartial
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  partialRootPath = EXT:test_fluid_template/Resources/Private/Partials
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_path_and_paths_fallback.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_path_and_paths_fallback.typoscript
new file mode 100644
index 000000000000..9f37b2041216
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_path_and_paths_fallback.typoscript
@@ -0,0 +1,13 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = WithPartial
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  partialRootPath = EXT:test_fluid_template/Resources/Private/FoobarPartials
+  partialRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private/Partials
+    0 = EXT:test_fluid_template/Resources/Private/PartialOverrides/Partials
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_fallback.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_fallback.typoscript
new file mode 100644
index 000000000000..1eebc9f9bafe
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_fallback.typoscript
@@ -0,0 +1,12 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = WithPartial
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  partialRootPaths {
+    0 = EXT:test_fluid_template/Resources/Private/FoobarPartials
+    10 = EXT:test_fluid_template/Resources/Private/PartialOverrides/Partials
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_stdwrap.typoscript
new file mode 100644
index 000000000000..47ce5f7b1a4b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_root_paths_stdwrap.typoscript
@@ -0,0 +1,10 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = WithPartial
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  partialRootPaths.0 = EXT:test_fluid_template/Resources/Private/
+  partialRootPaths.0.wrap = |Partials
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_stdwrap.typoscript
new file mode 100644
index 000000000000..465c6fe7af9b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/partial_stdwrap.typoscript
@@ -0,0 +1,10 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = WithPartial
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  partialRootPath = EXT:test_fluid_template/Resources/Private/
+  partialRootPath.wrap = |Partials
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/settings.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/settings.typoscript
new file mode 100644
index 000000000000..a86ab77631a5
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/settings.typoscript
@@ -0,0 +1,12 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Settings
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  settings {
+    value1 = I am coming
+    value2 = from the settings
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template.typoscript
new file mode 100644
index 000000000000..609f35dd7d36
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  template = TEXT
+  template.value = My fluid template
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name.typoscript
new file mode 100644
index 000000000000..3066e185c254
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name.typoscript
@@ -0,0 +1,8 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Foobar
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/FoobarTemplates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name_stdwrap.typoscript
new file mode 100644
index 000000000000..90eb835bfa89
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_name_stdwrap.typoscript
@@ -0,0 +1,9 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Foo
+  templateName.wrap = |bar
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/FoobarTemplates
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_rootpaths_stdwrap.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_rootpaths_stdwrap.typoscript
new file mode 100644
index 000000000000..ed56dc012a8b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/template_rootpaths_stdwrap.typoscript
@@ -0,0 +1,11 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Foobar
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Foobar
+    10 {
+      wrap = |Templates
+    }
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables.typoscript
new file mode 100644
index 000000000000..d3ce926cfa79
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables.typoscript
@@ -0,0 +1,14 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Variables
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  variables {
+    var1 = TEXT
+    var1.value = I am coming from the
+    var2 = TEXT
+    var2.value = variables
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_current.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_current.typoscript
new file mode 100644
index 000000000000..731d7797ec20
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_current.typoscript
@@ -0,0 +1,14 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Settings
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  variables {
+    current = foo
+    current {
+      bar = baz
+    }
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_data.typoscript b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_data.typoscript
new file mode 100644
index 000000000000..bfdc7aef7a62
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Configuration/TypoScript/variables_reserved_data.typoscript
@@ -0,0 +1,14 @@
+page = PAGE
+page.10 = FLUIDTEMPLATE
+page.10 {
+  templateName = Settings
+  templateRootPaths {
+    10 = EXT:test_fluid_template/Resources/Private/Templates
+  }
+  variables {
+    data = foo
+    data {
+      bar = baz
+    }
+  }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarLayouts/Foobar.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarLayouts/Foobar.html
new file mode 100644
index 000000000000..79386fd92181
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarLayouts/Foobar.html
@@ -0,0 +1 @@
+Foobar Layout
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarPartials/Foobar.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarPartials/Foobar.html
new file mode 100644
index 000000000000..48107bccbfa1
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarPartials/Foobar.html
@@ -0,0 +1 @@
+Foobar Partial
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.html
new file mode 100644
index 000000000000..d0e334007791
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.html
@@ -0,0 +1 @@
+Foobar
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.xml b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.xml
new file mode 100644
index 000000000000..0100296c699b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/FoobarTemplates/Foobar.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<text xmlns="http://www.w3.org/1999/XSL/Transform">
+    FoobarXML
+</text>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/LayoutOverrides/Layouts/Default.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/LayoutOverrides/Layouts/Default.html
new file mode 100644
index 000000000000..b4d4916cf3c6
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/LayoutOverrides/Layouts/Default.html
@@ -0,0 +1,2 @@
+LayoutOverride
+<f:render section="Main"/>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/AlternativeLayout.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/AlternativeLayout.html
new file mode 100644
index 000000000000..b12caeafd7d6
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/AlternativeLayout.html
@@ -0,0 +1,2 @@
+Alternative Layout
+<f:render section="Main"/>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/Default.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/Default.html
new file mode 100644
index 000000000000..22f39c3effec
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Layouts/Default.html
@@ -0,0 +1,2 @@
+Default Layout
+<f:render section="Main"/>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/PartialOverrides/Partials/Component.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/PartialOverrides/Partials/Component.html
new file mode 100644
index 000000000000..554e3d80ad91
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/PartialOverrides/Partials/Component.html
@@ -0,0 +1 @@
+Partial Override
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Partials/Component.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Partials/Component.html
new file mode 100644
index 000000000000..fa19b682a09b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Partials/Component.html
@@ -0,0 +1 @@
+Partial
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/AlternativeTemplate.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/AlternativeTemplate.html
new file mode 100644
index 000000000000..d961539f8338
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/AlternativeTemplate.html
@@ -0,0 +1,4 @@
+<f:layout name="AlternativeLayout"/>
+<f:section name="Main">
+Alternative Template
+</f:section>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Main.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Main.html
new file mode 100644
index 000000000000..f1cb6362c9d9
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Main.html
@@ -0,0 +1,4 @@
+<f:layout/>
+<f:section name="Main">
+Main Template
+</f:section>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Settings.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Settings.html
new file mode 100644
index 000000000000..2597367106ad
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Settings.html
@@ -0,0 +1 @@
+{settings.value1} {settings.value2}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Variables.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Variables.html
new file mode 100644
index 000000000000..398568fdd728
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/Variables.html
@@ -0,0 +1 @@
+{var1} {var2}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/WithPartial.html b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/WithPartial.html
new file mode 100644
index 000000000000..220da85d3f69
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Private/Templates/WithPartial.html
@@ -0,0 +1 @@
+Template with <f:render partial="Component"/>
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Public/Icons/Extension.svg b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Public/Icons/Extension.svg
new file mode 100644
index 000000000000..bca7a17509c5
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/Resources/Public/Icons/Extension.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill="#FF8700" d="M0 0h64v64H0z"/><path fill="#FFF" d="M42.8 32.8c-3.6 0-8.1-10.1-8.1-15.1 0-2.3.9-2.7 3.2-2.7 5.5 0 11 .9 11 4-.1 6.2-4 13.8-6.1 13.8zM28.5 18.5c0 5 6.4 20.2 10.7 20.2.5 0 .9-.1 1.4-.2-3.8 6.1-8.4 10.6-11.2 10.6-5.9 0-14.3-17.9-14.3-25.7 0-1.2.3-2.2.7-2.8 2-2.5 8.4-4.4 13.7-5-.6.4-1 1-1 2.9z"/></svg>
\ No newline at end of file
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/composer.json b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/composer.json
new file mode 100644
index 000000000000..dc69c2818b30
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/composer.json
@@ -0,0 +1,16 @@
+{
+    "name": "typo3/fixture-fluid-template-content-object-test",
+    "type": "typo3-cms-extension",
+    "description": "FluidTemplateContentObject Test",
+    "license": "GPL-2.0-or-later",
+    "autoload": {
+        "psr-4": {
+            "TYPO3Tests\\TestFluidTemplate\\": "Classes"
+        }
+    },
+    "extra": {
+        "typo3/cms": {
+            "extension-key": "test_fluid_template"
+        }
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_emconf.php b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_emconf.php
new file mode 100644
index 000000000000..5d293824e2f3
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_emconf.php
@@ -0,0 +1,18 @@
+<?php
+
+$EM_CONF[$_EXTKEY] = [
+    'title' => 'FluidTemplateContentObject Test',
+    'description' => 'FluidTemplateContentObject Test',
+    'category' => 'example',
+    'version' => '12.1.0',
+    'state' => 'beta',
+    'author' => 'Nikita Hovratov',
+    'author_company' => '',
+    'constraints' => [
+        'depends' => [
+            'typo3' => '12.1.0',
+        ],
+        'conflicts' => [],
+        'suggests' => [],
+    ],
+];
diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_localconf.php b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_localconf.php
new file mode 100644
index 000000000000..60a9a593d36a
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/Extensions/test_fluid_template/ext_localconf.php
@@ -0,0 +1,5 @@
+<?php
+
+use TYPO3Tests\TestFluidTemplate\ContentObjectCurrentValue;
+
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['postInit'][] = ContentObjectCurrentValue::class;
diff --git a/typo3/sysext/frontend/Tests/Unit/ContentObject/FluidTemplateContentObjectTest.php b/typo3/sysext/frontend/Tests/Unit/ContentObject/FluidTemplateContentObjectTest.php
deleted file mode 100644
index faad5eea5ac2..000000000000
--- a/typo3/sysext/frontend/Tests/Unit/ContentObject/FluidTemplateContentObjectTest.php
+++ /dev/null
@@ -1,1373 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
-
-use PHPUnit\Framework\MockObject\MockObject;
-use Prophecy\Argument;
-use Prophecy\Doubler\Generator\Node\ReturnTypeNode;
-use Prophecy\PhpUnit\ProphecyTrait;
-use Prophecy\Prophecy\ObjectProphecy;
-use Psr\Container\ContainerInterface;
-use TYPO3\CMS\Core\Core\Environment;
-use TYPO3\CMS\Core\Http\ServerRequest;
-use TYPO3\CMS\Core\Page\ImportMap;
-use TYPO3\CMS\Core\Page\ImportMapFactory;
-use TYPO3\CMS\Core\Page\PageRenderer;
-use TYPO3\CMS\Core\Tests\Unit\Page\PageRendererFactoryTrait;
-use TYPO3\CMS\Core\TypoScript\TypoScriptService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters;
-use TYPO3\CMS\Extbase\Mvc\Request;
-use TYPO3\CMS\Extbase\Mvc\RequestInterface;
-use TYPO3\CMS\Fluid\View\StandaloneView;
-use TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor;
-use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
-use TYPO3\CMS\Frontend\ContentObject\FluidTemplateContentObject;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
-use TYPO3\CMS\Frontend\DataProcessing\DataProcessorRegistry;
-use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-use TYPO3Fluid\Fluid\View\AbstractTemplateView;
-
-/**
- * @todo: Review these tests. Many of them test a lot of internal details like "see if stdWrap is called"
- *        and similar and thus heavily rely on mocking. When turned into functional tests with a proper
- *        fixture setup, the tests would shrink significantly, would be far better readable and could
- *        avoid dealing with internal class knowledge.
- */
-class FluidTemplateContentObjectTest extends UnitTestCase
-{
-    use ProphecyTrait;
-    use PageRendererFactoryTrait;
-
-    protected bool $resetSingletonInstances = true;
-
-    /**
-     * @var FluidTemplateContentObject|MockObject|AccessibleObjectInterface
-     */
-    protected MockObject $subject;
-
-    /** @var ObjectProphecy<ContentObjectRenderer> */
-    protected ObjectProphecy $contentObjectRendererProphecy;
-
-    protected ContentObjectRenderer $contentObjectRenderer;
-
-    /**
-     * @var ContentDataProcessor
-     */
-    protected ContentDataProcessor $contentDataProcessor;
-
-    /**
-     * @var StandaloneView|MockObject
-     */
-    protected MockObject $standaloneView;
-
-    /**
-     * @var Request|MockObject
-     */
-    protected MockObject $request;
-
-    /**
-     * Set up
-     */
-    protected function setUp(): void
-    {
-        parent::setUp();
-        $importMapProphecy = $this->prophesize(ImportMap::class);
-        $importMapProphecy->render(Argument::type('string'), Argument::type('string'))->willReturn('');
-        $importMapFactoryProphecy = $this->prophesize(ImportMapFactory::class);
-        $importMapFactoryProphecy->create()->willReturn($importMapProphecy->reveal());
-        GeneralUtility::setSingletonInstance(ImportMapFactory::class, $importMapFactoryProphecy->reveal());
-        $this->contentDataProcessor = new ContentDataProcessor(
-            $this->prophesize(ContainerInterface::class)->reveal(),
-            $this->prophesize(DataProcessorRegistry::class)->reveal()
-        );
-        $this->contentObjectRendererProphecy = $this->prophesize(ContentObjectRenderer::class);
-        $this->contentObjectRenderer = $this->contentObjectRendererProphecy->reveal();
-        $this->subject = $this->getAccessibleMock(
-            FluidTemplateContentObject::class,
-            ['initializeStandaloneViewInstance'],
-            [$this->contentDataProcessor]
-        );
-        $serverRequest = (new ServerRequest())->withAttribute('extbase', new ExtbaseRequestParameters());
-        $this->request = $this->getMockBuilder(Request::class)->setConstructorArgs([$serverRequest])->getMock();
-        $this->subject->setRequest($this->request);
-        $this->subject->setContentObjectRenderer($this->contentObjectRenderer);
-        $tsfe = $this->createMock(TypoScriptFrontendController::class);
-        $GLOBALS['TSFE'] = $tsfe;
-    }
-
-    /**
-     * Add a mock standalone view to subject
-     */
-    protected function addMockViewToSubject(): void
-    {
-        $this->standaloneView = $this->createMock(StandaloneView::class);
-        $this->standaloneView->method('getRequest')->willReturn($this->request);
-        $this->standaloneView->method('renderSection')->willReturn('');
-        $this->subject->_set('view', $this->standaloneView);
-    }
-
-    /**
-     * @test
-     */
-    public function constructSetsContentObjectRenderer(): void
-    {
-        $contentObjectRenderer = new ContentObjectRenderer();
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setContentObjectRenderer($contentObjectRenderer);
-        self::assertEquals($contentObjectRenderer, $subject->getContentObjectRenderer());
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsInitializeStandaloneViewInstance(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $this->addMockViewToSubject();
-        $this->subject->expects(self::once())->method('initializeStandaloneViewInstance');
-        $this->subject->render([]);
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapForGivenTemplateRootPathsWithStandardWrap(): void
-    {
-        $configuration = [
-            'templateName' => 'foobar',
-            'templateRootPaths.' => [
-                10 => 'dummyPath',
-                '10.' => [
-                    'wrap' => '|5/',
-                ],
-                15 => 'dummyPath6/',
-                '25.' => [
-                    'field' => 'someField',
-                ],
-            ],
-        ];
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplateRootPaths(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->setTemplate(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrap('dummyPath', ['wrap' => '|5/'])->shouldHaveBeenCalled();
-        $contentObjectRenderer->stdWrap('', ['field' => 'someField'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsTemplateFileInView(): void
-    {
-        $configuration = ['file' => 'EXT:core/bar.html'];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('file', $configuration)->willReturn('EXT:core/bar.html');
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:core/bar.html'))->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsTemplateFileByTemplateInView(): void
-    {
-        $configuration = [
-            'template' => 'FILE',
-            'template.' => [
-                'file' => Environment::getPublicPath() . '/foo/bar.html',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(7);
-        $contentObjectRenderer->cObjGetSingle('FILE', ['file' => Environment::getPublicPath() . '/foo/bar.html'], 'template')->willReturn('baz');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setTemplateSource('baz')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsTemplateFileByTemplateNameInView(): void
-    {
-        $configuration = [
-            'templateName' => 'foo',
-            'templateRootPaths.' => [
-                0 => 'dummyPath1/',
-                1 => 'dummyPath2/',
-            ],
-        ];
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('templateName', $configuration)->willReturn('foo');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplateRootPaths(Argument::cetera())->shouldBeCalled();
-        $standAloneView->assignMultiple(Argument::cetera())->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render()->willReturn('');
-        $standAloneView->getFormat()->willReturn('html');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setTemplate('foo')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsTemplateFileByTemplateNameStdWrapInView(): void
-    {
-        $configuration = [
-            'templateName' => 'TEXT',
-            'templateName.' => ['value' => 'bar'],
-            'templateRootPaths.' => [
-                0 => 'dummyPath1/',
-                1 => 'dummyPath2/',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('templateName', $configuration)->willReturn('bar');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplateRootPaths(Argument::cetera())->shouldBeCalled();
-        $standAloneView->assignMultiple(Argument::cetera())->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render()->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setTemplate('bar')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsLayoutRootPathInView(): void
-    {
-        $configuration = ['layoutRootPath' => 'foo/bar.html'];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('layoutRootPath', $configuration)->willReturn('foo/bar.html');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setLayoutRootPaths([Environment::getPublicPath() . '/foo/bar.html'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForLayoutRootPath(): void
-    {
-        $configuration = [
-            'layoutRootPath' => 'foo',
-            'layoutRootPath.' => [
-                'bar' => 'baz',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrapValue('layoutRootPath', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function layoutRootPathsHasStdWrapSupport(): void
-    {
-        $configuration = [
-            'layoutRootPaths.' => [
-                10 => 'FILE',
-                '10.' => [
-                    'file' => 'foo/bar.html',
-                ],
-                20 => 'foo/bar2.html',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrap('FILE', ['file' => 'foo/bar.html'])->shouldBeCalled();
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setLayoutRootPaths(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrap('FILE', ['file' => 'foo/bar.html'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function fallbacksForLayoutRootPathAreSet(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $this->addMockViewToSubject();
-        $this->standaloneView
-            ->expects(self::once())
-            ->method('setLayoutRootPaths')
-            ->with([
-                10 => Environment::getPublicPath() . '/foo/bar.html',
-                20 => Environment::getPublicPath() . '/foo/bar2.html',
-            ]);
-        $this->subject->render(['layoutRootPaths.' => [10 => 'foo/bar.html', 20 => 'foo/bar2.html']]);
-    }
-
-    /**
-     * @test
-     */
-    public function fallbacksForLayoutRootPathAreAppendedToLayoutRootPath(): void
-    {
-        $configuration = [
-            'layoutRootPath' => 'foo/main.html',
-            'layoutRootPaths.' => [10 => 'foo/bar.html', 20 => 'foo/bar2.html'],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('layoutRootPath', $configuration)->willReturn('foo/main.html');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setLayoutRootPaths([
-            0 => Environment::getPublicPath() . '/foo/main.html',
-            10 => Environment::getPublicPath() . '/foo/bar.html',
-            20 => Environment::getPublicPath() . '/foo/bar2.html',
-        ])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsPartialRootPathInView(): void
-    {
-        $configuration = ['partialRootPath' => 'foo/bar.html'];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('partialRootPath', $configuration)->willReturn('foo/bar.html');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setPartialRootPaths([Environment::getPublicPath() . '/foo/bar.html'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function partialRootPathsHasStdWrapSupport(): void
-    {
-        $configuration = [
-            'partialRootPaths.' => [
-                10 => 'FILE',
-                '10.' => [
-                    'file' => 'foo/bar.html',
-                ],
-                20 => 'foo/bar2.html',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setPartialRootPaths(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrap('FILE', ['file' => 'foo/bar.html'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForPartialRootPath(): void
-    {
-        $configuration = [
-            'partialRootPath' => 'foo',
-            'partialRootPath.' => ['bar' => 'baz'],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setPartialRootPaths(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrapValue('partialRootPath', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function fallbacksForPartialRootPathAreSet(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $this->addMockViewToSubject();
-        $this->standaloneView
-            ->expects(self::once())
-            ->method('setPartialRootPaths')
-            ->with([10 => Environment::getPublicPath() . '/foo', 20 => Environment::getPublicPath() . '/bar']);
-        $this->subject->render(['partialRootPaths.' => [10 => 'foo', 20 => 'bar']]);
-    }
-
-    /**
-     * @test
-     */
-    public function fallbacksForPartialRootPathAreAppendedToPartialRootPath(): void
-    {
-        $configuration = [
-            'partialRootPath' => 'main',
-            'partialRootPaths.' => [10 => 'foo', 20 => 'bar'],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('partialRootPath', $configuration)->willReturn(Environment::getPublicPath() . '/main');
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setPartialRootPaths([
-                0 => Environment::getPublicPath() . '/main',
-                10 => Environment::getPublicPath() . '/foo',
-                20 => Environment::getPublicPath() . '/bar',
-            ])
-            ->willReturn(new ReturnTypeNode('void'))
-            ->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsFormatInView(): void
-    {
-        $configuration = [
-            'format' => 'xml',
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('format', $configuration)->willReturn('xml');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->setFormat('xml')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForFormat(): void
-    {
-        $configuration = [
-            'format' => 'foo',
-            'format.' => ['bar' => 'baz'],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrapValue('format', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsExtbasePluginNameInRequest(): void
-    {
-        $configuration = [
-            'extbase.' => [
-                'pluginName' => 'foo',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('pluginName', ['pluginName' => 'foo'])->willReturn('foo');
-
-        $request = $this->prophesize(RequestInterface::class);
-        $request->withPluginName('foo')->willReturn($request);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($request->reveal());
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename('')->shouldBeCalled();
-        $standAloneView->assignMultiple(['data' => [], 'current' => null])->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render(Argument::cetera())->shouldBeCalled();
-        $standAloneView->setRequest($request->reveal())->shouldBeCalled();
-
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-        $request->withPluginName('foo')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForExtbasePluginName(): void
-    {
-        $configuration = [
-            'pluginName' => 'foo',
-            'pluginName.' => [
-                'bar' => 'baz',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render(['extbase.' => $configuration]);
-
-        $contentObjectRenderer->stdWrapValue('pluginName', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsExtbaseControllerExtensionNameInRequest(): void
-    {
-        $configuration = [
-            'extbase.' => [
-                'controllerExtensionName' => 'foo',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('controllerExtensionName', ['controllerExtensionName' => 'foo'])->willReturn('foo');
-
-        $request = $this->prophesize(RequestInterface::class);
-        $request->withControllerExtensionName('foo')->willReturn($request);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($request->reveal());
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename('')->shouldBeCalled();
-        $standAloneView->assignMultiple(['data' => [], 'current' => null])->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render(Argument::cetera())->shouldBeCalled();
-        $standAloneView->setRequest($request->reveal())->shouldBeCalled();
-
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $request->withControllerExtensionName('foo')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForExtbaseControllerExtensionName(): void
-    {
-        $configuration = [
-            'controllerExtensionName' => 'foo',
-            'controllerExtensionName.' => [
-                'bar' => 'baz',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-        $subject->render(['extbase.' => $configuration]);
-
-        $contentObjectRenderer->stdWrapValue('controllerExtensionName', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsExtbaseControllerNameInRequest(): void
-    {
-        $configuration = [
-            'extbase.' => [
-                'controllerName' => 'foo',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('controllerName', ['controllerName' => 'foo'])->willReturn('foo');
-
-        $request = $this->prophesize(RequestInterface::class);
-        $request->withControllerName('foo')->willReturn($request);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($request->reveal());
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename('')->shouldBeCalled();
-        $standAloneView->assignMultiple(['data' => [], 'current' => null])->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render(Argument::cetera())->shouldBeCalled();
-        $standAloneView->setRequest($request->reveal())->shouldBeCalled();
-
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $request->withControllerName('foo')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapValueForExtbaseControllerName(): void
-    {
-        $configuration = [
-            'controllerName' => 'foo',
-            'controllerName.' => [
-                'bar' => 'baz',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render(['extbase.' => $configuration]);
-
-        $contentObjectRenderer->stdWrapValue('controllerName', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderSetsExtbaseControllerActionNameInRequest(): void
-    {
-        $configuration = [
-            'extbase.' => [
-                'controllerActionName' => 'foo',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->stdWrapValue('controllerActionName', ['controllerActionName' => 'foo'])->willReturn('foo');
-
-        $request = $this->prophesize(RequestInterface::class);
-        $request->withControllerActionName('foo')->willReturn($request);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($request->reveal());
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename('')->shouldBeCalled();
-        $standAloneView->assignMultiple(['data' => [], 'current' => null])->shouldBeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render(Argument::cetera())->shouldBeCalled();
-        $standAloneView->setRequest($request->reveal())->shouldBeCalled();
-
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $request->withControllerActionName('foo')->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapForExtbaseControllerActionName(): void
-    {
-        $configuration = [
-            'controllerActionName' => 'foo',
-            'controllerActionName.' => [
-                'bar' => 'baz',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render(['extbase.' => $configuration]);
-
-        $contentObjectRenderer->stdWrapValue('controllerActionName', $configuration)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderAssignsSettingsArrayToView(): void
-    {
-        $configuration = [
-            'settings.' => [
-                'foo' => 'value',
-                'bar.' => [
-                    'baz' => 'value2',
-                ],
-            ],
-        ];
-
-        $expectedSettingsToBeSet = [
-            'foo' => 'value',
-            'bar' => [
-                'baz' => 'value2',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $typoScriptServiceMock = $this->getMockBuilder(TypoScriptService::class)->getMock();
-        $typoScriptServiceMock
-            ->expects(self::once())
-            ->method('convertTypoScriptArrayToPlainArray')
-            ->with($configuration['settings.'])
-            ->willReturn($expectedSettingsToBeSet);
-        GeneralUtility::addInstance(TypoScriptService::class, $typoScriptServiceMock);
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($this->prophesize(ContentObjectRenderer::class)->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->assign('settings', $expectedSettingsToBeSet)->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderThrowsExceptionForNotAllowedVariableData(): void
-    {
-        $this->addMockViewToSubject();
-        $configuration = [
-            'variables.' => [
-                'data' => 'foo',
-                'data.' => [
-                    'bar' => 'baz',
-                ],
-            ],
-        ];
-        $this->expectException(\InvalidArgumentException::class);
-        $this->expectExceptionCode(1288095720);
-        $this->subject->render($configuration);
-    }
-
-    /**
-     * @test
-     */
-    public function renderThrowsExceptionForNotAllowedVariableCurrent(): void
-    {
-        $this->addMockViewToSubject();
-        $configuration = [
-            'variables.' => [
-                'current' => 'foo',
-                'current.' => [
-                    'bar' => 'baz',
-                ],
-            ],
-        ];
-        $this->expectException(\InvalidArgumentException::class);
-        $this->expectExceptionCode(1288095720);
-        $this->subject->render($configuration);
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsCObjGetSingleForAllowedVariable(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $configuration = [
-            'variables.' => [
-                'aVar' => 'TEXT',
-                'aVar.' => [
-                    'value' => 'foo',
-                ],
-            ],
-        ];
-
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->assignMultiple(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->cObjGetSingle('TEXT', ['value' => 'foo'], Argument::any())->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderAssignsRenderedContentObjectVariableToView(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $configuration = [
-            'variables.' => [
-                'aVar' => 'TEXT',
-                'aVar.' => [
-                    'value' => 'foo',
-                ],
-            ],
-        ];
-
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-        $contentObjectRenderer->stdWrapValue(Argument::cetera())->shouldBeCalledTimes(8);
-        $contentObjectRenderer->cObjGetSingle(Argument::cetera())->willReturn('foo');
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename(Argument::cetera())->willReturn(new ReturnTypeNode('void'));
-        $standAloneView->render(Argument::cetera())->willReturn('');
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $standAloneView->assignMultiple(['aVar' => 'foo', 'data' => [], 'current' => null])
-            ->willReturn(new ReturnTypeNode('void'))
-            ->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @test
-     */
-    public function renderAssignsContentObjectRendererDataToView(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $this->addMockViewToSubject();
-        $this->contentObjectRenderer->data = ['foo'];
-        $this->standaloneView
-            ->expects(self::once())
-            ->method('assignMultiple')
-            ->with(['data' => ['foo'], 'current' => null]);
-        $this->subject->render([]);
-    }
-
-    /**
-     * @test
-     */
-    public function renderAssignsContentObjectRendererCurrentValueToView(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $this->addMockViewToSubject();
-        $this->contentObjectRenderer->data = ['currentKey' => 'currentValue'];
-        $this->contentObjectRenderer->currentValKey = 'currentKey';
-        $this->standaloneView
-            ->expects(self::once())
-            ->method('assignMultiple')
-            ->with(['data' => ['currentKey' => 'currentValue'], 'current' => 'currentValue']);
-        $this->subject->render([]);
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsRenderOnStandaloneView(): void
-    {
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $this->addMockViewToSubject();
-        $this->standaloneView
-            ->expects(self::once())
-            ->method('render');
-        $this->subject->render([]);
-    }
-
-    /**
-     * @test
-     */
-    public function renderCallsStandardWrapOnResultStringIfGivenInConfiguration(): void
-    {
-        $configuration = [
-            'stdWrap.' => [
-                'foo' => 'bar',
-            ],
-        ];
-
-        GeneralUtility::setSingletonInstance(
-            PageRenderer::class,
-            new PageRenderer(...$this->getPageRendererConstructorArgs()),
-        );
-
-        $contentObjectRenderer = $this->prophesize(ContentObjectRenderer::class);
-
-        $subject = new FluidTemplateContentObject($this->contentDataProcessor);
-        $subject->setRequest($this->request);
-        $subject->setContentObjectRenderer($contentObjectRenderer->reveal());
-
-        $standAloneView = $this->prophesize(StandaloneView::class);
-        $standAloneView->setRequest(Argument::cetera());
-        $standAloneView->setTemplatePathAndFilename('')->shouldBeCalled();
-        $standAloneView->assignMultiple(['data' => [], 'current' => null])->shouldbeCalled();
-        $standAloneView->renderSection(Argument::cetera())->willReturn('');
-        $standAloneView->render()->willReturn('baz');
-        GeneralUtility::addInstance(StandaloneView::class, $standAloneView->reveal());
-
-        $subject->render($configuration);
-
-        $contentObjectRenderer->stdWrap('baz', ['foo' => 'bar'])->shouldHaveBeenCalled();
-    }
-
-    /**
-     * @param AbstractTemplateView $viewMock
-     * @param string|null $expectedHeader
-     * @param string|null $expectedFooter
-     * @test
-     * @dataProvider headerAssetDataProvider
-     */
-    public function renderFluidTemplateAssetsIntoPageRendererRendersAndAttachesAssets(
-        AbstractTemplateView $viewMock,
-        ?string $expectedHeader,
-        ?string $expectedFooter
-    ): void {
-        $pageRendererMock = $this->getMockBuilder(PageRenderer::class)
-            ->setConstructorArgs($this->getPageRendererConstructorArgs())
-            ->onlyMethods([
-                'addHeaderData',
-                'addFooterData',
-            ])
-            ->getMock();
-        if ($expectedHeader !== null && !empty(trim($expectedHeader))) {
-            $pageRendererMock->expects(self::once())->method('addHeaderData')->with($expectedHeader);
-        } else {
-            $pageRendererMock->expects(self::never())->method('addHeaderData');
-        }
-        if ($expectedFooter !== null && !empty(trim($expectedFooter))) {
-            $pageRendererMock->expects(self::once())->method('addFooterData')->with($expectedFooter);
-        } else {
-            $pageRendererMock->expects(self::never())->method('addFooterData');
-        }
-
-        $subject = $this->getMockBuilder(FluidTemplateContentObject::class)->onlyMethods(['getPageRenderer'])->disableOriginalConstructor()->getMock();
-        $subject->expects(self::once())->method('getPageRenderer')->willReturn($pageRendererMock);
-        $viewProperty = new \ReflectionProperty($subject, 'view');
-        $viewProperty->setAccessible(true);
-        $viewProperty->setValue($subject, $viewMock);
-
-        $method = new \ReflectionMethod($subject, 'renderFluidTemplateAssetsIntoPageRenderer');
-        $method->setAccessible(true);
-        $method->invoke($subject);
-    }
-
-    /**
-     * @return array
-     */
-    public function headerAssetDataProvider(): array
-    {
-        $viewWithHeaderData = $this->getMockBuilder(AbstractTemplateView::class)->onlyMethods(['renderSection'])->disableOriginalConstructor()->getMock();
-        $viewWithHeaderData->expects(self::exactly(2))->method('renderSection')
-            ->withConsecutive(
-                [
-                    'HeaderAssets',
-                    self::anything(),
-                    true,
-                ],
-                [
-                    'FooterAssets',
-                    self::anything(),
-                    true,
-                ]
-            )->willReturnOnConsecutiveCalls('custom-header-data', '');
-        $viewWithFooterData = $this->getMockBuilder(AbstractTemplateView::class)->onlyMethods(['renderSection'])->disableOriginalConstructor()->getMock();
-        $viewWithFooterData->expects(self::exactly(2))->method('renderSection')
-            ->withConsecutive(
-                [
-                    'HeaderAssets',
-                    self::anything(),
-                    true,
-                ],
-                [
-                    'FooterAssets',
-                    self::anything(),
-                    true,
-                ]
-            )->willReturn('', 'custom-footer-data');
-        $viewWithBothData = $this->getMockBuilder(AbstractTemplateView::class)->onlyMethods(['renderSection'])->disableOriginalConstructor()->getMock();
-        $viewWithBothData->expects(self::exactly(2))->method('renderSection')
-            ->withConsecutive(
-                [
-                    'HeaderAssets',
-                    self::anything(),
-                    true,
-                ],
-                [
-                    'FooterAssets',
-                    self::anything(),
-                    true,
-                ]
-            )->willReturnOnConsecutiveCalls('custom-header-data', 'custom-footer-data');
-        return [
-            [$viewWithHeaderData, 'custom-header-data', ''],
-            [$viewWithFooterData, '', 'custom-footer-data'],
-            [$viewWithBothData, 'custom-header-data', 'custom-footer-data'],
-        ];
-    }
-}
-- 
GitLab