Files
michaelschiemer/tests/Unit/Framework/Logging/ValueObjects/LogEntryTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- 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.
2025-10-25 19:18:37 +02:00

222 lines
7.2 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Filesystem\ValueObjects\FilePath;
use App\Framework\Logging\LogLevel;
use App\Framework\Logging\ValueObjects\LogEntry;
describe('LogEntry', function () {
it('creates from parsed log line', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Test error message {"user_id":123}',
raw: '[2024-01-15 10:30:45] local.ERROR: Test error message {"user_id":123}',
sourcePath: $path
);
expect($entry->level)->toBe(LogLevel::ERROR);
expect($entry->message)->toBe('Test error message');
expect($entry->context)->toBe('{"user_id":123}');
expect($entry->parsed)->toBeTrue();
expect($entry->sourcePath)->toBe($path);
});
it('creates from raw unparsed line', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromRawLine('Some random log line', $path);
expect($entry->level)->toBe(LogLevel::INFO);
expect($entry->message)->toBe('Some random log line');
expect($entry->context)->toBe('');
expect($entry->parsed)->toBeFalse();
});
it('extracts message without context', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'INFO',
messageWithContext: 'Simple message without context',
raw: 'Simple message without context',
sourcePath: $path
);
expect($entry->message)->toBe('Simple message without context');
expect($entry->context)->toBe('');
});
it('matches search term in message', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Database connection failed',
raw: 'Database connection failed',
sourcePath: $path
);
expect($entry->matchesSearch('database'))->toBeTrue();
expect($entry->matchesSearch('Database'))->toBeTrue(); // Case insensitive
expect($entry->matchesSearch('connection'))->toBeTrue();
expect($entry->matchesSearch('redis'))->toBeFalse();
});
it('matches search term in context', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Error occurred {"database":"mysql"}',
raw: 'Error occurred {"database":"mysql"}',
sourcePath: $path
);
expect($entry->matchesSearch('mysql'))->toBeTrue();
});
it('checks log level match', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Test message',
raw: 'Test message',
sourcePath: $path
);
expect($entry->matchesLevel(LogLevel::ERROR))->toBeTrue();
expect($entry->matchesLevel(LogLevel::INFO))->toBeFalse();
});
it('checks minimum log level', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Test message',
raw: 'Test message',
sourcePath: $path
);
expect($entry->isAtLeastLevel(LogLevel::ERROR))->toBeTrue();
expect($entry->isAtLeastLevel(LogLevel::WARNING))->toBeTrue();
expect($entry->isAtLeastLevel(LogLevel::CRITICAL))->toBeFalse();
});
it('formats timestamp', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'INFO',
messageWithContext: 'Test',
raw: 'Test',
sourcePath: $path
);
expect($entry->getFormattedTimestamp())->toBe('2024-01-15 10:30:45');
expect($entry->getFormattedTimestamp('Y-m-d'))->toBe('2024-01-15');
});
it('parses context as array', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Error {"user_id":123,"action":"login"}',
raw: 'Error',
sourcePath: $path
);
$contextArray = $entry->getContextArray();
expect($contextArray)->toBeArray();
expect($contextArray['user_id'])->toBe(123);
expect($contextArray['action'])->toBe('login');
});
it('returns empty array for no context', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'INFO',
messageWithContext: 'Simple message',
raw: 'Simple message',
sourcePath: $path
);
expect($entry->getContextArray())->toBe([]);
expect($entry->hasContext())->toBeFalse();
});
it('converts to array', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'ERROR',
messageWithContext: 'Test error',
raw: '[2024-01-15 10:30:45] ERROR: Test error',
sourcePath: $path
);
$array = $entry->toArray();
expect($array)->toHaveKey('timestamp');
expect($array)->toHaveKey('level');
expect($array)->toHaveKey('message');
expect($array)->toHaveKey('context');
expect($array)->toHaveKey('raw');
expect($array)->toHaveKey('parsed');
expect($array)->toHaveKey('source_path');
expect($array['level'])->toBe('ERROR');
expect($array['message'])->toBe('Test error');
});
it('parses all log levels correctly', function () {
$path = FilePath::create('/tmp/test.log');
$levels = ['DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY'];
foreach ($levels as $levelName) {
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: $levelName,
messageWithContext: 'Test',
raw: 'Test',
sourcePath: $path
);
expect($entry->level->getName())->toBe($levelName);
}
});
it('handles unknown log level gracefully', function () {
$path = FilePath::create('/tmp/test.log');
$entry = LogEntry::fromParsedLine(
timestamp: '2024-01-15 10:30:45',
level: 'UNKNOWN',
messageWithContext: 'Test',
raw: 'Test',
sourcePath: $path
);
// Should fallback to INFO
expect($entry->level)->toBe(LogLevel::INFO);
});
});