Skip to content

Commit

Permalink
Merge pull request #5305 from mhsdesign/task/addBehatTestForFrontendN…
Browse files Browse the repository at this point in the history
…odeController

TASK: Introduce full behat test for FrontendNodeController
  • Loading branch information
mhsdesign authored Nov 12, 2024
2 parents 83575f3 + 3b38dff commit ab7f5f9
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 13 deletions.
3 changes: 3 additions & 0 deletions Neos.Fusion/Classes/Core/FusionSourceCodeCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public static function tryFromFilePath(string $filePath): self
return self::fromFilePath($filePath);
}

/**
* @deprecated with Neos 9, remove me :)
*/
public static function tryFromPackageRootFusion(string $packageKey): self
{
$fusionPathAndFilename = sprintf('resource://%s/Private/Fusion/Root.fusion', $packageKey);
Expand Down
15 changes: 15 additions & 0 deletions Neos.Neos/Classes/Domain/Service/FusionAutoIncludeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Neos\Neos\Domain\Service;

use Neos\Fusion\Core\FusionSourceCodeCollection;

/**
* @internal
*/
interface FusionAutoIncludeHandler
{
public function loadFusionFromPackage(string $packageKey, FusionSourceCodeCollection $sourceCodeCollection): FusionSourceCodeCollection;
}
21 changes: 13 additions & 8 deletions Neos.Neos/Classes/Domain/Service/FusionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,24 @@ class FusionService
*/
protected $fusionConfigurationCache;

/**
* @Flow\Inject
* @var FusionAutoIncludeHandler
*/
protected $fusionAutoIncludeHandler;

public function createFusionConfigurationFromSite(Site $site): FusionConfiguration
{
return $this->fusionConfigurationCache->cacheFusionConfigurationBySite($site, function () use ($site) {
$siteResourcesPackageKey = $site->getSiteResourcesPackageKey();

return $this->fusionParser->parseFromSource(
$this->fusionSourceCodeFactory->createFromNodeTypeDefinitions($site->getConfiguration()->contentRepositoryId)
->union(
$this->fusionSourceCodeFactory->createFromAutoIncludes()
)
->union(
FusionSourceCodeCollection::tryFromPackageRootFusion($siteResourcesPackageKey)
)
$this->fusionAutoIncludeHandler->loadFusionFromPackage(
$siteResourcesPackageKey,
$this->fusionSourceCodeFactory->createFromNodeTypeDefinitions($site->getConfiguration()->contentRepositoryId)
->union(
$this->fusionSourceCodeFactory->createFromAutoIncludes()
)
)
);
});
}
Expand Down
10 changes: 7 additions & 3 deletions Neos.Neos/Classes/Domain/Service/FusionSourceCodeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class FusionSourceCodeFactory
#[Flow\InjectConfiguration("fusion.autoInclude")]
protected array $autoIncludeConfiguration = [];

#[Flow\Inject]
protected FusionAutoIncludeHandler $fusionAutoIncludeHandler;

#[Flow\Inject]
protected ContentRepositoryRegistry $contentRepositoryRegistry;

Expand All @@ -50,14 +53,15 @@ public function createFromAutoIncludes(): FusionSourceCodeCollection
$sourcecode = FusionSourceCodeCollection::empty();
foreach (array_keys($this->packageManager->getAvailablePackages()) as $packageKey) {
if (isset($this->autoIncludeConfiguration[$packageKey]) && $this->autoIncludeConfiguration[$packageKey] === true) {
$sourcecode = $sourcecode->union(
FusionSourceCodeCollection::tryFromPackageRootFusion($packageKey)
);
$sourcecode = $this->fusionAutoIncludeHandler->loadFusionFromPackage($packageKey, $sourcecode);
}
}
return $sourcecode;
}

