Skip to content

Commit

Permalink
TASK: Introduce NodeWithContentStreamId for testing
Browse files Browse the repository at this point in the history
We cannot rely on $this->currentContentStreamId being the matching one for $this->currentNode, because the step

`I expect a node identified by live-cs-identifier;lady-eleonode-nodesworth;{} to exist in the content graph`

can initialize a foreign node!
  • Loading branch information
mhsdesign committed Jun 16, 2024
1 parent 6e29ec5 commit 313656c
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
Expand All @@ -30,6 +29,8 @@
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\FakeClock;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\FakeUserIdProvider;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\NodeWithContentStreamId;
use PHPUnit\Framework\Assert;

/**
* The node creation trait for behavioral tests
Expand All @@ -50,7 +51,11 @@ trait CRTestSuiteRuntimeVariables

protected ?\Exception $lastCommandException = null;

protected ?Node $currentNode = null;
/**
* The Node's content stream id doesn't necessarily have to match with {@see $currentContentStreamId} if the node was initialized via the content graph from another workspace
* thus we have to track it as well.
*/
protected ?NodeWithContentStreamId $currentNode = null;

protected ?NodeAggregate $currentNodeAggregate = null;

Expand Down Expand Up @@ -182,7 +187,12 @@ public function iRememberNodeAggregateIdOfNodesChildAs(string $parentNodeAggrega

protected function getCurrentNodeAggregateId(): NodeAggregateId
{
assert($this->currentNode instanceof Node);
$this->expectCurrentNode();
return $this->currentNode->aggregateId;
}

protected function expectCurrentNode(): void
{
Assert::assertNotNull($this->currentNode, 'No current node present');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function theCommandCopyNodesRecursivelyIsExecutedCopyingTheCurrentNodeAgg
$command = CopyNodesRecursively::createFromSubgraphAndStartNode(
$subgraph,
$workspaceName,
$this->currentNode,
$this->currentNode->instance,
$targetDimensionSpacePoint,
NodeAggregateId::fromString($commandArguments['targetParentNodeAggregateId']),
$targetSucceedingSiblingNodeAggregateId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ private function __construct(
) {
}

public static function create(ContentStreamId $contentStreamId, OriginDimensionSpacePoint $originDimensionSpacePoint, NodeAggregateId $aggregateId): self
{
return new self(
$contentStreamId,
$aggregateId,
$originDimensionSpacePoint
);
}

public static function fromShorthand(string $shorthand): self
{
list($contentStreamId, $nodeAggregateId, $originDimensionSpacePoint) = explode(';', $shorthand);
Expand All @@ -48,26 +57,12 @@ public static function fromShorthand(string $shorthand): self
);
}

/** @deprecated will be removed */
public static function fromNode(Node $node): self
public static function fromNode(NodeWithContentStreamId $decorated): self
{
return new self(
$node->subgraphIdentity->contentStreamId,
$node->aggregateId,
$node->originDimensionSpacePoint
);
}

public static function fromNodeAndContentGraph(Node $node, ContentGraphInterface $contentGraph): self
{
if (!$node->workspaceName->equals($contentGraph->getWorkspaceName())) {
throw new \InvalidArgumentException(sprintf('Expected nodes workspace %s to match given subgraph workspace %s.', $node->workspaceName->value, $contentGraph->getWorkspaceName()->value), 1718554466);
}

return new self(
$contentGraph->getContentStreamId(),
$node->aggregateId,
$node->originDimensionSpacePoint
$decorated->contentStreamId,
$decorated->instance->aggregateId,
$decorated->instance->originDimensionSpacePoint
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers;

use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;

final readonly class NodeWithContentStreamId
{
private function __construct(
public NodeAggregateId $aggregateId,
public Node $instance,
public ContentStreamId $contentStreamId,
) {
}

public static function create(Node $node, ContentStreamId $contentStreamId): self
{
return new self($node->aggregateId, $node, $contentStreamId);
}

public function withNode(Node $node): self
{
return new self($node->aggregateId, $node, $this->contentStreamId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
use Neos\ContentRepository\Core\SharedModel\Node\PropertyName;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\DayOfWeek;
use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\PostalAddress;
use Neos\ContentRepository\Core\Tests\Behavior\Fixtures\PriceSpecification;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\NodeDiscriminator;
use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\NodeWithContentStreamId;
use PHPUnit\Framework\Assert;

/**
Expand Down Expand Up @@ -96,7 +98,8 @@ public function iExpectANodeIdentifiedByXToExistInTheContentGraph(string $serial
. '" and originating in dimension space point "' . $nodeDiscriminator->originDimensionSpacePoint->toJson()
. '" was not found in content stream "' . $nodeDiscriminator->contentStreamId->value . '"'
);
$this->currentNode = $currentNodeAggregate->getNodeByOccupiedDimensionSpacePoint($nodeDiscriminator->originDimensionSpacePoint);
$node = $currentNodeAggregate->getNodeByOccupiedDimensionSpacePoint($nodeDiscriminator->originDimensionSpacePoint);
$this->currentNode = NodeWithContentStreamId::create($node, $nodeDiscriminator->contentStreamId);
}

/**
Expand All @@ -108,10 +111,10 @@ public function iExpectNodeAggregateIdToLeadToNode(
): void {
$nodeAggregateId = NodeAggregateId::fromString($serializedNodeAggregateId);
$expectedDiscriminator = NodeDiscriminator::fromShorthand($serializedNodeDiscriminator);
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph) use ($nodeAggregateId, $expectedDiscriminator) {
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph, ContentStreamId $currentContentStreamId) use ($nodeAggregateId, $expectedDiscriminator) {
$currentNode = $subgraph->findNodeById($nodeAggregateId);
Assert::assertNotNull($currentNode, 'No node could be found by node aggregate id "' . $nodeAggregateId->value . '" in content subgraph "' . $this->currentDimensionSpacePoint->toJson() . '@' . $this->currentWorkspaceName->value . '"');
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode);
$actualDiscriminator = NodeDiscriminator::create($currentContentStreamId, $currentNode->originDimensionSpacePoint, $currentNode->aggregateId);
Assert::assertTrue($expectedDiscriminator->equals($actualDiscriminator), 'Node discriminators do not match. Expected was ' . json_encode($expectedDiscriminator) . ' , given was ' . json_encode($actualDiscriminator));
return $currentNode;
});
Expand Down Expand Up @@ -145,10 +148,10 @@ public function iExpectPathToLeadToNode(string $serializedNodePath, string $seri
}
$nodePath = NodePath::fromString($serializedNodePath);
$expectedDiscriminator = NodeDiscriminator::fromShorthand($serializedNodeDiscriminator);
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph) use ($nodePath, $expectedDiscriminator) {
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph, ContentStreamId $currentContentStreamId) use ($nodePath, $expectedDiscriminator) {
$currentNode = $subgraph->findNodeByPath($nodePath, $this->getRootNodeAggregateId());
Assert::assertNotNull($currentNode, 'No node could be found by node path "' . $nodePath->serializeToString() . '" in content subgraph "' . $this->currentDimensionSpacePoint->toJson() . '@' . $this->currentWorkspaceName->value . '"');
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode);
$actualDiscriminator = NodeDiscriminator::create($currentContentStreamId, $currentNode->originDimensionSpacePoint, $currentNode->aggregateId);
Assert::assertTrue($expectedDiscriminator->equals($actualDiscriminator), 'Node discriminators do not match. Expected was ' . json_encode($expectedDiscriminator) . ' , given was ' . json_encode($actualDiscriminator));
return $currentNode;
});
Expand Down Expand Up @@ -275,9 +278,16 @@ public function iExpectThisNodeToExactlyInheritTheTags(string $expectedTagList):
});
}

/**
* @param callable(ContentSubgraphInterface $subgraph, ContentStreamId $currentContentStreamId): Node $query
*/
protected function initializeCurrentNodeFromContentSubgraph(callable $query): void
{
$this->currentNode = $query($this->getCurrentSubgraph());
$contentGraph = $this->getCurrentContentGraph();
$node = $query($this->getCurrentSubgraph($contentGraph), $contentGraph->getContentStreamId());
$this->currentNode = NodeWithContentStreamId::create(
$node, $contentGraph->getContentStreamId()
);
}

/**
Expand Down Expand Up @@ -457,15 +467,15 @@ public function iExpectThisNodeToHaveNoReferences(): void
public function iExpectThisNodeToBeReferencedBy(TableNode $expectedReferences): void
{
$contentGraph = $this->getCurrentContentGraph();
$this->assertOnCurrentNode(function (Node $currentNode) use ($expectedReferences, $contentGraph) {
$this->assertOnCurrentNodeWithContentStreamId(function (NodeWithContentStreamId $currentNode) use ($expectedReferences, $contentGraph) {
$actualReferences = $this->getCurrentSubgraph($contentGraph)
->findBackReferences($currentNode->aggregateId, FindBackReferencesFilter::create());

$this->assertReferencesMatch($expectedReferences, $actualReferences, $contentGraph);
$this->assertReferencesMatch($expectedReferences, $actualReferences, $currentNode->contentStreamId);
});
}

private function assertReferencesMatch(TableNode $expectedReferencesTable, References $actualReferences, ContentGraphInterface $contentGraph): void
private function assertReferencesMatch(TableNode $expectedReferencesTable, References $actualReferences, ContentStreamId $actualContentStreamId): void
{
$expectedReferences = $expectedReferencesTable->getHash();
Assert::assertSame(
Expand All @@ -481,7 +491,7 @@ private function assertReferencesMatch(TableNode $expectedReferencesTable, Refer
$actualReferences[$index]->name->value
);
$expectedReferenceDiscriminator = NodeDiscriminator::fromShorthand($row['Node']);
$actualReferenceDiscriminator = NodeDiscriminator::fromNodeAndContentGraph($actualReferences[$index]->node, $contentGraph);
$actualReferenceDiscriminator = NodeDiscriminator::create($actualContentStreamId, $actualReferences[$index]->node->originDimensionSpacePoint, $actualReferences[$index]->node->aggregateId);
Assert::assertTrue(
$expectedReferenceDiscriminator->equals($actualReferenceDiscriminator),
'Reference discriminator does not match.'
Expand Down Expand Up @@ -550,17 +560,17 @@ public function iExpectThisNodeToNotBeReferenced(): void
public function iExpectThisNodeToBeTheChildOfNode(string $serializedParentNodeDiscriminator): void
{
$expectedParentDiscriminator = NodeDiscriminator::fromShorthand($serializedParentNodeDiscriminator);
$this->assertOnCurrentNode(function (Node $currentNode) use ($expectedParentDiscriminator) {
$this->assertOnCurrentNodeWithContentStreamId(function (NodeWithContentStreamId $currentNode) use ($expectedParentDiscriminator) {
$subgraph = $this->getCurrentSubgraph();

$parent = $subgraph->findParentNode($currentNode->aggregateId);
Assert::assertInstanceOf(Node::class, $parent, 'Parent not found.');
$actualParentDiscriminator = NodeDiscriminator::fromNode($parent);
$actualParentDiscriminator = NodeDiscriminator::fromNode($currentNode->withNode($parent));
Assert::assertTrue($expectedParentDiscriminator->equals($actualParentDiscriminator), 'Parent discriminator does not match. Expected was ' . json_encode($expectedParentDiscriminator) . ', given was ' . json_encode($actualParentDiscriminator));

$expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode);
$child = $subgraph->findNodeByPath($currentNode->name, $parent->aggregateId);
$actualChildDiscriminator = NodeDiscriminator::fromNode($child);
$child = $subgraph->findNodeByPath($currentNode->instance->name, $parent->aggregateId);
$actualChildDiscriminator = NodeDiscriminator::fromNode($currentNode->withNode($child));
Assert::assertTrue($expectedChildDiscriminator->equals($actualChildDiscriminator), 'Child discriminator does not match. Expected was ' . json_encode($expectedChildDiscriminator) . ', given was ' . json_encode($actualChildDiscriminator));
});
}
Expand All @@ -583,7 +593,7 @@ public function iExpectThisNodeToHaveNoParentNode(): void
*/
public function iExpectThisNodeToHaveTheFollowingChildNodes(TableNode $expectedChildNodesTable): void
{
$this->assertOnCurrentNode(function (Node $currentNode) use ($expectedChildNodesTable) {
$this->assertOnCurrentNodeWithContentStreamId(function (NodeWithContentStreamId $currentNode) use ($expectedChildNodesTable) {
$subgraph = $this->getCurrentSubgraph();
$actualChildNodes = [];
foreach ($subgraph->findChildNodes($currentNode->aggregateId, FindChildNodesFilter::create()) as $actualChildNode) {
Expand All @@ -598,7 +608,7 @@ public function iExpectThisNodeToHaveTheFollowingChildNodes(TableNode $expectedC
Assert::assertTrue($expectedNodeName->equals($actualNodeName), 'ContentSubgraph::findChildNodes: Node name in index ' . $index . ' does not match. Expected: "' . $expectedNodeName->value . '" Actual: "' . $actualNodeName->value . '"');
if (isset($row['NodeDiscriminator'])) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualChildNodes[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($currentNode->withNode($actualChildNodes[$index]));
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findChildNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator->jsonSerialize()) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
}
Expand All @@ -624,7 +634,7 @@ public function iExpectThisNodeToHaveNoChildNodes(): void
*/
public function iExpectThisNodeToHaveTheFollowingPrecedingSiblings(TableNode $expectedPrecedingSiblingsTable): void
{
$this->assertOnCurrentNode(function (Node $currentNode) use ($expectedPrecedingSiblingsTable) {
$this->assertOnCurrentNodeWithContentStreamId(function (NodeWithContentStreamId $currentNode) use ($expectedPrecedingSiblingsTable) {
$actualSiblings = [];
foreach (
$this->getCurrentSubgraph()->findPrecedingSiblingNodes(
Expand All @@ -637,7 +647,7 @@ public function iExpectThisNodeToHaveTheFollowingPrecedingSiblings(TableNode $ex
Assert::assertCount(count($expectedPrecedingSiblingsTable->getHash()), $actualSiblings, 'ContentSubgraph::findPrecedingSiblingNodes: Sibling count does not match');
foreach ($expectedPrecedingSiblingsTable->getHash() as $index => $row) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualSiblings[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($currentNode->withNode($actualSiblings[$index]));
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findPrecedingSiblingNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
});
Expand All @@ -661,7 +671,7 @@ public function iExpectThisNodeToHaveNoPrecedingSiblings(): void
*/
public function iExpectThisNodeToHaveTheFollowingSucceedingSiblings(TableNode $expectedSucceedingSiblingsTable): void
{
$this->assertOnCurrentNode(function (Node $currentNode) use ($expectedSucceedingSiblingsTable) {
$this->assertOnCurrentNodeWithContentStreamId(function (NodeWithContentStreamId $currentNode) use ($expectedSucceedingSiblingsTable) {
$actualSiblings = [];
foreach (
$this->getCurrentSubgraph()->findSucceedingSiblingNodes(
Expand All @@ -674,7 +684,7 @@ public function iExpectThisNodeToHaveTheFollowingSucceedingSiblings(TableNode $e
Assert::assertCount(count($expectedSucceedingSiblingsTable->getHash()), $actualSiblings, 'ContentSubgraph::findSucceedingSiblingNodes: Sibling count does not match');
foreach ($expectedSucceedingSiblingsTable->getHash() as $index => $row) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualSiblings[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($currentNode->withNode($actualSiblings[$index]));
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findSucceedingSiblingNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
});
Expand All @@ -692,14 +702,15 @@ public function iExpectThisNodeToHaveNoSucceedingSiblings(): void
});
}

protected function assertOnCurrentNode(callable $assertions): void
protected function assertOnCurrentNodeWithContentStreamId(callable $assertions): void
{
$this->expectCurrentNode();
$assertions($this->currentNode);
}

protected function expectCurrentNode(): void
protected function assertOnCurrentNode(callable $assertions): void
{
Assert::assertNotNull($this->currentNode, 'No current node present');
$this->expectCurrentNode();
$assertions($this->currentNode->instance);
}
}

0 comments on commit 313656c

Please sign in to comment.