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

add table printer / BDD step for creating persistent resource / asset fixtures #18

Merged
merged 4 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 14 additions & 1 deletion Classes/StepGenerator/GherkinTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,23 @@ public function print()
echo ' ';
foreach ($row as $i => $value) {
echo ' | ';
echo str_pad($value, $this->maxColumnWidth[$i]);
echo self::escapeGherkinTableCellValue(str_pad($value, $this->maxColumnWidth[$i]));
}
echo ' |';
echo "\n";
}
}

public function isEmpty(): bool {
return count($this->rows) === 0;
}

private static function escapeGherkinTableCellValue(?string $value): ?string
{
if ($value === null) {
return null;
} else {
return str_replace('|', '\|', $value);
}
}
}
64 changes: 64 additions & 0 deletions Classes/StepGenerator/ImageTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Sandstorm\E2ETestTools\StepGenerator;

use Neos\Media\Domain\Model\ImageInterface;

/**
* Builder for printing a persistent resource fixture gherkin table.
*/
class ImageTable
{

private static array $IMAGE_DEFAULT_HEADER = [
'Image ID',
'Width',
'Height'
];

private GherkinTable $gherkinTable;
private PersistentResourceFixtures $persistentResourceFixtures;

private array $defaultProperties;

public function __construct(PersistentResourceFixtures $persistentResourceFixtures, array $defaultProperties = [])
{
$this->persistentResourceFixtures = $persistentResourceFixtures;
$this->defaultProperties = $defaultProperties;
$this->gherkinTable = new GherkinTable(
array_merge(
self::$IMAGE_DEFAULT_HEADER,
array_keys($defaultProperties),
PersistentResourceFixtures::$PERSISTENT_RESOURCE_DEFAULT_HEADER
)
);
}

public function addImage(string $objectIdentifier, ImageInterface $image): void
{
$persistentResourceCells = $this->persistentResourceFixtures->addPersistentResource($image->getResource());
$imageCells = array_merge(
$this->defaultProperties,
[
'Image ID' => $objectIdentifier,
'Width' => $image->getWidth(),
'Height' => $image->getHeight()
],
$persistentResourceCells
);
$this->gherkinTable->addRow($imageCells);
}

public function print(): void
{
if ($this->gherkinTable->isEmpty()) {
echo '# I have no images';
echo "\n";
return;
}
echo 'Given I have the following images:';
echo "\n";
$this->gherkinTable->print();
}

}
50 changes: 44 additions & 6 deletions Classes/StepGenerator/NodeTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@
namespace Sandstorm\E2ETestTools\StepGenerator;

use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Media\Domain\Model\ImageInterface;
use Neos\Media\Domain\Model\ResourceBasedInterface;
use Neos\Utility\ObjectAccess;
use Neos\Utility\TypeHandling;

