Skip to content
Merged
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
21 changes: 11 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ jobs:
codestyle:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php-versions: ['8.3']

steps:
- uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: ${{ matrix.php-versions }}

- name: Cache dependencies
uses: actions/cache@v3
Expand All @@ -47,16 +52,14 @@ jobs:
- name: Install dependencies
uses: php-actions/composer@v6
with:
php_version: 8.1
php_version: ${{ matrix.php-versions }}
version: 2

- name: PHPStan
uses: php-actions/phpstan@v3
with:
php_version: 8.1
version: 2.1.17
command: analyse
path: 'Classes/'
php_version: ${{ matrix.php-versions }}
configuration: phpstan.neon

php-unit-tests:
env:
Expand All @@ -68,7 +71,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.1']
php-versions: ['8.3']
flow-versions: ['8.3']

steps:
Expand Down Expand Up @@ -136,8 +139,6 @@ jobs:

e2e:
env:
# Solves error when parcel tries to count cpus via lscpu
PARCEL_WORKERS: 1
DEBUG: 'testcafe:tested-app:*'

runs-on: ubuntu-latest
Expand All @@ -159,7 +160,7 @@ jobs:
run: yarn build:plugin

- name: Run TestCafe
run: yarn test:e2e:github-actions
run: yarn testcafe --config-file .testcaferc.ci.json

- name: Archive failure screenshots
if: ${{ failure() }}
Expand Down
5 changes: 0 additions & 5 deletions .mocharc.json

This file was deleted.

27 changes: 27 additions & 0 deletions .testcaferc.ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"browsers": "chrome:headless --window-size=1280,720 --incognito --no-sandbox --disable-dev-shm-usage --disable-gpu --disable-software-rasterizer --disable-extensions",
"src": [
"packages/media-module/tests/**/*.ts"
],
"appCommand": "yarn dev:test",
"appInitDelay": 3000,
"screenshots": {
"takeOnFails": true
},
"reporter": [
{
"name": "spec"
}
],
"stopOnFirstFail": false,
"hostname": "localhost",
"baseUrl": "http://localhost:8000",
"pageLoadTimeout": 30000,
"pageRequestTimeout": 30000,
"ajaxRequestTimeout": 30000,
"browserInitTimeout": 60000,
"selectorTimeout": 10000,
"assertionTimeout": 10000,
"skipJsErrors": true,
"skipUncaughtErrors": true
}
11 changes: 6 additions & 5 deletions .testcaferc.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
{
"browsers": {
"path": "chromium",
"cmd": "--window-size=1280,720"
"cmd": "--window-size=1280,720 --incognito"
},
"src": ["packages/media-module/tests/**/*.ts"],
"src": [
"packages/media-module/tests/**/*.ts"
],
"appCommand": "yarn dev:test",
"appInitDelay": 2000,
"screenshots": {
"takeOnFails": true
},
"debugOnFail": false,
"stopOnFirstFail": true,
"hostname": "127.0.0.1",
"baseUrl": "http://127.0.0.1:8000",
"hostname": "localhost",
"baseUrl": "http://localhost:8000",
"retryTestPages": true,
"pageLoadTimeout": 10000,
"pageRequestTimeout": 60000,
Expand Down
3 changes: 2 additions & 1 deletion Classes/GraphQL/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use InvalidArgumentException;
use UnitEnum;
use Wwwision\Types\Exception\CoerceException;
use Wwwision\Types\Options;
use Wwwision\Types\Parser;
use Wwwision\Types\Schema\EnumCaseSchema;
use Wwwision\Types\Schema\EnumSchema;
Expand Down Expand Up @@ -94,7 +95,7 @@ public function typeConfigDecorator(array $typeConfig, TypeDefinitionNode $typeD
$schema = Parser::getSchema($className);
if ($schema instanceof EnumSchema) {
$typeConfig['values'] = array_map(static fn(EnumCaseSchema $caseSchema
) => $caseSchema->instantiate(null), $schema->caseSchemas);
) => $caseSchema->instantiate(null, Options::create()), $schema->caseSchemas);
}
}
return $typeConfig;
Expand Down
39 changes: 21 additions & 18 deletions Tests/Functional/GraphQL/AssetApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
use Flowpack\Media\Ui\GraphQL\Resolver\Type\AssetResolver;
use Flowpack\Media\Ui\GraphQL\Types;
use Flowpack\Media\Ui\Tests\Functional\AbstractMediaTestCase;
use Flowpack\Media\Ui\Tests\Functional\TestAssetUsageStrategy;
use Neos\Flow\Persistence\Doctrine\PersistenceManager;
use Neos\Flow\Tests\Behavior\Features\Bootstrap\SecurityOperationsTrait;
use Neos\Media\Domain\Service\AssetService;
use Neos\Media\Domain\Repository\AssetRepository;

use function Wwwision\Types\instantiate;

Expand All @@ -36,6 +37,11 @@ class AssetApiTest extends AbstractMediaTestCase
*/
protected static $testablePersistenceEnabled = true;

protected MediaApi $mediaApi;
protected AssetResolver $assetResolver;
protected TestAssetUsageStrategy $testAssetUsageStrategy;
protected AssetRepository $assetRepository;

public function setUp(): void
{
parent::setUp();
Expand All @@ -46,6 +52,11 @@ public function setUp(): void

$this->mediaApi = $this->objectManager->get(MediaApi::class);
$this->assetResolver = $this->objectManager->get(AssetResolver::class);
$this->testAssetUsageStrategy = $this->objectManager->get(TestAssetUsageStrategy::class);
$this->assetRepository = $this->objectManager->get(AssetRepository::class);

// Reset the test strategy before each test
$this->testAssetUsageStrategy->reset();

$this->iAmAuthenticatedWithRole('Neos.Neos:Editor');
}
Expand Down Expand Up @@ -83,8 +94,7 @@ public function testEditAsset(): void

