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);
});
});