2026-02-22 19:19:26 +05:30
|
|
|
# ruff: noqa: S101
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from uuid import uuid4
|
|
|
|
|
|
2026-02-22 20:20:19 +05:30
|
|
|
import pytest
|
|
|
|
|
|
2026-03-03 01:51:52 +05:30
|
|
|
import app.services.openclaw.session_service as session_service
|
2026-02-22 19:19:26 +05:30
|
|
|
from app.models.gateways import Gateway
|
2026-02-22 20:20:19 +05:30
|
|
|
from app.schemas.gateway_api import GatewayResolveQuery
|
2026-02-22 19:19:26 +05:30
|
|
|
from app.services.openclaw.gateway_resolver import (
|
|
|
|
|
gateway_client_config,
|
|
|
|
|
optional_gateway_client_config,
|
|
|
|
|
)
|
|
|
|
|
from app.services.openclaw.session_service import GatewaySessionService
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _gateway(
|
|
|
|
|
*,
|
|
|
|
|
disable_device_pairing: bool,
|
2026-02-22 20:20:19 +05:30
|
|
|
allow_insecure_tls: bool = False,
|
2026-02-22 19:19:26 +05:30
|
|
|
url: str = "ws://gateway.example:18789/ws",
|
|
|
|
|
token: str | None = " secret-token ",
|
|
|
|
|
) -> Gateway:
|
|
|
|
|
return Gateway(
|
|
|
|
|
id=uuid4(),
|
|
|
|
|
organization_id=uuid4(),
|
|
|
|
|
name="Primary gateway",
|
|
|
|
|
url=url,
|
|
|
|
|
token=token,
|
|
|
|
|
workspace_root="~/.openclaw",
|
|
|
|
|
disable_device_pairing=disable_device_pairing,
|
2026-02-22 20:20:19 +05:30
|
|
|
allow_insecure_tls=allow_insecure_tls,
|
2026-02-22 19:19:26 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_gateway_client_config_maps_disable_device_pairing() -> None:
|
|
|
|
|
config = gateway_client_config(_gateway(disable_device_pairing=True))
|
|
|
|
|
|
|
|
|
|
assert config.url == "ws://gateway.example:18789/ws"
|
|
|
|
|
assert config.token == "secret-token"
|
|
|
|
|
assert config.disable_device_pairing is True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_optional_gateway_client_config_maps_disable_device_pairing() -> None:
|
|
|
|
|
config = optional_gateway_client_config(_gateway(disable_device_pairing=False))
|
|
|
|
|
|
|
|
|
|
assert config is not None
|
|
|
|
|
assert config.disable_device_pairing is False
|
|
|
|
|
|
|
|
|
|
|
2026-02-22 20:20:19 +05:30
|
|
|
def test_gateway_client_config_maps_allow_insecure_tls() -> None:
|
|
|
|
|
config = gateway_client_config(
|
|
|
|
|
_gateway(disable_device_pairing=False, allow_insecure_tls=True),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert config.allow_insecure_tls is True
|
|
|
|
|
|
|
|
|
|
|
2026-02-22 19:19:26 +05:30
|
|
|
def test_optional_gateway_client_config_returns_none_for_missing_or_blank_url() -> None:
|
|
|
|
|
assert optional_gateway_client_config(None) is None
|
|
|
|
|
assert (
|
|
|
|
|
optional_gateway_client_config(
|
|
|
|
|
_gateway(disable_device_pairing=False, url=" "),
|
|
|
|
|
)
|
|
|
|
|
is None
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_to_resolve_query_keeps_gateway_disable_device_pairing_value() -> None:
|
|
|
|
|
resolved = GatewaySessionService.to_resolve_query(
|
|
|
|
|
board_id=None,
|
|
|
|
|
gateway_url="ws://gateway.example:18789/ws",
|
|
|
|
|
gateway_token="secret-token",
|
|
|
|
|
gateway_disable_device_pairing=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert resolved.gateway_disable_device_pairing is True
|
2026-02-22 20:20:19 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_to_resolve_query_keeps_gateway_allow_insecure_tls_value() -> None:
|
|
|
|
|
resolved = GatewaySessionService.to_resolve_query(
|
|
|
|
|
board_id=None,
|
|
|
|
|
gateway_url="wss://gateway.example:18789/ws",
|
|
|
|
|
gateway_token="secret-token",
|
|
|
|
|
gateway_allow_insecure_tls=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert resolved.gateway_allow_insecure_tls is True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
|
async def test_resolve_gateway_keeps_gateway_allow_insecure_tls_for_direct_url() -> None:
|
|
|
|
|
service = GatewaySessionService(session=object()) # type: ignore[arg-type]
|
|
|
|
|
_, config, _ = await service.resolve_gateway(
|
|
|
|
|
GatewayResolveQuery(
|
|
|
|
|
gateway_url="wss://gateway.example:18789/ws",
|
|
|
|
|
gateway_allow_insecure_tls=True,
|
|
|
|
|
),
|
|
|
|
|
user=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert config.allow_insecure_tls is True
|
2026-03-03 01:51:52 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
class _FakeGatewayQuery:
|
|
|
|
|
def __init__(self, gateway: Gateway | None) -> None:
|
|
|
|
|
self._gateway = gateway
|
|
|
|
|
self.filters: list[dict[str, object]] = []
|
|
|
|
|
|
|
|
|
|
def filter_by(self, **kwargs: object) -> _FakeGatewayQuery:
|
|
|
|
|
self.filters.append(kwargs)
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
async def first(self, _session: object) -> Gateway | None:
|
|
|
|
|
return self._gateway
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _FakeAsyncSession:
|
|
|
|
|
async def exec(
|
|
|
|
|
self, *_args: object, **_kwargs: object
|
|
|
|
|
) -> None: # pragma: no cover - guard only
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
|
async def test_resolve_gateway_uses_saved_gateway_settings_when_direct_flags_missing(
|
|
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
) -> None:
|
|
|
|
|
gateway = _gateway(
|
|
|
|
|
disable_device_pairing=True,
|
|
|
|
|
allow_insecure_tls=True,
|
|
|
|
|
url="wss://gateway.example:18789/ws",
|
|
|
|
|
token=" db-token ",
|
|
|
|
|
)
|
|
|
|
|
fake_query = _FakeGatewayQuery(gateway)
|
|
|
|
|
monkeypatch.setattr(session_service.Gateway, "objects", fake_query)
|
|
|
|
|
|
|
|
|
|
service = GatewaySessionService(session=_FakeAsyncSession()) # type: ignore[arg-type]
|
|
|
|
|
_, config, _ = await service.resolve_gateway(
|
|
|
|
|
GatewayResolveQuery(gateway_url=gateway.url),
|
|
|
|
|
user=None,
|
|
|
|
|
organization_id=gateway.organization_id,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert config.token is None
|
|
|
|
|
assert config.allow_insecure_tls is True
|
|
|
|
|
assert config.disable_device_pairing is True
|
|
|
|
|
assert fake_query.filters == [
|
|
|
|
|
{"url": gateway.url},
|
|
|
|
|
{"organization_id": gateway.organization_id},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
|
|
|
async def test_resolve_gateway_prefers_explicit_direct_flags_over_saved_settings(
|
|
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
) -> None:
|
|
|
|
|
gateway = _gateway(
|
|
|
|
|
disable_device_pairing=True,
|
|
|
|
|
allow_insecure_tls=True,
|
|
|
|
|
url="wss://gateway.example:18789/ws",
|
|
|
|
|
token="db-token",
|
|
|
|
|
)
|
|
|
|
|
fake_query = _FakeGatewayQuery(gateway)
|
|
|
|
|
monkeypatch.setattr(session_service.Gateway, "objects", fake_query)
|
|
|
|
|
|
|
|
|
|
service = GatewaySessionService(session=object()) # type: ignore[arg-type]
|
|
|
|
|
_, config, _ = await service.resolve_gateway(
|
|
|
|
|
GatewayResolveQuery(
|
|
|
|
|
gateway_url=gateway.url,
|
|
|
|
|
gateway_token="explicit-token",
|
|
|
|
|
gateway_allow_insecure_tls=False,
|
|
|
|
|
gateway_disable_device_pairing=False,
|
|
|
|
|
),
|
|
|
|
|
user=None,
|
|
|
|
|
organization_id=gateway.organization_id,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert config.token == "explicit-token"
|
|
|
|
|
assert config.allow_insecure_tls is False
|
|
|
|
|
assert config.disable_device_pairing is False
|