$this->persistenceManager->persistAll();

$assets = $this->mediaApi->assets();
$asset = $assets->getIterator()->current();
$asset = $this->mediaApi->assets()->assets[0];
$this->assertEquals($file->clientFilename, $asset->filename->value);

// Edit the asset
Expand All @@ -98,7 +108,7 @@ public function testEditAsset(): void
);

$this->assertTrue($editResult->success);
$editedAsset = $this->mediaApi->assets()->getIterator()->current();
$editedAsset = $this->mediaApi->assets()->assets[0];
$this->assertEquals('new-name.svg', $editedAsset->filename->value);
}

Expand All @@ -107,11 +117,9 @@ public function testDeleteUnusedAssetWorks(): void
$file = self::createFile();
$result = $this->mediaApi->uploadFiles(Types\UploadedFiles::fromArray([$file]));
$this->assertCount(1, $result->values);

$this->persistenceManager->persistAll();

$assets = $this->mediaApi->assets();
$asset = $assets->getIterator()->current();
$asset = $this->mediaApi->assets()->assets[0];
$this->assertEquals($file->clientFilename, $asset->filename->value);

// Delete the asset
Expand All @@ -125,20 +133,15 @@ public function testDeleteUnusedAssetWorks(): void

public function testDeleteUsedAssetFails(): void
{
$assetServiceMock = $this->getMockBuilder(AssetService::class)->setMethods(
['isInUse']
)->disableOriginalConstructor()->getMock();
$assetServiceMock->expects(self::once())->method('isInUse')->willReturn(true);

$file = self::createFile();
$result = $this->mediaApi->assets()->getIterator()->current();
$this->assertEquals($file->clientFilename, $result->filename->value);

$result = $this->mediaApi->uploadFiles(Types\UploadedFiles::fromArray([$file]));
$this->assertCount(1, $result->values);
$this->persistenceManager->persistAll();
$asset = $this->mediaApi->assets()->assets[0];

$assets = $this->mediaApi->assets();
$asset = $assets->getIterator()->current();
$this->assertEquals($file->clientFilename, $asset->filename->value);
// Get the actual asset entity from repository and mark it as used
$assetEntity = $this->assetRepository->findByIdentifier($asset->id->value);
$this->testAssetUsageStrategy->markAssetAsUsed($assetEntity);

// Try to delete the used asset
$deleteResult = $this->mediaApi->deleteAsset($asset->id, $asset->assetSource->id);
Expand Down
98 changes: 98 additions & 0 deletions Tests/Functional/TestAssetUsageStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace Flowpack\Media\Ui\Tests\Functional;

/*
* This file is part of the Flowpack.Media.Ui package.
*
* (c) Contributors of the Neos Project - www.neos.io
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Annotations as Flow;
use Neos\Media\Domain\Model\AssetInterface;
use Neos\Media\Domain\Model\Dto\UsageReference;
use Neos\Media\Domain\Strategy\AbstractAssetUsageStrategy;

/**
* A test asset usage strategy that allows marking assets as used for testing purposes.
*
* This strategy extends AbstractAssetUsageStrategy and provides a simple way to control
* asset usage state in functional tests. It maintains an internal registry of assets
* that are marked as "in use" and will be automatically discovered by the AssetService.
*
* Usage example:
* ```php
* // In your test setUp():
* $this->testAssetUsageStrategy = $this->objectManager->get(TestAssetUsageStrategy::class);
* $this->assetRepository = $this->objectManager->get(AssetRepository::class);
*
* // In your test:
* $assetEntity = $this->assetRepository->findByIdentifier($assetId);
* $this->testAssetUsageStrategy->markAssetAsUsed($assetEntity);
*
* // Now AssetService->isInUse($assetEntity) will return true
* // and deletion attempts will fail
* ```
*
* @Flow\Scope("singleton")
*/
class TestAssetUsageStrategy extends AbstractAssetUsageStrategy
{
/**
* @var array<string, AssetInterface>
*/
protected $usedAssets = [];

/**
* Mark an asset as being used
*
* @param AssetInterface $asset
* @return void
*/
public function markAssetAsUsed(AssetInterface $asset): void
{
$this->usedAssets[$asset->getIdentifier()] = $asset;
}

/**
* Mark an asset as not being used
*
* @param AssetInterface $asset
* @return void
*/
public function markAssetAsUnused(AssetInterface $asset): void
{
unset($this->usedAssets[$asset->getIdentifier()]);
}

/**
* Reset all usage markings
*
* @return void
*/
public function reset(): void
{
$this->usedAssets = [];
}

/**
* Returns an array of usage reference objects.
*
* @param AssetInterface $asset
* @return array<\Neos\Media\Domain\Model\Dto\UsageReference>
*/
public function getUsageReferences(AssetInterface $asset): array
{
if (isset($this->usedAssets[$asset->getIdentifier()])) {
return [new UsageReference($asset)];
}

return [];
}
}
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "This module allows managing media assets including pictures, videos, audio and documents.",
"type": "neos-package",
"require": {
"php": ">=8.1",
"php": ">=8.3",
"neos/media": "^8.3",
"neos/neos": "^8.3",
"neos/neos-ui": "^8.3",
Expand All @@ -12,10 +12,10 @@
"wwwision/types-graphql": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^1.12 || ^2"
},
"suggest": {
"phpstan/phpstan": "For running code quality checks",
"flowpack/neos-asset-usage": "Allows filtering unused assets and other related features",
"flowpack/entity-usage-databasestorage": "Required for the asset usage features"
},
Expand Down
Loading
Loading