- 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.
131 lines
2.8 KiB
PHP
131 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Support;
|
|
|
|
use App\Framework\Http\SseStreamInterface;
|
|
use App\Framework\Router\Result\SseEvent;
|
|
|
|
/**
|
|
* Mock SSE Stream for Testing
|
|
*
|
|
* Simulates SSE stream behavior without actual HTTP connection.
|
|
* Records all sent events for assertion in tests.
|
|
*
|
|
* This is a standalone test implementation that mimics SseStream
|
|
* but does not extend it (since it's final).
|
|
*/
|
|
final class MockSseStream implements SseStreamInterface
|
|
{
|
|
/** @var array<SseEvent> */
|
|
private array $sentEvents = [];
|
|
|
|
private bool $isActive = true;
|
|
|
|
private bool $connectionActive = true;
|
|
|
|
public function __construct()
|
|
{
|
|
// No parent constructor call - we don't need actual stream
|
|
}
|
|
|
|
public function sendEvent(SseEvent $event): void
|
|
{
|
|
if (!$this->isActive || !$this->connectionActive) {
|
|
throw new \RuntimeException('Connection is not active');
|
|
}
|
|
|
|
$this->sentEvents[] = $event;
|
|
}
|
|
|
|
public function sendHeartbeat(): void
|
|
{
|
|
if (!$this->isActive || !$this->connectionActive) {
|
|
throw new \RuntimeException('Connection is not active');
|
|
}
|
|
|
|
// Record heartbeat as special event
|
|
$this->sentEvents[] = new SseEvent(
|
|
data: ':heartbeat',
|
|
event: 'heartbeat'
|
|
);
|
|
}
|
|
|
|
public function isActive(): bool
|
|
{
|
|
return $this->isActive;
|
|
}
|
|
|
|
public function isConnectionActive(): bool
|
|
{
|
|
return $this->connectionActive;
|
|
}
|
|
|
|
/**
|
|
* Simulate connection becoming inactive (for testing)
|
|
*/
|
|
public function simulateDisconnect(): void
|
|
{
|
|
$this->isActive = false;
|
|
$this->connectionActive = false;
|
|
}
|
|
|
|
/**
|
|
* Simulate connection timeout (for testing)
|
|
*/
|
|
public function simulateTimeout(): void
|
|
{
|
|
$this->connectionActive = false;
|
|
}
|
|
|
|
/**
|
|
* Get all sent events (for testing)
|
|
*
|
|
* @return array<SseEvent>
|
|
*/
|
|
public function getSentEvents(): array
|
|
{
|
|
return $this->sentEvents;
|
|
}
|
|
|
|
/**
|
|
* Get sent events by type (for testing)
|
|
*
|
|
* @return array<SseEvent>
|
|
*/
|
|
public function getSentEventsByType(string $eventType): array
|
|
{
|
|
return array_filter(
|
|
$this->sentEvents,
|
|
fn(SseEvent $event) => $event->event === $eventType
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get sent events count
|
|
*/
|
|
public function getSentEventsCount(): int
|
|
{
|
|
return count($this->sentEvents);
|
|
}
|
|
|
|
/**
|
|
* Clear all sent events (for testing)
|
|
*/
|
|
public function clear(): void
|
|
{
|
|
$this->sentEvents = [];
|
|
}
|
|
|
|
/**
|
|
* Reset connection state (for testing)
|
|
*/
|
|
public function reset(): void
|
|
{
|
|
$this->sentEvents = [];
|
|
$this->isActive = true;
|
|
$this->connectionActive = true;
|
|
}
|
|
}
|