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:
@@ -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'
|
||||
]);
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user