# #region Test.Infrastructure.GradioProxy [C:3] [TYPE Module] [SEMANTICS test,nginx,docker,agent,gradio] # @BRIEF Verify Gradio agent proxy contracts across nginx, compose, and agent launch config. # @RELATION BINDS_TO -> [docker.nginx.conf] # @RELATION BINDS_TO -> [docker.nginx.ssl.conf] # @RELATION BINDS_TO -> [AgentChat.Config] # @TEST_EDGE: docker_dns_name -> Proxy targets compose service name `agent`. # @TEST_EDGE: prefix_forwarding -> Proxy preserves `/api/agent/gradio` for Gradio root_path. # @TEST_EDGE: auth_forwarding -> Browser Authorization header is forwarded. from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] def _read(relative_path: str) -> str: return (PROJECT_ROOT / relative_path).read_text(encoding="utf-8") def test_nginx_http_gradio_proxy_targets_agent_service_and_preserves_prefix(): """HTTP nginx routes Gradio traffic to compose service `agent` without stripping root_path.""" text = _read("docker/nginx.conf") assert "location /api/agent/gradio/" in text assert "set $agent_api http://agent:7860;" in text assert "superset-tools-agent" not in text assert "rewrite ^/api/agent/gradio" not in text assert "proxy_set_header Authorization $http_authorization;" in text assert "proxy_set_header Connection $connection_upgrade;" in text assert "proxy_redirect http://agent:7860/ /api/agent/gradio/;" in text def test_nginx_ssl_gradio_proxy_matches_http_contract(): """SSL nginx keeps the same Gradio proxy invariants as HTTP nginx.""" text = _read("docker/nginx.ssl.conf") assert "map $http_upgrade $connection_upgrade" in text assert "location /api/agent/gradio/" in text assert "set $agent_api http://agent:7860;" in text assert "superset-tools-agent" not in text assert "rewrite ^/api/agent/gradio" not in text assert "proxy_set_header Authorization $http_authorization;" in text assert "proxy_set_header X-Forwarded-Proto https;" in text def test_compose_frontend_depends_on_agent_and_agent_uses_root_path(): """Compose starts agent before frontend and configures Gradio root_path.""" for compose_path in ("docker-compose.yml", "docker-compose.enterprise-clean.yml"): text = _read(compose_path) assert " frontend:" in text frontend_block = text.split(" frontend:", 1)[1].split("\n\n", 1)[0] assert " - backend" in frontend_block assert " - agent" in frontend_block agent_block = text.split(" agent:", 1)[1] assert "GRADIO_ROOT_PATH: /api/agent/gradio" in agent_block def test_build_script_generated_enterprise_compose_keeps_agent_proxy_contract(): """Release bundle compose heredocs preserve frontend->agent dependency and root_path.""" text = _read("build.sh") assert text.count(" - agent") >= 2 assert text.count("GRADIO_ROOT_PATH: /api/agent/gradio") >= 2 def test_agent_launch_uses_default_gradio_root_path(): """Agent runtime exports `/api/agent/gradio` as Gradio root_path for @gradio/client.""" config_text = _read("agent/src/ss_tools/agent/_config.py") run_text = _read("agent/src/ss_tools/agent/run.py") app_text = _read("agent/src/ss_tools/agent/app.py") assert 'GRADIO_ROOT_PATH: str = os.getenv("GRADIO_ROOT_PATH", "/api/agent/gradio")' in config_text assert "root_path=GRADIO_ROOT_PATH" in run_text assert "root_path=GRADIO_ROOT_PATH" in app_text # #endregion Test.Infrastructure.GradioProxy