diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php index 6642d015bf7..9f54f1decaf 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php @@ -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; @@ -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 @@ -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; @@ -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'); + } } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php index 6c68de67e35..a51e3d0b87b 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Features/NodeCopying.php @@ -59,7 +59,7 @@ public function theCommandCopyNodesRecursivelyIsExecutedCopyingTheCurrentNodeAgg $command = CopyNodesRecursively::createFromSubgraphAndStartNode( $subgraph, $workspaceName, - $this->currentNode, + $this->currentNode->instance, $targetDimensionSpacePoint, NodeAggregateId::fromString($commandArguments['targetParentNodeAggregateId']), $targetSucceedingSiblingNodeAggregateId, diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeDiscriminator.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeDiscriminator.php index 8539c8c4cf5..934a48899c6 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeDiscriminator.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeDiscriminator.php @@ -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); @@ -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 ); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeWithContentStreamId.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeWithContentStreamId.php new file mode 100644 index 00000000000..aa58916ce0b --- /dev/null +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/Helpers/NodeWithContentStreamId.php @@ -0,0 +1,29 @@ +aggregateId, $node, $contentStreamId); + } + + public function withNode(Node $node): self + { + return new self($node->aggregateId, $node, $this->contentStreamId); + } +} diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php index 3eeb6cbc538..b772bd428b5 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php @@ -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; /** @@ -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); } /** @@ -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; }); @@ -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; }); @@ -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() + ); } /** @@ -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( @@ -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.' @@ -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)); }); } @@ -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) { @@ -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)); } } @@ -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( @@ -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)); } }); @@ -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( @@ -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)); } }); @@ -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); } }