Files

186 lines
5.6 KiB
Python

# -*- coding: utf-8 -*-
"""Integration tests for tool configuration HTTP API.
Covers GET /tools (list), PATCH /tools/{name}/toggle, and
GET /tools/{name}/config endpoints. Verifies that builtin tools
(e.g. get_current_time) appear in the list and can be toggled.
"""
from __future__ import annotations
import pytest
from helpers import default_http_timeout, scoped
_TOOL_HTTP_TIMEOUT = default_http_timeout(15.0)
# ------------------------------------------------------------------ #
# C1: tool list includes get_current_time
# ------------------------------------------------------------------ #
@pytest.mark.integration
@pytest.mark.p1
def test_tool_list_includes_get_current_time(app_server) -> None:
"""Test purpose:
- Verify GET /tools returns a list that includes the
get_current_time builtin tool with enabled=true.
Test flow:
1. GET /api/agents/default/tools.
2. Assert response is a list.
3. Find get_current_time in the list.
4. Assert it is enabled.
API endpoints:
- GET /api/agents/{agentId}/tools
"""
resp = app_server.api_request(
"GET",
scoped("default", "/tools"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert resp.status_code == 200, app_server.logs_tail()
tools = resp.json()
assert isinstance(tools, list)
assert len(tools) > 0, "tool list should not be empty"
names = {t.get("name") for t in tools}
assert (
"get_current_time" in names
), f"get_current_time not in tool list: {names}"
tool = next(t for t in tools if t["name"] == "get_current_time")
assert tool.get("enabled") is True
# ------------------------------------------------------------------ #
# C2: tool toggle disable / enable
# ------------------------------------------------------------------ #
@pytest.mark.integration
@pytest.mark.p1
def test_tool_toggle_disable_enable(app_server) -> None:
"""Test purpose:
- Verify PATCH /tools/{name}/toggle toggles the tool's
enabled state and the change is reflected in GET /tools.
Test flow:
1. PATCH toggle get_current_time → should return toggled state.
2. GET /tools → verify new enabled state.
3. PATCH toggle again to restore original state.
4. GET /tools → verify restored.
API endpoints:
- PATCH /api/agents/{agentId}/tools/{tool_name}/toggle
- GET /api/agents/{agentId}/tools
"""
get_before = app_server.api_request(
"GET",
scoped("default", "/tools"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert get_before.status_code == 200
tools = get_before.json()
tool = next(t for t in tools if t["name"] == "get_current_time")
original_enabled = tool["enabled"]
try:
toggle_resp = app_server.api_request(
"PATCH",
scoped("default", "/tools/get_current_time/toggle"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert toggle_resp.status_code == 200
toggled = toggle_resp.json()
assert toggled.get("enabled") is (not original_enabled)
get_after = app_server.api_request(
"GET",
scoped("default", "/tools"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert get_after.status_code == 200
after_tool = next(
t for t in get_after.json() if t["name"] == "get_current_time"
)
assert after_tool["enabled"] is (not original_enabled)
finally:
app_server.api_request(
"PATCH",
scoped("default", "/tools/get_current_time/toggle"),
timeout=_TOOL_HTTP_TIMEOUT,
)
# ------------------------------------------------------------------ #
# C3: agent-scoped tool list matches global
# ------------------------------------------------------------------ #
@pytest.mark.integration
@pytest.mark.p2
def test_tool_list_agent_scoped_matches_global(
app_server,
) -> None:
"""Test purpose:
- Verify agent-scoped GET /tools and header GET /tools return
the same set of tool names for the default agent.
Test flow:
1. GET /api/agents/default/tools (scoped).
2. GET /api/tools with X-Agent-Id: default (header).
3. Assert both return the same tool name set.
API endpoints:
- GET /api/agents/{agentId}/tools
- GET /api/tools
"""
scoped_resp = app_server.api_request(
"GET",
scoped("default", "/tools"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert scoped_resp.status_code == 200
header_resp = app_server.api_request(
"GET",
"/api/tools",
headers={"X-Agent-Id": "default"},
timeout=_TOOL_HTTP_TIMEOUT,
)
assert header_resp.status_code == 200
scoped_names = {t["name"] for t in scoped_resp.json()}
header_names = {t["name"] for t in header_resp.json()}
assert scoped_names == header_names
# ------------------------------------------------------------------ #
# C4: tool config get returns dict
# ------------------------------------------------------------------ #
@pytest.mark.integration
@pytest.mark.p2
def test_tool_config_get_returns_dict(app_server) -> None:
"""Test purpose:
- Verify GET /tools/{name}/config returns a valid dict.
Test flow:
1. GET /api/agents/default/tools/get_current_time/config.
2. Assert 200 + response is dict.
API endpoints:
- GET /api/agents/{agentId}/tools/{tool_name}/config
"""
resp = app_server.api_request(
"GET",
scoped("default", "/tools/get_current_time/config"),
timeout=_TOOL_HTTP_TIMEOUT,
)
assert resp.status_code == 200, app_server.logs_tail()
config = resp.json()
assert isinstance(config, dict)