Files
michaelschiemer/tests/Framework/Health/ValueObjects/HealthDetailsTest.php
Michael Schiemer 5050c7d73a docs: consolidate documentation into organized structure
- 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
2025-10-05 11:05:04 +02:00

181 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Framework\Health\ValueObjects;
use App\Framework\Health\ValueObjects\HealthDetails;
use InvalidArgumentException;
describe('HealthDetails Value Object', function () {
it('can be created empty', function () {
$details = HealthDetails::empty();
expect($details->isEmpty())->toBeTrue();
expect($details->count())->toBe(0);
expect($details->toArray())->toBe([]);
});
it('can be created from array', function () {
$data = ['host' => 'localhost', 'port' => 3306];
$details = HealthDetails::fromArray($data);
expect($details->isEmpty())->toBeFalse();
expect($details->count())->toBe(2);
expect($details->get('host'))->toBe('localhost');
expect($details->get('port'))->toBe(3306);
});
it('can add and remove details immutably', function () {
$details = HealthDetails::empty();
$newDetails = $details->with('key', 'value');
expect($details->has('key'))->toBeFalse(); // Original unchanged
expect($newDetails->has('key'))->toBeTrue();
expect($newDetails->get('key'))->toBe('value');
$withoutKey = $newDetails->without('key');
expect($withoutKey->has('key'))->toBeFalse();
expect($newDetails->has('key'))->toBeTrue(); // Original unchanged
});
it('gets values with defaults', function () {
$details = HealthDetails::fromArray(['existing' => 'value']);
expect($details->get('existing'))->toBe('value');
expect($details->get('missing'))->toBeNull();
expect($details->get('missing', 'default'))->toBe('default');
});
it('creates database details correctly', function () {
$details = HealthDetails::forDatabase('localhost', 3306, 'testdb', 25.5, 10);
expect($details->get('host'))->toBe('localhost');
expect($details->get('port'))->toBe(3306);
expect($details->get('database'))->toBe('testdb');
expect($details->get('connection_time_ms'))->toBe(25.5);
expect($details->get('active_connections'))->toBe(10);
});
it('creates cache details correctly', function () {
$details = HealthDetails::forCache('redis', 95, 1000, '128MB');
expect($details->get('driver'))->toBe('redis');
expect($details->get('hit_rate_percent'))->toBe(95);
expect($details->get('total_keys'))->toBe(1000);
expect($details->get('memory_usage'))->toBe('128MB');
});
it('creates disk details correctly', function () {
$details = HealthDetails::forDisk('/var/log', '100GB', '25GB', 75.0);
expect($details->get('path'))->toBe('/var/log');
expect($details->get('total_space'))->toBe('100GB');
expect($details->get('free_space'))->toBe('25GB');
expect($details->get('usage_percent'))->toBe(75.0);
});
it('creates system details correctly', function () {
$details = HealthDetails::forSystem(45.2, '8GB/16GB', 1.5, '5 days');
expect($details->get('cpu_usage_percent'))->toBe(45.2);
expect($details->get('memory_usage'))->toBe('8GB/16GB');
expect($details->get('load_average'))->toBe(1.5);
expect($details->get('uptime'))->toBe('5 days');
});
it('creates API details correctly', function () {
$details = HealthDetails::forApi('/health', 200, 150.5, 'v1.2.3');
expect($details->get('endpoint'))->toBe('/health');
expect($details->get('status_code'))->toBe(200);
expect($details->get('response_time_ms'))->toBe(150.5);
expect($details->get('version'))->toBe('v1.2.3');
});
it('creates error details correctly', function () {
$exception = new \RuntimeException('Test error', 500);
$details = HealthDetails::forError($exception);
expect($details->get('error_type'))->toBe('RuntimeException');
expect($details->get('error_message'))->toBe('Test error');
expect($details->get('error_code'))->toBe(500);
expect($details->get('error_file'))->toBeString();
expect($details->get('error_line'))->toBeInt();
});
it('can merge details', function () {
$details1 = HealthDetails::fromArray(['key1' => 'value1']);
$details2 = HealthDetails::fromArray(['key2' => 'value2']);
$merged = $details1->merge($details2);
expect($merged->get('key1'))->toBe('value1');
expect($merged->get('key2'))->toBe('value2');
expect($merged->count())->toBe(2);
});
it('identifies sensitive keys', function () {
$details = HealthDetails::fromArray([
'username' => 'john',
'password' => 'secret123',
'api_key' => 'abc123',
'database_token' => 'xyz789',
'normal_field' => 'value',
]);
$sensitiveKeys = $details->getSensitiveKeys();
expect($sensitiveKeys)->toContain('password');
expect($sensitiveKeys)->toContain('api_key');
expect($sensitiveKeys)->toContain('database_token');
expect($sensitiveKeys)->not->toContain('username');
expect($sensitiveKeys)->not->toContain('normal_field');
});
it('sanitizes sensitive data', function () {
$details = HealthDetails::fromArray([
'username' => 'john',
'password' => 'secret123',
'normal_field' => 'value',
]);
$sanitized = $details->toSanitizedArray();
expect($sanitized['username'])->toBe('john');
expect($sanitized['password'])->toBe('[REDACTED]');
expect($sanitized['normal_field'])->toBe('value');
});
it('throws exception for non-string keys', function () {
expect(fn () => HealthDetails::fromArray([123 => 'value']))->toThrow(InvalidArgumentException::class);
});
it('throws exception for empty keys', function () {
expect(fn () => HealthDetails::fromArray(['' => 'value']))->toThrow(InvalidArgumentException::class);
expect(fn () => HealthDetails::fromArray([' ' => 'value']))->toThrow(InvalidArgumentException::class);
});
it('throws exception for resource values', function () {
$resource = fopen('php://memory', 'r');
expect(fn () => HealthDetails::fromArray(['resource' => $resource]))->toThrow(InvalidArgumentException::class);
fclose($resource);
});
it('allows scalar and null values', function () {
$details = HealthDetails::fromArray([
'string' => 'text',
'int' => 123,
'float' => 12.34,
'bool' => true,
'null' => null,
]);
expect($details->get('string'))->toBe('text');
expect($details->get('int'))->toBe(123);
expect($details->get('float'))->toBe(12.34);
expect($details->get('bool'))->toBeTrue();
expect($details->get('null'))->toBeNull();
});
});