Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: BUGFIX: Fix Behat tests without CATCHUPTRIGGER_ENABLE_SYNCHRONOUS_OPTION #4689

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
"test:functional": [
"../../bin/phpunit --colors --stop-on-failure -c ../../Build/BuildEssentials/PhpUnit/FunctionalTests.xml Neos.ContentRepository.Core/Tests/Functional"
],
"test:behat-cli": "../../bin/behat -f progress --strict --no-interaction",
"test:behat-cli": [
"Composer\\Config::disableProcessTimeout",
"../../bin/behat -f progress --strict --no-interaction"
],
"test:behavioral": [
"@test:behat-cli -c Neos.ContentRepository.BehavioralTests/Tests/Behavior/behat.yml.dist",
"@test:behat-cli -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
use Behat\Gherkin\Node\TableNode;
use Doctrine\DBAL\Connection;
use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\Dimension\ContentDimensionSourceInterface;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\GherkinTableNodeBasedContentDimensionSource;
use Neos\EventStore\EventStoreInterface;
use Symfony\Component\Yaml\Yaml;

/**
* Subject provider for behavioral tests
Expand All @@ -40,6 +42,10 @@ trait CRBehavioralTestsSubjectProvider

protected ?ContentRepository $currentContentRepository = null;

private ?array $nodeTypesConfiguration = null;

private ?ContentDimensionSourceInterface $contentDimensionsToUse = null;

/**
* @throws \DomainException if the requested content repository instance does not exist
*/
Expand All @@ -57,23 +63,23 @@ protected function getContentRepository(ContentRepositoryId $contentRepositoryId
*/
public function usingNoContentDimensions(): void
{
GherkinTableNodeBasedContentDimensionSourceFactory::$contentDimensionsToUse = GherkinTableNodeBasedContentDimensionSource::createEmpty();
$this->contentDimensionsToUse = GherkinTableNodeBasedContentDimensionSource::createEmpty();
}

/**
* @Given /^using the following content dimensions:$/
*/
public function usingTheFollowingContentDimensions(TableNode $contentDimensions): void
{
GherkinTableNodeBasedContentDimensionSourceFactory::initializeFromTableNode($contentDimensions);
$this->contentDimensionsToUse = GherkinTableNodeBasedContentDimensionSource::fromGherkinTableNode($contentDimensions);
}

/**
* @Given /^using the following node types:$/
*/
public function usingTheFollowingNodeTypes(PyStringNode $serializedNodeTypesConfiguration): void
{
GherkinPyStringNodeBasedNodeTypeManagerFactory::initializeWithPyStringNode($serializedNodeTypesConfiguration);
$this->nodeTypesConfiguration = Yaml::parse($serializedNodeTypesConfiguration->getRaw()) ?? [];
}

/**
Expand All @@ -83,9 +89,14 @@ public function usingIdentifierIDefineAContentRepository(string $contentReposito
{
if (array_key_exists($contentRepositoryId, $this->contentRepositories)) {
throw new \DomainException('already defined content repository ' . $contentRepositoryId);
} else {
$this->contentRepositories[$contentRepositoryId] = $this->setUpContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
}
if ($this->nodeTypesConfiguration !== null) {
GherkinPyStringNodeBasedNodeTypeManagerFactory::registerNodeTypeConfigurationForContentRepository(ContentRepositoryId::fromString($contentRepositoryId), $this->nodeTypesConfiguration);
}
if ($this->contentDimensionsToUse !== null) {
GherkinTableNodeBasedContentDimensionSourceFactory::registerContentDimensionsForContentRepository(ContentRepositoryId::fromString($contentRepositoryId), $this->contentDimensionsToUse);
}
$this->contentRepositories[$contentRepositoryId] = $this->setUpContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
}

/**
Expand All @@ -95,14 +106,12 @@ public function iChangeTheContentDimensionsInContentRepositoryTo(string $content
{
if (!array_key_exists($contentRepositoryId, $this->contentRepositories)) {
throw new \DomainException('undeclared content repository ' . $contentRepositoryId);
} else {
$contentRepository = $this->contentRepositories[$contentRepositoryId];
GherkinPyStringNodeBasedNodeTypeManagerFactory::$nodeTypesToUse = $contentRepository->getNodeTypeManager();
GherkinTableNodeBasedContentDimensionSourceFactory::initializeFromTableNode($contentDimensions);
$this->contentRepositories[$contentRepositoryId] = $this->createContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
if ($this->currentContentRepository->id->value === $contentRepositoryId) {
$this->currentContentRepository = $this->contentRepositories[$contentRepositoryId];
}
}
$contentRepository = $this->contentRepositories[$contentRepositoryId];
GherkinTableNodeBasedContentDimensionSourceFactory::registerContentDimensionsForContentRepository($contentRepository->id, GherkinTableNodeBasedContentDimensionSource::fromGherkinTableNode($contentDimensions));
$this->contentRepositories[$contentRepositoryId] = $this->createContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
if ($this->currentContentRepository->id->value === $contentRepositoryId) {
$this->currentContentRepository = $this->contentRepositories[$contentRepositoryId];
}
}

Expand All @@ -115,14 +124,12 @@ public function iChangeTheNodeTypesInContentRepositoryTo(
): void {
if (!array_key_exists($contentRepositoryId, $this->contentRepositories)) {
throw new \DomainException('undeclared content repository ' . $contentRepositoryId);
} else {
$contentRepository = $this->contentRepositories[$contentRepositoryId];
GherkinPyStringNodeBasedNodeTypeManagerFactory::initializeWithPyStringNode($serializedNodeTypesConfiguration);
GherkinTableNodeBasedContentDimensionSourceFactory::$contentDimensionsToUse = $contentRepository->getContentDimensionSource();
$this->contentRepositories[$contentRepositoryId] = $this->createContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
if ($this->currentContentRepository->id->value === $contentRepositoryId) {
$this->currentContentRepository = $this->contentRepositories[$contentRepositoryId];
}
}
$contentRepository = $this->contentRepositories[$contentRepositoryId];
GherkinPyStringNodeBasedNodeTypeManagerFactory::registerNodeTypeConfigurationForContentRepository($contentRepository->id, Yaml::parse($serializedNodeTypesConfiguration->getRaw()) ?? []);
$this->contentRepositories[$contentRepositoryId] = $this->createContentRepository(ContentRepositoryId::fromString($contentRepositoryId));
if ($this->currentContentRepository->id->value === $contentRepositoryId) {
$this->currentContentRepository = $this->contentRepositories[$contentRepositoryId];
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace Neos\ContentRepository\BehavioralTests\TestSuite\Behavior;

use Behat\Gherkin\Node\PyStringNode;
use JsonException;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\Core\NodeType\NodeLabelGeneratorFactoryInterface;
use Neos\ContentRepository\Core\NodeType\NodeLabelGeneratorInterface;
Expand All @@ -29,23 +30,22 @@
*/
final class GherkinPyStringNodeBasedNodeTypeManagerFactory implements NodeTypeManagerFactoryInterface
{
public static ?NodeTypeManager $nodeTypesToUse = null;

/**
* @param array<string,mixed> $options
*/
public function build(ContentRepositoryId $contentRepositoryId, array $options): NodeTypeManager
{
if (!self::$nodeTypesToUse) {
throw new \DomainException('NodeTypeManagerFactory uninitialized');
$nodeTypesConfigurationJson = file_get_contents(self::cacheFileName($contentRepositoryId));
if ($nodeTypesConfigurationJson === false) {
throw new \RuntimeException(sprintf('NodeTypeManagerFactory uninitialized for ContentRepository "%s"', $contentRepositoryId->value));
}
return self::$nodeTypesToUse;
}

public static function initializeWithPyStringNode(PyStringNode $nodeTypesToUse): void
{
self::$nodeTypesToUse = new NodeTypeManager(
fn (): array => Yaml::parse($nodeTypesToUse->getRaw()) ?? [],
try {
$nodeTypesConfiguration = json_decode($nodeTypesConfigurationJson, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new \RuntimeException(sprintf('Failed to parse JSON for node types configuration: %s', $nodeTypesConfigurationJson));
}
return new NodeTypeManager(
fn () => $nodeTypesConfiguration,
new class implements NodeLabelGeneratorFactoryInterface {
public function create(NodeType $nodeType): NodeLabelGeneratorInterface
{
Expand All @@ -60,8 +60,20 @@ public function getLabel(Node $node): string
);
}

/**
* @param array<mixed> $nodeTypeConfiguration
*/
public static function registerNodeTypeConfigurationForContentRepository(ContentRepositoryId $contentRepositoryId, array $nodeTypeConfiguration): void
{
file_put_contents(self::cacheFileName($contentRepositoryId), json_encode($nodeTypeConfiguration, JSON_THROW_ON_ERROR));
}

public static function reset(): void
{
self::$nodeTypesToUse = null;
}

private static function cacheFileName(ContentRepositoryId $contentRepositoryId): string
{
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'nodeTypesConfiguration_' . $contentRepositoryId->value . '.json';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,36 @@

namespace Neos\ContentRepository\BehavioralTests\TestSuite\Behavior;

use Behat\Gherkin\Node\TableNode;
use Neos\ContentRepository\Core\Dimension\ContentDimensionSourceInterface;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\GherkinTableNodeBasedContentDimensionSource;
use Neos\ContentRepositoryRegistry\Factory\ContentDimensionSource\ContentDimensionSourceFactoryInterface;

class GherkinTableNodeBasedContentDimensionSourceFactory implements ContentDimensionSourceFactoryInterface
{
public static ?ContentDimensionSourceInterface $contentDimensionsToUse = null;
public static function registerContentDimensionsForContentRepository(ContentRepositoryId $contentRepositoryId, GherkinTableNodeBasedContentDimensionSource $contentDimensions): void
{
file_put_contents(self::cacheFileName($contentRepositoryId), serialize($contentDimensions));
}

/**
* @param array<string,mixed> $options
*/
public function build(ContentRepositoryId $contentRepositoryId, array $options): ContentDimensionSourceInterface
{
if (!self::$contentDimensionsToUse) {
throw new \DomainException('Content dimension source not initialized.');
$contentDimensionSource = file_get_contents(self::cacheFileName($contentRepositoryId));
if ($contentDimensionSource === false) {
throw new \RuntimeException(sprintf('Content dimension source uninitialized for ContentRepository "%s"', $contentRepositoryId->value));
}
return self::$contentDimensionsToUse;
return unserialize($contentDimensionSource);
}

public static function initializeFromTableNode(TableNode $contentDimensionsToUse): void
public static function reset(): void
{
self::$contentDimensionsToUse = GherkinTableNodeBasedContentDimensionSource::fromGherkinTableNode($contentDimensionsToUse);
}

public static function reset(): void
private static function cacheFileName(ContentRepositoryId $contentRepositoryId): string
{
self::$contentDimensionsToUse = null;
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'contentDimensionsConfiguration_' . $contentRepositoryId->value . '.json';
}
}
3 changes: 2 additions & 1 deletion Neos.ContentRepository.BehavioralTests/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"GPL-3.0-or-later"
],
"require": {
"neos/contentrepository-core": "self.version"
"neos/contentrepository-core": "self.version",
"neos/contentrepositoryregistry": "*"
},
"autoload": {
"psr-4": {
Expand Down
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"neos/flow-development-collection": "9.0.x-dev",
"doctrine/dbal": "^2.8",
"doctrine/migrations": "*",
"neos/eventstore": "~1.0.0",
"neos/eventstore-doctrineadapter": "~1.0.0",
"neos/eventstore": "^1",
"neos/eventstore-doctrineadapter": "^1 || ^2",
"php": "^8.2",
"neos/error-messages": "*",
"neos/utility-objecthandling": "*",
Expand Down Expand Up @@ -116,7 +116,10 @@
"test:functional": [
"../../bin/phpunit --colors --stop-on-failure -c ../../Build/BuildEssentials/PhpUnit/FunctionalTests.xml Neos.ContentRepository.Core/Tests/Functional"
],
"test:behat-cli": "../../bin/behat -f progress --strict --no-interaction",
"test:behat-cli": [
"Composer\\Config::disableProcessTimeout",
"../../bin/behat -f progress --strict --no-interaction"
],
"test:behavioral": [
"@test:behat-cli -c Neos.ContentRepository.BehavioralTests/Tests/Behavior/behat.yml.dist",
"@test:behat-cli -c Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/behat.yml.dist",
Expand Down
Loading