feat(cli): update tests for self-hosted

This commit is contained in:
l2and
2026-07-31 09:56:10 -07:00
parent 1c9b0c791c
commit c5d0500e76
3 changed files with 184 additions and 0 deletions
+46
View File
@@ -1354,3 +1354,49 @@ def test_prepare_args_and_stdin_distributed_mode() -> None:
assert "langgraph-executor:" in actual_stdin
assert "FROM langchain/langgraph-executor:" in actual_stdin
assert "executor_entrypoint.sh" in actual_stdin
def test_deploy_image_uri_rejects_incompatible_source(monkeypatch, tmp_path) -> None:
"""--image-uri raises UsageError when applied to a non-external_docker deployment."""
# --no-input sets the module-level _no_input global; ensure it's restored.
monkeypatch.setattr(deploy_module, "_no_input", False)
config = tmp_path / "langgraph.json"
config.write_text('{"graphs": {"agent": "agent.py:graph"}, "dependencies": ["."]}')
class FakeClient:
def __init__(self, host_url: str, api_key: str, tenant_id: str | None = None):
self.base_url = host_url
def get_deployment(self, deployment_id: str):
return {
"id": deployment_id,
"name": "test-deploy",
"source": "internal_docker",
"tenant_id": "tenant-1",
}
monkeypatch.setattr(deploy_module, "HostBackendClient", FakeClient)
runner = CliRunner()
result = runner.invoke(
cli,
[
"deploy",
"--api-key",
"test-key",
"--host-url",
"https://api.example.com",
"--deployment-id",
"dep-123",
"--image-uri",
"registry.example.com/app:latest",
"--config",
str(config),
"--no-input",
],
)
assert result.exit_code != 0
assert "different build mode" in result.output
assert "cannot be updated with --image-uri" in result.output
@@ -543,6 +543,55 @@ class TestCreateHostBackendClientNoInput:
assert client is not None
class TestCreateHostBackendClientEndpointFallback:
def test_langsmith_endpoint_env_var_used_as_fallback(self, monkeypatch):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.setenv("LANGSMITH_ENDPOINT", "https://smith.example.com/api/v1")
monkeypatch.delenv("LANGGRAPH_HOST_URL", raising=False)
client = _create_host_backend_client(host_url=None, api_key=None, env_vars={})
assert client.base_url == "https://smith.example.com/api-host"
def test_langsmith_endpoint_from_env_vars_dict(self, monkeypatch):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.delenv("LANGSMITH_ENDPOINT", raising=False)
client = _create_host_backend_client(
host_url=None,
api_key=None,
env_vars={"LANGSMITH_ENDPOINT": "https://smith.example.com/api/v1"},
)
assert client.base_url == "https://smith.example.com/api-host"
def test_cloud_langsmith_endpoint_not_used_as_self_hosted(self, monkeypatch):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.setenv("LANGSMITH_ENDPOINT", "https://api.smith.langchain.com")
client = _create_host_backend_client(host_url=None, api_key=None, env_vars={})
assert client.base_url == "https://api.host.langchain.com"
def test_langchain_api_endpoint_not_used_as_self_hosted(self, monkeypatch):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.setenv("LANGSMITH_ENDPOINT", "https://api.langchain.com")
client = _create_host_backend_client(host_url=None, api_key=None, env_vars={})
assert client.base_url == "https://api.host.langchain.com"
def test_explicit_host_url_takes_precedence_over_langsmith_endpoint(
self, monkeypatch
):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.setenv("LANGSMITH_ENDPOINT", "https://smith.example.com/api/v1")
client = _create_host_backend_client(
host_url="https://custom.host.com",
api_key=None,
env_vars={},
)
assert client.base_url == "https://custom.host.com"
def test_no_endpoint_falls_back_to_cloud_default(self, monkeypatch):
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
monkeypatch.delenv("LANGSMITH_ENDPOINT", raising=False)
client = _create_host_backend_client(host_url=None, api_key=None, env_vars={})
assert client.base_url == "https://api.host.langchain.com"
class TestSmithDashboardBaseUrl:
def test_none_returns_default(self):
assert _smith_dashboard_base_url(None) == "https://smith.langchain.com"
@@ -598,6 +647,42 @@ class TestSmithDashboardBaseUrl:
== "https://smith.langchain.com"
)
def test_self_hosted_api_host_suffix(self):
assert (
_smith_dashboard_base_url("https://smith.example.com/api-host")
== "https://smith.example.com"
)
def test_self_hosted_api_host_trailing_slash(self):
assert (
_smith_dashboard_base_url("https://smith.example.com/api-host/")
== "https://smith.example.com"
)
def test_self_hosted_localhost_api_host(self):
assert (
_smith_dashboard_base_url("http://localhost:8080/api-host")
== "http://localhost:8080"
)
def test_self_hosted_api_host_suffix(self):
assert (
_smith_dashboard_base_url("https://langsmith.example.com/api-host")
== "https://langsmith.example.com"
)
def test_self_hosted_api_host_trailing_slash(self):
assert (
_smith_dashboard_base_url("https://langsmith.example.com/api-host/")
== "https://langsmith.example.com"
)
def test_self_hosted_localhost_api_host(self):
assert (
_smith_dashboard_base_url("http://localhost:8080/api-host")
== "http://localhost:8080"
)
class TestResolvePushedImageDigest:
"""Tests for ``_resolve_pushed_image_digest`` — runner is mocked to
@@ -178,6 +178,59 @@ def test_update_deployment_no_secrets(client):
assert result == {"ok": True}
def test_update_deployment_external():
captured: dict = {}
c = _capturing_client(captured)
result = c.update_deployment_external(
"dep-123", "registry.example.com/app@sha256:abc123"
)
assert result == {"ok": True}
body = json.loads(captured["body"])
assert "revision_source" not in body
assert body["source_revision_config"]["image_uri"] == (
"registry.example.com/app@sha256:abc123"
)
def test_update_deployment_external_forwards_tracked_packages():
captured: dict = {}
c = _capturing_client(captured)
c.update_deployment_external(
"dep-123",
"registry.example.com/app:latest",
tracked_packages=["google-adk:1.0.0"],
)
body = json.loads(captured["body"])
assert body["tracked_packages"] == ["google-adk:1.0.0"]
assert "revision_source" not in body
def test_update_deployment_external_omits_tracked_packages_when_absent():
captured: dict = {}
c = _capturing_client(captured)
c.update_deployment_external("dep-123", "registry.example.com/app:latest")
body = json.loads(captured["body"])
assert "tracked_packages" not in body
assert "revision_source" not in body
def test_request_builds_full_url_with_path_prefix():
"""base_url with a path prefix (/api-host) must not be dropped when paths start with /."""
def handler(req: httpx.Request) -> httpx.Response:
assert str(req.url) == "https://smith.example.com/api-host/v2/deployments"
return httpx.Response(200, json={"ok": True})
c = HostBackendClient("https://smith.example.com/api-host", "key")
c._client = httpx.Client(
transport=httpx.MockTransport(handler),
headers={"X-Api-Key": "key", "Accept": "application/json"},
timeout=30,
)
result = c._request("GET", "/v2/deployments")
assert result == {"ok": True}
def _capturing_client(captured: dict) -> HostBackendClient:
def handler(req: httpx.Request) -> httpx.Response:
captured["body"] = req.read()