From 08193796b7ecf810b39b32dd34c17553b2f9e29f Mon Sep 17 00:00:00 2001
From: mhsdesign <85400359+mhsdesign@users.noreply.github.com>
Date: Sun, 20 Oct 2024 14:11:36 +0200
Subject: [PATCH 1/8] TASK: Introduce full behat test for
FrontendNodeController
---
.../Bootstrap/Features/NodeCreation.php | 2 +-
.../Classes/Domain/Service/FusionService.php | 12 ++
.../Features/Bootstrap/DispatcherTrait.php | 103 ++++++++++++++++
.../Features/Bootstrap/FeatureContext.php | 1 +
.../DefaultFusionRendering.feature | 113 ++++++++++++++++++
5 files changed, 230 insertions(+), 1 deletion(-)
create mode 100644 Neos.Neos/Tests/Behavior/Features/Bootstrap/DispatcherTrait.php
create mode 100644 Neos.Neos/Tests/Behavior/Features/FrontendNodeController/DefaultFusionRendering.feature
diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php
index d20ebdab535..5f4a1b8c699 100644
--- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php
+++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCreation.php
@@ -205,7 +205,7 @@ public function theFollowingCreateNodeAggregateWithNodeCommandsAreExecuted(Table
if (isset($row['tetheredDescendantNodeAggregateIds'])) {
$command = $command->withTetheredDescendantNodeAggregateIds(NodeAggregateIdsByNodePaths::fromJsonString($row['tetheredDescendantNodeAggregateIds']));
}
- if (isset($row['nodeName'])) {
+ if (!empty($row['nodeName'])) {
$command = $command->withNodeName(NodeName::fromString($row['nodeName']));
}
$this->currentContentRepository->handle($command);
diff --git a/Neos.Neos/Classes/Domain/Service/FusionService.php b/Neos.Neos/Classes/Domain/Service/FusionService.php
index 528b8315a31..9573ef9befe 100644
--- a/Neos.Neos/Classes/Domain/Service/FusionService.php
+++ b/Neos.Neos/Classes/Domain/Service/FusionService.php
@@ -44,6 +44,16 @@ class FusionService
*/
protected $fusionConfigurationCache;
+ private ?FusionSourceCodeCollection $additionalFusionSourceCode = null;
+
+ /**
+ * @deprecated fixme!!!
+ */
+ public function unsafeSetAdditionalFusionSourceCodeToThisSingleton(string $additionalFusionSourceCode)
+ {
+ $this->additionalFusionSourceCode = FusionSourceCodeCollection::fromString($additionalFusionSourceCode);
+ }
+
public function createFusionConfigurationFromSite(Site $site): FusionConfiguration
{
return $this->fusionConfigurationCache->cacheFusionConfigurationBySite($site, function () use ($site) {
@@ -56,6 +66,8 @@ public function createFusionConfigurationFromSite(Site $site): FusionConfigurati
)
->union(
FusionSourceCodeCollection::tryFromPackageRootFusion($siteResourcesPackageKey)
+ )->union(
+ $this->additionalFusionSourceCode ?? FusionSourceCodeCollection::empty()
)
);
});
diff --git a/Neos.Neos/Tests/Behavior/Features/Bootstrap/DispatcherTrait.php b/Neos.Neos/Tests/Behavior/Features/Bootstrap/DispatcherTrait.php
new file mode 100644
index 00000000000..56a39fa4e9e
--- /dev/null
+++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/DispatcherTrait.php
@@ -0,0 +1,103 @@
+ $className
+ *
+ * @return T
+ */
+ abstract private function getObject(string $className): object;
+
+ /**
+ * @BeforeScenario
+ */
+ public function setupDispatcherTest(): void
+ {
+ $this->getObject(ContentCache::class)->flush();
+ $this->response = null;
+ }
+
+ /**
+ * @When the sites Fusion code is:
+ */
+ public function iHaveTheFollowingFusionCodeForTheSite(PyStringNode $fusionCode)
+ {
+ $this->getObject(
+ FusionService::class
+ )->unsafeSetAdditionalFusionSourceCodeToThisSingleton(
+ $fusionCode->getRaw()
+ );
+ // $fakeFusionService = new class ($original) extends \Neos\Neos\Domain\Service\FusionService
+ // {
+ // public function __construct(
+ // private \Neos\Neos\Domain\Service\FusionService $original,
+ // private \Neos\Fusion\Core\FusionSourceCode $additionalFusion
+ // ) {
+ // }
+ // public function createFusionConfigurationFromSite(\Neos\Neos\Domain\Model\Site $site): \Neos\Fusion\Core\FusionConfiguration
+ // {
+ // $this->original->createFusionConfigurationFromSite($site)-> ... doest work
+ // }
+ // };
+ }
+
+ /**
+ * @When I dispatch the following request :requestUri
+ */
+ public function iDispatchTheFollowingRequest(string $requestUri)
+ {
+ $httpRequest = $this->getObject(ServerRequestFactoryInterface::class)->createServerRequest('GET', $requestUri);
+
+ $this->response = $this->getObject(\Neos\Flow\Http\Middleware\MiddlewaresChain::class)->handle(
+ $httpRequest
+ );
+ }
+
+ /**
+ * @Then I expect the following response header:
+ */
+ public function iExpectTheFollowingResponseHeader(PyStringNode $expectedResult): void
+ {
+ Assert::assertNotNull($this->response);
+ Assert::assertSame($expectedResult->getRaw(), $this->response->getBody()->getContents());
+ }
+
+ /**
+ * @Then I expect the following response:
+ */
+ public function iExpectTheFollowingResponse(PyStringNode $expectedResult): void
+ {
+ Assert::assertNotNull($this->response);
+ Assert::assertEquals($expectedResult->getRaw(), str_replace("\r\n", "\n", Message::toString($this->response)));
+ }
+}
diff --git a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php
index 9d06ce491eb..b02048f437e 100644
--- a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php
+++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php
@@ -39,6 +39,7 @@ class FeatureContext implements BehatContext
use CRBehavioralTestsSubjectProvider;
use RoutingTrait;
use MigrationsTrait;
+ use DispatcherTrait;
use FusionTrait;
use ContentCacheTrait;
diff --git a/Neos.Neos/Tests/Behavior/Features/FrontendNodeController/DefaultFusionRendering.feature b/Neos.Neos/Tests/Behavior/Features/FrontendNodeController/DefaultFusionRendering.feature
new file mode 100644
index 00000000000..cb7689bf7cb
--- /dev/null
+++ b/Neos.Neos/Tests/Behavior/Features/FrontendNodeController/DefaultFusionRendering.feature
@@ -0,0 +1,113 @@
+@flowEntities
+Feature: Test the default Fusion rendering for a request
+ Background:
+ Given using no content dimensions
+ And using the following node types:
+ """yaml
+ 'Neos.ContentRepository:Root': {}
+ 'Neos.Neos:ContentCollection': {}
+ 'Neos.Neos:Content': {}
+ 'Neos.Neos:Sites':
+ superTypes:
+ 'Neos.ContentRepository:Root': true
+ 'Neos.Neos:Document':
+ properties:
+ title:
+ type: string
+ uriPathSegment:
+ type: string
+ 'Neos.Neos:Site':
+ superTypes:
+ 'Neos.Neos:Document': true
+ childNodes:
+ main:
+ type: 'Neos.Neos:ContentCollection'
+ 'Neos.Neos:Test.DocumentType':
+ superTypes:
+ 'Neos.Neos:Document': true
+ childNodes:
+ main:
+ type: 'Neos.Neos:ContentCollection'
+ 'Neos.Neos:Test.ContentType':
+ superTypes:
+ 'Neos.Neos:Content': true
+ properties:
+ text:
+ type: string
+ """
+ And using identifier "default", I define a content repository
+ And I am in content repository "default"
+ When the command CreateRootWorkspace is executed with payload:
+ | Key | Value |
+ | workspaceName | "live" |
+ | newContentStreamId | "cs-identifier" |
+ And I am in workspace "live" and dimension space point {}
+ And the command CreateRootNodeAggregateWithNode is executed with payload:
+ | Key | Value |
+ | nodeAggregateId | "root" |
+ | nodeTypeName | "Neos.Neos:Sites" |
+ And the following CreateNodeAggregateWithNode commands are executed:
+ | nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | tetheredDescendantNodeAggregateIds | nodeName |
+ | a | root | Neos.Neos:Site | {"title": "Node a"} | {} | a |
+ | a1 | a | Neos.Neos:Test.DocumentType | {"uriPathSegment": "a1", "title": "Node a1"} | {"main": "a-tetherton" } | |
+ | a1a1 | a-tetherton | Neos.Neos:Test.ContentType | {"text": "my first text"} | {} | |
+ | a1a2 | a-tetherton | Neos.Neos:Test.ContentType | {"text": "my second text"} | {} | |
+ And A site exists for node name "a" and domain "http://localhost"
+ And the sites configuration is:
+ """yaml
+ Neos:
+ Neos:
+ sites:
+ 'a':
+ preset: default
+ uriPathSuffix: ''
+ contentDimensions:
+ resolver:
+ factoryClassName: Neos\Neos\FrontendRouting\DimensionResolution\Resolver\NoopResolverFactory
+ """
+
+ Scenario: Default output
+ And the sites Fusion code is:
+ """fusion
+ prototype(Neos.Neos:Test.DocumentType) < prototype(Neos.Neos:Page) {
+ body {
+ content = Neos.Fusion:Component {
+ renderer = afx`
+ {String.chr(10)}title: {node.properties.title}
+ {String.chr(10)}children: