feat(cms,asset): add comprehensive test suite and finalize modules

- Add comprehensive test suite for CMS and Asset modules using Pest Framework
- Implement ContentTypeService::delete() protection against deletion of in-use content types
- Add CannotDeleteContentTypeInUseException for better error handling
- Fix DerivatPipelineRegistry::getAllPipelines() to handle object uniqueness correctly
- Fix VariantName::getScale() to correctly parse scales with file extensions
- Update CMS module documentation with new features, exceptions, and test coverage
- Add CmsTestHelpers and AssetTestHelpers for test data factories
- Fix BlockTypeRegistry to be immutable after construction
- Update ContentTypeService to check for associated content before deletion
- Improve BlockRendererRegistry initialization

Test coverage:
- Value Objects: All CMS and Asset value objects
- Services: ContentService, ContentTypeService, SlugGenerator, BlockValidator, ContentLocalizationService, AssetService, DeduplicationService, MetadataExtractor
- Repositories: All database repositories with mocked connections
- Rendering: Block renderers and ContentRenderer
- Controllers: API endpoints for both modules

254 tests passing, 38 remaining (mostly image processing pipeline tests)
This commit is contained in:
2025-11-10 02:12:28 +01:00
parent 74d50a29cc
commit 2d53270056
53 changed files with 5699 additions and 15 deletions

View File

@@ -106,6 +106,37 @@ $updated = $contentService->updateBlocks(
);
```
### ContentTypeService
```php
use App\Domain\Cms\Services\ContentTypeService;
use App\Domain\Cms\ValueObjects\ContentTypeId;
// Content Type erstellen
$contentType = $contentTypeService->create(
name: 'Landing Page',
slug: 'landing_page',
description: 'Landing pages for marketing campaigns',
isSystem: false
);
// Content Type aktualisieren
$updated = $contentTypeService->update(
id: ContentTypeId::fromString('landing_page'),
name: 'Updated Name',
description: 'New description'
);
// Content Type löschen
// Wirft CannotDeleteContentTypeInUseException wenn noch Content existiert
// Wirft CannotDeleteSystemContentTypeException für System-Types
try {
$contentTypeService->delete(ContentTypeId::fromString('landing_page'));
} catch (CannotDeleteContentTypeInUseException $e) {
// Content Type wird noch von Content verwendet
}
```
## REST API
### Endpoints
@@ -191,3 +222,141 @@ php console.php db:migrate
Die Migrations erstellen die Tabellen `content_types` und `contents` mit JSON-Spalten für Blocks.
## Exceptions
Das CMS Modul definiert folgende Domain-Exceptions:
### Content Exceptions
- **`ContentNotFoundException`** - Wird geworfen wenn Content nicht gefunden wird
```php
throw ContentNotFoundException::forId($contentId);
throw ContentNotFoundException::forSlug($slug);
```
- **`DuplicateSlugException`** - Wird geworfen wenn ein Slug bereits existiert
```php
throw DuplicateSlugException::forSlug($slug);
```
- **`InvalidContentStatusException`** - Wird geworfen bei ungültigen Status-Übergängen
```php
throw InvalidContentStatusException::invalidTransition($currentStatus, $targetStatus);
```
- **`InvalidBlockException`** - Wird geworfen bei ungültigen Block-Daten
```php
throw InvalidBlockException::missingRequiredField($blockId, $field);
throw InvalidBlockException::invalidFieldType($blockId, $field, $expectedType);
```
### ContentType Exceptions
- **`ContentTypeNotFoundException`** - Wird geworfen wenn ContentType nicht gefunden wird
```php
throw ContentTypeNotFoundException::forId($id);
```
- **`DuplicateContentTypeSlugException`** - Wird geworfen wenn ein ContentType-Slug bereits existiert
```php
throw DuplicateContentTypeSlugException::forSlug($slug);
```
- **`CannotDeleteSystemContentTypeException`** - Wird geworfen beim Versuch, einen System-ContentType zu löschen
```php
throw CannotDeleteSystemContentTypeException::forId($id);
```
- **`CannotDeleteContentTypeInUseException`** - Wird geworfen beim Versuch, einen ContentType zu löschen, der noch von Content verwendet wird
```php
throw CannotDeleteContentTypeInUseException::forId($id, $contentCount);
```
## ContentTypeService::delete() - Schutz vor versehentlichem Löschen
Die `ContentTypeService::delete()` Methode implementiert eine Schutzfunktion, die verhindert, dass ContentTypes gelöscht werden, die noch von Content-Instanzen verwendet werden:
```php
public function delete(ContentTypeId $id): void
{
$contentType = $this->contentTypeRepository->findById($id);
if ($contentType === null) {
throw ContentTypeNotFoundException::forId($id);
}
// System ContentTypes können nicht gelöscht werden
if ($contentType->isSystem) {
throw CannotDeleteSystemContentTypeException::forId($id);
}
// Prüfe ob ContentType noch von Content verwendet wird
$contents = $this->contentRepository->findByType($id);
if (count($contents) > 0) {
throw CannotDeleteContentTypeInUseException::forId($id, count($contents));
}
$this->contentTypeRepository->delete($id);
}
```
Dies verhindert Datenverlust und stellt sicher, dass keine verwaisten Content-Instanzen entstehen.
## Tests
Das CMS Modul verfügt über eine umfassende Test-Suite mit Pest Framework:
### Test-Struktur
```
tests/
├── Unit/
│ └── Domain/
│ └── Cms/
│ ├── ValueObjects/ # Value Object Tests
│ ├── Services/ # Service Tests
│ ├── Repositories/ # Repository Tests
│ └── Rendering/ # Rendering Tests
├── Feature/
│ └── Application/
│ └── Cms/ # Controller Tests
└── Support/
└── CmsTestHelpers.php # Test Helper Functions
```
### Test-Abdeckung
- **Value Objects**: Alle Value Objects (ContentId, ContentSlug, BlockType, etc.)
- **Services**: ContentService, ContentTypeService, SlugGenerator, BlockValidator, ContentLocalizationService
- **Repositories**: DatabaseContentRepository, DatabaseContentTypeRepository, DatabaseContentTranslationRepository
- **Rendering**: BlockRendererRegistry, HeroBlockRenderer, TextBlockRenderer, ImageBlockRenderer, DefaultBlockRenderer, ContentRenderer
- **Controllers**: ContentsController, ContentTypesController
### Tests ausführen
```bash
# Alle CMS Tests
./vendor/bin/pest tests/Unit/Domain/Cms tests/Feature/Application/Cms
# Spezifische Test-Datei
./vendor/bin/pest tests/Unit/Domain/Cms/Services/ContentServiceTest.php
```
### Test Helpers
Die `CmsTestHelpers` Klasse bietet Factory-Methoden für Test-Daten:
```php
use Tests\Support\CmsTestHelpers;
$content = CmsTestHelpers::createContent($clock, [
'title' => 'Test Content',
'blocks' => $blocks,
'slug' => ContentSlug::fromString('test-slug')
]);
$contentType = CmsTestHelpers::createContentType([
'name' => 'Test Type',
'slug' => 'test_type'
]);
```