- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
158 lines
5.2 KiB
PHP
158 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Router\ValueObjects\Placeholder;
|
|
use App\Framework\Router\ValueObjects\RoutePath;
|
|
|
|
describe('RoutePath', function () {
|
|
describe('creation', function () {
|
|
it('can be created from elements', function () {
|
|
$path = RoutePath::fromElements('api', 'users', Placeholder::fromString('id'));
|
|
|
|
expect($path->toString())->toBe('/api/users/{id}');
|
|
expect($path->isDynamic())->toBeTrue();
|
|
expect($path->getParameterNames())->toBe(['id']);
|
|
});
|
|
|
|
it('can be created from string', function () {
|
|
$path = RoutePath::fromString('/api/users/{id}');
|
|
|
|
expect($path->toString())->toBe('/api/users/{id}');
|
|
expect($path->isDynamic())->toBeTrue();
|
|
expect($path->getParameterNames())->toBe(['id']);
|
|
});
|
|
|
|
it('handles static routes', function () {
|
|
$path = RoutePath::fromElements('api', 'health');
|
|
|
|
expect($path->toString())->toBe('/api/health');
|
|
expect($path->isStatic())->toBeTrue();
|
|
expect($path->getParameterNames())->toBe([]);
|
|
});
|
|
|
|
it('handles wildcard parameters', function () {
|
|
$path = RoutePath::fromString('/files/{path*}');
|
|
|
|
expect($path->toString())->toBe('/files/{path*}');
|
|
|
|
$placeholders = $path->getPlaceholders();
|
|
expect($placeholders)->toHaveCount(1);
|
|
expect($placeholders[0]->isWildcard())->toBeTrue();
|
|
});
|
|
|
|
it('throws on empty path', function () {
|
|
expect(fn() => RoutePath::fromElements())
|
|
->toThrow(InvalidArgumentException::class);
|
|
});
|
|
});
|
|
|
|
describe('fluent builder', function () {
|
|
it('can build paths fluently', function () {
|
|
$path = RoutePath::create()
|
|
->segment('api')
|
|
->segment('users')
|
|
->parameter('id')
|
|
->build();
|
|
|
|
expect($path->toString())->toBe('/api/users/{id}');
|
|
});
|
|
|
|
it('supports typed parameters', function () {
|
|
$path = RoutePath::create()
|
|
->segment('api')
|
|
->segment('users')
|
|
->typedParameter('id', 'uuid')
|
|
->build();
|
|
|
|
$placeholders = $path->getPlaceholders();
|
|
expect($placeholders[0]->getType())->toBe('uuid');
|
|
});
|
|
|
|
it('supports quick patterns', function () {
|
|
$path = RoutePath::create()
|
|
->segment('api')
|
|
->segment('users')
|
|
->uuid();
|
|
|
|
expect($path->toString())->toBe('/api/users/{id}');
|
|
});
|
|
});
|
|
|
|
describe('regex compilation', function () {
|
|
it('compiles static routes to regex', function () {
|
|
$path = RoutePath::fromString('/api/health');
|
|
|
|
expect($path->toRegex())->toBe('~^/api/health$~');
|
|
});
|
|
|
|
it('compiles dynamic routes to regex', function () {
|
|
$path = RoutePath::fromString('/api/users/{id}');
|
|
|
|
expect($path->toRegex())->toBe('~^/api/users/([^/]+)$~');
|
|
});
|
|
|
|
it('compiles typed parameters correctly', function () {
|
|
$path = RoutePath::fromElements(
|
|
'api',
|
|
'users',
|
|
Placeholder::typed('id', 'int')
|
|
);
|
|
|
|
expect($path->toRegex())->toBe('~^/api/users/(\d+)$~');
|
|
});
|
|
|
|
it('compiles wildcard parameters', function () {
|
|
$path = RoutePath::fromElements(
|
|
'files',
|
|
Placeholder::wildcard('path')
|
|
);
|
|
|
|
expect($path->toRegex())->toBe('~^/files/(.+?)$~');
|
|
});
|
|
});
|
|
|
|
describe('manipulation', function () {
|
|
it('can append elements', function () {
|
|
$base = RoutePath::fromElements('api', 'users');
|
|
$extended = $base->append(Placeholder::fromString('id'));
|
|
|
|
expect($extended->toString())->toBe('/api/users/{id}');
|
|
});
|
|
|
|
it('can prepend elements', function () {
|
|
$base = RoutePath::fromElements('users', Placeholder::fromString('id'));
|
|
$extended = $base->prepend('api');
|
|
|
|
expect($extended->toString())->toBe('/api/users/{id}');
|
|
});
|
|
});
|
|
|
|
describe('analysis', function () {
|
|
it('counts segments correctly', function () {
|
|
$path = RoutePath::fromString('/api/users/{id}');
|
|
|
|
expect($path->getSegmentCount())->toBe(3);
|
|
});
|
|
|
|
it('identifies placeholders', function () {
|
|
$path = RoutePath::fromString('/api/users/{id}/posts/{postId}');
|
|
|
|
$placeholders = $path->getPlaceholders();
|
|
expect($placeholders)->toHaveCount(2);
|
|
expect($path->getParameterNames())->toBe(['id', 'postId']);
|
|
});
|
|
});
|
|
|
|
describe('validation', function () {
|
|
it('validates segment content', function () {
|
|
expect(fn() => RoutePath::fromElements('api', ''))
|
|
->toThrow(InvalidArgumentException::class);
|
|
});
|
|
|
|
it('rejects invalid characters in segments', function () {
|
|
expect(fn() => RoutePath::fromElements('api', 'users{id}'))
|
|
->toThrow(InvalidArgumentException::class);
|
|
});
|
|
});
|
|
}); |