/**
*
* @internal
*/
class NodeTable
{
private GherkinTable $gherkinTable;
private GherkinTable $nodeTable;
private PersistentResourceFixtures $persistentResourceFixtures;
private ImageTable $imageTable;

private array $defaultProperties;

public function __construct(array $defaultProperties = [])
public function __construct(array $defaultProperties = [], ?string $fixtureBasePath = null, array $defaultPersistentResourceProperties = [], array $defaultImageProperties = [])
{
$this->defaultProperties = $defaultProperties;
$this->gherkinTable = new GherkinTable(array_merge([
$this->nodeTable = new GherkinTable(array_merge([
'Path',
'Node Type',
'Properties',
'HiddenInIndex'
], array_keys($defaultProperties)));
$this->persistentResourceFixtures = new PersistentResourceFixtures($fixtureBasePath, $defaultPersistentResourceProperties);
$this->imageTable = new ImageTable($this->persistentResourceFixtures, $defaultImageProperties);
}

public function addNode(NodeInterface $node): void
Expand All @@ -34,14 +42,39 @@ public function addNode(NodeInterface $node): void
if ($node->isAutoCreated()) {
return;
}
$this->gherkinTable->addRow(array_merge($this->defaultProperties, [
$this->nodeTable->addRow(array_merge($this->defaultProperties, [
'Path' => $node->getPath(),
'Node Type' => $node->getNodeType()->getName(),
'Properties' => json_encode($node->getNodeData()->getProperties()),
'Properties' => $this->serializeNodeProperties($node),
'HiddenInIndex' => $node->isHiddenInIndex() ? 'true' : 'false'
]));
}

private function serializeNodeProperties(NodeInterface $node): string
{
$properties = $node->getNodeData()->getProperties();
$propertiesSerialized = [];
foreach ($properties as $propertyName => $propertyValue) {
if ($propertyValue instanceof ResourceBasedInterface) {
$objectType = TypeHandling::getTypeForValue($propertyValue);
$objectIdentifier = ObjectAccess::getProperty($propertyValue, 'Persistence_Object_Identifier', true);
$serializedReference = [
'__flow_object_type' => $objectType,
'__identifier' => $objectIdentifier
];
$propertiesSerialized[$propertyName] = $serializedReference;
// keep track of external resources that needs to be stored as fixtures later
if ($propertyValue instanceof ImageInterface) {
// add image
$this->imageTable->addImage($objectIdentifier, $propertyValue);
}
} else {
$propertiesSerialized[$propertyName] = $propertyValue;
}
}
return json_encode($propertiesSerialized);
}

/**
* Auto generated child-nodes are excluded here. But we don't need them anyways, since they
* are created automatically during import based on the node type yaml.
Expand Down Expand Up @@ -76,8 +109,13 @@ public function addParents(NodeInterface $node): void

public function print(): void
{
$this->persistentResourceFixtures->storeFixtures();

$this->imageTable->print();

echo 'Given I have the following nodes:';
echo "\n";
$this->gherkinTable->print();
$this->nodeTable->print();
}

}
78 changes: 78 additions & 0 deletions Classes/StepGenerator/PersistentResourceFixtures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Sandstorm\E2ETestTools\StepGenerator;

use Neos\Flow\ResourceManagement\PersistentResource;

/**
* Model for persistent resources fixtures collected in a NodeTable.
*/
class PersistentResourceFixtures
{

public static array $PERSISTENT_RESOURCE_DEFAULT_HEADER = [
'Filename',
'Collection',
'Relative Publication Path',
'Path'
];

private ?string $fixtureBasePath;

private array $defaultProperties = [];
private array $fixtureResources = [];

public function __construct(?string $fixtureBasePath, array $defaultProperties = [])
{
$this->fixtureBasePath = $fixtureBasePath . (str_ends_with($fixtureBasePath, '/') ? '' : '/');
$this->defaultProperties = $defaultProperties;
}

/**
* Adds a persistent resource to the fixtures for later storing.
* Returns the gherkin table cells of the PersistentResource to be printed in a Media fixture table row.
*
* @param PersistentResource $persistentResource
* @return array the PersistentResource table cells
*/
public function addPersistentResource(PersistentResource $persistentResource): array
{
if ($this->fixtureBasePath === null) {
throw new \Exception("No fixture base path given for NodeTable");
}
$fixturePath = $this->fixtureBasePath . $persistentResource->getSha1() . '.' . $persistentResource->getFileExtension();
if (!array_key_exists($persistentResource->getSha1(), $this->fixtureResources)) {
$this->fixtureResources[$persistentResource->getSha1()] = [
'object' => $persistentResource,
'path' => $fixturePath
];
}
return array_merge($this->defaultProperties, [
'Filename' => $persistentResource->getFilename(),
'Collection' => $persistentResource->getCollectionName(),
'Relative Publication Path' => $persistentResource->getRelativePublicationPath(),
'Path' => $fixturePath
]);
}

public function storeFixtures(): void
{
if (count($this->fixtureResources) === 0) {
return;
}
if (!file_exists($this->fixtureBasePath)) {
mkdir($this->fixtureBasePath, 0777, true);
}
foreach ($this->fixtureResources as $sha1 => $persistentResourceObjectAndPath) {
$path = $persistentResourceObjectAndPath['path'];
if (!file_exists($path)) {
/**
* @var PersistentResource $persistentResource
*/
$persistentResource = $persistentResourceObjectAndPath['object'];
file_put_contents($path, $persistentResource->getStream());
}
}
}

}
Loading