Skip to content

Commit 7261937

Browse files
committed
TASK: Resolve persistence issues in tests
1 parent d295bcb commit 7261937

File tree

7 files changed

+152
-22
lines changed

7 files changed

+152
-22
lines changed

.github/workflows/tests.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ jobs:
7575
php-versions: ['8.2']
7676
flow-versions: ['9.0']
7777

78+
services:
79+
mariadb:
80+
# see https://mariadb.com/kb/en/mariadb-server-release-dates/
81+
# this should be a current release, e.g. the LTS version
82+
image: mariadb:10.8
83+
env:
84+
MYSQL_USER: neos
85+
MYSQL_PASSWORD: neos
86+
MYSQL_DATABASE: neos_functional_testing
87+
MYSQL_ROOT_PASSWORD: neos
88+
ports:
89+
- "3306:3306"
90+
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
91+
7892
steps:
7993
- uses: actions/checkout@v3
8094

@@ -116,11 +130,37 @@ jobs:
116130
cd ${FLOW_FOLDER}
117131
bin/phpunit --colors -c Build/BuildEssentials/PhpUnit/UnitTests.xml Packages/Application/Flowpack.Media.Ui/Tests/Unit/
118132
133+
- name: Setup Flow configuration
134+
run: |
135+
cd ${FLOW_FOLDER}
136+
rm -f Configuration/Testing/Settings.yaml
137+
cat <<EOF >> Configuration/Testing/Settings.yaml
138+
Neos:
139+
Flow:
140+
persistence:
141+
backendOptions:
142+
host: '127.0.0.1'
143+
driver: pdo_mysql
144+
user: 'neos'
145+
password: 'neos'
146+
dbname: 'neos_functional_testing'
147+
EOF
148+
119149
- name: Run Functional tests
120150
run: |
121151
cd ${FLOW_FOLDER}
122152
bin/phpunit --colors -c Build/BuildEssentials/PhpUnit/FunctionalTests.xml Packages/Application/Flowpack.Media.Ui/Tests/Functional/
123153
154+
- name: Show log on failure
155+
if: ${{ failure() }}
156+
run: |
157+
cd ${FLOW_PATH_ROOT}
158+
cat Data/Logs/System_Testing.log
159+
for file in Data/Logs/Exceptions/*; do
160+
echo $file
161+
cat $file
162+
done
163+
124164
js-unit-tests:
125165
runs-on: ubuntu-latest
126166

Classes/GraphQL/Types/AssetCollection.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ private function __construct(
1717
public readonly ?AssetCollectionPath $path = null,
1818
) {
1919
}
20+
21+
public function equals(?AssetCollection $assetCollection): bool
22+
{
23+
return $assetCollection !== null && $this->id->equals($assetCollection->id);
24+
}
2025
}

Classes/GraphQL/Types/AssetCollectionId.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,9 @@ public function isUnassigned(): bool
3838
{
3939
return $this->value === self::UNASSIGNED;
4040
}
41+
42+
public function equals(?AssetCollectionId $id): bool
43+
{
44+
return $this->value === $id?->value;
45+
}
4146
}

Classes/GraphQL/Types/AssetCollections.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#[ListBased(itemClassName: AssetCollection::class)]
1414
final class AssetCollections implements \IteratorAggregate
1515
{
16+
/**
17+
* @param AssetCollection[] $collections
18+
*/
1619
private function __construct(public readonly array $collections)
1720
{
1821
}

Tests/Functional/AbstractMediaTestCase.php

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
namespace Flowpack\Media\Ui\Tests\Functional;
34

45
/*
@@ -12,6 +13,7 @@
1213
*/
1314

