Default content

'); expect($slot->name)->toBe('default'); expect($slot->defaultContent)->toBe('

Default content

'); expect($slot->required)->toBeFalse(); expect($slot->isDefault())->toBeTrue(); expect($slot->isScoped())->toBeFalse(); }); it('creates named slot', function () { $slot = SlotDefinition::named('header', '

Default Header

'); expect($slot->name)->toBe('header'); expect($slot->defaultContent)->toBe('

Default Header

'); expect($slot->isDefault())->toBeFalse(); }); it('creates scoped slot with props', function () { $slot = SlotDefinition::scoped('content', ['userId', 'userName']); expect($slot->name)->toBe('content'); expect($slot->props)->toBe(['userId', 'userName']); expect($slot->isScoped())->toBeTrue(); }); it('marks slot as required', function () { $slot = SlotDefinition::named('body')->withRequired(true); expect($slot->required)->toBeTrue(); }); it('updates default content', function () { $slot = SlotDefinition::named('header') ->withDefaultContent('

New Default

'); expect($slot->defaultContent)->toBe('

New Default

'); }); it('updates props', function () { $slot = SlotDefinition::named('content') ->withProps(['prop1', 'prop2']); expect($slot->props)->toBe(['prop1', 'prop2']); expect($slot->isScoped())->toBeTrue(); }); it('checks if has default content', function () { $slotWithDefault = SlotDefinition::named('header', '

Default

'); $slotWithoutDefault = SlotDefinition::named('header', ''); expect($slotWithDefault->hasDefaultContent())->toBeTrue(); expect($slotWithoutDefault->hasDefaultContent())->toBeFalse(); }); it('throws on empty slot name', function () { expect(fn () => new SlotDefinition(''))->toThrow(\InvalidArgumentException::class); }); it('converts to array for serialization', function () { $slot = SlotDefinition::scoped('content', ['key1', 'key2'], '

Default

') ->withRequired(true); $array = $slot->toArray(); expect($array['name'])->toBe('content'); expect($array['default_content'])->toBe('

Default

'); expect($array['props'])->toBe(['key1', 'key2']); expect($array['required'])->toBeTrue(); expect($array['is_scoped'])->toBeTrue(); }); it('checks equality', function () { $slot1 = SlotDefinition::named('header', '

Header

'); $slot2 = SlotDefinition::named('header', '

Header

'); $slot3 = SlotDefinition::named('header', '

Different

'); expect($slot1->equals($slot2))->toBeTrue(); expect($slot1->equals($slot3))->toBeFalse(); }); }); describe('SlotContent', function () { it('creates default slot content', function () { $content = SlotContent::default('

Content

'); expect($content->slotName)->toBe('default'); expect($content->content)->toBe('

Content

'); expect($content->isDefault())->toBeTrue(); }); it('creates named slot content', function () { $content = SlotContent::named('header', '

Header

'); expect($content->slotName)->toBe('header'); expect($content->content)->toBe('

Header

'); expect($content->isDefault())->toBeFalse(); }); it('creates slot content with data', function () { $content = SlotContent::named('content', '

{title}

', ['title' => 'My Title']); expect($content->hasData())->toBeTrue(); expect($content->getData('title'))->toBe('My Title'); }); it('creates slot content from component', function () { $componentId = ComponentId::generate(); $content = SlotContent::fromComponent('header', $componentId, '

Header

'); expect($content->isFromComponent())->toBeTrue(); expect($content->componentId)->toBe($componentId); }); it('checks if content is empty', function () { $emptyContent = SlotContent::named('header', ' '); $filledContent = SlotContent::named('header', '

Header

'); expect($emptyContent->isEmpty())->toBeTrue(); expect($filledContent->isEmpty())->toBeFalse(); }); it('gets data with default value', function () { $content = SlotContent::named('content', '

Content

', ['key' => 'value']); expect($content->getData('key'))->toBe('value'); expect($content->getData('missing', 'default'))->toBe('default'); }); it('adds data to content', function () { $content = SlotContent::named('content', '

Content

') ->withData(['key1' => 'value1', 'key2' => 'value2']); expect($content->hasData())->toBeTrue(); expect($content->getData('key1'))->toBe('value1'); expect($content->getData('key2'))->toBe('value2'); }); it('updates content', function () { $content = SlotContent::named('header', '

Old

') ->withContent('

New

'); expect($content->content)->toBe('

New

