toString())->toBe('hero-1'); expect((string) $blockId)->toBe('hero-1'); }); it('accepts lowercase letters, numbers, hyphens, and underscores', function () { $validIds = ['block-1', 'text_block', 'image123', 'my-block-id']; foreach ($validIds as $id) { $blockId = BlockId::fromString($id); expect($blockId->toString())->toBe($id); } }); it('can generate unique block IDs', function () { $blockId1 = BlockId::generate('hero'); $blockId2 = BlockId::generate('hero'); expect($blockId1->toString())->toStartWith('hero_'); expect($blockId2->toString())->toStartWith('hero_'); expect($blockId1->toString())->not->toBe($blockId2->toString()); }); it('generates block IDs with custom prefix', function () { $blockId = BlockId::generate('custom'); expect($blockId->toString())->toStartWith('custom_'); }); it('throws exception for empty string', function () { expect(fn () => BlockId::fromString('')) ->toThrow(InvalidArgumentException::class, 'Block ID cannot be empty'); }); it('throws exception for uppercase letters', function () { expect(fn () => BlockId::fromString('Block-1')) ->toThrow(InvalidArgumentException::class, 'Block ID must contain only lowercase letters, numbers, hyphens, and underscores'); }); it('throws exception for special characters', function () { expect(fn () => BlockId::fromString('block@1')) ->toThrow(InvalidArgumentException::class); }); it('throws exception for block ID exceeding 100 characters', function () { $longId = str_repeat('a', 101); expect(fn () => BlockId::fromString($longId)) ->toThrow(InvalidArgumentException::class, 'Block ID cannot exceed 100 characters'); }); it('can compare two BlockIds for equality', function () { $id1 = BlockId::fromString('block-1'); $id2 = BlockId::fromString('block-1'); $id3 = BlockId::fromString('block-2'); expect($id1->equals($id2))->toBeTrue(); expect($id1->equals($id3))->toBeFalse(); }); });