[TASK] Restructure functional frontend tests 87/30687/4
authorOliver Hader <oliver@typo3.org>
Tue, 10 Jun 2014 09:53:05 +0000 (11:53 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Fri, 13 Jun 2014 08:37:15 +0000 (10:37 +0200)
In the scope of enabling Extbase frontend rendering during
functional test runs, the response object contains multiple
data values for TypoScript ("default") and the called Extbase
actions. Processing them all at once just has practical reasons
to avoid additional frontend requests for each aspect.
To decouple the actual testing structure from assertions
and constraints, a new Contraint namespace has been introduced.

The irre_tutorial extension has been enriched with an accordant
frontend rendering for Extbase context to return structured JSON
data like in the current frontend tests.

This change contains Extbase TypoScript which will be activated
in a separate bugfixing change.

Resolves: #59521
Releases: 6.2
Change-Id: I42c0bf8957d9c4c1e4389049695512851b436d14
Reviewed-on: https://review.typo3.org/30687
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
67 files changed:
typo3/sysext/core/Tests/Functional/DataHandling/AbstractDataHandlerActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/FAL/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/Group/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/ManyToMany/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/Select/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Content.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Hotel.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Offer.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Price.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Repository/ContentRepository.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Service/QueueService.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/ExtensionBuilder/settings.yaml [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/constants.txt [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/setup.txt [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Layouts/Default.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/FormFields.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/Properties.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/FormErrors.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Edit.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/List.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/New.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Show.html [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_localconf.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_tables.php
typo3/sysext/core/Tests/Functional/Fixtures/Frontend/ExtbaseJsonRenderer.ts [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractStructureRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/DoesNotHaveRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/HasRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureDoesNotHaveRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureHasRecordConstraint.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Frontend/Collector.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Frontend/Parser.php [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Framework/Frontend/Renderer.php
typo3/sysext/core/Tests/Functional/Framework/Frontend/Response.php
typo3/sysext/core/Tests/Functional/Framework/Frontend/ResponseContent.php
typo3/sysext/core/Tests/Functional/Framework/Frontend/ResponseSection.php [new file with mode: 0644]
typo3/sysext/workspaces/Tests/Functional/DataHandling/FAL/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/FAL/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/FAL/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Group/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Group/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Group/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/CSV/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/CSV/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/CSV/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/ForeignField/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/IRRE/ForeignField/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/ManyToMany/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/ManyToMany/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/ManyToMany/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Select/Modify/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Select/Publish/ActionTest.php
typo3/sysext/workspaces/Tests/Functional/DataHandling/Select/PublishAll/ActionTest.php

index 28a5764..41858d7 100644 (file)
@@ -26,7 +26,6 @@ namespace TYPO3\CMS\Core\Tests\Functional\DataHandling;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Tests\Functional\DataHandling\Framework\DataSet;
-use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseContent;
 
 /**
  * Functional test for the DataHandler
@@ -349,194 +348,31 @@ abstract class AbstractDataHandlerActionTestCase extends \TYPO3\CMS\Core\Tests\F
        }
 
        /**
-        * @param ResponseContent $responseContent
-        * @param string $structureRecordIdentifier
-        * @param string $structureFieldName
-        * @param string $tableName
-        * @param string $fieldName
-        * @param bool $strict
-        * @param string|array $values
+        * @return \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\HasRecordConstraint
         */
-       protected function assertResponseContentStructureHasRecords(ResponseContent $responseContent, $structureRecordIdentifier, $structureFieldName, $tableName, $fieldName, $values, $strict = FALSE) {
-               $nonMatchingVariants = array();
-               $remainingRecordVariants = array();
-
-               foreach ($responseContent->findStructures($structureRecordIdentifier, $structureFieldName) as $path => $structure) {
-                       $remainingRecords = array();
-                       $nonMatchingValues = $this->getNonMatchingValuesFrontendResponseRecords($structure, $tableName, $fieldName, $values);
-
-                       if ($strict) {
-                               $remainingRecords = $this->getRemainingFrontendResponseRecords($structure, $tableName, $fieldName, $values);
-                       }
-
-                       if (empty($nonMatchingValues) && (!$strict || empty($remainingRecords))) {
-                               // Increase assertion counter
-                               $this->assertEmpty($nonMatchingValues);
-                               return;
-                       }
-
-                       if (!empty($nonMatchingValues)) {
-                               $nonMatchingVariants[$path] = $nonMatchingValues;
-                       }
-                       if ($strict && !empty($remainingRecords)) {
-                               $remainingRecordVariants[$path] = $remainingRecords;
-                       }
-               }
-
-               $failureMessage = '';
-
-               if (!empty($nonMatchingVariants)) {
-                       $failureMessage .= 'Could not assert all values for "' . $tableName . '.' . $fieldName . '"' . LF;
-                       foreach ($nonMatchingVariants as $path => $nonMatchingValues) {
-                               $failureMessage .= '* ' . $path . ': ' . implode(', ', $nonMatchingValues) . LF;
-                       }
-               }
-
-               if (!empty($remainingRecordVariants)) {
-                       $failureMessage .= 'Found remaining records for "' . $tableName . '.' . $fieldName . '"' . LF;
-                       foreach ($remainingRecordVariants as $path => $remainingRecords) {
-                               $failureMessage .= '* ' . $path . ': ' . implode(', ', array_keys($remainingRecords)) . LF;
-                       }
-               }
-
-               $this->fail($failureMessage);
+       protected function getRequestSectionHasRecordConstraint() {
+               return new \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\HasRecordConstraint();
        }
 
        /**
-        * @param ResponseContent $responseContent
-        * @param string $structureRecordIdentifier
-        * @param string $structureFieldName
-        * @param string $tableName
-        * @param string $fieldName
-        * @param string|array $values
+        * @return \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\DoesNotHaveRecordConstraint
         */
-       protected function assertResponseContentStructureDoesNotHaveRecords(ResponseContent $responseContent, $structureRecordIdentifier, $structureFieldName, $tableName, $fieldName, $values) {
-               if (is_string($values)) {
-                       $values = array($values);
-               }
-
-               $matchingVariants = array();
-
-               foreach ($responseContent->findStructures($structureRecordIdentifier, $structureFieldName) as $path => $structure) {
-                       $nonMatchingValues = $this->getNonMatchingValuesFrontendResponseRecords($structure, $tableName, $fieldName, $values);
-                       $matchingValues = array_diff($values, $nonMatchingValues);
-
-                       if (!empty($matchingValues)) {
-                               $matchingVariants[$path] = $matchingValues;
-                       }
-               }
-
-               if (empty($matchingVariants)) {
-                       // Increase assertion counter
-                       $this->assertEmpty($matchingVariants);
-                       return;
-               }
-
-               $matchingMessage = '';
-               foreach ($matchingVariants as $path => $matchingValues) {
-                       $matchingMessage .= '* ' . $path . ': ' . implode(', ', $matchingValues);
-               }
-
-               $this->fail('Could not assert not having values for "' . $tableName . '.' . $fieldName . '"' . LF . $matchingMessage);
+       protected function getRequestSectionDoesNotHaveRecordConstraint() {
+               return new \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\DoesNotHaveRecordConstraint();
        }
 
        /**
-        * @param ResponseContent $responseContent
-        * @param string $tableName
-        * @param string $fieldName
-        * @param string|array $values
+        * @return \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\StructureHasRecordConstraint
         */
-       protected function assertResponseContentHasRecords(ResponseContent $responseContent, $tableName, $fieldName, $values) {
-               $nonMatchingValues = $this->getNonMatchingValuesFrontendResponseRecords($responseContent->getRecords(), $tableName, $fieldName, $values);
-
-               if (!empty($nonMatchingValues)) {
-                       $this->fail('Could not assert all values for "' . $tableName . '.' . $fieldName . '": ' . implode(', ', $nonMatchingValues));
-               }
-
-               // Increase assertion counter
-               $this->assertEmpty($nonMatchingValues);
+       protected function getRequestSectionStructureHasRecordConstraint() {
+               return new \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\StructureHasRecordConstraint();
        }
 
        /**
-        * @param ResponseContent $responseContent
-        * @param string $tableName
-        * @param string $fieldName
-        * @param string|array $values
+        * @return \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\StructureDoesNotHaveRecordConstraint
         */
-       protected function assertResponseContentDoesNotHaveRecords(ResponseContent $responseContent, $tableName, $fieldName, $values) {
-               if (is_string($values)) {
-                       $values = array($values);
-               }
-
-               $nonMatchingValues = $this->getNonMatchingValuesFrontendResponseRecords($responseContent->getRecords(), $tableName, $fieldName, $values);
-               $matchingValues = array_diff($values, $nonMatchingValues);
-
-               if (!empty($matchingValues)) {
-                       $this->fail('Could not assert not having values for "' . $tableName . '.' . $fieldName . '": ' . implode(', ', $matchingValues));
-               }
-
-               // Increase assertion counter
-               $this->assertTrue(TRUE);
-       }
-
-       /**
-        * @param string|array $data
-        * @param string $tableName
-        * @param string $fieldName
-        * @param string|array $values
-        * @return array
-        */
-       protected function getNonMatchingValuesFrontendResponseRecords($data, $tableName, $fieldName, $values) {
-               if (empty($data) || !is_array($data)) {
-                       $this->fail('Frontend Response data does not have any records');
-               }
-
-               if (is_string($values)) {
-                       $values = array($values);
-               }
-
-               foreach ($data as $recordIdentifier => $recordData) {
-                       if (strpos($recordIdentifier, $tableName . ':') !== 0) {
-                               continue;
-                       }
-
-                       if (($foundValueIndex = array_search($recordData[$fieldName], $values)) !== FALSE) {
-                               unset($values[$foundValueIndex]);
-                       }
-               }
-
-               return $values;
-       }
-
-       /**
-        * @param string|array $data
-        * @param string $tableName
-        * @param string $fieldName
-        * @param string|array $values
-        * @return array
-        */
-       protected function getRemainingFrontendResponseRecords($data, $tableName, $fieldName, $values) {
-               if (empty($data) || !is_array($data)) {
-                       $this->fail('Frontend Response data does not have any records');
-               }
-
-               if (is_string($values)) {
-                       $values = array($values);
-               }
-
-               foreach ($data as $recordIdentifier => $recordData) {
-                       if (strpos($recordIdentifier, $tableName . ':') !== 0) {
-                               unset($data[$recordIdentifier]);
-                               continue;
-                       }
-
-                       if (($foundValueIndex = array_search($recordData[$fieldName], $values)) !== FALSE) {
-                               unset($values[$foundValueIndex]);
-                               unset($data[$recordIdentifier]);
-                       }
-               }
-
-               return $data;
+       protected function getRequestSectionStructureDoesNotHaveRecordConstraint() {
+               return new \TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection\StructureDoesNotHaveRecordConstraint();
        }
 
 }
index 9c30af7..3a87f3a 100644 (file)
@@ -48,12 +48,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::modifyContent();
                $this->assertAssertionDataSet('modifyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
        }
 
        /**
@@ -64,9 +64,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::deleteContent();
                $this->assertAssertionDataSet('deleteContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #1');
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -77,12 +79,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::copyContent();
                $this->assertAssertionDataSet('copyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2 (copy 1)');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2 (copy 1)'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
        }
 
        /**
@@ -93,15 +95,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::localizeContent();
                $this->assertAssertionDataSet('localizeContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
 
                // @todo Values in sys_file_reference are not copied during localization...
                /*
-                       $this->assertResponseContentStructureHasRecords(
-                               $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                               self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-                       );
+                       $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
                */
        }
 
@@ -113,16 +115,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::changeContentSorting();
                $this->assertAssertionDataSet('changeContentSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
        }
 
        /**
@@ -133,18 +134,18 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::moveContentToDifferentPage();
                $this->assertAssertionDataSet('moveContentToDifferentPage');
 
-               $responseContentSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentSource, self::TABLE_Content, 'header', 'Regular Element #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContentSource, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD')
-               );
-               $responseContentTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentTarget, self::TABLE_Content, 'header', 'Regular Element #2');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContentTarget, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-               );
+               $responseSectionsSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD'));
+               $responseSectionsTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
        }
 
        /**
@@ -155,16 +156,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::moveContentToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('moveContentToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD'));
        }
 
        /**
@@ -179,12 +179,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::createContentWithFileReference();
                $this->assertAssertionDataSet('createContentWFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'Image #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Image #1'));
        }
 
        /**
@@ -195,12 +195,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::modifyContentWithFileReference();
                $this->assertAssertionDataSet('modifyContentWFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'Image #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'Image #1'));
        }
 
        /**
@@ -211,11 +211,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::modifyContentAndAddFileReference();
                $this->assertAssertionDataSet('modifyContentNAddFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'This is Kasper', 'Image #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'This is Kasper', 'Image #3'));
        }
 
        /**
@@ -226,15 +225,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::modifyContentAndDeleteFileReference();
                $this->assertAssertionDataSet('modifyContentNDeleteFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'This is Kasper'
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'Taken at T3BOARD'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD'));
        }
 
        /**
@@ -245,11 +242,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\FAL\Abstr
                parent::modifyContentAndDeleteAllFileReference();
                $this->assertAssertionDataSet('modifyContentNDeleteAllFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'This is Kasper')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'This is Kasper'));
        }
 
 }
index 1772123..4503363 100644 (file)
@@ -48,11 +48,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::addElementRelation();
                $this->assertAssertionDataSet('addElementRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2', 'Element #3'));
        }
 
        /**
@@ -63,15 +62,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::deleteElementRelation();
                $this->assertAssertionDataSet('deleteElementRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -82,11 +79,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::changeElementSorting();
                $this->assertAssertionDataSet('changeElementSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2'));
        }
 
        /**
@@ -97,11 +93,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::changeElementRelationSorting();
                $this->assertAssertionDataSet('changeElementRelationSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2'));
        }
 
        /**
@@ -112,12 +107,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::createContentAndAddElementRelation();
                $this->assertAssertionDataSet('createContentNAddRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', 'Element #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
        }
 
        /**
@@ -128,12 +123,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::createContentAndCreateElementRelation();
                $this->assertAssertionDataSet('createContentNCreateRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', 'Testing #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -144,11 +139,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::modifyElementOfRelation();
                $this->assertAssertionDataSet('modifyElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Testing #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1', 'Element #2'));
        }
 
        /**
@@ -159,8 +153,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::modifyContentOfRelation();
                $this->assertAssertionDataSet('modifyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -171,12 +166,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::modifyBothSidesOfRelation();
                $this->assertAssertionDataSet('modifyBothSidesOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Testing #1', 'Element #2')
-               );
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1', 'Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -187,8 +182,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::deleteContentOfRelation();
                $this->assertAssertionDataSet('deleteContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -199,11 +195,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::deleteElementOfRelation();
                $this->assertAssertionDataSet('deleteElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
        }
 
        /**
@@ -214,12 +209,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::copyContentOfRelation();
                $this->assertAssertionDataSet('copyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
                // Referenced elements are not copied with the "parent", which is expected and correct
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -230,16 +224,14 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::copyElementOfRelation();
                $this->assertAssertionDataSet('copyElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
                // Referenced elements are not updated at the "parent", which is expected and correct
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1 (copy 1)')
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1 (copy 1)'));
        }
 
        /**
@@ -250,11 +242,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::localizeContentOfRelation();
                $this->assertAssertionDataSet('localizeContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -265,11 +256,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::localizeElementOfRelation();
                $this->assertAssertionDataSet('localizeElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('[Translate to Dansk:] Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('[Translate to Dansk:] Element #1', 'Element #2'));
        }
 
        /**
@@ -280,11 +270,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Group\Abs
                parent::moveContentOfRelationToDifferentPage();
                $this->assertAssertionDataSet('moveContentOfRelationToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
 }
index 2661f97..01e1b71 100644 (file)
@@ -48,8 +48,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::createParentContent();
                $this->assertAssertionDataSet('createParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -60,12 +61,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyParentContent();
                $this->assertAssertionDataSet('modifyParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -76,8 +77,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::deleteParentContent();
                $this->assertAssertionDataSet('deleteParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -88,11 +90,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::copyParentContent();
                $this->assertAssertionDataSet('copyParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -103,11 +104,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::copyParentContentToDifferentPage();
                $this->assertAssertionDataSet('copyParentContentToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -118,11 +118,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::localizeParentContentInKeepMode();
                $this->assertAssertionDataSet('localizeParentContentKeep');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -133,11 +132,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::localizeParentContentWithAllChildrenInKeepMode();
                $this->assertAssertionDataSet('localizeParentContentWAllChildrenKeep');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -148,11 +146,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::localizeParentContentInSelectMode();
                $this->assertAssertionDataSet('localizeParentContentSelect');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -163,11 +160,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::localizeParentContentWithAllChildrenInSelectMode();
                $this->assertAssertionDataSet('localizeParentContentWAllChildrenSelect');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -178,15 +174,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::changeParentContentSorting();
                $this->assertAssertionDataSet('changeParentContentSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -197,12 +191,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::moveParentContentToDifferentPage();
                $this->assertAssertionDataSet('moveParentContentToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -213,16 +207,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::moveParentContentToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('moveParentContentToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #2', 'Regular Element #1'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2', 'Regular Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -237,8 +230,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyPage();
                $this->assertAssertionDataSet('modifyPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -261,8 +255,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::copyPage();
                $this->assertAssertionDataSet('copyPage');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -273,8 +268,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::copyPageWithHotelBeforeParentContent();
                $this->assertAssertionDataSet('copyPageWHotelBeforeParentContent');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -289,12 +285,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::createParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -305,19 +301,16 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::createAndCopyParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createNCopyParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Hotel . ':' . $this->recordIds['copiedHotelId'], self::FIELD_HotelOffer,
-                       self::TABLE_Offer, 'title', 'Offer #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Hotel . ':' . $this->recordIds['copiedHotelId'])->setRecordField(self::FIELD_HotelOffer)
+                       ->setTable(self::TABLE_Offer)->setField('title')->setValues('Offer #1'));
        }
 
        /**
@@ -328,17 +321,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::createAndLocalizeParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createNLocalizeParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
                // Content record gets overlaid, thus using newContentId
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', '[Translate to Dansk:] Hotel #1'
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
                // Content record directly points to localized child, thus using localizedHotelId
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Hotel . ':' . $this->recordIds['localizedHotelId'], self::FIELD_HotelOffer,
-                       self::TABLE_Offer, 'title', '[Translate to Dansk:] Offer #1'
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Hotel . ':' . $this->recordIds['localizedHotelId'])->setRecordField(self::FIELD_HotelOffer)
+                       ->setTable(self::TABLE_Offer)->setField('title')->setValues('[Translate to Dansk:] Offer #1'));
        }
 
        /**
@@ -349,11 +340,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyOnlyHotelChild();
                $this->assertAssertionDataSet('modifyOnlyHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Testing #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Testing #1'));
        }
 
        /**
@@ -364,11 +354,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyParentAndChangeHotelChildrenSorting();
                $this->assertAssertionDataSet('modifyParentNChangeHotelChildrenSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #2', 'Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -379,11 +368,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyParentWithHotelChild();
                $this->assertAssertionDataSet('modifyParentNHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Testing #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Testing #1'));
        }
 
        /**
@@ -394,11 +382,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyParentAndAddHotelChild();
                $this->assertAssertionDataSet('modifyParentNAddHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
        }
 
        /**
@@ -409,15 +396,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
                parent::modifyParentAndDeleteHotelChild();
                $this->assertAssertionDataSet('modifyParentNDeleteHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #2'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #2'));
        }
 
 }
index 79c7e66..a97cebd 100644 (file)
@@ -59,7 +59,13 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
                $this->importScenarioDataSet('LiveDefaultPages');
                $this->importScenarioDataSet('LiveDefaultElements');
 
-               $this->setUpFrontendRootPage(1, array('typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts'));
+               $this->setUpFrontendRootPage(
+                       1,
+                       array(
+                               'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts',
+                               // 'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/ExtbaseJsonRenderer.ts',
+                       )
+               );
                $this->backendUser->workspace = 0;
        }
 
index 378b8a3..bf338f0 100644 (file)
@@ -48,8 +48,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::createParentContent();
                $this->assertAssertionDataSet('createParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -60,12 +61,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyParentContent();
                $this->assertAssertionDataSet('modifyParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -76,8 +77,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::deleteParentContent();
                $this->assertAssertionDataSet('deleteParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -88,11 +90,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::copyParentContent();
                $this->assertAssertionDataSet('copyParentContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -103,11 +104,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::copyParentContentToDifferentPage();
                $this->assertAssertionDataSet('copyParentContentToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -118,11 +118,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::localizeParentContentInKeepMode();
                $this->assertAssertionDataSet('localizeParentContentKeep');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -133,11 +132,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::localizeParentContentWithAllChildrenInKeepMode();
                $this->assertAssertionDataSet('localizeParentContentWAllChildrenKeep');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -148,11 +146,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::localizeParentContentInSelectMode();
                $this->assertAssertionDataSet('localizeParentContentSelect');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -163,11 +160,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::localizeParentContentWithAllChildrenInSelectMode();
                $this->assertAssertionDataSet('localizeParentContentWAllChildrenSelect');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('[Translate to Dansk:] Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
        }
 
        /**
@@ -178,15 +174,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::changeParentContentSorting();
                $this->assertAssertionDataSet('changeParentContentSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -197,12 +191,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::moveParentContentToDifferentPage();
                $this->assertAssertionDataSet('moveParentContentToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -213,16 +207,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::moveParentContentToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('moveParentContentToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #2', 'Regular Element #1'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2', 'Regular Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -237,8 +230,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyPage();
                $this->assertAssertionDataSet('modifyPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -261,8 +255,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::copyPage();
                $this->assertAssertionDataSet('copyPage');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -273,8 +268,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::copyPageWithHotelBeforeParentContent();
                $this->assertAssertionDataSet('copyPageWHotelBeforeParentContent');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -289,12 +285,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::createParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
        }
 
        /**
@@ -305,19 +301,16 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::createAndCopyParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createNCopyParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Hotel . ':' . $this->recordIds['copiedHotelId'], self::FIELD_HotelOffer,
-                       self::TABLE_Offer, 'title', 'Offer #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Hotel . ':' . $this->recordIds['copiedHotelId'])->setRecordField(self::FIELD_HotelOffer)
+                       ->setTable(self::TABLE_Offer)->setField('title')->setValues('Offer #1'));
        }
 
        /**
@@ -328,17 +321,15 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::createAndLocalizeParentContentWithHotelAndOfferChildren();
                $this->assertAssertionDataSet('createNLocalizeParentContentNHotelNOfferChildren');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
                // Content record gets overlaid, thus using newContentId
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', '[Translate to Dansk:] Hotel #1'
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1'));
                // Hotel record gets overlaid, thus using newHotelId
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Hotel . ':' . $this->recordIds['newHotelId'], self::FIELD_HotelOffer,
-                       self::TABLE_Offer, 'title', '[Translate to Dansk:] Offer #1'
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Hotel . ':' . $this->recordIds['newHotelId'])->setRecordField(self::FIELD_HotelOffer)
+                       ->setTable(self::TABLE_Offer)->setField('title')->setValues('[Translate to Dansk:] Offer #1'));
        }
 
        /**
@@ -349,11 +340,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyOnlyHotelChild();
                $this->assertAssertionDataSet('modifyOnlyHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Testing #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Testing #1'));
        }
 
        /**
@@ -364,11 +354,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyParentAndChangeHotelChildrenSorting();
                $this->assertAssertionDataSet('modifyParentNChangeHotelChildrenSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #2', 'Hotel #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #2', 'Hotel #1'));
        }
 
        /**
@@ -379,11 +368,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyParentWithHotelChild();
                $this->assertAssertionDataSet('modifyParentNHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Testing #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Testing #1'));
        }
 
        /**
@@ -394,11 +382,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyParentAndAddHotelChild();
                $this->assertAssertionDataSet('modifyParentNAddHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1', 'Hotel #2'));
        }
 
        /**
@@ -409,15 +396,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
                parent::modifyParentAndDeleteHotelChild();
                $this->assertAssertionDataSet('modifyParentNDeleteHotelChild');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #1'
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentHotel,
-                       self::TABLE_Hotel, 'title', 'Hotel #2'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
+                       ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #2'));
        }
 
 }
index 453131d..a70ad17 100644 (file)
@@ -48,11 +48,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::addCategoryRelation();
                $this->assertAssertionDataSet('addCategoryRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category A', 'Category B', 'Category A.A')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A', 'Category B', 'Category A.A'));
        }
 
        /**
@@ -63,15 +62,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::deleteCategoryRelation();
                $this->assertAssertionDataSet('deleteCategoryRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category A')
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category B', 'Category C', 'Category A.A')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category B', 'Category C', 'Category A.A'));
        }
 
        /**
@@ -82,11 +79,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::changeCategoryRelationSorting();
                $this->assertAssertionDataSet('changeCategoryRelationSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category A', 'Category B')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A', 'Category B'));
        }
 
        /**
@@ -97,11 +93,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::modifyCategoryOfRelation();
                $this->assertAssertionDataSet('modifyCategoryOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Testing #1', 'Category B')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Testing #1', 'Category B'));
        }
 
        /**
@@ -112,8 +107,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::modifyContentOfRelation();
                $this->assertAssertionDataSet('modifyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -124,12 +120,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::modifyBothsOfRelation();
                $this->assertAssertionDataSet('modifyBothsOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Testing #1', 'Category B')
-               );
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Testing #1', 'Category B'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -140,8 +136,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::deleteContentOfRelation();
                $this->assertAssertionDataSet('deleteContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -152,11 +149,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::deleteCategoryOfRelation();
                $this->assertAssertionDataSet('deleteCategoryOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category A')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A'));
        }
 
        /**
@@ -167,11 +163,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::copyContentOfRelation();
                $this->assertAssertionDataSet('copyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], 'categories',
-                       self::TABLE_Category, 'title', array('Category B', 'Category C')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category B', 'Category C'));
        }
 
        /**
@@ -182,11 +177,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::copyCategoryOfRelation();
                $this->assertAssertionDataSet('copyCategoryOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('Category A', 'Category A (copy 1)')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A', 'Category A (copy 1)'));
        }
 
        /**
@@ -197,11 +191,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::localizeContentOfRelation();
                $this->assertAssertionDataSet('localizeContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, 'categories',
-                       self::TABLE_Category, 'title', array('Category B', 'Category C')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category B', 'Category C'));
        }
 
        /**
@@ -212,11 +205,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::localizeCategoryOfRelation();
                $this->assertAssertionDataSet('localizeCategoryOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, 'categories',
-                       self::TABLE_Category, 'title', array('[Translate to Dansk:] Category A', 'Category B')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('[Translate to Dansk:] Category A', 'Category B'));
        }
 
        /**
@@ -227,11 +219,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::moveContentOfRelationToDifferentPage();
                $this->assertAssertionDataSet('moveContentOfRelationToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, 'categories',
-                       self::TABLE_Category, 'title', array('Category B', 'Category C')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category B', 'Category C'));
        }
 
        /**
@@ -242,17 +233,17 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\ManyToMan
                parent::copyPage();
                $this->assertAssertionDataSet('copyPage');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Relations');
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentIdFirst'], 'categories',
-                       self::TABLE_Category, 'title', array('Category A', 'Category B')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentIdLast'], 'categories',
-                       self::TABLE_Category, 'title', array('Category B', 'Category C')
-               );
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Relations'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentIdFirst'])->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category A', 'Category B'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentIdLast'])->setRecordField('categories')
+                       ->setTable(self::TABLE_Category)->setField('title')->setValues('Category B', 'Category C'));
        }
 
 }
index 520c6cb..f561aca 100644 (file)
@@ -48,8 +48,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::createContents();
                $this->assertAssertionDataSet('createContents');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Testing #1', 'Testing #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1', 'Testing #2'));
        }
 
        /**
@@ -60,8 +61,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::modifyContent();
                $this->assertAssertionDataSet('modifyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -72,9 +74,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::deleteContent();
                $this->assertAssertionDataSet('deleteContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #1');
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -85,8 +89,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::copyContent();
                $this->assertAssertionDataSet('copyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2 (copy 1)');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2 (copy 1)'));
        }
 
        /**
@@ -97,8 +102,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::copyPasteContent();
                $this->assertAssertionDataSet('copyPasteContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -109,8 +115,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::localizeContent();
                $this->assertAssertionDataSet('localizeContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
        }
 
        /**
@@ -121,8 +128,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::changeContentSorting();
                $this->assertAssertionDataSet('changeContentSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
        }
 
        /**
@@ -133,10 +141,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::moveContentToDifferentPage();
                $this->assertAssertionDataSet('moveContentToDifferentPage');
 
-               $responseContentSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentSource, self::TABLE_Content, 'header', 'Regular Element #1');
-               $responseContentTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentTarget, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSectionsSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $responseSectionsTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -147,10 +157,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::movePasteContentToDifferentPage();
                $this->assertAssertionDataSet('movePasteContentToDifferentPage');
 
-               $responseContentSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentSource, self::TABLE_Content, 'header', 'Regular Element #1');
-               $responseContentTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentTarget, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSectionsSource = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $responseSectionsTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -161,8 +173,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::moveContentToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('moveContentToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
        }
 
        /**
@@ -177,8 +190,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::createPage();
                $this->assertAssertionDataSet('createPage');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Testing #1');
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -189,8 +203,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::modifyPage();
                $this->assertAssertionDataSet('modifyPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -213,8 +228,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::copyPage();
                $this->assertAssertionDataSet('copyPage');
 
-               $responseContent = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Relations');
+               $responseSections = $this->getFrontendResponse($this->recordIds['newPageId'])->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Relations'));
        }
 
        /**
@@ -225,8 +241,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::localizePage();
                $this->assertAssertionDataSet('localizePage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', '[Translate to Dansk:] Relations');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('[Translate to Dansk:] Relations'));
        }
 
        /**
@@ -237,9 +254,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::changePageSorting();
                $this->assertAssertionDataSet('changePageSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Relations');
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Relations'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
        }
 
        /**
@@ -250,9 +269,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::movePageToDifferentPage();
                $this->assertAssertionDataSet('movePageToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Relations');
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Relations'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
        }
 
        /**
@@ -263,9 +284,11 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Regular\A
                parent::movePageToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('movePageToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Page, 'title', 'Relations');
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Page)->setField('title')->setValues('Relations'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
        }
 
 }
index 3d0a7d9..7184eff 100644 (file)
@@ -48,11 +48,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::addElementRelation();
                $this->assertAssertionDataSet('addElementRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2', 'Element #3'));
        }
 
        /**
@@ -63,15 +62,13 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::deleteElementRelation();
                $this->assertAssertionDataSet('deleteElementRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -82,11 +79,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::changeElementSorting();
                $this->assertAssertionDataSet('changeElementSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2'));
        }
 
        /**
@@ -97,11 +93,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::changeElementRelationSorting();
                $this->assertAssertionDataSet('changeElementRelationSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1', 'Element #2'));
        }
 
        /**
@@ -112,12 +107,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::createContentAndAddElementRelation();
                $this->assertAssertionDataSet('createContentNAddRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', 'Element #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
        }
 
        /**
@@ -128,12 +123,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::createContentAndCreateElementRelation();
                $this->assertAssertionDataSet('createContentNCreateRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', 'Testing #1'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1'));
        }
 
        /**
@@ -144,11 +139,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::modifyElementOfRelation();
                $this->assertAssertionDataSet('modifyElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Testing #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1', 'Element #2'));
        }
 
        /**
@@ -159,8 +153,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::modifyContentOfRelation();
                $this->assertAssertionDataSet('modifyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -171,12 +166,12 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::modifyBothSidesOfRelation();
                $this->assertAssertionDataSet('modifyBothSidesOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Testing #1', 'Element #2')
-               );
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Testing #1', 'Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -187,8 +182,9 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::deleteContentOfRelation();
                $this->assertAssertionDataSet('deleteContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
        }
 
        /**
@@ -199,11 +195,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::deleteElementOfRelation();
                $this->assertAssertionDataSet('deleteElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
        }
 
        /**
@@ -214,11 +209,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::copyContentOfRelation();
                $this->assertAssertionDataSet('copyContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -229,16 +223,14 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::copyElementOfRelation();
                $this->assertAssertionDataSet('copyElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1'));
                // Referenced elements are not updated at the "parent", which is expected and correct
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #1 (copy 1)')
-               );
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #1 (copy 1)'));
        }
 
        /**
@@ -249,11 +241,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::localizeContentOfRelation();
                $this->assertAssertionDataSet('localizeContentOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
        /**
@@ -264,11 +255,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::localizeElementOfRelation();
                $this->assertAssertionDataSet('localizeElementOfRelation');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('[Translate to Dansk:] Element #1', 'Element #2')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('[Translate to Dansk:] Element #1', 'Element #2'));
        }
 
        /**
@@ -279,11 +269,10 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\Select\Ab
                parent::moveContentOfRelationToDifferentPage();
                $this->assertAssertionDataSet('moveContentOfRelationToDifferentPage');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentElement,
-                       self::TABLE_Element, 'title', array('Element #2', 'Element #3')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
+                       ->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
        }
 
 }
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php
new file mode 100644 (file)
index 0000000..3e426cb
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+namespace OliverHader\IrreTutorial\Controller;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * ContentController
+ */
+abstract class AbstractController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
+
+       /**
+        * @inject
+        * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
+        */
+       protected $dataMapFactory;
+
+       /**
+        * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
+        * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response
+        * @throws \RuntimeException
+        */
+       public function processRequest(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request, \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response) {
+               try {
+                       parent::processRequest($request, $response);
+               } catch (\TYPO3\CMS\Extbase\Property\Exception $exception) {
+                       throw new \RuntimeException(
+                               $this->getRuntimeIdentifier() . ': ' . $exception->getMessage() . ' (' . $exception->getCode() . ')'
+                       );
+               }
+       }
+
+       /**
+        * @param \Iterator|\TYPO3\CMS\Extbase\DomainObject\AbstractEntity[] $iterator
+        * @return array
+        */
+       protected function getStructure($iterator) {
+               $structure = array();
+
+               if (!$iterator instanceof \Iterator) {
+                       $iterator = array($iterator);
+               }
+
+               foreach ($iterator as $entity) {
+                       $tableName = $this->dataMapFactory->buildDataMap(get_class($entity))->getTableName();
+                       $identifier = $tableName . ':' . $entity->getUid();
+                       $structureItem = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettableProperties($entity);
+                       foreach ($structureItem as $propertyName => $propertyValue) {
+                               if ($propertyValue instanceof \Iterator) {
+                                       $structureItem[$propertyName] = $this->getStructure($propertyValue);
+                               }
+                       }
+                       $structure[$identifier] = $structureItem;
+               }
+
+               return $structure;
+       }
+
+       /**
+        * @param mixed $value
+        */
+       protected function process($value) {
+               if ($this->getQueueService()->isActive()) {
+                       $this->getQueueService()->addValue($this->getRuntimeIdentifier(), $value);
+                       $this->forward('process', 'Queue');
+               }
+               $this->view->assign('value', $value);
+       }
+
+       /**
+        * @return string
+        */
+       protected function getRuntimeIdentifier() {
+               $arguments = array();
+               foreach ($this->request->getArguments() as $argumentName => $argumentValue) {
+                       $arguments[] = $argumentName . '=' . $argumentValue;
+               }
+               return $this->request->getControllerActionName() . '(' . implode(', ', $arguments) . ')';
+       }
+
+       /**
+        * @return \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
+        */
+       protected function getPersistenceManager() {
+               return $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\PersistenceManagerInterface');
+       }
+
+       /**
+        * @return \OliverHader\IrreTutorial\Service\QueueService
+        */
+       protected function getQueueService() {
+               return $this->objectManager->get('OliverHader\\IrreTutorial\\Service\\QueueService');
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php
new file mode 100644 (file)
index 0000000..3c8126f
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+namespace OliverHader\IrreTutorial\Controller;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * ContentController
+ */
+class ContentController extends AbstractController {
+
+       /**
+        * @inject
+        * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
+        */
+       protected $contentRepository;
+
+       /**
+        * @var string
+        */
+       protected $defaultViewObjectName = 'TYPO3\\CMS\\Extbase\\Mvc\\View\\JsonView';
+
+       /**
+        * @return void
+        */
+       public function listAction() {
+               $contents = $this->contentRepository->findAll();
+               $value = $this->getStructure($contents);
+               $this->process($value);
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $content
+        * @return void
+        */
+       public function showAction(\OliverHader\IrreTutorial\Domain\Model\Content $content) {
+               $value = $this->getStructure($content);
+               $this->process($value);
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $newContent
+        * @ignorevalidation $newContent
+        * @return void
+        */
+       public function newAction(\OliverHader\IrreTutorial\Domain\Model\Content $newContent = NULL) {
+               $this->view->assign('newContent', $newContent);
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $newContent
+        * @return void
+        */
+       public function createAction(\OliverHader\IrreTutorial\Domain\Model\Content $newContent) {
+               $this->contentRepository->add($newContent);
+               $this->redirect('list');
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $content
+        * @ignorevalidation $content
+        * @return void
+        */
+       public function editAction(\OliverHader\IrreTutorial\Domain\Model\Content $content) {
+               $this->view->assign('content', $content);
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $content
+        * @return void
+        */
+       public function updateAction(\OliverHader\IrreTutorial\Domain\Model\Content $content) {
+               $this->contentRepository->update($content);
+               $this->redirect('list');
+       }
+
+       /**
+        * @param \OliverHader\IrreTutorial\Domain\Model\Content $content
+        * @return void
+        */
+       public function deleteAction(\OliverHader\IrreTutorial\Domain\Model\Content $content) {
+               $this->contentRepository->remove($content);
+               $this->redirect('list');
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
new file mode 100644 (file)
index 0000000..f34018e
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+namespace OliverHader\IrreTutorial\Controller;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * ContentController
+ */
+class QueueController extends AbstractController {
+
+       /**
+        * @inject
+        * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
+        */
+       protected $contentRepository;
+
+       /**
+        * @var string
+        */
+       protected $defaultViewObjectName = 'TYPO3\\CMS\\Extbase\\Mvc\\View\\JsonView';
+
+       /**
+        * @return void
+        */
+       public function indexAction() {
+               $calls = array();
+               $calls[] = array('Content', 'list');
+               $contents = $this->contentRepository->findAll();
+               foreach ($contents as $content) {
+                       $uid = $content->getUid();
+                       $calls[] = array('Content', 'show', array('content' => (string)$uid));
+               }
+               $this->getQueueService()->set($calls);
+               $this->forward('process');
+       }
+
+       /**
+        * @return void
+        */
+       public function processAction() {
+               $call = $this->getQueueService()->shift();
+               if ($call === NULL) {
+                       $this->forward('finish');
+               }
+               // Clear these states and fetch fresh entities!
+               $this->getPersistenceManager()->clearState();
+               $this->forward($call[1], $call[0], NULL, isset($call[2]) ? $call[2] : NULL);
+       }
+
+       public function finishAction() {
+               $this->request->setDispatched(TRUE);
+               $value = $this->getQueueService()->getValues();
+               $this->view->assign('value', $value);
+       }
+
+       /**
+        * Finds and instanciates a controller that matches the current request.
+        * If no controller can be found, an instance of NotFoundControllerInterface is returned.
+        *
+        * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request to dispatch
+        * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerException
+        * @return \TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface
+        */
+       protected function resolveController(\TYPO3\CMS\Extbase\Mvc\RequestInterface $request) {
+               $controllerObjectName = $request->getControllerObjectName();
+               $controller = $this->objectManager->get($controllerObjectName);
+               if (!$controller instanceof \TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface) {
+                       throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerException('Invalid controller "' . $request->getControllerObjectName() . '". The controller must implement the TYPO3\\CMS\\Extbase\\Mvc\\Controller\\ControllerInterface.', 1202921619);
+               }
+               return $controller;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Content.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Content.php
new file mode 100644 (file)
index 0000000..263b3cf
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+namespace OliverHader\IrreTutorial\Domain\Model;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Content
+ */
+class Content extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $header = '';
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Hotel>
+        */
+       protected $hotels = NULL;
+
+       /**
+        * Initializes this object.
+        */
+       public function __construct() {
+               $this->hotels = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+       }
+
+       /**
+        * @return string $header
+        */
+       public function getHeader() {
+               return $this->header;
+       }
+
+       /**
+        * @param string $header
+        * @return void
+        */
+       public function setHeader($header) {
+               $this->header = $header;
+       }
+
+       /**
+        * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Hotel>
+        */
+       public function getHotels() {
+               return $this->hotels;
+       }
+
+       /**
+        * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Hotel> $hotels
+        * @return void
+        */
+       public function setHotels(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $hotels) {
+               $this->hotels = $hotels;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Hotel.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Hotel.php
new file mode 100644 (file)
index 0000000..a16e62e
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+namespace OliverHader\IrreTutorial\Domain\Model;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Hotel
+ */
+class Hotel extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $title = '';
+
+       /**
+        * @lazy
+        * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer>
+        */
+       protected $offers = NULL;
+
+       /**
+        * Initializes this object.
+        */
+       public function __construct() {
+               $this->offers = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+       }
+
+       /**
+        * @return string $title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * @param string $title
+        * @return void
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+       }
+
+       /**
+        * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer>
+        */
+       public function getOffers() {
+               return $this->offers;
+       }
+
+       /**
+        * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer> $offers
+        * @return void
+        */
+       public function setOffers(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $offers) {
+               $this->offers = $offers;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Offer.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Offer.php
new file mode 100644 (file)
index 0000000..8d7667f
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+namespace OliverHader\IrreTutorial\Domain\Model;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Offer
+ */
+class Offer extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $title = '';
+
+       /**
+        * @lazy
+        * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer>
+        */
+       protected $prices = NULL;
+
+       /**
+        * Initializes this object.
+        */
+       public function __construct() {
+               $this->prices = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
+       }
+
+       /**
+        * @return string $title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * @param string $title
+        * @return void
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+       }
+
+       /**
+        * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer>
+        */
+       public function getPrices() {
+               return $this->prices;
+       }
+
+       /**
+        * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\OliverHader\IrreTutorial\Domain\Model\Offer> $prices
+        * @return void
+        */
+       public function setPrices(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $prices) {
+               $this->prices = $prices;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Price.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Model/Price.php
new file mode 100644 (file)
index 0000000..28a7f49
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+namespace OliverHader\IrreTutorial\Domain\Model;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Price
+ */
+class Price extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $title = '';
+
+       /**
+        * @var float
+        */
+       protected $price = 0.0;
+
+       /**
+        * @return string $title
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * @param string $title
+        * @return void
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+       }
+
+       /**
+        * @return float $price
+        */
+       public function getPrice() {
+               return $this->price;
+       }
+
+       /**
+        * @param float $price
+        * @return void
+        */
+       public function setPrice($price) {
+               $this->price = $price;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Repository/ContentRepository.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Domain/Repository/ContentRepository.php
new file mode 100644 (file)
index 0000000..617e6a7
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+namespace OliverHader\IrreTutorial\Domain\Repository;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Content Repository
+ */
+class ContentRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
+
+       /**
+        * @var array
+        */
+       protected $defaultOrderings = array(
+               'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
+       );
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Service/QueueService.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Service/QueueService.php
new file mode 100644 (file)
index 0000000..e96d9a1
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+namespace OliverHader\IrreTutorial\Service;
+
+/***************************************************************
+ *
+ *  Copyright notice
+ *
+ *  (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * ContentController
+ */
+class QueueService implements \TYPO3\CMS\Core\SingletonInterface {
+
+       /**
+        * @var array
+        */
+       protected $calls;
+
+       /**
+        * @var array
+        */
+       protected $values = array();
+
+       /**
+        * @var bool
+        */
+       protected $active = FALSE;
+
+       /**
+        * @param array $calls
+        */
+       public function set(array $calls) {
+               $this->calls = $calls;
+               $this->active = TRUE;
+       }
+
+       /**
+        * @return array
+        */
+       public function get() {
+               return $this->calls;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isActive() {
+               return $this->active;
+       }
+
+       public function setActive($active = TRUE) {
+               $this->active = (bool)$active;
+       }
+
+       /**
+        * @return NULL|array
+        */
+       public function shift() {
+               return array_shift($this->calls);
+       }
+
+       /**
+        * @param string $identifier
+        * @param mixed $value
+        */
+       public function addValue($identifier, $value) {
+               $this->values[$identifier] = $value;
+       }
+
+       /**
+        * @return array
+        */
+       public function getValues() {
+               return $this->values;
+       }
+
+}
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/ExtensionBuilder/settings.yaml b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/ExtensionBuilder/settings.yaml
new file mode 100644 (file)
index 0000000..9c1e02f
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# Extension Builder settings for extension irre_tutorial
+# generated 2014-06-06T11:22:00Z
+#
+# See http://www.yaml.org/spec/1.2/spec.html
+#
+
+---
+
+###########    Overwrite settings  ###########
+#
+# These settings only apply, if the roundtrip feature of the extension builder
+# is enabled in the extension manager
+#
+# Usage:
+# nesting reflects the file structure
+# a setting applies to a file or recursive to all files and subfolders
+#
+# merge:
+#   means for classes: All properties ,methods and method bodies
+#   of the existing class will be modified according to the new settings
+#   but not overwritten
+#
+#   for locallang xlf files: Existing keys and labels are always
+#   preserved (renaming a property or DomainObject will result in new keys and new labels)
+#
+#   for other files: You will find a Split token at the end of the file
+#   After this token you can write whatever you want and it will be appended
+#   everytime the code is generated
+#
+# keep:
+#   files are never overwritten
+#   These settings may break the functionality of the extension builder!
+#   Handle with care!
+#
+#
+
+############  extension settings  ##############
+
+overwriteSettings:
+  Classes:
+    Controller: merge
+    Domain:
+      Model: merge
+      Repository: merge
+
+  Configuration:
+    #TCA: merge
+    #TypoScript: keep
+
+  Resources:
+    Private:
+      #Language: merge
+      #Templates: keep
+
+  ext_icon.gif: keep
+
+#  ext_localconf.php: merge
+
+#  ext_tables.php: merge
+
+#  ext_tables.sql: merge
+
+## use static date attribute in xliff files ##
+#staticDateInXliffFiles: 2014-06-06T11:22:00Z
+
+## list of error codes for warnings that should be ignored ##
+#ignoreWarnings:
+  #503
+
+######### settings for classBuilder #############################
+#
+# here you may define default parent classes for your classes
+# these settings only apply for new generated classes
+# you may also just change the parent class in the generated class file.
+# It will be kept on next code generation, if the overwrite settings
+# are configured to merge it
+#
+#################################################################
+
+classBuilder:
+
+  Controller:
+    parentClass: \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+
+  Model:
+    AbstractEntity:
+      parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+
+    AbstractValueObject:
+      parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
+
+  Repository:
+    parentClass: \TYPO3\CMS\Extbase\Persistence\Repository
+
+  setDefaultValuesForClassProperties: true
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/constants.txt b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/constants.txt
new file mode 100644 (file)
index 0000000..15a2cbb
--- /dev/null
@@ -0,0 +1,15 @@
+
+plugin.tx_irretutorial {
+       view {
+               # cat=plugin.tx_irretutorial/file; type=string; label=Path to template root (FE)
+               templateRootPath = EXT:irre_tutorial/Resources/Private/Templates/
+               # cat=plugin.tx_irretutorial/file; type=string; label=Path to template partials (FE)
+               partialRootPath = EXT:irre_tutorial/Resources/Private/Partials/
+               # cat=plugin.tx_irretutorial/file; type=string; label=Path to template layouts (FE)
+               layoutRootPath = EXT:irre_tutorial/Resources/Private/Layouts/
+       }
+       persistence {
+               # cat=plugin.tx_irretutorial//a; type=string; label=Default storage PID
+               storagePid =
+       }
+}
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/setup.txt b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TypoScript/setup.txt
new file mode 100644 (file)
index 0000000..7bd2912
--- /dev/null
@@ -0,0 +1,71 @@
+plugin.tx_irretutorial {
+       view {
+               templateRootPath = {$plugin.tx_irretutorial.view.templateRootPath}
+               partialRootPath = {$plugin.tx_irretutorial.view.partialRootPath}
+               layoutRootPath = {$plugin.tx_irretutorial.view.layoutRootPath}
+       }
+       persistence {
+               storagePid.data = page:uid
+               classes {
+                       OliverHader\IrreTutorial\Domain\Model\Content {
+                               mapping {
+                                       tableName = tt_content
+                                       columns {
+                                               tx_irretutorial_1nff_hotels.mapOnProperty = hotels
+                                       }
+                               }
+                       }
+                       OliverHader\IrreTutorial\Domain\Model\Hotel {
+                               mapping {
+                                       tableName = tx_irretutorial_1nff_hotel
+                               }
+                       }
+                       OliverHader\IrreTutorial\Domain\Model\Offer {
+                               mapping {
+                                       tableName = tx_irretutorial_1nff_offer
+                               }
+                       }
+                       OliverHader\IrreTutorial\Domain\Model\Price {
+                               mapping {
+                                       tableName = tx_irretutorial_1nff_price
+                               }
+                       }
+               }
+       }
+       features {
+               rewrittenPropertyMapper = 1
+       }
+}
+
+plugin.tx_irretutorial._CSS_DEFAULT_STYLE (
+       textarea.f3-form-error {
+               background-color:#FF9F9F;
+               border: 1px #FF0000 solid;
+       }
+
+       input.f3-form-error {
+               background-color:#FF9F9F;
+               border: 1px #FF0000 solid;
+       }
+
+       .tx-irre-tutorial table {
+               border-collapse:separate;
+               border-spacing:10px;
+       }
+
+       .tx-irre-tutorial table th {
+               font-weight:bold;
+       }
+
+       .tx-irre-tutorial table td {
+               vertical-align:top;
+       }
+
+       .typo3-messages .message-error {
+               color:red;
+       }
+
+       .typo3-messages .message-ok {
+               color:green;
+       }
+)
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Layouts/Default.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Layouts/Default.html
new file mode 100644 (file)
index 0000000..90a5e68
--- /dev/null
@@ -0,0 +1,4 @@
+
+<div class="tx-irre-tutorial">
+       <f:render section="main" />
+</div>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/FormFields.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/FormFields.html
new file mode 100644 (file)
index 0000000..70f41ec
--- /dev/null
@@ -0,0 +1,5 @@
+
+<label for="header">
+       <f:translate key="tx_irretutorial_domain_model_content.header" />
+</label><br />
+       <f:form.textfield property="header" /><br />
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/Properties.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/Content/Properties.html
new file mode 100644 (file)
index 0000000..254ec6b
--- /dev/null
@@ -0,0 +1,11 @@
+
+<table class="tx-irre-tutorial" >
+       <tr>
+               <td>
+                       <f:translate key="tx_irretutorial_domain_model_content.header" />
+               </td>
+               <td>
+               {content.header}
+               </td>
+       </tr>
+</table>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/FormErrors.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Partials/FormErrors.html
new file mode 100644 (file)
index 0000000..bdf280a
--- /dev/null
@@ -0,0 +1,13 @@
+
+<f:form.validationResults for="{object}">
+       <f:if condition="{validationResults.flattenedErrors}">
+               <ul>
+               <f:for each="{validationResults.flattenedErrors}" key="propertyPath" as="errors">
+                       <li>
+                       {propertyPath}: <ul>
+                               <f:for each="{errors}" as="error"><li>{error}</li></f:for>
+                               </ul>
+                       </li>
+               </f:for></ul>
+</f:if>
+</f:form.validationResults>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Edit.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Edit.html
new file mode 100644 (file)
index 0000000..bb2d188
--- /dev/null
@@ -0,0 +1,26 @@
+
+<f:layout name="Default" />
+
+This template displays a EDIT form for the current domain object.
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        Edit.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="main">
+<h1>Edit Content</h1>
+
+<f:flashMessages renderMode="div" />
+
+<f:render partial="FormErrors" arguments="{object:Content}" />
+
+<f:form action="update" name="content" object="{content}" >
+<f:render partial="Content/FormFields" arguments="{content:content}" />
+       <f:form.submit value="Save" />
+</f:form>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/List.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/List.html
new file mode 100644 (file)
index 0000000..bcba1b1
--- /dev/null
@@ -0,0 +1,37 @@
+
+<f:layout name="Default" />
+
+This Template is responsible for creating a table of domain objects.
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        List.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="main">
+<h1>Listing for Content</h1>
+
+<f:flashMessages renderMode="div" />
+
+<table  class="tx_irretutorial" >
+       <tr>
+               <th><f:translate key="tx_irretutorial_domain_model_content.header" /></th>
+               <th> </th>
+               <th> </th>
+       </tr>
+
+       <f:for each="{contents}" as="content">
+               <tr>
+                       <td><f:link.action action="show" arguments="{content : content}"> {content.header}</f:link.action></td>
+                       <td><f:link.action action="edit" arguments="{content : content}">Edit</f:link.action></td>
+                       <td><f:link.action action="delete" arguments="{content : content}">Delete</f:link.action></td>
+               </tr>
+       </f:for>
+</table>
+
+<f:link.action action="new">New Content</f:link.action>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/New.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/New.html
new file mode 100644 (file)
index 0000000..64f19c6
--- /dev/null
@@ -0,0 +1,26 @@
+
+<f:layout name="Default" />
+
+This template displays a NEW form for the current domain object.
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        New.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="main">
+<h1>New Content</h1>
+
+<f:flashMessages renderMode="div" />
+
+<f:render partial="FormErrors" arguments="{object:Content}" />
+
+<f:form action="create"  name="newContent" object="{newContent}">
+<f:render partial="Content/FormFields" />
+       <f:form.submit value="Create new" />
+</f:form>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Show.html b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Show.html
new file mode 100644 (file)
index 0000000..dfb338e
--- /dev/null
@@ -0,0 +1,23 @@
+
+<f:layout name="Default" />
+
+This Template is responsible for displaying a single view for a domain object
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        Show.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="main">
+<h1>Single View for Content</h1>
+<f:debug>{content}</f:debug>
+
+<f:flashMessages renderMode="div" />
+<f:render partial="Content/Properties" arguments="{content:content}" />
+<f:link.action action="list">Back to list</f:link.action><br />
+<f:link.action action="new">New Content</f:link.action>
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_localconf.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_localconf.php
new file mode 100644 (file)
index 0000000..ed5ce42
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die('Access denied.');
+}
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+       'OliverHader.' . $_EXTKEY, 'Irre',
+       array(
+               'Queue' => 'index',
+               'Content' => 'list, show, new, create, edit, update, delete'
+       ),
+       array(
+               'Content' => 'create, update, delete'
+       )
+);
index fb32a0f..6b3a8b5 100644 (file)
@@ -1,5 +1,10 @@
 <?php
-if (!defined ('TYPO3_MODE'))   die ('Access denied.');
+if (!defined ('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin($_EXTKEY, 'Irre', 'IRRE');
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'IRRE Tutorial');
 
        // ext_tables.php is split to each single part of application
 require(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY)).'Configuration/ExtTables/ext_tables.general.php';
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Frontend/ExtbaseJsonRenderer.ts b/typo3/sysext/core/Tests/Functional/Fixtures/Frontend/ExtbaseJsonRenderer.ts
new file mode 100644 (file)
index 0000000..8c301ec
--- /dev/null
@@ -0,0 +1,16 @@
+<INCLUDE_TYPOSCRIPT: source="FILE:EXT:irre_tutorial/Configuration/TypoScript/setup.txt">
+
+page {
+       20 = COA
+       20 {
+               10 = USER
+               10 {
+                       userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
+                       extensionName = IrreTutorial
+                       pluginName = Irre
+                       vendorName = OliverHader
+               }
+               stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->parseValues
+               stdWrap.postUserFunc.as = Extbase
+       }
+}
\ No newline at end of file
index d74e7c0..d7a4017 100644 (file)
@@ -33,7 +33,7 @@ lib.watcherDataObject {
        1 = LOAD_REGISTER
        1.watcher.dataWrap = |
        2 = USER
-       2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->addRecordData
+       2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->addRecordData
        99 = RESTORE_REGISTER
 }
 
@@ -42,184 +42,189 @@ lib.watcherFileObject {
        1 = LOAD_REGISTER
        1.watcher.dataWrap = |
        2 = USER
-       2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->addFileData
+       2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->addFileData
        99 = RESTORE_REGISTER
 }
 
 page = PAGE
 page {
-       1 = LOAD_REGISTER
-       1.watcher.dataWrap = pages:{field:uid}
-       2 = USER
-       2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->addRecordData
-       10 = CONTENT
+       10 = COA
        10 {
-               stdWrap.required = 1
-               table = pages
-               select {
-                       orderBy = sorting
-                       pidInList = this
-               }
-               renderObj < lib.watcherDataObject
-               renderObj.1.watcher.dataWrap = {register:watcher}|.__pages/pages:{field:uid}
-       }
-       20 = CONTENT
-       20 {
-               table = tt_content
-               select {
-                       orderBy = sorting
-                       where = colPos=0
-                       languageField = sys_language_uid
+               1 = LOAD_REGISTER
+               1.watcher.dataWrap = pages:{field:uid}
+               2 = USER
+               2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->addRecordData
+               10 = CONTENT
+               10 {
+                       stdWrap.required = 1
+                       table = pages
+                       select {
+                               orderBy = sorting
+                               pidInList = this
+                       }
+                       renderObj < lib.watcherDataObject
+                       renderObj.1.watcher.dataWrap = {register:watcher}|.__pages/pages:{field:uid}
                }
-               renderObj < lib.watcherDataObject
-               renderObj.1.watcher.dataWrap = {register:watcher}|.__contents/tt_content:{field:uid}
-               renderObj {
-                       10 = CONTENT
-                       10 {
-                               if.isTrue.field = categories
-                               table = sys_category
-                               select {
-                                       pidInList = root,-1
-                                       selectFields = sys_category.*
-                                       join = sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid
-                                       where.data = field:_ORIG_uid // field:uid
-                                       where.intval = 1
-                                       where.wrap = sys_category_record_mm.uid_foreign=|
-                                       orderBy = sys_category_record_mm.sorting_foreign
-                                       languageField = sys_category.sys_language_uid
-                               }
-                               renderObj < lib.watcherDataObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.categories/sys_category:{field:uid}
+               20 = CONTENT
+               20 {
+                       table = tt_content
+                       select {
+                               orderBy = sorting
+                               where = colPos=0
+                               languageField = sys_language_uid
                        }
-                       20 = CONTENT
-                       20 {
-                               if.isTrue.field = tx_irretutorial_1nff_hotels
-                               table = tx_irretutorial_1nff_hotel
-                               select {
-                                       orderBy = sorting
-                                       where.field = uid
-                                       where.intval = 1
-                                       where.wrap = parenttable="tt_content" AND parentid=|
-                                       languageField = sys_language_uid
+                       renderObj < lib.watcherDataObject
+                       renderObj.1.watcher.dataWrap = {register:watcher}|.__contents/tt_content:{field:uid}
+                       renderObj {
+                               10 = CONTENT
+                               10 {
+                                       if.isTrue.field = categories
+                                       table = sys_category
+                                       select {
+                                               pidInList = root,-1
+                                               selectFields = sys_category.*
+                                               join = sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid
+                                               where.data = field:_ORIG_uid // field:uid
+                                               where.intval = 1
+                                               where.wrap = sys_category_record_mm.uid_foreign=|
+                                               orderBy = sys_category_record_mm.sorting_foreign
+                                               languageField = sys_category.sys_language_uid
+                                       }
+                                       renderObj < lib.watcherDataObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.categories/sys_category:{field:uid}
                                }
-                               renderObj < lib.watcherDataObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.tx_irretutorial_1nff_hotels/tx_irretutorial_1nff_hotel:{field:uid}
-                               renderObj {
-                                       10 = CONTENT
-                                       10 {
-                                               if.isTrue.field = offers
-                                               table = tx_irretutorial_1nff_offer
-                                               select {
-                                                       orderBy = sorting
-                                                       where.field = uid
-                                                       where.intval = 1
-                                                       where.wrap = parenttable="tx_irretutorial_1nff_hotel" AND parentid=|
-                                                       languageField = sys_language_uid
-                                               }
-                                               renderObj < lib.watcherDataObject
-                                               renderObj.1.watcher.dataWrap = {register:watcher}|.offers/tx_irretutorial_1nff_offer:{field:uid}
-                                               renderObj {
-                                                       10 = CONTENT
-                                                       10 {
-                                                               if.isTrue.field = prices
-                                                               table = tx_irretutorial_1nff_price
-                                                               select {
-                                                                       orderBy = sorting
-                                                                       where.field = uid
-                                                                       where.intval = 1
-                                                                       where.wrap = parenttable="tx_irretutorial_1nff_offer" AND parentid=|
-                                                                       languageField = sys_language_uid
+                               20 = CONTENT
+                               20 {
+                                       if.isTrue.field = tx_irretutorial_1nff_hotels
+                                       table = tx_irretutorial_1nff_hotel
+                                       select {
+                                               orderBy = sorting
+                                               where.field = uid
+                                               where.intval = 1
+                                               where.wrap = parenttable="tt_content" AND parentid=|
+                                               languageField = sys_language_uid
+                                       }
+                                       renderObj < lib.watcherDataObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.tx_irretutorial_1nff_hotels/tx_irretutorial_1nff_hotel:{field:uid}
+                                       renderObj {
+                                               10 = CONTENT
+                                               10 {
+                                                       if.isTrue.field = offers
+                                                       table = tx_irretutorial_1nff_offer
+                                                       select {
+                                                               orderBy = sorting
+                                                               where.field = uid
+                                                               where.intval = 1
+                                                               where.wrap = parenttable="tx_irretutorial_1nff_hotel" AND parentid=|
+                                                               languageField = sys_language_uid
+                                                       }
+                                                       renderObj < lib.watcherDataObject
+                                                       renderObj.1.watcher.dataWrap = {register:watcher}|.offers/tx_irretutorial_1nff_offer:{field:uid}
+                                                       renderObj {
+                                                               10 = CONTENT
+                                                               10 {
+                                                                       if.isTrue.field = prices
+                                                                       table = tx_irretutorial_1nff_price
+                                                                       select {
+                                                                               orderBy = sorting
+                                                                               where.field = uid
+                                                                               where.intval = 1
+                                                                               where.wrap = parenttable="tx_irretutorial_1nff_offer" AND parentid=|
+                                                                               languageField = sys_language_uid
+                                                                       }
+                                                                       renderObj < lib.watcherDataObject
+                                                                       renderObj.1.watcher.dataWrap = {register:watcher}|.prices/tx_irretutorial_1nff_price:{field:uid}
                                                                }
-                                                               renderObj < lib.watcherDataObject
-                                                               renderObj.1.watcher.dataWrap = {register:watcher}|.prices/tx_irretutorial_1nff_price:{field:uid}
                                                        }
                                                }
                                        }
                                }
-                       }
-                       30 = CONTENT
-                       30 {
-                               if.isTrue.field = tx_irretutorial_1ncsv_hotels
-                               table = tx_irretutorial_1ncsv_hotel
-                               select {
-                                       uidInList.data = field:tx_irretutorial_1ncsv_hotels
-                                       orderBy = sorting
-                                       # not including sys_language_uid lookup
-                                       # languageField = sys_language_uid
-                               }
-                               renderObj < lib.watcherDataObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.tx_irretutorial_1ncsv_hotels/tx_irretutorial_1ncsv_hotel:{field:uid}
-                               renderObj {
-                                       10 = CONTENT
-                                       10 {
-                                               if.isTrue.field = offers
-                                               table = tx_irretutorial_1ncsv_offer
-                                               select {
-                                                       uidInList.data = field:offers
-                                                       orderBy = sorting
-                                                       # not including sys_language_uid lookup
-                                                       # languageField = sys_language_uid
-                                               }
-                                               renderObj < lib.watcherDataObject
-                                               renderObj.1.watcher.dataWrap = {register:watcher}|.offers/tx_irretutorial_1ncsv_offer:{field:uid}
-                                               renderObj {
-                                                       10 = CONTENT
-                                                       10 {
-                                                               if.isTrue.field = prices
-                                                               table = tx_irretutorial_1ncsv_price
-                                                               select {
-                                                                       uidInList.data = field:prices
-                                                                       orderBy = sorting
-                                                                       # not including sys_language_uid lookup
-                                                                       # languageField = sys_language_uid
+                               30 = CONTENT
+                               30 {
+                                       if.isTrue.field = tx_irretutorial_1ncsv_hotels
+                                       table = tx_irretutorial_1ncsv_hotel
+                                       select {
+                                               uidInList.data = field:tx_irretutorial_1ncsv_hotels
+                                               orderBy = sorting
+                                               # not including sys_language_uid lookup
+                                               # languageField = sys_language_uid
+                                       }
+                                       renderObj < lib.watcherDataObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.tx_irretutorial_1ncsv_hotels/tx_irretutorial_1ncsv_hotel:{field:uid}
+                                       renderObj {
+                                               10 = CONTENT
+                                               10 {
+                                                       if.isTrue.field = offers
+                                                       table = tx_irretutorial_1ncsv_offer
+                                                       select {
+                                                               uidInList.data = field:offers
+                                                               orderBy = sorting
+                                                               # not including sys_language_uid lookup
+                                                               # languageField = sys_language_uid
+                                                       }
+                                                       renderObj < lib.watcherDataObject
+                                                       renderObj.1.watcher.dataWrap = {register:watcher}|.offers/tx_irretutorial_1ncsv_offer:{field:uid}
+                                                       renderObj {
+                                                               10 = CONTENT
+                                                               10 {
+                                                                       if.isTrue.field = prices
+                                                                       table = tx_irretutorial_1ncsv_price
+                                                                       select {
+                                                                               uidInList.data = field:prices
+                                                                               orderBy = sorting
+                                                                               # not including sys_language_uid lookup
+                                                                               # languageField = sys_language_uid
+                                                                       }
+                                                                       renderObj < lib.watcherDataObject
+                                                                       renderObj.1.watcher.dataWrap = {register:watcher}|.prices/tx_irretutorial_1ncsv_price:{field:uid}
                                                                }
-                                                               renderObj < lib.watcherDataObject
-                                                               renderObj.1.watcher.dataWrap = {register:watcher}|.prices/tx_irretutorial_1ncsv_price:{field:uid}
                                                        }
                                                }
                                        }
                                }
-                       }
-                       40 = FILES
-                       40 {
-                               if.isTrue.field = image
-                               references {
-                                       fieldName = image
+                               40 = FILES
+                               40 {
+                                       if.isTrue.field = image
+                                       references {
+                                               fieldName = image
+                                       }
+                                       renderObj < lib.watcherFileObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.image/
                                }
-                               renderObj < lib.watcherFileObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.image/
-                       }
-                       50 = CONTENT
-                       50 {
-                               if.isTrue.field = tx_testdatahandler_select
-                               table = tx_testdatahandler_element
-                               select {
-                                       uidInList.data = field:tx_testdatahandler_select
-                                       pidInList = 0
-                                       orderBy = sorting
-                                       # not including sys_language_uid lookup
-                                       # languageField = sys_language_uid
+                               50 = CONTENT
+                               50 {
+                                       if.isTrue.field = tx_testdatahandler_select
+                                       table = tx_testdatahandler_element
+                                       select {
+                                               uidInList.data = field:tx_testdatahandler_select
+                                               pidInList = 0
+                                               orderBy = sorting
+                                               # not including sys_language_uid lookup
+                                               # languageField = sys_language_uid
+                                       }
+                                       renderObj < lib.watcherDataObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.tx_testdatahandler_select/tx_testdatahandler_element:{field:uid}
                                }
-                               renderObj < lib.watcherDataObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.tx_testdatahandler_select/tx_testdatahandler_element:{field:uid}
-                       }
-                       60 = CONTENT
-                       60 {
-                               if.isTrue.field = tx_testdatahandler_group
-                               table = tx_testdatahandler_element
-                               select {
-                                       uidInList.data = field:tx_testdatahandler_group
-                                       pidInList = 0
-                                       orderBy = sorting
-                                       # not including sys_language_uid lookup
-                                       # languageField = sys_language_uid
+                               60 = CONTENT
+                               60 {
+                                       if.isTrue.field = tx_testdatahandler_group
+                                       table = tx_testdatahandler_element
+                                       select {
+                                               uidInList.data = field:tx_testdatahandler_group
+                                               pidInList = 0
+                                               orderBy = sorting
+                                               # not including sys_language_uid lookup
+                                               # languageField = sys_language_uid
+                                       }
+                                       renderObj < lib.watcherDataObject
+                                       renderObj.1.watcher.dataWrap = {register:watcher}|.tx_testdatahandler_group/tx_testdatahandler_element:{field:uid}
                                }
-                               renderObj < lib.watcherDataObject
-                               renderObj.1.watcher.dataWrap = {register:watcher}|.tx_testdatahandler_group/tx_testdatahandler_element:{field:uid}
                        }
                }
+               stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->attachSection
+               stdWrap.postUserFunc.as = Default
        }
-       stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->render
+       stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->renderSections
 }
 
 [globalVar = GP:L = 1]
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractRecordConstraint.php
new file mode 100644 (file)
index 0000000..de152d5
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+abstract class AbstractRecordConstraint extends \PHPUnit_Framework_Constraint {
+
+       /**
+        * @var array
+        */
+       protected $sectionFailures = array();
+
+       /**
+        * @var string
+        */
+       protected $table;
+
+       /**
+        * @var string
+        */
+       protected $field;
+
+       /**
+        * @var bool
+        */
+       protected $strict = FALSE;
+
+       /**
+        * @var array
+        */
+       protected $values;
+
+       public function setTable($table) {
+               $this->table = $table;
+               return $this;
+       }
+
+       public function setField($field) {
+               $this->field = $field;
+               return $this;
+       }
+
+       public function setValues() {
+               $values = func_get_args();
+               $this->values = $values;
+               return $this;
+       }
+
+       public function setStrict($strict) {
+               $this->strict = (bool)$strict;
+               return $this;
+       }
+
+       /**
+        * Evaluates the constraint for parameter $other. Returns true if the
+        * constraint is met, false otherwise.
+        *
+        * @param array|ResponseSection|ResponseSection[] $other ResponseSections to evaluate
+        * @return bool
+        */
+       protected function matches($other) {
+               if (is_array($other)) {
+                       $success = NULL;
+                       foreach ($other as $item) {
+                               $currentSuccess = $this->matchesSection($item);
+                               $success = ($success === NULL ? $currentSuccess : $success || $currentSuccess);
+                       }
+                       return !empty($success);
+               } else {
+                       return $this->matchesSection($other);
+               }
+       }
+
+       /**
+        * @param ResponseSection $responseSection
+        * @return bool
+        */
+       abstract protected function matchesSection(ResponseSection $responseSection);
+
+       /**
+        * @param array $records
+        * @return array
+        */
+       protected function getNonMatchingValues(array $records) {
+               $values = $this->values;
+
+               foreach ($records as $recordIdentifier => $recordData) {
+                       if (strpos($recordIdentifier, $this->table . ':') !== 0) {
+                               continue;
+                       }
+
+                       if (($foundValueIndex = array_search($recordData[$this->field], $values)) !== FALSE) {
+                               unset($values[$foundValueIndex]);
+                       }
+               }
+
+               return $values;
+       }
+
+       /**
+        * @param array $records
+        * @return array
+        */
+       protected function getRemainingRecords(array $records) {
+               $values = $this->values;
+
+               foreach ($records as $recordIdentifier => $recordData) {
+                       if (strpos($recordIdentifier, $this->table . ':') !== 0) {
+                               unset($records[$recordIdentifier]);
+                               continue;
+                       }
+
+                       if (($foundValueIndex = array_search($recordData[$this->field], $values)) !== FALSE) {
+                               unset($values[$foundValueIndex]);
+                               unset($records[$recordIdentifier]);
+                       }
+               }
+
+               return $records;
+       }
+
+       /**
+        * Returns the description of the failure
+        *
+        * The beginning of failure messages is "Failed asserting that" in most
+        * cases. This method should return the second part of that sentence.
+        *
+        * @param mixed $other Evaluated value or object.
+        * @return string
+        */
+       protected function failureDescription($other) {
+               return $this->toString();
+       }
+
+       /**
+        * Return additional failure description where needed
+        *
+        * The function can be overridden to provide additional failure
+        * information like a diff
+        *
+        * @param mixed $other Evaluated value or object.
+        * @return string
+        */
+       protected function additionalFailureDescription($other) {
+               $failureDescription = '';
+               foreach ($this->sectionFailures as $sectionIdentifier => $sectionFailure) {
+                       $failureDescription .= '* Section "' . $sectionIdentifier . '": ' . $sectionFailure . LF;
+               }
+               return $failureDescription;
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractStructureRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/AbstractStructureRecordConstraint.php
new file mode 100644 (file)
index 0000000..bdb6500
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+abstract class AbstractStructureRecordConstraint extends AbstractRecordConstraint {
+
+       /**
+        * @var string
+        */
+       protected $recordIdentifier;
+
+       /**
+        * @var string
+        */
+       protected $recordField;
+
+       public function setRecordIdentifier($recordIdentifier) {
+               $this->recordIdentifier = $recordIdentifier;
+               return $this;
+       }
+
+       public function setRecordField($recordField) {
+               $this->recordField = $recordField;
+               return $this;
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/DoesNotHaveRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/DoesNotHaveRecordConstraint.php
new file mode 100644 (file)
index 0000000..02e6a80
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+class DoesNotHaveRecordConstraint extends AbstractRecordConstraint {
+
+       /**
+        * @param ResponseSection $responseSection
+        * @return bool
+        */
+       protected function matchesSection(ResponseSection $responseSection) {
+               $records = $responseSection->getRecords();
+
+               if (empty($records) || !is_array($records)) {
+                       $this->sectionFailures[$responseSection->getIdentifier()] = 'No records found.';
+                       return FALSE;
+               }
+
+               $nonMatchingValues = $this->getNonMatchingValues($records);
+               $matchingValues = array_diff($this->values, $nonMatchingValues);
+
+               if (!empty($matchingValues)) {
+                       $this->sectionFailures[$responseSection->getIdentifier()] = 'Could not assert not having values for "' . $this->table . '.' . $this->field . '": ' . implode(', ', $matchingValues);
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Returns a string representation of the constraint.
+        *
+        * @return string
+        */
+       public function toString() {
+               return 'response does not have record';
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/HasRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/HasRecordConstraint.php
new file mode 100644 (file)
index 0000000..297dc9e
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+class HasRecordConstraint extends AbstractRecordConstraint {
+
+       /**
+        * @param ResponseSection $responseSection
+        * @return bool
+        */
+       protected function matchesSection(ResponseSection $responseSection) {
+               $records = $responseSection->getRecords();
+
+               if (empty($records) || !is_array($records)) {
+                       $this->sectionFailures[$responseSection->getIdentifier()] = 'No records found.';
+                       return FALSE;
+               }
+
+               $nonMatchingValues = $this->getNonMatchingValues($records);
+
+               if (!empty($nonMatchingValues)) {
+                       $this->sectionFailures[$responseSection->getIdentifier()] = 'Could not assert all values for "' . $this->table . '.' . $this->field . '": ' . implode(', ', $nonMatchingValues);
+                       return FALSE;
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Returns a string representation of the constraint.
+        *
+        * @return string
+        */
+       public function toString() {
+               return 'response has records';
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureDoesNotHaveRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureDoesNotHaveRecordConstraint.php
new file mode 100644 (file)
index 0000000..2020420
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+class StructureDoesNotHaveRecordConstraint extends AbstractStructureRecordConstraint {
+
+       /**
+        * @param ResponseSection $responseSection
+        * @return bool
+        */
+       protected function matchesSection(ResponseSection $responseSection) {
+               $matchingVariants = array();
+
+               foreach ($responseSection->findStructures($this->recordIdentifier, $this->recordField) as $path => $structure) {
+                       if (empty($structure) || !is_array($structure)) {
+                               $this->sectionFailures[$responseSection->getIdentifier()] = 'No records found in "' . $path . '"';
+                               return FALSE;
+                       }
+
+                       $nonMatchingValues = $this->getNonMatchingValues($structure);
+                       $matchingValues = array_diff($this->values, $nonMatchingValues);
+
+                       if (!empty($matchingValues)) {
+                               $matchingVariants[$path] = $matchingValues;
+                       }
+               }
+
+               if (empty($matchingVariants)) {
+                       return TRUE;
+               }
+
+               $matchingMessage = '';
+               foreach ($matchingVariants as $path => $matchingValues) {
+                       $matchingMessage .= '  * Found in "' . $path . '": ' . implode(', ', $matchingValues);
+               }
+
+               $this->sectionFailures[$responseSection->getIdentifier()] = 'Could not assert not having values for "' . $this->table . '.' . $this->field . '"' . LF . $matchingMessage;
+               return FALSE;
+       }
+
+       /**
+        * Returns a string representation of the constraint.
+        *
+        * @return string
+        */
+       public function toString() {
+               return 'structure does not have record';
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureHasRecordConstraint.php b/typo3/sysext/core/Tests/Functional/Framework/Constraint/RequestSection/StructureHasRecordConstraint.php
new file mode 100644 (file)
index 0000000..f828265
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Constraint\RequestSection;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\ResponseSection;
+
+/**
+ * Model of frontend response
+ */
+class StructureHasRecordConstraint extends AbstractStructureRecordConstraint {
+
+       /**
+        * @param ResponseSection $responseSection
+        * @return bool
+        */
+       protected function matchesSection(ResponseSection $responseSection) {
+               $nonMatchingVariants = array();
+               $remainingRecordVariants = array();
+
+               foreach ($responseSection->findStructures($this->recordIdentifier, $this->recordField) as $path => $structure) {
+                       if (empty($structure) || !is_array($structure)) {
+                               $this->sectionFailures[$responseSection->getIdentifier()] = 'No records found in "' . $path . '"';
+                               return FALSE;
+                       }
+
+                       $remainingRecords = array();
+                       $nonMatchingValues = $this->getNonMatchingValues($structure);
+
+                       if ($this->strict) {
+                               $remainingRecords = $this->getRemainingRecords($structure);
+                       }
+
+                       if (empty($nonMatchingValues) && (!$this->strict || empty($remainingRecords))) {
+                               return TRUE;
+                       }
+
+                       if (!empty($nonMatchingValues)) {
+                               $nonMatchingVariants[$path] = $nonMatchingValues;
+                       }
+                       if ($this->strict && !empty($remainingRecords)) {
+                               $remainingRecordVariants[$path] = $remainingRecords;
+                       }
+               }
+
+               $failureMessage = '';
+
+               if (!empty($nonMatchingVariants)) {
+                       $failureMessage .= 'Could not assert all values for "' . $this->table . '.' . $this->field . '"' . LF;
+                       foreach ($nonMatchingVariants as $path => $nonMatchingValues) {
+                               $failureMessage .= '  * Not found in "' . $path . '": ' . implode(', ', $nonMatchingValues) . LF;
+                       }
+               }
+
+               if (!empty($remainingRecordVariants)) {
+                       $failureMessage .= 'Found remaining records for "' . $this->table . '.' . $this->field . '"' . LF;
+                       foreach ($remainingRecordVariants as $path => $remainingRecords) {
+                               $failureMessage .= '  * Found in "' . $path . '": ' . implode(', ', array_keys($remainingRecords)) . LF;
+                       }
+               }
+
+               $this->sectionFailures[$responseSection->getIdentifier()] = $failureMessage;
+               return FALSE;
+       }
+
+       /**
+        * Returns a string representation of the constraint.
+        *
+        * @return string
+        */
+       public function toString() {
+               return 'structure has record';
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Frontend/Collector.php b/typo3/sysext/core/Tests/Functional/Framework/Frontend/Collector.php
new file mode 100644 (file)
index 0000000..b581a15
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Model of frontend response
+ */
+class Collector implements \TYPO3\CMS\Core\SingletonInterface {
+
+       /**
+        * @var array
+        */
+       protected $tableFields;
+
+       /**
+        * @var array
+        */
+       protected $structure = array();
+
+       /**
+        * @var array
+        */
+       protected $structurePaths = array();
+
+       /**
+        * @var array
+        */
+       protected $records = array();
+
+       /**
+        * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
+        */
+       public $cObj;
+
+       public function addRecordData($content, array $configuration = NULL) {
+               $recordIdentifier = $this->cObj->currentRecord;
+               list($tableName) = explode(':', $recordIdentifier);
+               $currentWatcherValue = $this->getCurrentWatcherValue();
+               $position = strpos($currentWatcherValue, '/' . $recordIdentifier);
+
+               $recordData = $this->filterFields($tableName, $this->cObj->data);
+               $this->records[$recordIdentifier] = $recordData;
+
+               if ($currentWatcherValue === $recordIdentifier) {
+                       $this->structure[$recordIdentifier] = $recordData;
+                       $this->structurePaths[$recordIdentifier] = array(array());
+               } elseif(!empty($position)) {
+                       $levelIdentifier = substr($currentWatcherValue, 0, $position);
+                       $this->addToStructure($levelIdentifier, $recordIdentifier, $recordData);
+               }
+       }
+
+       public function addFileData($content, array $configuration = NULL) {
+               $currentFile = $this->cObj->getCurrentFile();
+
+               if ($currentFile instanceof \TYPO3\CMS\Core\Resource\File) {
+                       $tableName = 'sys_file';
+               } elseif ($currentFile instanceof \TYPO3\CMS\Core\Resource\FileReference) {
+                       $tableName = 'sys_file_reference';
+               } else {
+                       return;
+               }
+
+               $recordData = $this->filterFields($tableName, $currentFile->getProperties());
+               $recordIdentifier = $tableName . ':' . $currentFile->getUid();
+               $this->records[$recordIdentifier] = $recordData;
+
+               $currentWatcherValue = $this->getCurrentWatcherValue();
+               $levelIdentifier = rtrim($currentWatcherValue, '/');
+               $this->addToStructure($levelIdentifier, $recordIdentifier, $recordData);
+       }
+
+       /**
+        * @param string $tableName
+        * @param array $recordData
+        * @return array
+        */
+       protected function filterFields($tableName, array $recordData) {
+               $recordData = array_intersect_key(
+                       $recordData,
+                       array_flip($this->getTableFields($tableName))
+               );
+               return $recordData;
+       }
+
+       protected function addToStructure($levelIdentifier, $recordIdentifier, array $recordData) {
+               $steps = explode('/', $levelIdentifier);
+               $structurePaths = array();
+               $structure = &$this->structure;
+
+               foreach ($steps as $step) {
+                       list($identifier, $fieldName) = explode('.', $step);
+                       $structurePaths[] = $identifier;
+                       $structurePaths[] = $fieldName;
+                       if (!isset($structure[$identifier])) {
+                               return;
+                       }
+                       $structure = &$structure[$identifier];
+                       if (!isset($structure[$fieldName]) || !is_array($structure[$fieldName])) {
+                               $structure[$fieldName] = array();
+                       }
+                       $structure = &$structure[$fieldName];
+               }
+
+               $structure[$recordIdentifier] = $recordData;
+               $this->structurePaths[$recordIdentifier][] = $structurePaths;
+       }
+
+       /**
+        * @param string $content
+        * @param NULL|array $configuration
+        * @return void
+        */
+       public function attachSection($content, array $configuration = NULL) {
+               $section = array(
+                       'structure' => $this->structure,
+                       'structurePaths' => $this->structurePaths,
+                       'records' => $this->records,
+               );
+
+               $as = (!empty($configuration['as']) ? $configuration['as'] : NULL);
+               $this->getRenderer()->addSection($section, $as);
+       }
+
+       /**
+        * @param string $tableName
+        * @return array
+        */
+       protected function getTableFields($tableName) {
+               if (!isset($this->tableFields) && !empty($this->getFrontendController()->tmpl->setup['config.']['watcher.']['tableFields.'])) {
+                       $this->tableFields = $this->getFrontendController()->tmpl->setup['config.']['watcher.']['tableFields.'];
+                       foreach ($this->tableFields as &$fieldList) {
+                               $fieldList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fieldList, TRUE);
+                       }
+                       unset($fieldList);
+               }
+
+               return (!empty($this->tableFields[$tableName]) ? $this->tableFields[$tableName] : array());
+       }
+
+       /**
+        * @return string
+        */
+       protected function getCurrentWatcherValue() {
+               $watcherValue = NULL;
+               if (isset($this->getFrontendController()->register['watcher'])) {
+                       $watcherValue = $this->getFrontendController()->register['watcher'];
+               }
+               return $watcherValue;
+       }
+
+       /**
+        * @return Renderer
+        */
+       protected function getRenderer() {
+               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                       'TYPO3\\CMS\\Core\\Tests\\Functional\\Framework\\Frontend\\Renderer'
+               );
+       }
+
+       /**
+        * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+        */
+       protected function getFrontendController() {
+               return $GLOBALS['TSFE'];
+       }
+
+}
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Frontend/Parser.php b/typo3/sysext/core/Tests/Functional/Framework/Frontend/Parser.php
new file mode 100644 (file)
index 0000000..72357f9
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Model of frontend response
+ */
+class Parser implements \TYPO3\CMS\Core\SingletonInterface {
+
+       /**
+        * @var array
+        */
+       protected $paths = array();
+
+       /**
+        * @var array
+        */
+       protected $records = array();
+
+       /**
+        * @return array
+        */
+       public function getPaths() {
+               return $this->paths;
+       }
+
+       /**
+        * @return array
+        */
+       public function getRecords() {
+               return $this->records;
+       }
+
+       /**
+        * @param array $structure
+        * @param array $path
+        */
+       public function parse(array $structure, array $path = array()) {
+               $this->process($structure);
+       }
+
+       /**
+        * @param array $iterator
+        * @param array $path
+        */
+       protected function process(array $iterator, array $path = array()) {
+               foreach ($iterator as $identifier => $properties) {
+                       $this->addRecord($identifier, $properties);
+                       $this->addPath($identifier, $path);
+                       foreach ($properties as $propertyName => $propertyValue) {
+                               if (!is_array($propertyValue)) {
+                                       continue;
+                               }
+                               $nestedPath = array_merge($path, array($identifier, $propertyName));
+                               $this->process($propertyValue, $nestedPath);
+                       }
+               }
+       }
+
+       /**
+        * @param string $identifier
+        * @param array $properties
+        */
+       protected function addRecord($identifier, array $properties) {
+               if (isset($this->records[$identifier])) {
+                       return;
+               }
+
+               foreach ($properties as $propertyName => $propertyValue) {
+                       if (is_array($propertyValue)) {
+                               unset($properties[$propertyName]);
+                       }
+               }
+
+               $this->records[$identifier] = $properties;
+       }
+
+       /**
+        * @param string $identifier
+        * @param array $path
+        */
+       protected function addPath($identifier, array $path) {
+               if (!isset($this->paths[$identifier])) {
+                       $this->paths[$identifier] = array();
+               }
+
+               $this->paths[$identifier][] = $path;
+       }
+
+}
index 956a159..6e89150 100644 (file)
@@ -32,148 +32,68 @@ class Renderer implements \TYPO3\CMS\Core\SingletonInterface {
        /**
         * @var array
         */
-       protected $tableFields;
+       protected $sections = array();
 
        /**
-        * @var array
-        */
-       protected $structure = array();
-
-       /**
-        * @var array
+        * @param string $content
+        * @param NULL|array $configuration
+        * @return void
         */
-       protected $structurePaths = array();
-
-       /**
-        * @var array
-        */
-       protected $records = array();
-
-       /**
-        * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
-        */
-       public $cObj;
-
-       public function addRecordData($content, array $configuration = NULL) {
-               $recordIdentifier = $this->cObj->currentRecord;
-               list($tableName) = explode(':', $recordIdentifier);
-               $currentWatcherValue = $this->getCurrentWatcherValue();
-               $position = strpos($currentWatcherValue, '/' . $recordIdentifier);
-
-               $recordData = $this->filterFields($tableName, $this->cObj->data);
-               $this->records[$recordIdentifier] = $recordData;
-
-               if ($currentWatcherValue === $recordIdentifier) {
-                       $this->structure[$recordIdentifier] = $recordData;
-                       $this->structurePaths[$recordIdentifier] = array(array());
-               } elseif(!empty($position)) {
-                       $levelIdentifier = substr($currentWatcherValue, 0, $position);
-                       $this->addToStructure($levelIdentifier, $recordIdentifier, $recordData);
+       public function parseValues($content, array $configuration = NULL) {
+               if (empty($content)) {
+                       return;
                }
-       }
 
-       public function addFileData($content, array $configuration = NULL) {
-               $currentFile = $this->cObj->getCurrentFile();
+               $values = json_decode($content, TRUE);
 
-               if ($currentFile instanceof \TYPO3\CMS\Core\Resource\File) {
-                       $tableName = 'sys_file';
-               } elseif ($currentFile instanceof \TYPO3\CMS\Core\Resource\FileReference) {
-                       $tableName = 'sys_file_reference';
-               } else {
+               if (empty($values) || !is_array($values)) {
                        return;
                }
 
-               $recordData = $this->filterFields($tableName, $currentFile->getProperties());
-               $recordIdentifier = $tableName . ':' . $currentFile->getUid();
-               $this->records[$recordIdentifier] = $recordData;
+               $asPrefix = (!empty($configuration['as']) ? $configuration['as'] . ':' : NULL);
+               foreach ($values as $identifier => $structure) {
+                       $parser = $this->createParser();
+                       $parser->parse($structure);
 
-               $currentWatcherValue = $this->getCurrentWatcherValue();
-               $levelIdentifier = rtrim($currentWatcherValue, '/');
-               $this->addToStructure($levelIdentifier, $recordIdentifier, $recordData);
-       }
+                       $section = array(
+                               'structure' => $structure,
+                               'structurePaths' => $parser->getPaths(),
+                               'records' => $parser->getRecords(),
+                       );
 
-       /**
-        * @param string $tableName
-        * @param array $recordData
-        * @return array
-        */
-       protected function filterFields($tableName, array $recordData) {
-               $recordData = array_intersect_key(
-                       $recordData,
-                       array_flip($this->getTableFields($tableName))
-               );
-               return $recordData;
-       }
-
-       protected function addToStructure($levelIdentifier, $recordIdentifier, array $recordData) {
-               $steps = explode('/', $levelIdentifier);
-               $structurePaths = array();
-               $structure = &$this->structure;
-
-               foreach ($steps as $step) {
-                       list($identifier, $fieldName) = explode('.', $step);
-                       $structurePaths[] = $identifier;
-                       $structurePaths[] = $fieldName;
-                       if (!isset($structure[$identifier])) {
-                               return;
-                       }
-                       $structure = &$structure[$identifier];
-                       if (!isset($structure[$fieldName]) || !is_array($structure[$fieldName])) {
-                               $structure[$fieldName] = array();
-                       }
-                       $structure = &$structure[$fieldName];
+                       $this->addSection($section, $asPrefix . $identifier);
                }
-
-               $structure[$recordIdentifier] = $recordData;
-               $this->structurePaths[$recordIdentifier][] = $structurePaths;
-       }
-
-       /**
-        * @param array $parameters
-        * @param \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $frontendController
-        */
-       public function render($content, array $configuration = NULL) {
-               $result = array(
-                       'structure' => $this->structure,
-                       'structurePaths' => $this->structurePaths,
-                       'records' => $this->records,
-               );
-               $content = json_encode($result);
-               return $content;
        }
 
        /**
-        * @param string $tableName
-        * @return array
+        * @param array $section
+        * @param NULL|string $as
         */
-       protected function getTableFields($tableName) {
-               if (!isset($this->tableFields) && !empty($this->getFrontendController()->tmpl->setup['config.']['watcher.']['tableFields.'])) {
-                       $this->tableFields = $this->getFrontendController()->tmpl->setup['config.']['watcher.']['tableFields.'];
-                       foreach ($this->tableFields as &$fieldList) {
-                               $fieldList = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $fieldList, TRUE);
-                       }
-                       unset($fieldList);
+       public function addSection(array $section, $as = NULL) {
+               if (!empty($as)) {
+                       $this->sections[$as] = $section;
+               } else {
+                       $this->sections[] = $section;
                }
-
-               return (!empty($this->tableFields[$tableName]) ? $this->tableFields[$tableName] : array());
        }
 
        /**
+        * @param string $content
+        * @param NULL|array $configuration
         * @return string
         */
-       protected function getCurrentWatcherValue() {
-               $watcherValue = NULL;
-               if (isset($this->getFrontendController()->register['watcher'])) {
-                       $watcherValue = $this->getFrontendController()->register['watcher'];
-               }
-               return $watcherValue;
+       public function renderSections($content, array $configuration = NULL) {
+               $content = json_encode($this->sections);
+               return $content;
        }
 
        /**
-        * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+        * @return Parser
         */
-       protected function getFrontendController() {
-               return $GLOBALS['TSFE'];
+       protected function createParser() {
+               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                       'TYPO3\\CMS\\Core\\Tests\\Functional\\Framework\\Frontend\\Parser'
+               );
        }
 
 }
index b0e6839..c80921f 100644 (file)
@@ -50,7 +50,7 @@ class Response {
        /**
         * @var ResponseContent
         */
-       protected $responseContent;
+       protected $responseSection;
 
        /**
         * @param string $status
@@ -94,4 +94,22 @@ class Response {
                return $this->responseContent;
        }
 
+       /**
+        * @return NULL|array|ResponseSection[]
+        */
+       public function getResponseSections() {
+               $sectionIdentifiers = func_get_args();
+
+               if (empty($sectionIdentifiers)) {
+                       $sectionIdentifiers = array('Default');
+               }
+
+               $sections = array();
+               foreach ($sectionIdentifiers as $sectionIdentifier) {
+                       $sections[] = $this->getResponseContent()->getSection($sectionIdentifier);
+               }
+
+               return $sections;
+       }
+
 }
index 93ccb36..62162e6 100644 (file)
@@ -30,9 +30,9 @@ namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
 class ResponseContent {
 
        /**
-        * @var Response
+        * @var array|ResponseSection[]
         */
-       protected $response;
+       protected $sections;
 
        /**
         * @var array
@@ -58,79 +58,27 @@ class ResponseContent {
         * @param Response $response
         */
        public function __construct(Response $response) {
-               $this->response = $response;
                $content = json_decode($response->getContent(), TRUE);
 
                if ($content !== NULL && is_array($content)) {
-                       $this->structure = $content['structure'];
-                       $this->structurePaths = $content['structurePaths'];
-                       $this->records = $content['records'];
-                       $this->queries = $content['queries'];
+                       foreach ($content as $sectionIdentifier => $sectionData) {
+                               $section = new ResponseSection($sectionIdentifier, $sectionData);
+                               $this->sections[$sectionIdentifier] = $section;
+                       }
                }
        }
 
        /**
-        * @return array
-        */
-       public function getStructure() {
-               return $this->structure;
-       }
-
-       /**
-        * @return array
-        */
-       public function getStructurePaths() {
-               return $this->structurePaths;
-       }
-
-       /**
-        * @return array
-        */
-       public function getRecords() {
-               return $this->records;
-       }
-
-       /**
-        * @return array
+        * @param string $sectionIdentifier
+        * @return NULL|ResponseSection
+        * @throws \RuntimeException
         */
-       public function getQueries() {
-               return $this->queries;
-       }
-
-       /**
-        * @param string $recordIdentifier
-        * @param string $fieldName
-        * @return array
-        */
-       public function findStructures($recordIdentifier, $fieldName = '') {
-               $structures = array();
-
-               if (empty($this->structurePaths[$recordIdentifier])) {
-                       return $structures;
-               }
-
-               foreach ($this->structurePaths[$recordIdentifier] as $steps) {
-                       $structure = $this->structure;
-                       $steps[] = $recordIdentifier;
-
-                       if (!empty($fieldName)) {
-                               $steps[] = $fieldName;
-                       }
-
-                       foreach ($steps as $step) {
-                               if (!isset($structure[$step])) {
-                                       $structure = NULL;
-                                       break;
-                               }
-                               $structure = $structure[$step];
-                       }
-
-                       if (!empty($structure)) {
-                               $structures[implode('/', $steps)] = $structure;
-                       }
+       public function getSection($sectionIdentifier) {
+               if (isset($this->sections[$sectionIdentifier])) {
+                       return $this->sections[$sectionIdentifier];
                }
 
-               return $structures;
+               throw new \RuntimeException('ResponseSection "' . $sectionIdentifier . '" does not exist');
        }
 
 }
diff --git a/typo3/sysext/core/Tests/Functional/Framework/Frontend/ResponseSection.php b/typo3/sysext/core/Tests/Functional/Framework/Frontend/ResponseSection.php
new file mode 100644 (file)
index 0000000..801b3d7
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+namespace TYPO3\CMS\Core\Tests\Functional\Framework\Frontend;
+
+/***************************************************************
+ * Copyright notice
+ *
+ * (c) 2014 Oliver Hader <oliver.hader@typo3.org>
+ * All rights reserved
+ *
+ * This script is part of the TYPO3 project. The TYPO3 project is
+ * free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The GNU General Public License can be found at
+ * http://www.gnu.org/copyleft/gpl.html.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Model of frontend response content
+ */
+class ResponseSection {
+
+       /**
+        * @var string
+        */
+       protected $identifier;
+
+       /**
+        * @var array
+        */
+       protected $structure;
+
+       /**
+        * @var array
+        */
+       protected $structurePaths;
+
+       /**
+        * @var array
+        */
+       protected $records;
+
+       /**
+        * @var array
+        */
+       protected $queries;
+
+       /**
+        * @param string $identifier
+        * @param array $data
+        */
+       public function __construct($identifier, array $data) {
+               $this->identifier = (string)$identifier;
+               $this->structure = $data['structure'];
+               $this->structurePaths = $data['structurePaths'];
+               $this->records = $data['records'];
+
+               if (!empty($data['queries'])) {
+                       $this->queries = $data['queries'];
+               }
+       }
+
+       /**
+        * @return string
+        */
+       public function getIdentifier() {
+               return $this->identifier;
+       }
+
+       /**
+        * @return array
+        */
+       public function getStructure() {
+               return $this->structure;
+       }
+
+       /**
+        * @return array
+        */
+       public function getStructurePaths() {
+               return $this->structurePaths;
+       }
+
+       /**
+        * @return array
+        */
+       public function getRecords() {
+               return $this->records;
+       }
+
+       /**
+        * @return array
+        */
+       public function getQueries() {
+               return $this->queries;
+       }
+
+       /**
+        * @param string $recordIdentifier
+        * @param string $fieldName
+        * @return array
+        */
+       public function findStructures($recordIdentifier, $fieldName = '') {
+               $structures = array();
+
+               if (empty($this->structurePaths[$recordIdentifier])) {
+                       return $structures;
+               }
+
+               foreach ($this->structurePaths[$recordIdentifier] as $steps) {
+                       $structure = $this->structure;
+                       $steps[] = $recordIdentifier;
+
+                       if (!empty($fieldName)) {
+                               $steps[] = $fieldName;
+                       }
+
+                       foreach ($steps as $step) {
+                               if (!isset($structure[$step])) {
+                                       $structure = NULL;
+                                       break;
+                               }
+                               $structure = $structure[$step];
+                       }
+
+                       if (!empty($structure)) {
+                               $structures[implode('/', $steps)] = $structure;
+                       }
+               }
+
+               return $structures;
+       }
+
+}
index 8ae14fb..a0d216c 100644 (file)
@@ -48,12 +48,12 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::modifyContent();
                $this->assertAssertionDataSet('modifyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**
@@ -64,9 +64,11 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::deleteContent();
                $this->assertAssertionDataSet('deleteContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #1');
-               $this->assertResponseContentDoesNotHaveRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2');
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionDoesNotHaveRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
        }
 
        /**
@@ -77,12 +79,12 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::copyContent();
                $this->assertAssertionDataSet('copyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Regular Element #2 (copy 1)');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['copiedContentId'], self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2 (copy 1)'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['copiedContentId'])->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**
@@ -93,15 +95,15 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::localizeContent();
                $this->assertAssertionDataSet('localizeContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', '[Translate to Dansk:] Regular Element #2'));
 
                // @todo Values in sys_file_reference are not copied during localization...
                /*
-                       $this->assertResponseContentStructureHasRecords(
-                               $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                               self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-                       );
+                       $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
                */
        }
 
@@ -113,16 +115,15 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::changeContentSorting();
                $this->assertAssertionDataSet('changeContentSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD')
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**
@@ -133,19 +134,19 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::moveContentToDifferentPage();
                $this->assertAssertionDataSet('moveContentToDifferentPage');
 
-               $responseContentSource = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentSource, self::TABLE_Content, 'header', 'Regular Element #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContentSource, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD'), TRUE
-               );
-
-               $responseContentTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContentTarget, self::TABLE_Content, 'header', 'Regular Element #2');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContentTarget, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSectionsSource = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1'));
+               $this->assertThat($responseSectionsSource, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD')->setStrict(TRUE));
+
+               $responseSectionsTarget = $this->getFrontendResponse(self::VALUE_PageIdTarget, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #2'));
+               $this->assertThat($responseSectionsTarget, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**
@@ -156,16 +157,15 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::moveContentToDifferentPageAndChangeSorting();
                $this->assertAssertionDataSet('moveContentToDifferentPageNChangeSorting');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageIdTarget, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', array('Regular Element #1', 'Regular Element #2'));
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdFirst, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Kasper', 'T3BOARD'), TRUE
-               );
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageIdTarget, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Regular Element #1', 'Regular Element #2'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdFirst)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Kasper', 'T3BOARD')->setStrict(TRUE));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**
@@ -180,12 +180,12 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::createContentWithFileReference();
                $this->assertAssertionDataSet('createContentWFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . $this->recordIds['newContentId'], self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'Image #1', TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . $this->recordIds['newContentId'])->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Image #1')->setStrict(TRUE));
        }
 
        /**
@@ -196,12 +196,12 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::modifyContentWithFileReference();
                $this->assertAssertionDataSet('modifyContentWFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'Image #1'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'Image #1')->setStrict(TRUE));
        }
 
        /**
@@ -212,11 +212,10 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::modifyContentAndAddFileReference();
                $this->assertAssertionDataSet('modifyContentNAddFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'This is Kasper', 'Image #3'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'This is Kasper', 'Image #3')->setStrict(TRUE));
        }
 
        /**
@@ -227,15 +226,13 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::modifyContentAndDeleteFileReference();
                $this->assertAssertionDataSet('modifyContentNDeleteFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'This is Kasper', TRUE
-               );
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', 'Taken at T3BOARD'
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper')->setStrict(TRUE));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD'));
        }
 
        /**
@@ -246,11 +243,10 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                parent::modifyContentAndDeleteAllFileReference();
                $this->assertAssertionDataSet('modifyContentNDeleteAllFileReference');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseContent();
-               $this->assertResponseContentStructureDoesNotHaveRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('Taken at T3BOARD', 'This is Kasper')
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId, 0, self::VALUE_BackendUserId, self::VALUE_WorkspaceId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionStructureDoesNotHaveRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('Taken at T3BOARD', 'This is Kasper'));
        }
 
 }
index a872cbf..6beadf6 100644 (file)
@@ -49,12 +49,12 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\FAL
                $this->actionService->publishRecord(self::TABLE_Content, self::VALUE_ContentIdLast);
                $this->assertAssertionDataSet('modifyContent');
 
-               $responseContent = $this->getFrontendResponse(self::VALUE_PageId)->getResponseContent();
-               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Content, 'header', 'Testing #1');
-               $this->assertResponseContentStructureHasRecords(
-                       $responseContent, self::TABLE_Content . ':' . self::VALUE_ContentIdLast, self::FIELD_ContentImage,
-                       self::TABLE_FileReference, 'title', array('This is Kasper', 'Taken at T3BOARD'), TRUE
-               );
+               $responseSections = $this->getFrontendResponse(self::VALUE_PageId)->getResponseSections();
+               $this->assertThat($responseSections, $this->getRequestSectionHasRecordConstraint()
+                       ->setTable(self::TABLE_Content)->setField('header')->setValues('Testing #1'));
+               $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+                       ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentImage)
+                       ->setTable(self::TABLE_FileReference)->setField('title')->setValues('This is Kasper', 'Taken at T3BOARD')->setStrict(TRUE));
        }
 
        /**