Proxies (Cloudflare, nginx) drop idle WebSocket connections before the application notices, leaving clients typing into dead sockets. - Add server-side ping/pong heartbeat (30s) in terminal-server.js; terminate unresponsive clients instead of letting connections go stale - Move client keepAlive interval start to the connect event so it restarts correctly after reconnects - Remove hidden-tab keepalive short-circuit — server pings now own liveness; suppressing client pings while hidden masked proxy drops - Fix clearAllTimers to use clearTimeout for one-shot timers - On visibility resume, probe with a 5s timeout instead of the default 35s so half-open sockets are detected quickly - Bump coolify-realtime to 1.0.14 across all compose files
59 lines
2.6 KiB
PHP
59 lines
2.6 KiB
PHP
<?php
|
|
|
|
it('copies the realtime terminal utilities into the container image', function () {
|
|
$dockerfile = file_get_contents(base_path('docker/coolify-realtime/Dockerfile'));
|
|
|
|
expect($dockerfile)->toContain('COPY docker/coolify-realtime/terminal-utils.js /terminal/terminal-utils.js');
|
|
});
|
|
|
|
it('mounts the realtime terminal utilities in local development compose files', function (string $composeFile) {
|
|
$composeContents = file_get_contents(base_path($composeFile));
|
|
|
|
expect($composeContents)->toContain('./docker/coolify-realtime/terminal-utils.js:/terminal/terminal-utils.js');
|
|
})->with([
|
|
'default dev compose' => 'docker-compose.dev.yml',
|
|
'maxio dev compose' => 'docker-compose-maxio.dev.yml',
|
|
]);
|
|
|
|
it('keeps terminal browser logging restricted to Vite development mode', function () {
|
|
$terminalClient = file_get_contents(base_path('resources/js/terminal.js'));
|
|
|
|
expect($terminalClient)
|
|
->toContain('const terminalDebugEnabled = import.meta.env.DEV;')
|
|
->toContain("logTerminal('log', '[Terminal] WebSocket connection established.');")
|
|
->not->toContain("console.log('[Terminal] WebSocket connection established. Cool cool cool cool cool cool.');");
|
|
});
|
|
|
|
it('keeps realtime terminal server logging restricted to development environments', function () {
|
|
$terminalServer = file_get_contents(base_path('docker/coolify-realtime/terminal-server.js'));
|
|
|
|
expect($terminalServer)
|
|
->toContain("const terminalDebugEnabled = ['local', 'development'].includes(")
|
|
->toContain('if (!terminalDebugEnabled) {')
|
|
->not->toContain("console.log('Coolify realtime terminal server listening on port 6002. Let the hacking begin!');");
|
|
});
|
|
|
|
it('configures a server-initiated WebSocket heartbeat to survive proxy idle timeouts', function () {
|
|
$terminalServer = file_get_contents(base_path('docker/coolify-realtime/terminal-server.js'));
|
|
|
|
expect($terminalServer)
|
|
->toContain('ws.isAlive = true;')
|
|
->toContain("ws.on('pong'")
|
|
->toContain('ws.ping();')
|
|
->toContain('ws.terminate();')
|
|
->toContain('HEARTBEAT_INTERVAL_MS');
|
|
});
|
|
|
|
it('removes the keepalive short-circuit that fired when the tab was hidden', function () {
|
|
$terminalClient = file_get_contents(base_path('resources/js/terminal.js'));
|
|
|
|
expect($terminalClient)
|
|
->not->toContain('// Skip keepalive when document is hidden to prevent unnecessary disconnects');
|
|
});
|
|
|
|
it('uses a fast probe timeout when the tab regains visibility', function () {
|
|
$terminalClient = file_get_contents(base_path('resources/js/terminal.js'));
|
|
|
|
expect($terminalClient)
|
|
->toContain("'Visibility-resume timeout'");
|
|
});
|