- 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.
293 lines
14 KiB
PHP
293 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Framework\Development\HotReload;
|
|
|
|
use App\Framework\Development\HotReload\FileChangeEvent;
|
|
use App\Framework\Development\HotReload\FileChangeType;
|
|
use App\Framework\Development\HotReload\HotReloadServer;
|
|
use App\Framework\Development\HotReload\ReloadType;
|
|
|
|
describe('HotReloadServer', function () {
|
|
it('determines full reload for PHP files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('determineReloadType');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/src/Controller/UserController.php');
|
|
$reloadType = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($reloadType)->toBe(ReloadType::FULL);
|
|
});
|
|
|
|
it('determines CSS reload for CSS files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('determineReloadType');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/resources/css/app.css');
|
|
$reloadType = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($reloadType)->toBe(ReloadType::CSS);
|
|
});
|
|
|
|
it('determines HMR reload for JavaScript files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('determineReloadType');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/resources/js/app.js');
|
|
$reloadType = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($reloadType)->toBe(ReloadType::HMR);
|
|
});
|
|
|
|
it('determines HMR reload for TypeScript files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('determineReloadType');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/resources/js/module.ts');
|
|
$reloadType = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($reloadType)->toBe(ReloadType::HMR);
|
|
});
|
|
|
|
it('determines full reload for view files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('determineReloadType');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/resources/views/home.view.php');
|
|
$reloadType = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($reloadType)->toBe(ReloadType::FULL);
|
|
});
|
|
|
|
it('should clear cache for config changes', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('shouldClearCache');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/config/app.php');
|
|
$shouldClear = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($shouldClear)->toBeTrue();
|
|
});
|
|
|
|
it('should clear cache for controller changes', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('shouldClearCache');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/src/Controller/UserController.php');
|
|
$shouldClear = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($shouldClear)->toBeTrue();
|
|
});
|
|
|
|
it('should clear cache for route changes', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('shouldClearCache');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/src/Router/WebRoutes.php');
|
|
$shouldClear = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($shouldClear)->toBeTrue();
|
|
});
|
|
|
|
it('should clear cache for view changes', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('shouldClearCache');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/resources/views/components/header.view.php');
|
|
$shouldClear = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($shouldClear)->toBeTrue();
|
|
});
|
|
|
|
it('should not clear cache for regular PHP files', function () {
|
|
$server = new \ReflectionClass(HotReloadServer::class);
|
|
$method = $server->getMethod('shouldClearCache');
|
|
|
|
$fileWatcher = new class extends \App\Framework\Filesystem\FileWatcher {
|
|
public function __construct() {}
|
|
};
|
|
|
|
$sseStream = new class implements \App\Framework\Http\SseStreamInterface {
|
|
public function start($headers, $status, array $initialEvents = []): void {}
|
|
public function sendEvent($event): void {}
|
|
public function send(string $data, ?string $event = null, ?string $id = null, ?int $retry = null): void {}
|
|
public function sendJson(array $data, ?string $event = null, ?string $id = null): void {}
|
|
public function sendHeartbeat(?string $id = null): void {}
|
|
public function sendRetry(int $milliseconds): void {}
|
|
public function close(?string $message = null): void {}
|
|
public function isConnectionActive(): bool { return true; }
|
|
public function isActive(): bool { return true; }
|
|
};
|
|
|
|
$hotReloadServer = new HotReloadServer($fileWatcher, $sseStream);
|
|
|
|
$event = FileChangeEvent::modified('/var/www/html/src/Service/UserService.php');
|
|
$shouldClear = $method->invoke($hotReloadServer, $event);
|
|
|
|
expect($shouldClear)->toBeFalse();
|
|
});
|
|
});
|