true, 'padding' => 20]); expect($settings->toArray())->toBe(['fullWidth' => true, 'padding' => 20]); }); it('can be created as empty', function () { $settings = BlockSettings::empty(); expect($settings->toArray())->toBe([]); expect($settings->has('key'))->toBeFalse(); }); it('can get values by key', function () { $settings = BlockSettings::fromArray(['fullWidth' => true, 'padding' => 20]); expect($settings->get('fullWidth'))->toBeTrue(); expect($settings->get('padding'))->toBe(20); expect($settings->get('missing'))->toBeNull(); expect($settings->get('missing', 'default'))->toBe('default'); }); it('can check if key exists', function () { $settings = BlockSettings::fromArray(['fullWidth' => true]); expect($settings->has('fullWidth'))->toBeTrue(); expect($settings->has('missing'))->toBeFalse(); }); it('can add new key-value pair', function () { $settings = BlockSettings::fromArray(['fullWidth' => true]); $newSettings = $settings->with('padding', 20); expect($newSettings->get('fullWidth'))->toBeTrue(); expect($newSettings->get('padding'))->toBe(20); expect($settings->has('padding'))->toBeFalse(); // Original unchanged }); it('can remove key', function () { $settings = BlockSettings::fromArray(['fullWidth' => true, 'padding' => 20]); $newSettings = $settings->without('fullWidth'); expect($newSettings->has('fullWidth'))->toBeFalse(); expect($newSettings->has('padding'))->toBeTrue(); expect($settings->has('fullWidth'))->toBeTrue(); // Original unchanged }); it('accepts scalar values', function () { $settings = BlockSettings::fromArray([ 'string' => 'test', 'int' => 123, 'float' => 45.67, 'bool' => true, 'null' => null, ]); expect($settings->get('string'))->toBe('test'); expect($settings->get('int'))->toBe(123); expect($settings->get('float'))->toBe(45.67); expect($settings->get('bool'))->toBeTrue(); expect($settings->get('null'))->toBeNull(); }); it('accepts arrays of scalar values', function () { $settings = BlockSettings::fromArray([ 'classes' => ['container', 'full-width'], 'numbers' => [1, 2, 3], ]); expect($settings->get('classes'))->toBe(['container', 'full-width']); expect($settings->get('numbers'))->toBe([1, 2, 3]); }); it('accepts nested arrays', function () { $settings = BlockSettings::fromArray([ 'style' => [ 'margin' => 10, 'padding' => 20, ], ]); expect($settings->get('style'))->toBe(['margin' => 10, 'padding' => 20]); }); it('throws exception for non-string keys', function () { expect(fn () => BlockSettings::fromArray([0 => 'value'])) ->toThrow(InvalidArgumentException::class, 'BlockSettings keys must be strings'); }); it('throws exception for non-serializable values', function () { expect(fn () => BlockSettings::fromArray(['key' => fopen('php://memory', 'r')])) ->toThrow(InvalidArgumentException::class, 'BlockSettings value for key'); }); });