[TASK] Functional test for tt_content rendering 33/53633/4
authorTymoteusz Motylewski <t.motylewski@gmail.com>
Mon, 31 Jul 2017 16:42:59 +0000 (18:42 +0200)
committerTymoteusz Motylewski <t.motylewski@gmail.com>
Wed, 2 Aug 2017 06:37:15 +0000 (08:37 +0200)
Add functional tests for tt_content rendering
with different combinations of TypoScript language
settings sys_language_overlay and sys_language_mode.

It also backports a change from testing framework
which is required by this patch
 https://github.com/TYPO3/testing-framework/pull/23

Resolves: #81185
Releases: master, 8.7, 7.6
Change-Id: I7df5b48a2baa3a52f8c6103b0657b21226c6ea5c
Reviewed-on: https://review.typo3.org/53633
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Tested-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts
typo3/sysext/core/Tests/Functional/Framework/Frontend/Renderer.php
typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html [new file with mode: 0644]
typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultElements.csv [new file with mode: 0644]
typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv [new file with mode: 0644]
typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php [new file with mode: 0644]

index 69cda93..0258c30 100644 (file)
@@ -12,10 +12,10 @@ config {
 
        watcher {
                tableFields {
-                       pages = uid,_ORIG_uid,pid,sorting,title
+                       pages = uid,_PAGES_OVERLAY_UID,pid,sorting,title,tx_irretutorial_hotels
                        sys_category = uid,_ORIG_uid,_LOCALIZED_UID,pid,sys_language_uid,title,parent,items,sys_language_uid
                        sys_file = uid,_ORIG_uid,_LOCALIZED_UID,pid,title,sys_language_uid
-                       sys_file_reference = uid,_ORIG_uid,_LOCALIZED_UID,title,description,alternative,link,downloadname,missing,identifier,file,pid,sys_language_uid,title,parent,items,sys_language_uid,uid_local,uid_foreign,tablenames,fieldname,table_local
+                       sys_file_reference = uid,_ORIG_uid,_LOCALIZED_UID,title,description,alternative,link,missing,identifier,file,pid,sys_language_uid,title,parent,items,sys_language_uid,uid_local,uid_foreign,tablenames,fieldname,table_local
                        tt_content = uid,_ORIG_uid,_LOCALIZED_UID,pid,sorting,sys_language_uid,header,categories,tx_irretutorial_1nff_hotels
                        tx_irretutorial_1nff_hotel = uid,_ORIG_uid,_LOCALIZED_UID,pid,sorting,sys_language_uid,title,offers
                        tx_irretutorial_1nff_offer = uid,_ORIG_uid,_LOCALIZED_UID,pid,sorting,sys_language_uid,title,prices
@@ -67,6 +67,19 @@ page {
                        renderObj < lib.watcherDataObject
                        renderObj.1.watcher.dataWrap = {register:watcher}|.__pages/pages:{field:uid}
                }
+               15 = CONTENT
+               15 {
+                       if.isTrue.field = tx_irretutorial_hotels
+                       table = tx_irretutorial_1nff_hotel
+                       select {
+                               orderBy = sorting
+                               where.field = uid
+                               where.intval = 1
+                               where.wrap = parenttable='pages' AND parentid=|
+                       }
+                       renderObj < lib.watcherDataObject
+                       renderObj.1.watcher.dataWrap = {register:watcher}|.tx_irretutorial_hotels/tx_irretutorial_1nff_hotel:{field:uid}
+               }
                20 = CONTENT
                20 {
                        table = tt_content
@@ -222,6 +235,24 @@ page {
                stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->attachSection
                stdWrap.postUserFunc.as = Default
        }
+       99999 = COA
+       99999 {
+               stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->renderValues
+               stdWrap.postUserFunc.values {
+                       page.children {
+                               uid.data = page:uid
+                               pid.data = page:pid
+                               title.data = page:title
+                       }
+                       tsfe.children {
+                               sys_language_uid.data = tsfe:sys_language_uid
+                               sys_language_mode.data = tsfe:sys_language_mode
+                               sys_language_content.data = tsfe:sys_language_content
+                               sys_language_contentOL.data = tsfe:sys_language_contentOL
+                       }
+               }
+               stdWrap.postUserFunc.as = Scope
+       }
        stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->renderSections
 }
 
@@ -230,4 +261,7 @@ config.sys_language_uid = 1
 [end]
 [globalVar = GP:L = 2]
 config.sys_language_uid = 2
+[end]
+[globalVar = GP:L = 3]
+config.sys_language_uid = 3
 [end]
\ No newline at end of file
index 8a5b124..1f2d385 100644 (file)
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
  */
 
 /**
- * Model of frontend response
+ * Section renderer for frontend responses.
  */
 class Renderer implements \TYPO3\CMS\Core\SingletonInterface
 {
@@ -25,6 +25,11 @@ class Renderer implements \TYPO3\CMS\Core\SingletonInterface
     protected $sections = [];
 
     /**
+     * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
+     */
+    public $cObj;
+
+    /**
      * @param string $content
      * @param NULL|array $configuration
      * @return void
@@ -57,6 +62,33 @@ class Renderer implements \TYPO3\CMS\Core\SingletonInterface
     }
 
     /**
+     * Possible structure of $configuration:
+     * {
+     *   values {
+     *     propertyA.data = tsfe:id
+     *     propertyB.children {
+     *       propertyB1.data = page:id
+     *       propertyB2.data = page:pid
+     *       propertyB2.intval = 1
+     *     }
+     *   }
+     *   as = CustomData
+     * }
+     *
+     * @param string $content
+     * @param array|null $configuration
+     */
+    public function renderValues($content, array $configuration = null)
+    {
+        if (empty($configuration['values.'])) {
+            return;
+        }
+
+        $as = (!empty($configuration['as']) ? $configuration['as'] : null);
+        $this->addSection($this->stdWrapValues($configuration['values.']), $as);
+    }
+
+    /**
      * @param array $section
      * @param NULL|string $as
      */
@@ -81,6 +113,42 @@ class Renderer implements \TYPO3\CMS\Core\SingletonInterface
     }
 
     /**
+     * Possible structure of $values:
+     * {
+     *   propertyA.data = tsfe:id
+     *   propertyB.children {
+     *     propertyB1.data = page:id
+     *     propertyB2.data = page:pid
+     *     propertyB2.intval = 1
+     *   }
+     * }
+     *
+     * @param array $values
+     * @return array
+     */
+    protected function stdWrapValues(array $values)
+    {
+        $renderedValues = [];
+
+        foreach ($values as $propertyName => $propertyInstruction)
+        {
+            $plainPropertyName = rtrim($propertyName, '.');
+            if (!empty($propertyInstruction['children.'])) {
+                $renderedValues[$plainPropertyName] = $this->stdWrapValues(
+                    $propertyInstruction['children.']
+                );
+            } else {
+                $renderedValues[$plainPropertyName] = $this->cObj->stdWrap(
+                    '',
+                    $propertyInstruction
+                );
+            }
+        }
+
+        return $renderedValues;
+    }
+
+    /**
      * @return Parser
      */
     protected function createParser()
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html b/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html
new file mode 100644 (file)
index 0000000..bb8bf0d
--- /dev/null
@@ -0,0 +1,4 @@
+{
+"status": 404,
+"error": "###REASON###"
+}
\ No newline at end of file
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultElements.csv b/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultElements.csv
new file mode 100644 (file)
index 0000000..61e7c11
--- /dev/null
@@ -0,0 +1,17 @@
+sys_language,,,,,,,,,,,,,
+,uid,pid,hidden,title,flag,,,,,,,,
+,1,0,0,Dansk,dk,,,,,,,,
+,2,0,0,Deutsch,de,,,,,,,,
+,3,0,0,Polski,pl,,,,,,,,
+tt_content,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header
+,297,89,256,0,0,0,0,0,0,0,0,0,Regular Element #1
+,298,89,512,0,0,0,0,0,0,0,0,0,Regular Element #2
+,299,89,768,0,0,0,0,0,0,0,0,0,Regular Element #3
+,300,89,1024,0,1,299,299,0,0,0,0,0,[Translate to Dansk:] Regular Element #3
+,301,89,384,0,1,297,297,0,0,0,0,0,[Translate to Dansk:] Regular Element #1
+,302,89,448,0,2,297,301,0,0,0,0,0,[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1
+,303,89,1250,0,1,0,0,0,0,0,0,0,[DK] Without default language
+,304,89,1250,0,2,0,0,0,0,0,0,0,[DE] Without default language
+,305,89,512,0,3,297,297,0,0,0,0,0,[Translate to Polski:] Regular Element #1
+,306,89,1024,0,3,0,0,0,0,0,0,0,[PL] Without default language
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv b/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv
new file mode 100644 (file)
index 0000000..0df7780
--- /dev/null
@@ -0,0 +1,9 @@
+pages,,,,,,,,,,,
+,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title
+,1,0,256,0,0,0,0,0,0,0,Root page
+,88,1,256,0,0,0,0,0,0,0,Subpage
+,89,88,256,0,0,0,0,0,0,0,Default language Page
+pages_language_overlay,,,,,,,,,,,
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,,
+,1,89,0,1,0,0,0,0,[DK]Page,,
+,2,89,0,3,0,0,0,0,[PL]Page,,
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php
new file mode 100644 (file)
index 0000000..52e9dc4
--- /dev/null
@@ -0,0 +1,830 @@
+<?php
+
+namespace TYPO3\CMS\Frontend\Tests\Functional\Rendering;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Response;
+
+/**
+ * Test case checking if localized tt_content is rendered correctly with different language settings
+ *
+ * The following values are relevant:
+ *
+ * -- TypoScript --
+ * config.sys_language_uid = [0,1,2,3,4...] (set via the language parameter &L=1 from the FrontendRequest in the tests)
+ *      Fetch the page overlay of the current page if the value is > 0 and if not available, then
+ *      "config.sys_language_mode" is evaluated.
+ *      If this setting is set to "0" or empty, then no page overlay is evaluated, and no further parameters are
+ *      relevant or evaluated.
+ *
+ * config.sys_language_mode = [strict, content_fallback;2,3, ignore]
+ *      Only evaluated when sys_language_uid > 0, and the requested page translation is NOT available.
+ *      Decides if "pageNotFound" (strict), "content_fallback" with a fallback chain ($TSFE->sys_language_content is set
+ *      to that value) or "ignore" (just render the page and the content as this translation would exist).
+ *      When set to "0" or not set "", this means that the page request is using the default language for content
+ *      and page properties.
+ *      Content fallback is evaluated on page level, not on the CE level. So it only makes a difference when the pages_language_overlay
+ *      for the requested language does not exist.
+ *
+ * config.sys_language_overlay = [0, 1, hideNonTranslated]
+ *      Only relevant if $TSFE->sys_language_content is > 0.
+ *      Sets the property $TSFE->sys_language_contentOL at a request. Further calls via $TSFE->sys_page->getRecordOverlay
+ *      receive this value to see if an overlay should happen.
+ *      0:
+ *          Just fetch records from selected ($TSFE->sys_language_content) language, no overlay will happen,
+ *          no fetching of the records from the default language. This boils down to "free mode" language handling.
+ *
+ *      1:
+ *          Fetch records from the default language and overlay them with translations. If some record is not translated
+ *          default language version will be shown.
+ *
+ *      hideNotTranslated:
+ *          Fetch records from the default language and overlay them with translations. If some record is not translated
+ *          it will not be shown.
+ *
+ * -- Frontend / TypoScriptFrontendController --
+ *
+ * $TSFE->sys_language_uid
+ *      Defines in which language the current page was requested, this is relevant when building menus or links to other
+ *      pages.
+ * $TSFE->sys_language_content
+ *      Contains the language UID of the content records that should be overlaid to would be fetched.
+ *      This is especially useful when a page requested with language=4 should fall back to showing content of language=2 (see config.sys_language_mode=content_fallback)
+ * $TSFE->sys_language_contentOL
+ *      Contains the info if and how record overlays (when fetching content) should be handled, either "0" (no overlays done)
+ *      or "1" (do overlays with possible mixed content, or "hideNonTranslated". see "config.sys_language_overlay"
+ *      This is used in conjunction with $TSFE->sys_language_content.
+ * $TSFE->sys_language_mode
+ *      Contains the config.sys_language_mode parameter, which is either "", "strict", "content_fallback" or "ignore"
+ *      Only used within $TSFE->settingLanguage() and in Extbase.
+ */
+class LocalizedContentRenderingTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase
+{
+    const VALUE_PageId = 89;
+    const TABLE_Content = 'tt_content';
+    const TABLE_Pages = 'pages';
+
+    /**
+     * @var string
+     */
+    protected $scenarioDataSetDirectory = 'typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/';
+
+    /**
+     * Custom 404 handler returning valid json is registered so the $this->getFrontendResponse()
+     * does not fail on 404 pages
+     *
+     * @var array
+     */
+    protected $configurationToUseInTestInstance = [
+        'FE' => [
+            'pageNotFound_handling' => 'READFILE:typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/404Template.html'
+        ]
+    ];
+
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->importScenarioDataSet('LiveDefaultPages');
+        $this->importScenarioDataSet('LiveDefaultElements');
+
+        $this->backendUser->workspace = 0;
+    }
+
+    public function defaultLanguageConfigurationDataProvider()
+    {
+        return [
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode =',
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback;1,0',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = strict',
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = ignore',
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode =',
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback;1,0',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = strict',
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = ignore',
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode =',
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback;1,0',
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = strict',
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = ignore',
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+        ];
+    }
+
+    /**
+     * For the default language all combination of language settings should give the same result,
+     * regardless of TypoScript settings, if the requested language is "0" then no TypoScript settings apply.
+     *
+     * @test
+     * @dataProvider defaultLanguageConfigurationDataProvider
+     *
+     * @param string $typoScript
+     * @param string $sysLanguageMode
+     * @param string $sysLanguageContentOL
+     */
+    public function onlyEnglishContentIsRenderedForDefaultLanguage($typoScript, $sysLanguageMode, $sysLanguageContentOL)
+    {
+        $this->setUpFrontendRootPage(1, [
+            'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts',
+        ]);
+        $this->addTypoScriptToTemplateRecord(1, $typoScript);
+
+        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 0);
+        $responseSections = $frontendResponse->getResponseSections();
+        $visibleHeaders = ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'];
+        $constraint = $this->getRequestSectionHasRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $visibleHeaders);
+        $this->assertThat($responseSections, $constraint);
+
+        $constraint = $this->getRequestSectionDoesNotHaveRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $this->getNonVisibleHeaders($visibleHeaders));
+        $this->assertThat($responseSections, $constraint);
+
+        $content = json_decode($frontendResponse->getContent());
+        $this->assertEquals('Default language Page', $content->Scope->page->title);
+        $this->assertEquals(0, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
+        $this->assertEquals(0, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
+        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
+        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
+    }
+
+    /**
+     * Dutch language has pages_language_overlay record and some content elements are translated
+     *
+     * @return array
+     */
+    public function dutchDataProvider()
+    {
+        //Expected behaviour:
+        //Page is translated to Dutch, so changing sys_language_mode does NOT change the results
+        //Page title is always [DK]Page, and both sys_language_content and sys_language_uid are always 1
+        return [
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Same as config.sys_language_mode = content_fallback because we're requesting language 1, so no additional fallback possible
+            //
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Non translated default language elements are not shown, because of hideNonTranslated
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            //Setting sys_language_mode = strict has the same effect as previous data sets, because the translation of the page exists
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider dutchDataProvider
+     *
+     * @param string $typoScript
+     * @param array $visibleHeaders
+     * @param string $sysLanguageMode
+     * @param string $sysLanguageContentOL
+     */
+    public function renderingOfDutchLanguage($typoScript, array $visibleHeaders, $sysLanguageMode, $sysLanguageContentOL)
+    {
+        $this->setUpFrontendRootPage(1, [
+            'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts',
+        ]);
+        $this->addTypoScriptToTemplateRecord(1, $typoScript);
+        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 1);
+        $responseSections = $frontendResponse->getResponseSections();
+        $constraint = $this->getRequestSectionHasRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $visibleHeaders);
+        $this->assertThat($responseSections, $constraint);
+
+        $constraint = $this->getRequestSectionDoesNotHaveRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $this->getNonVisibleHeaders($visibleHeaders));
+        $this->assertThat($responseSections, $constraint);
+
+        $content = json_decode($frontendResponse->getContent());
+        $this->assertEquals('[DK]Page', $content->Scope->page->title);
+        $this->assertEquals(1, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
+        $this->assertEquals(1, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
+        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
+        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
+    }
+
+    public function contentOnNonTranslatedPageDataProvider()
+    {
+        //Expected behaviour:
+        //the page is NOT translated so setting sys_language_mode to different values changes the results
+        //- setting sys_language_mode to empty value makes TYPO3 return default language records
+        //- setting it to strict throws 404, independently from other settings
+        //Setting config.sys_language_overlay = 0
+        return [
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 0,
+                'sys_language_content' => 0,
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 0,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 0,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3', '[DK] Without default language'],
+                'pageTitle' => 'Default language Page', //TODO: change it to "[DK]Page" once #81657 is fixed
+                'sys_language_uid' => 2,
+                'sys_language_content' => 1,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => [],
+                'pageTitle' => '',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 0,
+                'status' => 404,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1', '[DE] Without default language'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 0,
+            ],
+            5 => [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 0,
+                'sys_language_content' => 0,
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 1,
+            ],
+            //falling back to default language
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 0,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1,
+            ],
+            //Dutch elements are shown because of the content fallback 1,0 - first Dutch, then default language
+            //note that '[DK] Without default language' is NOT shown - due to overlays (fetch default language and overlay it with translations)
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+                'pageTitle' => 'Default language Page', //TODO: change it to "[DK]Page" once #81657 is fixed
+                'sys_language_uid' => 2,
+                'sys_language_content' => 1,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => [],
+                'pageTitle' => '',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 1,
+                'status' => 404
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 1,
+            ],
+            10 => [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 0,
+                'sys_language_content' => 0,
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 'hideNonTranslated',
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 0,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated',
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Dansk:] Regular Element #1', '[Translate to Dansk:] Regular Element #3'],
+                'pageTitle' => 'Default language Page', //TODO: change it to "[DK]Page" once #81657 is fixed
+                'sys_language_uid' => 2,
+                'sys_language_content' => 1,
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated',
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => [],
+                'pageTitle' => '',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 'hideNonTranslated',
+                'status' => 404,
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1'],
+                'pageTitle' => 'Default language Page',
+                'sys_language_uid' => 2,
+                'sys_language_content' => 2,
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 'hideNonTranslated',
+            ],
+        ];
+    }
+
+    /**
+     * Page uid 89 is NOT translated to german
+     *
+     * @test
+     * @dataProvider contentOnNonTranslatedPageDataProvider
+     *
+     * @param string $typoScript
+     * @param array $visibleHeaders
+     * @param string $pageTitle
+     * @param int $sysLanguageUid
+     * @param int $sysLanguageContent
+     * @param string $sysLanguageMode
+     * @param string $sysLanguageContentOL
+     * @param string $status 'success' or 404
+     */
+    public function contentOnNonTranslatedPageGerman($typoScript, array $visibleHeaders, $pageTitle, $sysLanguageUid, $sysLanguageContent, $sysLanguageMode, $sysLanguageContentOL, $status='success')
+    {
+        $this->setUpFrontendRootPage(1, [
+            'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts',
+        ]);
+        $this->addTypoScriptToTemplateRecord(1, $typoScript);
+
+        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 2);
+        if ($status === Response::STATUS_Success) {
+            $responseSections = $frontendResponse->getResponseSections();
+            $constraint = $this->getRequestSectionHasRecordConstraint()
+                ->setTable(self::TABLE_Content)
+                ->setField('header');
+            call_user_func_array([$constraint, 'setValues'], $visibleHeaders);
+            $this->assertThat($responseSections, $constraint);
+
+            $constraint = $this->getRequestSectionDoesNotHaveRecordConstraint()
+                ->setTable(self::TABLE_Content)
+                ->setField('header');
+            call_user_func_array([$constraint, 'setValues'], $this->getNonVisibleHeaders($visibleHeaders));
+            $this->assertThat($responseSections, $constraint);
+
+            $content = json_decode($frontendResponse->getContent());
+            $this->assertEquals($pageTitle, $content->Scope->page->title);
+            $this->assertEquals($sysLanguageUid, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
+            $this->assertEquals($sysLanguageContent, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
+            $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
+            $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
+        }
+        //some configuration combinations results in 404, in that case status will be set to 404
+        $this->assertEquals($status, $frontendResponse->getStatus());
+    }
+
+    public function contentOnPartiallyTranslatedPageDataProvider()
+    {
+
+        //Expected behaviour:
+        //Setting sys_language_mode to different values doesn't influence the result as the requested page is translated to Polish,
+        //Page title is always [PL]Page, and both sys_language_content and sys_language_uid are always 3
+        return [
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 0
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 0
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 0
+            ],
+            5 => [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Element #3 is not translated in PL and it is translated in DK. It's not shown as content_fallback is not related to single CE level
+            // but on page level - and this page is translated to Polish, so no fallback is happening
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 1
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = 1
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 1
+            ],
+            // Expected behaviour:
+            // Non translated default language elements are not shown, because of hideNonTranslated
+            10 => [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode =',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
+                'sys_language_mode' => '',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = content_fallback;1,0',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
+                'sys_language_mode' => 'content_fallback',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = strict',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
+                'sys_language_mode' => 'strict',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ],
+            [
+                'typoScript' => 'config.sys_language_overlay = hideNonTranslated
+                                config.sys_language_mode = ignore',
+                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1'],
+                'sys_language_mode' => 'ignore',
+                'sys_language_contentOL' => 'hideNonTranslated'
+            ]
+        ];
+    }
+
+    /**
+     * Page uid 89 is translated to to Polish, but not all CE are translated
+     *
+     * @test
+     * @dataProvider contentOnPartiallyTranslatedPageDataProvider
+     *
+     * @param string $typoScript
+     * @param array $visibleHeaders
+     * @param string $sysLanguageMode
+     * @param string $sysLanguageContentOL
+     */
+    public function contentOnPartiallyTranslatedPage($typoScript, array $visibleHeaders, $sysLanguageMode, $sysLanguageContentOL)
+    {
+        $this->setUpFrontendRootPage(1, [
+            'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts',
+        ]);
+        $this->addTypoScriptToTemplateRecord(1, $typoScript);
+
+        $frontendResponse = $this->getFrontendResponse(self::VALUE_PageId, 3);
+        $this->assertEquals('success', $frontendResponse->getStatus());
+        $responseSections = $frontendResponse->getResponseSections();
+
+        $constraint = $this->getRequestSectionHasRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $visibleHeaders);
+        $this->assertThat($responseSections, $constraint);
+
+        $constraint = $this->getRequestSectionDoesNotHaveRecordConstraint()
+            ->setTable(self::TABLE_Content)
+            ->setField('header');
+        call_user_func_array([$constraint, 'setValues'], $this->getNonVisibleHeaders($visibleHeaders));
+        $this->assertThat($responseSections, $constraint);
+
+        $content = json_decode($frontendResponse->getContent());
+        $this->assertEquals('[PL]Page', $content->Scope->page->title);
+        $this->assertEquals(3, $content->Scope->tsfe->sys_language_uid, 'sys_language_uid doesn\'t match');
+        $this->assertEquals(3, $content->Scope->tsfe->sys_language_content, 'sys_language_content doesn\'t match');
+        $this->assertEquals($sysLanguageMode, $content->Scope->tsfe->sys_language_mode, 'sys_language_mode doesn\t match');
+        $this->assertEquals($sysLanguageContentOL, $content->Scope->tsfe->sys_language_contentOL, 'sys_language_contentOL doesn\t match');
+    }
+
+    /**
+     * Helper function to ease asserting that rest of the data set is not visible
+     *
+     * @param array $visibleHeaders
+     * @return array
+     */
+    protected function getNonVisibleHeaders(array $visibleHeaders)
+    {
+        $allElements = [
+            'Regular Element #1',
+            'Regular Element #2',
+            'Regular Element #3',
+            '[Translate to Dansk:] Regular Element #1',
+            '[Translate to Dansk:] Regular Element #3',
+            '[DK] Without default language',
+            '[DE] Without default language',
+            '[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1',
+            '[Translate to Polski:] Regular Element #1',
+            '[PL] Without default language'
+        ];
+        return array_diff($allElements, $visibleHeaders);
+    }
+
+    /**
+     * Adds TypoScript setup snippet to the existing template record
+     *
+     * @param int $pageId
+     * @param string $typoScript
+     */
+    protected function addTypoScriptToTemplateRecord($pageId, $typoScript)
+    {
+        $connection = $this->getDatabaseConnection();
+
+        $template = $connection->exec_SELECTgetSingleRow('*', 'sys_template', 'pid = '. $pageId . ' AND root = 1');
+        if (empty($template)) {
+            $this->fail('Cannot find root template on page with id: "' . $pageId . '"');
+        }
+        $updateFields['config'] = $template['config'] . LF . $typoScript;
+        $connection->exec_UPDATEquery(
+            'sys_template',
+            'uid = ' . $template['uid'],
+            $updateFields
+        );
+    }
+}