clock = new SystemClock(); $this->blockRegistry = new BlockRendererRegistry(); // Create minimal real TemplateLoader for testing $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'); // Create minimal real TemplateProcessor for testing $container = new DefaultContainer(); $templateProcessor = new TemplateProcessor( astTransformers: [], stringProcessors: [], container: $container, chainOptimizer: null, compiledTemplateCache: null, performanceTracker: null ); // Create real FileStorage for testing $fileStorage = new FileStorage( basePath: sys_get_temp_dir() . '/test-components' ); $this->componentRenderer = new ComponentRenderer( $templateProcessor, $componentCache, $templateLoader, $fileStorage ); // Create real ContentLocalizationService for testing $contentTranslationRepository = Mockery::mock(\App\Domain\Cms\Repositories\ContentTranslationRepository::class); $this->localizationService = new ContentLocalizationService( $contentTranslationRepository, $this->clock ); $this->defaultRenderer = new DefaultBlockRenderer(); $this->renderer = new ContentRenderer( $this->blockRegistry, $this->componentRenderer, $this->localizationService, $this->defaultRenderer ); }); it('renders content with multiple blocks', function () { $content = CmsTestHelpers::createContent($this->clock); // ContentLocalizationService is real instance, no need to mock $html = $this->renderer->render($content); expect($html)->toBeString(); expect($html)->not->toBeEmpty(); }); it('uses default renderer for unregistered block types', function () { $blocks = ContentBlocks::fromArray([ [ 'id' => 'custom-1', 'type' => 'custom-block', 'data' => ['key' => 'value'], ], ]); $content = CmsTestHelpers::createContent($this->clock, blocks: $blocks); // ContentLocalizationService is real instance, no need to mock $html = $this->renderer->render($content); expect($html)->toBeString(); expect($html)->not->toBeEmpty(); }); it('uses registered renderer for block type', function () { $this->blockRegistry->registerForType('hero', new HeroBlockRenderer()); $content = CmsTestHelpers::createContent($this->clock); // ContentLocalizationService is real instance, no need to mock $html = $this->renderer->render($content); expect($html)->toBeString(); expect($html)->not->toBeEmpty(); }); it('renders blocks to component data array', function () { $this->blockRegistry->registerForType('hero', new HeroBlockRenderer()); $this->blockRegistry->registerForType('text', new TextBlockRenderer()); $content = CmsTestHelpers::createContent($this->clock); // ContentLocalizationService is real instance, no need to mock $componentData = $this->renderer->renderBlocksToComponentData($content); expect($componentData)->toBeArray(); expect($componentData)->toHaveCount(2); expect($componentData[0]['component'])->toBe('cms/hero'); expect($componentData[1]['component'])->toBe('cms/text'); }); it('uses provided locale for rendering', function () { $content = CmsTestHelpers::createContent($this->clock); $locale = Locale::german(); // ContentLocalizationService is real instance, no need to mock $html = $this->renderer->render($content, $locale); expect($html)->toBeString(); expect($html)->not->toBeEmpty(); }); });