container = new DefaultContainer(); // Setup dependencies $this->container->singleton( PlaceholderReplacer::class, new PlaceholderReplacer($this->container) ); $this->componentService = new DomComponentService(); $this->componentRenderer = new ComponentRenderer( __DIR__ . '/../../../src/Framework/View/templates/components' ); $this->processor = new ComponentProcessor( $this->componentService, $this->componentRenderer, $this->container ); $this->parser = new DomTemplateParser(); }); describe('ComponentProcessor', function () { it('processes simple component without attributes', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext( template: 'test', data: [ 'type' => 'info', 'message' => 'Test message', ] ); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); expect($output)->toContain('alert alert-info'); expect($output)->toContain('Test message'); }); it('processes component with attributes', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext(template: 'test', data: []); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); expect($output)->toContain('alert alert-warning'); expect($output)->toContain('Custom message'); }); it('processes nested components', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext(template: 'test', data: []); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); expect($output)->toContain('card'); expect($output)->toContain('Test Card'); expect($output)->toContain('Card content'); }); it('handles components with placeholder variables', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext( template: 'test', data: [ 'alertType' => 'success', 'alertMessage' => 'Operation successful', ] ); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); expect($output)->toContain('alert alert-success'); expect($output)->toContain('Operation successful'); }); it('gracefully handles missing component files', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext(template: 'test', data: []); // Should not throw exception $result = $this->processor->process($dom, $context); expect($result)->toBeInstanceOf(App\Framework\View\DomWrapper::class); }); it('processes multiple components in sequence', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext(template: 'test', data: []); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); expect($output)->toContain('First alert'); expect($output)->toContain('Second alert'); expect($output)->toContain('Third alert'); expect($output)->toContain('alert-info'); expect($output)->toContain('alert-warning'); expect($output)->toContain('alert-danger'); }); it('skips components without name attribute', function () { $html = << HTML; $dom = $this->parser->parseToWrapper($html); $context = new RenderContext(template: 'test', data: []); $result = $this->processor->process($dom, $context); $output = $result->document->saveHTML(); // Should only process the valid component expect($output)->toContain('Valid component'); }); });