'api.truckwash.io:4433', 'HTTP_X_FORWARDED_PROTO' => 'https', ], function (): void { $manager = new EdgeGatewayManagerUrlHarness(); $script = $manager->buildInstallScript('abc123'); expect($manager->getApiBaseUrl())->toBe('https://api.truckwash.io:4433'); expect($manager->buildInstallTokenVerifyUrl('abc123'))->toBe('https://api.truckwash.io:4433/edge-agent/install-token/verify?token=abc123'); expect($manager->buildInstallScriptUrl('abc123'))->toBe('https://api.truckwash.io:4433/edge-agent/install.sh?token=abc123'); expect($manager->buildInstallCommand('abc123'))->toContain("https://api.truckwash.io:4433/edge-agent/install.sh?token=abc123"); expect($script)->toContain('curl -fsSL "https://api.truckwash.io:4433/edge-agent/install-token/verify?token=abc123" >/dev/null'); expect($script)->toContain('mkdir -p "$INSTALL_DIR"'); expect($script)->toContain('curl -fsSL "https://api.truckwash.io:4433/edge-agent/artifacts/package.json" -o "$INSTALL_DIR/package.json"'); expect($script)->toContain('curl -fsSL "https://api.truckwash.io:4433/edge-agent/artifacts/agent.mjs" -o "$INSTALL_DIR/agent.mjs"'); expect($script)->toContain('"apiUrl":"https://api.truckwash.io:4433"'); expect($script)->toContain('"installDir":"/opt/truckwash-edge-agent"'); expect($script)->toContain('"serviceName":"truckwash-edge-agent.service"'); expect($script)->toContain('"commandPollTimeoutSeconds":20'); expect($script)->toContain('"shellActionPollTimeoutSeconds":20'); expect($script)->toContain('"updateVerificationTimeoutSeconds":45'); expect($script)->toContain('"brokerUrl":"https://api.truckwash.io:4300"'); expect($script)->not->toContain('Undefined variable $INSTALL_DIR'); }); }); it('appends forwarded ports when the forwarded host omits them', function (): void { with_edge_gateway_server_state([ 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_HOST' => 'api.truckwash.io', 'HTTP_X_FORWARDED_PORT' => '4433', ], function (): void { $manager = new EdgeGatewayManagerUrlHarness(); expect($manager->getApiBaseUrl())->toBe('https://api.truckwash.io:4433'); }); }); it('infers https for the staging api host when only the https port is present', function (): void { with_edge_gateway_server_state([ 'HTTP_HOST' => 'api.truckwash.io:4433', 'SERVER_PORT' => '4433', ], function (): void { $manager = new EdgeGatewayManagerUrlHarness(); $script = $manager->buildInstallScript('port-only'); expect($manager->getApiBaseUrl())->toBe('https://api.truckwash.io:4433'); expect($script)->toContain('"apiUrl":"https://api.truckwash.io:4433"'); expect($script)->toContain('"serviceName":"truckwash-edge-agent.service"'); expect($script)->toContain('"brokerUrl":"https://api.truckwash.io:4300"'); }); }); it('prefers EDGE_PUBLIC_API_URL when explicitly configured', function (): void { with_edge_gateway_server_state([ 'HTTP_HOST' => 'localhost', 'HTTP_X_FORWARDED_PROTO' => 'http', ], function (): void { putenv('EDGE_PUBLIC_API_URL=https://edge.example.test/api'); putenv('EDGE_PUBLIC_BROKER_URL=https://broker.edge.example.test'); $manager = new EdgeGatewayManagerUrlHarness(); expect($manager->getApiBaseUrl())->toBe('https://edge.example.test/api'); expect($manager->buildInstallScriptUrl('token-1'))->toBe('https://edge.example.test/api/edge-agent/install.sh?token=token-1'); expect($manager->buildInstallScript('token-1'))->toContain('"brokerUrl":"https://broker.edge.example.test"'); }); }); it('includes node-pty build prerequisites in the generated install script', function (): void { with_edge_gateway_server_state([ 'HTTP_HOST' => 'api.truckwash.io:4433', 'HTTP_X_FORWARDED_PROTO' => 'https', ], function (): void { $manager = new EdgeGatewayManagerUrlHarness(); $script = $manager->buildInstallScript('pty-token'); expect($script)->toMatch('/set -euo pipefail\s+curl -fsSL "https:\/\/api\.truckwash\.io:4433\/edge-agent\/install-token\/verify\?token=pty-token" >\/dev\/null\s+INSTALL_DIR=\/opt\/truckwash-edge-agent/'); expect($script)->toContain('apt-get install -y curl ca-certificates nodejs npm python3 make g++'); expect($script)->toContain('npm install --omit=dev'); }); });