fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
284
tests/Feature/Application/Cms/ShowCmsContentTest.php
Normal file
284
tests/Feature/Application/Cms/ShowCmsContentTest.php
Normal file
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Application\Cms\ShowCmsContent;
|
||||
use App\Domain\Cms\Entities\Content;
|
||||
use App\Domain\Cms\Enums\ContentStatus;
|
||||
use App\Domain\Cms\Exceptions\ContentNotFoundException;
|
||||
use App\Domain\Cms\Repositories\ContentRepository;
|
||||
use App\Domain\Cms\Services\BlockTypeRegistry;
|
||||
use App\Domain\Cms\Services\BlockValidator;
|
||||
use App\Domain\Cms\Services\ContentLocalizationService;
|
||||
use App\Domain\Cms\Services\ContentRenderer;
|
||||
use App\Domain\Cms\Services\ContentService;
|
||||
use App\Domain\Cms\Services\SlugGenerator;
|
||||
use App\Domain\Cms\Rendering\BlockRendererRegistry;
|
||||
use App\Domain\Cms\Rendering\DefaultBlockRenderer;
|
||||
use App\Domain\Cms\Rendering\HeroBlockRenderer;
|
||||
use App\Domain\Cms\Rendering\ImageBlockRenderer;
|
||||
use App\Domain\Cms\Rendering\TextBlockRenderer;
|
||||
use App\Domain\Cms\ValueObjects\BlockData;
|
||||
use App\Domain\Cms\ValueObjects\ContentBlocks;
|
||||
use App\Domain\Cms\ValueObjects\ContentId;
|
||||
use App\Domain\Cms\ValueObjects\ContentSlug;
|
||||
use App\Domain\Cms\ValueObjects\ContentTypeId;
|
||||
use App\Domain\Cms\ValueObjects\Locale;
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\View\Caching\CacheManager;
|
||||
use App\Framework\View\ComponentRenderer;
|
||||
use App\Framework\View\ComponentCache;
|
||||
use App\Framework\View\Loading\TemplateLoader;
|
||||
use App\Framework\View\TemplateProcessor;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
use App\Framework\Filesystem\FileStorage;
|
||||
use App\Framework\Cache\Driver\NullCache;
|
||||
use App\Framework\Cache\GeneralCache;
|
||||
use App\Framework\Core\PathProvider;
|
||||
use App\Framework\Serializer\Serializer;
|
||||
use Tests\Support\CmsTestHelpers;
|
||||
|
||||
describe('ShowCmsContent', function () {
|
||||
beforeEach(function () {
|
||||
$this->clock = new SystemClock();
|
||||
$this->repository = Mockery::mock(ContentRepository::class);
|
||||
$this->blockTypeRegistry = new BlockTypeRegistry();
|
||||
$this->blockValidator = new BlockValidator($this->blockTypeRegistry);
|
||||
$this->slugGenerator = new SlugGenerator($this->repository);
|
||||
$this->contentService = new ContentService(
|
||||
$this->repository,
|
||||
$this->blockValidator,
|
||||
$this->slugGenerator,
|
||||
$this->clock
|
||||
);
|
||||
|
||||
// Setup ContentRenderer with real dependencies (similar to ContentRendererTest)
|
||||
$blockRendererRegistry = new BlockRendererRegistry();
|
||||
$blockRendererRegistry->registerForType('hero', new HeroBlockRenderer());
|
||||
$blockRendererRegistry->registerForType('text', new TextBlockRenderer());
|
||||
$blockRendererRegistry->registerForType('image', new ImageBlockRenderer());
|
||||
|
||||
// Create real ComponentRenderer
|
||||
$pathProvider = new PathProvider(__DIR__ . '/../../../../');
|
||||
$nullCacheDriver = new NullCache();
|
||||
$serializer = Mockery::mock(Serializer::class);
|
||||
$serializer->shouldReceive('serialize')->andReturnUsing(fn($data) => serialize($data));
|
||||
$serializer->shouldReceive('unserialize')->andReturnUsing(fn($data) => unserialize($data));
|
||||
$cache = new GeneralCache($nullCacheDriver, $serializer);
|
||||
$templateLoader = new TemplateLoader(
|
||||
pathProvider: $pathProvider,
|
||||
cache: $cache,
|
||||
discoveryRegistry: null,
|
||||
templates: [],
|
||||
templatePath: '/src/Framework/View/templates',
|
||||
cacheEnabled: false
|
||||
);
|
||||
|
||||
$componentCache = new ComponentCache('/tmp/test-cache');
|
||||
$container = new DefaultContainer();
|
||||
$templateProcessor = new TemplateProcessor(
|
||||
astTransformers: [],
|
||||
stringProcessors: [],
|
||||
container: $container,
|
||||
chainOptimizer: null,
|
||||
compiledTemplateCache: null,
|
||||
performanceTracker: null
|
||||
);
|
||||
|
||||
$fileStorage = new FileStorage(
|
||||
basePath: sys_get_temp_dir() . '/test-components'
|
||||
);
|
||||
|
||||
$componentRenderer = new ComponentRenderer(
|
||||
$templateProcessor,
|
||||
$componentCache,
|
||||
$templateLoader,
|
||||
$fileStorage
|
||||
);
|
||||
|
||||
$contentTranslationRepository = Mockery::mock(\App\Domain\Cms\Repositories\ContentTranslationRepository::class);
|
||||
$localizationService = new ContentLocalizationService(
|
||||
$contentTranslationRepository,
|
||||
$this->clock
|
||||
);
|
||||
$defaultRenderer = new DefaultBlockRenderer();
|
||||
|
||||
$this->contentRenderer = new ContentRenderer(
|
||||
$blockRendererRegistry,
|
||||
$componentRenderer,
|
||||
$localizationService,
|
||||
$defaultRenderer
|
||||
);
|
||||
|
||||
$this->cacheManager = Mockery::mock(CacheManager::class);
|
||||
$this->controller = new ShowCmsContent(
|
||||
$this->contentService,
|
||||
$this->contentRenderer,
|
||||
$this->cacheManager
|
||||
);
|
||||
});
|
||||
|
||||
it('renders published homepage content', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
$content = CmsTestHelpers::createContent(
|
||||
$this->clock,
|
||||
slug: $slug,
|
||||
title: 'Homepage',
|
||||
status: ContentStatus::PUBLISHED
|
||||
);
|
||||
|
||||
$renderedHtml = '<div class="cms-hero"><h1>Homepage</h1></div>';
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn($content);
|
||||
|
||||
$this->cacheManager->shouldReceive('render')
|
||||
->once()
|
||||
->andReturn($renderedHtml);
|
||||
|
||||
$result = $this->controller->home();
|
||||
|
||||
expect($result)->toBeInstanceOf(\App\Framework\Router\Result\ViewResult::class);
|
||||
expect($result->template)->toBe('cms-content');
|
||||
expect($result->metaData->title)->toBe('Homepage');
|
||||
expect($result->data['bodyContent'])->toBeInstanceOf(\App\Framework\View\RawHtml::class);
|
||||
});
|
||||
|
||||
it('throws exception when homepage content not found', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn(null);
|
||||
|
||||
expect(fn () => $this->controller->home())
|
||||
->toThrow(ContentNotFoundException::class);
|
||||
});
|
||||
|
||||
it('throws exception when content is not published', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
$content = CmsTestHelpers::createContent(
|
||||
$this->clock,
|
||||
slug: $slug,
|
||||
status: ContentStatus::DRAFT
|
||||
);
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn($content);
|
||||
|
||||
expect(fn () => $this->controller->home())
|
||||
->toThrow(ContentNotFoundException::class);
|
||||
});
|
||||
|
||||
it('extracts meta data from CMS content', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
$metaData = BlockData::fromArray([
|
||||
'title' => 'SEO Title',
|
||||
'description' => 'SEO Description',
|
||||
]);
|
||||
|
||||
$content = new Content(
|
||||
id: ContentId::generate($this->clock),
|
||||
contentTypeId: ContentTypeId::fromString('page'),
|
||||
slug: $slug,
|
||||
title: 'Homepage',
|
||||
blocks: ContentBlocks::fromArray([]),
|
||||
status: ContentStatus::PUBLISHED,
|
||||
authorId: null,
|
||||
publishedAt: Timestamp::now(),
|
||||
metaData: $metaData,
|
||||
defaultLocale: Locale::english(),
|
||||
createdAt: Timestamp::now(),
|
||||
updatedAt: Timestamp::now()
|
||||
);
|
||||
|
||||
$renderedHtml = '<div>Content</div>';
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn($content);
|
||||
|
||||
$this->cacheManager->shouldReceive('render')
|
||||
->once()
|
||||
->andReturn($renderedHtml);
|
||||
|
||||
$result = $this->controller->home();
|
||||
|
||||
expect($result->metaData->title)->toBe('SEO Title');
|
||||
expect($result->metaData->description)->toBe('SEO Description');
|
||||
});
|
||||
|
||||
it('falls back to content title when meta data is missing', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
$content = CmsTestHelpers::createContent(
|
||||
$this->clock,
|
||||
slug: $slug,
|
||||
title: 'Homepage Title',
|
||||
status: ContentStatus::PUBLISHED
|
||||
);
|
||||
|
||||
$renderedHtml = '<div>Content</div>';
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn($content);
|
||||
|
||||
$this->cacheManager->shouldReceive('render')
|
||||
->once()
|
||||
->andReturn($renderedHtml);
|
||||
|
||||
$result = $this->controller->home();
|
||||
|
||||
expect($result->metaData->title)->toBe('Homepage Title');
|
||||
expect($result->metaData->description)->toBe('');
|
||||
});
|
||||
|
||||
it('uses cache manager for rendering', function () {
|
||||
$slug = ContentSlug::fromString('homepage');
|
||||
$content = CmsTestHelpers::createContent(
|
||||
$this->clock,
|
||||
slug: $slug,
|
||||
status: ContentStatus::PUBLISHED
|
||||
);
|
||||
|
||||
$renderedHtml = '<div>Cached Content</div>';
|
||||
|
||||
$this->repository->shouldReceive('findBySlug')
|
||||
->once()
|
||||
->with(Mockery::on(function ($arg) use ($slug) {
|
||||
return $arg instanceof ContentSlug && $arg->toString() === $slug->toString();
|
||||
}))
|
||||
->andReturn($content);
|
||||
|
||||
$this->cacheManager->shouldReceive('render')
|
||||
->once()
|
||||
->with(
|
||||
Mockery::type(\App\Framework\View\Caching\TemplateContext::class),
|
||||
Mockery::type('Closure')
|
||||
)
|
||||
->andReturn($renderedHtml);
|
||||
|
||||
$result = $this->controller->home();
|
||||
|
||||
expect($result->data['bodyContent']->content)->toBe($renderedHtml);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user