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.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -0,0 +1,112 @@
<?php
declare(strict_types=1);
use App\Framework\LiveComponents\Batch\BatchResult;
describe('BatchResult', function () {
it('creates success result with html', function () {
$result = BatchResult::success(
operationId: 'op-1',
html: '<div>Counter: 5</div>',
state: ['count' => 5],
events: [['type' => 'counter:incremented']]
);
expect($result->success)->toBeTrue();
expect($result->operationId)->toBe('op-1');
expect($result->html)->toBe('<div>Counter: 5</div>');
expect($result->state)->toBe(['count' => 5]);
expect($result->events)->toBe([['type' => 'counter:incremented']]);
expect($result->fragments)->toBeNull();
expect($result->error)->toBeNull();
expect($result->errorCode)->toBeNull();
});
it('creates success result with fragments', function () {
$result = BatchResult::success(
operationId: 'op-1',
fragments: ['counter-display' => '<span>5</span>'],
state: ['count' => 5]
);
expect($result->success)->toBeTrue();
expect($result->fragments)->toBe(['counter-display' => '<span>5</span>']);
expect($result->html)->toBeNull();
});
it('creates failure result', function () {
$result = BatchResult::failure(
error: 'Component not found',
errorCode: 'COMPONENT_NOT_FOUND',
operationId: 'op-1'
);
expect($result->success)->toBeFalse();
expect($result->error)->toBe('Component not found');
expect($result->errorCode)->toBe('COMPONENT_NOT_FOUND');
expect($result->operationId)->toBe('op-1');
expect($result->html)->toBeNull();
expect($result->fragments)->toBeNull();
expect($result->state)->toBeNull();
});
it('converts success to array', function () {
$result = BatchResult::success(
operationId: 'op-1',
html: '<div>Test</div>',
state: ['value' => 'test'],
events: []
);
$array = $result->toArray();
expect($array)->toBe([
'success' => true,
'operationId' => 'op-1',
'html' => '<div>Test</div>',
'state' => ['value' => 'test'],
'events' => [],
]);
});
it('converts failure to array', function () {
$result = BatchResult::failure(
error: 'Action not allowed',
errorCode: 'ACTION_NOT_ALLOWED',
operationId: 'op-2'
);
$array = $result->toArray();
expect($array)->toBe([
'success' => false,
'operationId' => 'op-2',
'error' => 'Action not allowed',
'errorCode' => 'ACTION_NOT_ALLOWED',
]);
});
it('includes fragments in array when present', function () {
$result = BatchResult::success(
operationId: 'op-1',
fragments: ['header' => '<h1>Title</h1>'],
state: ['title' => 'Title']
);
$array = $result->toArray();
expect($array['fragments'])->toBe(['header' => '<h1>Title</h1>']);
expect($array)->not->toHaveKey('html');
});
it('creates minimal success result', function () {
$result = BatchResult::success();
expect($result->success)->toBeTrue();
expect($result->operationId)->toBeNull();
expect($result->html)->toBeNull();
expect($result->state)->toBeNull();
expect($result->events)->toBe([]);
});
});