getName())->toBe('id'); expect($placeholder->toString())->toBe('{id}'); expect($placeholder->isWildcard())->toBeFalse(); }); it('can be created with type', function () { $placeholder = Placeholder::typed('id', 'int'); expect($placeholder->getName())->toBe('id'); expect($placeholder->getType())->toBe('int'); expect($placeholder->getPattern())->toBe('(\d+)'); }); it('can be created as wildcard', function () { $placeholder = Placeholder::wildcard('path'); expect($placeholder->getName())->toBe('path'); expect($placeholder->toString())->toBe('{path*}'); expect($placeholder->isWildcard())->toBeTrue(); expect($placeholder->getPattern())->toBe('(.+?)'); }); it('validates placeholder names', function () { expect(fn () => Placeholder::fromString('')) ->toThrow(InvalidArgumentException::class); expect(fn () => Placeholder::fromString('123invalid')) ->toThrow(InvalidArgumentException::class); expect(fn () => Placeholder::fromString('invalid-name')) ->toThrow(InvalidArgumentException::class); }); it('accepts valid placeholder names', function () { $validNames = ['id', 'userId', 'user_id', '_private', 'snake_case']; foreach ($validNames as $name) { $placeholder = Placeholder::fromString($name); expect($placeholder->getName())->toBe($name); } }); }); describe('type patterns', function () { it('provides correct patterns for common types', function () { $patterns = [ 'int' => '(\d+)', 'uuid' => '([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', 'slug' => '([a-z0-9\-]+)', 'alpha' => '([a-zA-Z]+)', 'alphanumeric' => '([a-zA-Z0-9]+)', 'filename' => '([a-zA-Z0-9._\-]+)', ]; foreach ($patterns as $type => $expectedPattern) { $placeholder = Placeholder::typed('test', $type); expect($placeholder->getPattern())->toBe($expectedPattern); } }); it('falls back to default pattern for unknown types', function () { $placeholder = Placeholder::typed('test', 'unknown'); expect($placeholder->getPattern())->toBe('([^/]+)'); }); it('allows custom patterns', function () { $placeholder = Placeholder::typed('test', 'custom', '([a-z]{3})'); expect($placeholder->getPattern())->toBe('([a-z]{3})'); }); }); describe('string representation', function () { it('converts to proper placeholder syntax', function () { $regular = Placeholder::fromString('id'); $wildcard = Placeholder::wildcard('path'); expect($regular->toString())->toBe('{id}'); expect($wildcard->toString())->toBe('{path*}'); }); }); describe('pattern generation', function () { it('returns correct regex patterns', function () { $regular = Placeholder::fromString('id'); $wildcard = Placeholder::wildcard('path'); $typed = Placeholder::typed('id', 'int'); expect($regular->getPattern())->toBe('([^/]+)'); expect($wildcard->getPattern())->toBe('(.+?)'); expect($typed->getPattern())->toBe('(\d+)'); }); }); });