Files
michaelschiemer/tests/Unit/Framework/Logging/Formatter/LineFormatterTest.php.old
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

355 lines
11 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Logging\Formatter\LineFormatter;
use App\Framework\Logging\LogChannel;
use App\Framework\Logging\LogLevel;
use App\Framework\Logging\LogRecord;
describe('LineFormatter', function () {
describe('default format', function () {
it('formats basic log record with default format', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('app');
expect($formatted)->toContain('INFO');
expect($formatted)->toContain('Test message');
});
it('includes timestamp in formatted output', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
// Check for timestamp pattern (YYYY-MM-DD HH:MM:SS)
expect($formatted)->toMatch('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/');
});
it('includes channel in formatted output', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('security')
);
$formatted = $formatter($record);
expect($formatted)->toContain('security');
});
it('includes level name in formatted output', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::ERROR,
message: 'Error message',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('ERROR');
});
it('includes message in formatted output', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Important information',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('Important information');
});
it('defaults to "app" channel when no channel specified', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: null
);
$formatted = $formatter($record);
expect($formatted)->toContain('app');
});
});
describe('custom format', function () {
it('uses custom format string', function () {
$formatter = new LineFormatter(format: '{level}: {message}');
$record = new LogRecord(
level: LogLevel::WARNING,
message: 'Custom format',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toBe('WARNING: Custom format');
});
it('allows custom timestamp format', function () {
$formatter = new LineFormatter(timestampFormat: 'Y-m-d');
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
// Should match YYYY-MM-DD format without time
expect($formatted)->toMatch('/\d{4}-\d{2}-\d{2}/');
expect($formatted)->not->toMatch('/\d{2}:\d{2}:\d{2}/');
});
it('supports minimal format', function () {
$formatter = new LineFormatter(format: '{message}');
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Just the message',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toBe('Just the message');
});
});
describe('context handling', function () {
it('includes context data as JSON when present', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'User action',
channel: new LogChannel('app'),
context: ['user_id' => 123, 'action' => 'login']
);
$formatted = $formatter($record);
expect($formatted)->toContain('user_id');
expect($formatted)->toContain('123');
expect($formatted)->toContain('action');
expect($formatted)->toContain('login');
});
it('includes extra data as JSON when present', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('app'),
extra: ['request_id' => 'req-123']
);
$formatted = $formatter($record);
expect($formatted)->toContain('request_id');
expect($formatted)->toContain('req-123');
});
it('merges context and extra data in JSON', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Test message',
channel: new LogChannel('app'),
context: ['key1' => 'value1'],
extra: ['key2' => 'value2']
);
$formatted = $formatter($record);
expect($formatted)->toContain('key1');
expect($formatted)->toContain('value1');
expect($formatted)->toContain('key2');
expect($formatted)->toContain('value2');
});
it('shows empty string when no context or extra data', function () {
$formatter = new LineFormatter(format: '{message} {context}');
$record = new LogRecord(
level: LogLevel::INFO,
message: 'No context',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toBe('No context ');
});
});
describe('different log levels', function () {
it('formats DEBUG level correctly', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::DEBUG,
message: 'Debug info',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('DEBUG');
});
it('formats NOTICE level correctly', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::NOTICE,
message: 'Notice',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('NOTICE');
});
it('formats CRITICAL level correctly', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::CRITICAL,
message: 'Critical error',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('CRITICAL');
});
it('formats EMERGENCY level correctly', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::EMERGENCY,
message: 'Emergency',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('EMERGENCY');
});
});
describe('special characters', function () {
it('handles unicode characters in message', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Übung mit Ümläüten und 日本語',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('Übung mit Ümläüten und 日本語');
});
it('handles newlines in message', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: "Line 1\nLine 2",
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain("Line 1\nLine 2");
});
it('handles quotes in message', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Message with "quotes" and \'apostrophes\'',
channel: new LogChannel('app')
);
$formatted = $formatter($record);
expect($formatted)->toContain('Message with "quotes" and \'apostrophes\'');
});
});
describe('complex scenarios', function () {
it('formats record with all fields', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::ERROR,
message: 'Database error',
channel: new LogChannel('database'),
context: ['query' => 'SELECT * FROM users'],
extra: ['request_id' => 'req-456']
);
$formatted = $formatter($record);
expect($formatted)->toContain('ERROR');
expect($formatted)->toContain('Database error');
expect($formatted)->toContain('database');
expect($formatted)->toContain('query');
expect($formatted)->toContain('request_id');
});
it('is invokable', function () {
$formatter = new LineFormatter();
$record = new LogRecord(
level: LogLevel::INFO,
message: 'Invokable test',
channel: new LogChannel('app')
);
// Test that formatter is invokable
$formatted = $formatter($record);
expect($formatted)->toBeString();
expect($formatted)->toContain('Invokable test');
});
});
});