- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
106 lines
3.9 KiB
PHP
106 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\OAuth\ValueObjects\TokenScope;
|
|
|
|
describe('TokenScope Value Object', function () {
|
|
it('creates from array of scopes', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write', 'admin']);
|
|
|
|
expect($scope->toArray())->toBe(['read', 'write', 'admin']);
|
|
expect($scope->toString())->toBe('read write admin');
|
|
});
|
|
|
|
it('creates from space-separated string', function () {
|
|
$scope = TokenScope::fromString('read write admin');
|
|
|
|
expect($scope->toArray())->toBe(['read', 'write', 'admin']);
|
|
});
|
|
|
|
it('handles extra whitespace in string', function () {
|
|
$scope = TokenScope::fromString(' read write admin ');
|
|
|
|
expect($scope->toArray())->toBe(['read', 'write', 'admin']);
|
|
});
|
|
|
|
it('rejects empty scope array', function () {
|
|
TokenScope::fromArray([]);
|
|
})->throws(\InvalidArgumentException::class, 'Token scope cannot be empty');
|
|
|
|
it('rejects empty scope string', function () {
|
|
TokenScope::fromString('');
|
|
})->throws(\InvalidArgumentException::class, 'Token scope cannot be empty');
|
|
|
|
it('rejects scope array with empty strings', function () {
|
|
TokenScope::fromArray(['read', '', 'write']);
|
|
})->throws(\InvalidArgumentException::class, 'Invalid scope value');
|
|
|
|
it('rejects scope array with non-strings', function () {
|
|
TokenScope::fromArray(['read', 123, 'write']);
|
|
})->throws(\InvalidArgumentException::class, 'Invalid scope value');
|
|
|
|
it('checks if scope includes specific permission', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write', 'admin']);
|
|
|
|
expect($scope->includes('read'))->toBeTrue();
|
|
expect($scope->includes('write'))->toBeTrue();
|
|
expect($scope->includes('admin'))->toBeTrue();
|
|
expect($scope->includes('delete'))->toBeFalse();
|
|
});
|
|
|
|
it('checks if scope includes all required permissions', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write', 'admin']);
|
|
|
|
expect($scope->includesAll(['read', 'write']))->toBeTrue();
|
|
expect($scope->includesAll(['read', 'admin']))->toBeTrue();
|
|
expect($scope->includesAll(['read', 'write', 'admin']))->toBeTrue();
|
|
expect($scope->includesAll(['read', 'delete']))->toBeFalse();
|
|
});
|
|
|
|
it('checks if scope includes any of specified permissions', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write']);
|
|
|
|
expect($scope->includesAny(['read', 'admin']))->toBeTrue();
|
|
expect($scope->includesAny(['write', 'delete']))->toBeTrue();
|
|
expect($scope->includesAny(['admin', 'delete']))->toBeFalse();
|
|
});
|
|
|
|
it('adds additional scopes immutably', function () {
|
|
$originalScope = TokenScope::fromArray(['read', 'write']);
|
|
|
|
$extendedScope = $originalScope->withAdditional(['admin', 'delete']);
|
|
|
|
// Original unchanged
|
|
expect($originalScope->toArray())->toBe(['read', 'write']);
|
|
|
|
// New instance extended
|
|
expect($extendedScope->toArray())->toBe(['read', 'write', 'admin', 'delete']);
|
|
});
|
|
|
|
it('removes specific scopes immutably', function () {
|
|
$originalScope = TokenScope::fromArray(['read', 'write', 'admin', 'delete']);
|
|
|
|
$reducedScope = $originalScope->without(['admin', 'delete']);
|
|
|
|
// Original unchanged
|
|
expect($originalScope->toArray())->toBe(['read', 'write', 'admin', 'delete']);
|
|
|
|
// New instance reduced
|
|
expect($reducedScope->toArray())->toBe(['read', 'write']);
|
|
});
|
|
|
|
it('prevents removing all scopes', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write']);
|
|
|
|
$scope->without(['read', 'write']);
|
|
})->throws(\InvalidArgumentException::class, 'Cannot remove all scopes');
|
|
|
|
it('converts to string correctly', function () {
|
|
$scope = TokenScope::fromArray(['read', 'write', 'admin']);
|
|
|
|
expect($scope->toString())->toBe('read write admin');
|
|
expect((string) $scope)->toBe('read write admin');
|
|
});
|
|
});
|