'); }); it('throws on empty slot name', function () { expect(fn () => new SlotContent('', 'content'))->toThrow(\InvalidArgumentException::class); }); it('converts to array for serialization', function () { $componentId = ComponentId::generate(); $content = SlotContent::fromComponent('header', $componentId, '

Header

', ['key' => 'value']); $array = $content->toArray(); expect($array['slot_name'])->toBe('header'); expect($array['content'])->toBe('

Header

'); expect($array['data'])->toBe(['key' => 'value']); expect($array['component_id'])->toBe($componentId->toString()); expect($array['is_default'])->toBeFalse(); expect($array['has_data'])->toBeTrue(); }); it('creates from array', function () { $array = [ 'slot_name' => 'header', 'content' => '

Header

', 'data' => ['key' => 'value'], ]; $content = SlotContent::fromArray($array); expect($content->slotName)->toBe('header'); expect($content->content)->toBe('

Header

'); expect($content->getData('key'))->toBe('value'); }); }); describe('SlotContext', function () { it('creates empty context', function () { $context = SlotContext::empty(); expect($context->isEmpty())->toBeTrue(); expect($context->count())->toBe(0); }); it('creates context with data', function () { $context = SlotContext::create(['key1' => 'value1', 'key2' => 'value2']); expect($context->isEmpty())->toBeFalse(); expect($context->count())->toBe(2); expect($context->get('key1'))->toBe('value1'); expect($context->get('key2'))->toBe('value2'); }); it('creates context with metadata', function () { $context = SlotContext::create( ['data' => 'value'], ['timestamp' => 1234567890] ); expect($context->getMetadata('timestamp'))->toBe(1234567890); }); it('checks if key exists', function () { $context = SlotContext::create(['key' => 'value']); expect($context->has('key'))->toBeTrue(); expect($context->has('missing'))->toBeFalse(); }); it('gets value with default', function () { $context = SlotContext::create(['key' => 'value']); expect($context->get('key'))->toBe('value'); expect($context->get('missing', 'default'))->toBe('default'); }); it('adds data to context', function () { $context = SlotContext::empty() ->withData(['key1' => 'value1']) ->withData(['key2' => 'value2']); expect($context->count())->toBe(2); expect($context->get('key1'))->toBe('value1'); expect($context->get('key2'))->toBe('value2'); }); it('sets single data value', function () { $context = SlotContext::empty() ->with('key1', 'value1') ->with('key2', 'value2'); expect($context->count())->toBe(2); }); it('removes data key', function () { $context = SlotContext::create(['key1' => 'value1', 'key2' => 'value2']) ->without('key1'); expect($context->has('key1'))->toBeFalse(); expect($context->has('key2'))->toBeTrue(); }); it('gets all data keys', function () { $context = SlotContext::create(['key1' => 'value1', 'key2' => 'value2']); $keys = $context->keys(); expect($keys)->toBe(['key1', 'key2']); }); it('merges contexts', function () { $context1 = SlotContext::create(['key1' => 'value1']); $context2 = SlotContext::create(['key2' => 'value2']); $merged = $context1->merge($context2); expect($merged->count())->toBe(2); expect($merged->get('key1'))->toBe('value1'); expect($merged->get('key2'))->toBe('value2'); }); it('adds metadata to context', function () { $context = SlotContext::empty() ->withMetadata(['meta1' => 'value1']) ->withMetadata(['meta2' => 'value2']); expect($context->getMetadata('meta1'))->toBe('value1'); expect($context->getMetadata('meta2'))->toBe('value2'); }); it('converts to array for serialization', function () { $context = SlotContext::create( ['key1' => 'value1', 'key2' => 'value2'], ['timestamp' => 1234567890] ); $array = $context->toArray(); expect($array['data'])->toBe(['key1' => 'value1', 'key2' => 'value2']); expect($array['metadata'])->toBe(['timestamp' => 1234567890]); expect($array['is_empty'])->toBeFalse(); expect($array['keys'])->toBe(['key1', 'key2']); expect($array['count'])->toBe(2); }); it('converts to plain array', function () { $context = SlotContext::create(['key1' => 'value1', 'key2' => 'value2']); $plain = $context->toPlainArray(); expect($plain)->toBe(['key1' => 'value1', 'key2' => 'value2']); }); it('creates from array', function () { $array = [ 'data' => ['key1' => 'value1'], 'metadata' => ['timestamp' => 1234567890], ]; $context = SlotContext::fromArray($array); expect($context->get('key1'))->toBe('value1'); expect($context->getMetadata('timestamp'))->toBe(1234567890); }); });