1415
use Flowpack\Media\Ui\GraphQL\Types;
16+
use Neos\Behat\FlowEntitiesTrait;
1517
use Neos\Flow\Persistence\PersistenceManagerInterface;
1618
use Neos\Flow\ResourceManagement\PersistentResource;
1719
use Neos\Flow\ResourceManagement\ResourceManager;
@@ -27,6 +29,7 @@
2729
abstract class AbstractMediaTestCase extends FunctionalTestCase
2830
{
2931
use SecurityOperationsTrait;
32+
use FlowEntitiesTrait;
3033

3134
/**
3235
* @var string
@@ -38,43 +41,98 @@ abstract class AbstractMediaTestCase extends FunctionalTestCase
3841
*/
3942
protected $resourceManager;
4043

44+
protected function setUp(): void
45+
{
46+
$this->objectManager = self::$bootstrap->getObjectManager();
47+
48+
$this->truncateAndSetupFlowEntities();
49+
50+
$this->cleanupPersistentResourcesDirectory();
51+
self::$bootstrap->getObjectManager()->forgetInstance(ResourceManager::class);
52+
$session = $this->objectManager->get(\Neos\Flow\Session\SessionInterface::class);
53+
if ($session->isStarted()) {
54+
$session->destroy(
55+
sprintf(
56+
'assure that session is fresh, in setUp() method of functional test %s.',
57+
get_class($this) . '::' . $this->getName()
58+
)
59+
);
60+
}
61+
62+
$privilegeManager = $this->objectManager->get(\Neos\Flow\Security\Authorization\TestingPrivilegeManager::class);
63+
$privilegeManager->reset();
64+
65+
if ($this->testableSecurityEnabled === true || static::$testablePersistenceEnabled === true) {
66+
$this->persistenceManager = $this->objectManager->get(
67+
PersistenceManagerInterface::class
68+
);
69+
} else {
70+
$privilegeManager->setOverrideDecision(true);
71+
}
72+
73+
// HTTP must be initialized before Session and Security because they rely
74+
// on an HTTP request being available via the request handler:
75+
$this->setupHttp();
76+
77+
$session = $this->objectManager->get(\Neos\Flow\Session\SessionInterface::class);
78+
if ($session->isStarted()) {
79+
$session->destroy(
80+
sprintf(
81+
'assure that session is fresh, in setUp() method of functional test %s.',
82+
get_class($this) . '::' . $this->getName()
83+
)
84+
);
85+
}
86+
87+
$this->setupSecurity();
88+
}
89+
90+
protected function persist(): void
91+
{
92+
$this->persistenceManager->persistAll();
93+
$this->persistenceManager->clearState();
94+
}
95+
4196
public function tearDown(): void
4297
{
43-
$persistenceManager = self::$bootstrap->getObjectManager()->get(PersistenceManagerInterface::class);
44-
if (is_callable([$persistenceManager, 'tearDown'])) {
45-
$persistenceManager->tearDown();
98+
try {
99+
$this->persistenceManager->persistAll();
100+
} catch (\Exception $exception) {
46101
}
47-
self::$bootstrap->getObjectManager()->forgetInstance(PersistenceManagerInterface::class);
48-
parent::tearDown();
102+
103+
//if (is_callable([$this->persistenceManager, 'tearDown'])) {
104+
// $this->persistenceManager->tearDown();
105+
//}
106+
//$persistenceManager = self::$bootstrap->getObjectManager()->get(PersistenceManagerInterface::class);
107+
//if (is_callable([$persistenceManager, 'tearDown'])) {
108+
// $persistenceManager->tearDown();
109+
//}
110+
//self::$bootstrap->getObjectManager()->forgetInstance(PersistenceManagerInterface::class);
111+
//parent::tearDown();
49112
}
50113

51114
/**
52115
* Creates an Image object from a file using a mock resource (in order to avoid a database resource pointer entry)
53-
* @param string $imagePathAndFilename
54-
* @return PersistentResource
55116
*/
56-
protected function getMockResourceByImagePath($imagePathAndFilename)
117+
protected function getMockResourceByImagePath(string $imagePathAndFilename): PersistentResource
57118
{
58119
$imagePathAndFilename = Files::getUnixStylePath($imagePathAndFilename);
59120
$hash = sha1_file($imagePathAndFilename);
60121
copy($imagePathAndFilename, 'resource://' . $hash);
61-
return $mockResource = $this->createMockResourceAndPointerFromHash($hash);
122+
return $this->createMockResourceAndPointerFromHash($hash);
62123
}
63124

64125
/**
65126
* Creates a mock ResourcePointer and PersistentResource from a given hash.
66127
* Make sure that a file representation already exists, e.g. with
67128
* file_put_content('resource://' . $hash) before
68-
*
69-
* @param string $hash
70-
* @return PersistentResource
71129
*/
72-
protected function createMockResourceAndPointerFromHash($hash)
130+
protected function createMockResourceAndPointerFromHash(string $hash): PersistentResource
73131
{
74132
$mockResource = $this->getMockBuilder(PersistentResource::class)->setMethods(['getHash', 'getUri'])->getMock();
75133
$mockResource->expects(self::any())
76-
->method('getHash')
77-
->will(self::returnValue($hash));
134+
->method('getHash')
135+
->will(self::returnValue($hash));
78136
$mockResource->expects(self::any())
79137
->method('getUri')
80138
->will(self::returnValue('resource://' . $hash));
@@ -83,11 +141,12 @@ protected function createMockResourceAndPointerFromHash($hash)
83141

84142
/**
85143
* Builds a temporary directory to work on.
86-
* @return void
87144
*/
88-
protected function prepareTemporaryDirectory()
145+
protected function prepareTemporaryDirectory(): void
89146
{
90-
$this->temporaryDirectory = Files::concatenatePaths([FLOW_PATH_DATA, 'Temporary', 'Testing', str_replace('\\', '_', __CLASS__)]);
147+
$this->temporaryDirectory = Files::concatenatePaths(
148+
[FLOW_PATH_DATA, 'Temporary', 'Testing', str_replace('\\', '_', __CLASS__)]
149+
);
91150
if (!file_exists($this->temporaryDirectory)) {
92151
Files::createDirectoryRecursively($this->temporaryDirectory);
93152
}

Tests/Functional/GraphQL/AssetCollectionApiTest.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,36 @@ public function testCreateAssetCollection(): void
5656

5757
$this->assertInstanceOf(Types\AssetCollection::class, $childCollection);
5858
$this->assertTrue(str_starts_with($childCollection->path->value, $assetCollection->path->value));
59+
60+
$this->persist();
61+
62+
$assetCollections = $this->mediaApi->assetCollections();
63+
$this->assertNotEmpty($assetCollections->collections);
64+
65+
// Assert that the created asset collection is in the list of asset collections
66+
$foundCollection = false;
67+
foreach ($assetCollections->collections as $collection) {
68+
if ($collection->equals($assetCollection)) {
69+
$foundCollection = true;
70+
break;
71+
}
72+
}
73+
$this->assertTrue($foundCollection, 'The created asset collection was not found in the list of asset collections.');
5974
}
6075

6176
public function testDeleteAssetCollection(): void
6277
{
6378
$assetCollection = $this->mediaApi->createAssetCollection(
6479
Types\AssetCollectionTitle::fromString('Test Collection'),
6580
);
66-
$result = $this->mediaApi->deleteAssetCollection($assetCollection->id);
6781

82+
$result = $this->mediaApi->deleteAssetCollection($assetCollection->id);
6883
$this->assertTrue($result->success);
6984

70-
$assetCollection = $this->mediaApi->assetCollection($assetCollection->id);
71-
$this->assertNull($assetCollection);
85+
$this->persist();
86+
87+
$deletedAssetCollection = $this->mediaApi->assetCollection($assetCollection->id);
88+
$this->assertNull($deletedAssetCollection);
7289
}
7390

7491
public function testDeleteNonExistingAssetCollection(): void

Tests/Functional/GraphQL/TagApiTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ public function testDeleteTag(): void
6363
{
6464
$tag = $this->mediaApi->createTag(Types\TagLabel::fromString('Test Tag'));
6565
$result = $this->mediaApi->deleteTag($tag->id);
66-
6766
$this->assertTrue($result->success);
6867

68+
$this->persist();
69+
6970
$deletedTag = $this->mediaApi->tag($tag->id);
7071
$this->assertNull($deletedTag);
7172
}

0 commit comments

Comments
 (0)