componentId = ComponentId::generate('admin-block-editor'); $this->blockTypeRegistry = new BlockTypeRegistry(); $this->componentRegistry = Mockery::mock(ComponentRegistry::class); // Mock ContentPreviewService $this->previewService = Mockery::mock(ContentPreviewService::class); $this->previewService ->shouldReceive('renderPreview') ->andReturn('
Preview HTML
'); // Mock BlockTemplateService $this->templateService = Mockery::mock(BlockTemplateService::class); $this->templateService ->shouldReceive('getAllTemplates') ->andReturn([ 'landing-page' => [ 'name' => 'Landing Page', 'description' => 'Test template', 'blocks' => [], ], ]); $this->state = BlockEditorState::empty(); }); it('creates component with initial state', function () { $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); expect($component->id)->toBe($this->componentId); expect($component->state)->toBe($this->state); }); it('adds a new block', function () { $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $newState = $component->addBlock('hero'); expect($newState->blocks)->toHaveCount(1); expect($newState->blocks[0]['type'])->toBe('hero'); }); it('does not add block for invalid block type', function () { $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $newState = $component->addBlock('invalid-type'); expect($newState->blocks)->toBeEmpty(); }); it('removes a block', function () { $state = $this->state->withBlockAdded('hero', ['title' => 'Test']); $component = new BlockEditorComponent( id: $this->componentId, state: $state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $blockId = $state->blocks[0]['id']; $newState = $component->removeBlock($blockId); expect($newState->blocks)->toBeEmpty(); }); it('updates block field', function () { $state = $this->state->withBlockAdded('text', ['content' => 'Old content']); $component = new BlockEditorComponent( id: $this->componentId, state: $state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $blockId = $state->blocks[0]['id']; $newState = $component->updateBlockField($blockId, 'content', 'New content'); expect($newState->blocks[0]['data']['content'])->toBe('New content'); }); it('reorders blocks', function () { $state = $this->state ->withBlockAdded('hero', ['title' => 'Hero']) ->withBlockAdded('text', ['content' => 'Text']); $component = new BlockEditorComponent( id: $this->componentId, state: $state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $blockIds = array_map(fn ($block) => $block['id'], $state->blocks); $reorderedIds = array_reverse($blockIds); $newState = $component->reorderBlocks($reorderedIds); expect($newState->blocks[0]['type'])->toBe('text'); expect($newState->blocks[1]['type'])->toBe('hero'); }); it('toggles preview mode', function () { $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $newState = $component->togglePreview(); expect($newState->isPreviewMode)->toBeTrue(); expect($newState->previewHtml)->not->toBeNull(); }); it('applies template', function () { $this->templateService ->shouldReceive('hasTemplate') ->with('landing-page') ->andReturn(true); $this->templateService ->shouldReceive('getTemplate') ->with('landing-page') ->andReturn([ 'name' => 'Landing Page', 'description' => 'Test', 'blocks' => [ [ 'type' => 'hero', 'data' => ['title' => 'Hero Title'], ], ], ]); $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $newState = $component->applyTemplate('landing-page'); expect($newState->blocks)->not->toBeEmpty(); expect($newState->blocks[0]['type'])->toBe('hero'); }); it('does not apply invalid template', function () { $this->templateService ->shouldReceive('hasTemplate') ->with('invalid') ->andReturn(false); $component = new BlockEditorComponent( id: $this->componentId, state: $this->state, blockTypeRegistry: $this->blockTypeRegistry, previewService: $this->previewService, componentRegistry: $this->componentRegistry, templateService: $this->templateService ); $newState = $component->applyTemplate('invalid'); expect($newState->blocks)->toBeEmpty(); }); });