/**
* @deprecated with Neos 9 - YAGNI from the start :)
*/
public function createFromSite(Site $site): FusionSourceCodeCollection
{
return FusionSourceCodeCollection::tryFromPackageRootFusion($site->getSiteResourcesPackageKey());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Neos\Neos\Domain\Service;

use Neos\Flow\Annotations as Flow;
use Neos\Fusion\Core\FusionSourceCodeCollection;

/**
* @internal
* @Flow\Scope("singleton")
*/
class ResourceFusionAutoIncludeHandler implements FusionAutoIncludeHandler
{
public function loadFusionFromPackage(string $packageKey, FusionSourceCodeCollection $sourceCodeCollection): FusionSourceCodeCollection
{
return $sourceCodeCollection->union(
FusionSourceCodeCollection::tryFromFilePath(sprintf('resource://%s/Private/Fusion/Root.fusion', $packageKey))
);
}
}
60 changes: 60 additions & 0 deletions Neos.Neos/Classes/Testing/TestingFusionAutoIncludeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace Neos\Neos\Testing;

use Neos\Flow\Annotations as Flow;
use Neos\Fusion\Core\FusionSourceCodeCollection;
use Neos\Neos\Domain\Service\FusionAutoIncludeHandler;
use Neos\Neos\Domain\Service\ResourceFusionAutoIncludeHandler;

/**
* @internal only for testing purposes of the Neos.Neos package
* @Flow\Scope("singleton")
*/
class TestingFusionAutoIncludeHandler implements FusionAutoIncludeHandler
{
/**
* @Flow\Inject
*/
protected ResourceFusionAutoIncludeHandler $defaultHandler;

/**
* @var array<string,FusionSourceCodeCollection|true>
*/
private array $overriddenIncludes = [];

public function setIncludeFusionPackage(string $packageKey): void
{
$this->overriddenIncludes[$packageKey] = true;
}

public function setFusionForPackage(string $packageKey, FusionSourceCodeCollection $packageFusionSource): void
{
$this->overriddenIncludes[$packageKey] = $packageFusionSource;
}

public function reset(): void
{
$this->overriddenIncludes = [];
}

/**
* If no override is set via {@see setIncludeFusionPackage} or {@see setFusionForPackage} we load all the fusion via the default implementation
*/
public function loadFusionFromPackage(string $packageKey, FusionSourceCodeCollection $sourceCodeCollection): FusionSourceCodeCollection
{
if ($this->overriddenIncludes === []) {
return $this->defaultHandler->loadFusionFromPackage($packageKey, $sourceCodeCollection);
}
$override = $this->overriddenIncludes[$packageKey] ?? null;
if ($override === null) {
return $sourceCodeCollection;
}
if ($override === true) {
return $this->defaultHandler->loadFusionFromPackage($packageKey, $sourceCodeCollection);
}
return $sourceCodeCollection->union($override);
}
}
3 changes: 3 additions & 0 deletions Neos.Neos/Configuration/Objects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Neos\Neos\Domain\Service\FusionConfigurationCache:
2:
setting: "Neos.Neos.fusion.enableObjectTreeCache"

Neos\Neos\Domain\Service\FusionAutoIncludeHandler:
className: Neos\Neos\Domain\Service\ResourceFusionAutoIncludeHandler

Neos\Fusion\Core\Cache\RuntimeContentCache:
properties:
serializer:
Expand Down
2 changes: 2 additions & 0 deletions Neos.Neos/Configuration/Testing/Objects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Neos\Neos\Domain\Service\FusionAutoIncludeHandler:
className: Neos\Neos\Testing\TestingFusionAutoIncludeHandler
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class FeatureContext implements BehatContext
use CRBehavioralTestsSubjectProvider;
use RoutingTrait;
use MigrationsTrait;
use FrontendNodeControllerTrait;
use FusionTrait;

use ContentCacheTrait;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Neos.ContentRepository package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Behat\Gherkin\Node\PyStringNode;
use GuzzleHttp\Psr7\Message;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\CRTestSuiteRuntimeVariables;
use Neos\Fusion\Core\Cache\ContentCache;
use PHPUnit\Framework\Assert;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestFactoryInterface;

/**
* @internal only for behat tests within the Neos.Neos package
*/
trait FrontendNodeControllerTrait
{
use CRTestSuiteRuntimeVariables;

private ResponseInterface|null $frontendNodeControllerResponse = null;

/**
* @template T of object
* @param class-string<T> $className
*
* @return T
*/
abstract private function getObject(string $className): object;

/**
* @BeforeScenario
*/
public function setupFrontendNodeControllerTrait(): void
{
$this->getObject(ContentCache::class)->flush();
$this->getObject(\Neos\Neos\Testing\TestingFusionAutoIncludeHandler::class)->reset();
$this->frontendNodeControllerResponse = null;
}

/**
* @When the Fusion code for package :package is:
*/
public function iHaveTheFollowingFusionCodeForTheSite(PyStringNode $fusionCode, string $package)
{
$testingFusionHandler = $this->getObject(\Neos\Neos\Testing\TestingFusionAutoIncludeHandler::class);
$testingFusionHandler->setFusionForPackage($package, \Neos\Fusion\Core\FusionSourceCodeCollection::fromString($fusionCode->getRaw()));
}

/**
* @When I dispatch the following request :requestUri
*/
public function iDispatchTheFollowingRequest(string $requestUri)
{
$testingFusionHandler = $this->getObject(\Neos\Neos\Testing\TestingFusionAutoIncludeHandler::class);
$testingFusionHandler->setIncludeFusionPackage('Neos.Fusion');
$testingFusionHandler->setIncludeFusionPackage('Neos.Neos');

$httpRequest = $this->getObject(ServerRequestFactoryInterface::class)->createServerRequest('GET', $requestUri);

$this->frontendNodeControllerResponse = $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->frontendNodeControllerResponse);
Assert::assertSame($expectedResult->getRaw(), $this->frontendNodeControllerResponse->getBody()->getContents());
}

/**
* @Then I expect the following response:
*/
public function iExpectTheFollowingResponse(PyStringNode $expectedResult): void
{
Assert::assertNotNull($this->frontendNodeControllerResponse);
Assert::assertEquals($expectedResult->getRaw(), str_replace("\r\n", "\n", Message::toString($this->frontendNodeControllerResponse)));
}
}
5 changes: 3 additions & 2 deletions Neos.Neos/Tests/Behavior/Features/Bootstrap/RoutingTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ abstract private function getObject(string $className): object;
/**
* @Given A site exists for node name :nodeName
* @Given A site exists for node name :nodeName and domain :domain
* @Given A site exists for node name :nodeName and domain :domain and package :package
*/
public function theSiteExists(string $nodeName, string $domain = null): void
public function theSiteExists(string $nodeName, string $domain = null, string $package = null): void
{
$siteRepository = $this->getObject(SiteRepository::class);
$persistenceManager = $this->getObject(PersistenceManagerInterface::class);

$site = new Site($nodeName);
$site->setSiteResourcesPackageKey('Neos.Neos');
$site->setSiteResourcesPackageKey($package ?: 'Neos.Neos');
$site->setState(Site::STATE_ONLINE);
$siteRepository->add($site);

Expand Down
Loading

0 comments on commit ab7f5f9

Please sign in to comment.