'Hero Title']) ); expect($block->type->toString())->toBe('hero'); expect($block->blockId->toString())->toBe('hero-1'); expect($block->data->get('title'))->toBe('Hero Title'); expect($block->settings)->toBeNull(); }); it('can be created with settings', function () { $settings = BlockSettings::fromArray(['fullWidth' => true]); $block = ContentBlock::create( type: BlockType::hero(), blockId: BlockId::fromString('hero-1'), data: BlockData::fromArray(['title' => 'Hero Title']), settings: $settings ); expect($block->settings)->not->toBeNull(); expect($block->settings->get('fullWidth'))->toBeTrue(); }); it('can be created from array', function () { $block = ContentBlock::fromArray([ 'id' => 'hero-1', 'type' => 'hero', 'data' => ['title' => 'Hero Title'], 'settings' => ['fullWidth' => true], ]); expect($block->blockId->toString())->toBe('hero-1'); expect($block->type->toString())->toBe('hero'); expect($block->data->get('title'))->toBe('Hero Title'); expect($block->settings->get('fullWidth'))->toBeTrue(); }); it('can be created from array without settings', function () { $block = ContentBlock::fromArray([ 'id' => 'text-1', 'type' => 'text', 'data' => ['content' => 'Hello World'], ]); expect($block->settings)->toBeNull(); }); it('throws exception when creating from array with missing required fields', function () { expect(fn () => ContentBlock::fromArray(['id' => 'hero-1'])) ->toThrow(InvalidArgumentException::class, 'Invalid block data: missing required fields'); expect(fn () => ContentBlock::fromArray(['type' => 'hero'])) ->toThrow(InvalidArgumentException::class); expect(fn () => ContentBlock::fromArray(['id' => 'hero-1', 'type' => 'hero'])) ->toThrow(InvalidArgumentException::class); }); it('can convert to array', function () { $block = ContentBlock::create( type: BlockType::hero(), blockId: BlockId::fromString('hero-1'), data: BlockData::fromArray(['title' => 'Hero Title']), settings: BlockSettings::fromArray(['fullWidth' => true]) ); $array = $block->toArray(); expect($array)->toHaveKeys(['id', 'type', 'data', 'settings']); expect($array['id'])->toBe('hero-1'); expect($array['type'])->toBe('hero'); expect($array['data'])->toBe(['title' => 'Hero Title']); expect($array['settings'])->toBe(['fullWidth' => true]); }); it('can update data immutably', function () { $block = ContentBlock::create( type: BlockType::hero(), blockId: BlockId::fromString('hero-1'), data: BlockData::fromArray(['title' => 'Old Title']) ); $newData = BlockData::fromArray(['title' => 'New Title']); $updatedBlock = $block->withData($newData); expect($updatedBlock->data->get('title'))->toBe('New Title'); expect($block->data->get('title'))->toBe('Old Title'); // Original unchanged }); it('can update settings immutably', function () { $block = ContentBlock::create( type: BlockType::hero(), blockId: BlockId::fromString('hero-1'), data: BlockData::fromArray(['title' => 'Hero Title']) ); $newSettings = BlockSettings::fromArray(['fullWidth' => true]); $updatedBlock = $block->withSettings($newSettings); expect($updatedBlock->settings)->not->toBeNull(); expect($updatedBlock->settings->get('fullWidth'))->toBeTrue(); expect($block->settings)->toBeNull(); // Original unchanged }); it('can remove settings', function () { $block = ContentBlock::create( type: BlockType::hero(), blockId: BlockId::fromString('hero-1'), data: BlockData::fromArray(['title' => 'Hero Title']), settings: BlockSettings::fromArray(['fullWidth' => true]) ); $updatedBlock = $block->withSettings(null); expect($updatedBlock->settings)->toBeNull(); expect($block->settings)->not->toBeNull(); // Original unchanged }); });