|
- import json
- import logging
-
- import httpx
- import pytest
- from autogen_core import CancellationToken, Component, ComponentModel
- from autogen_ext.tools.http import HttpTool
- from pydantic import ValidationError
-
-
- def test_tool_schema_generation(test_config: ComponentModel) -> None:
- tool = HttpTool.load_component(test_config)
- schema = tool.schema
-
- assert schema["name"] == "TestHttpTool"
- assert "description" in schema
- assert schema["description"] == "A test HTTP tool"
- assert "parameters" in schema
- assert schema["parameters"]["type"] == "object"
- assert "properties" in schema["parameters"]
- assert schema["parameters"]["properties"]["query"]["description"] == "The test query"
- assert schema["parameters"]["properties"]["query"]["type"] == "string"
- assert schema["parameters"]["properties"]["value"]["description"] == "A test value"
- assert schema["parameters"]["properties"]["value"]["type"] == "integer"
- assert "required" in schema["parameters"]
- assert set(schema["parameters"]["required"]) == {"query", "value"}
-
-
- def test_tool_properties(test_config: ComponentModel) -> None:
- tool = HttpTool.load_component(test_config)
-
- assert tool.name == "TestHttpTool"
- assert tool.description == "A test HTTP tool"
- assert tool.server_params.host == "localhost"
- assert tool.server_params.port == 8000
- assert tool.server_params.path == "/test"
- assert tool.server_params.scheme == "http"
- assert tool.server_params.method == "POST"
-
-
- def test_component_base_class(test_config: ComponentModel) -> None:
- tool = HttpTool.load_component(test_config)
- assert tool.dump_component() is not None
- assert HttpTool.load_component(tool.dump_component(), HttpTool) is not None
- assert isinstance(tool, Component)
-
-
- @pytest.mark.asyncio
- async def test_post_request(test_config: ComponentModel, test_server: None, caplog: pytest.LogCaptureFixture) -> None:
- tool = HttpTool.load_component(test_config)
-
- with caplog.at_level(logging.INFO):
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
- assert "Received: test query with value 42" in caplog.text
-
-
- @pytest.mark.asyncio
- async def test_post_request_json_return(test_config: ComponentModel, test_server: None) -> None:
- # Modify config to use json return type
- config = test_config.model_copy()
- config.config["return_type"] = "json"
- tool = HttpTool.load_component(config)
- result = await tool.run_json({"query": "test query", "value": 45}, CancellationToken())
-
- assert isinstance(result, dict)
- assert result["result"] == "Received: test query with value 45"
-
-
- @pytest.mark.asyncio
- async def test_get_request(test_config: ComponentModel, test_server: None) -> None:
- # Modify config for GET request
- config = test_config.model_copy()
- config.config["method"] = "GET"
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
-
- @pytest.mark.asyncio
- async def test_put_request(test_config: ComponentModel, test_server: None) -> None:
- # Modify config for PUT request
- config = test_config.model_copy()
- config.config["method"] = "PUT"
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
-
- @pytest.mark.asyncio
- async def test_path_params(test_config: ComponentModel, test_server: None) -> None:
- # Modify config to use path parameters
- config = test_config.model_copy()
- config.config["path"] = "/test/{query}/{value}"
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
-
- @pytest.mark.asyncio
- async def test_path_params_and_body(test_config: ComponentModel, test_server: None) -> None:
- # Modify config to use path parameters and include body parameters
- config = test_config.model_copy()
- config.config["method"] = "PUT"
- config.config["path"] = "/test/{query}/{value}"
- config.config["json_schema"] = {
- "type": "object",
- "properties": {
- "query": {"type": "string", "description": "The test query"},
- "value": {"type": "integer", "description": "A test value"},
- "extra": {"type": "string", "description": "Extra body parameter"},
- },
- "required": ["query", "value", "extra"],
- }
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42, "extra": "extra data"}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42 and extra extra data"
-
-
- @pytest.mark.asyncio
- async def test_delete_request(test_config: ComponentModel, test_server: None) -> None:
- # Modify config for DELETE request
- config = test_config.model_copy()
- config.config["method"] = "DELETE"
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
-
- @pytest.mark.asyncio
- async def test_patch_request(test_config: ComponentModel, test_server: None) -> None:
- # Modify config for PATCH request
- config = test_config.model_copy()
- config.config["method"] = "PATCH"
- tool = HttpTool.load_component(config)
-
- result = await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
- assert isinstance(result, str)
- assert json.loads(result)["result"] == "Received: test query with value 42"
-
-
- @pytest.mark.asyncio
- async def test_invalid_schema(test_config: ComponentModel, test_server: None) -> None:
- # Create an invalid schema missing required properties
- config: ComponentModel = test_config.model_copy()
- config.config["host"] = True # Incorrect type
-
- with pytest.raises(ValidationError):
- # Should fail when trying to create model from invalid schema
- HttpTool.load_component(config)
-
-
- @pytest.mark.asyncio
- async def test_invalid_request(test_config: ComponentModel, test_server: None) -> None:
- # Use an invalid URL
- config = test_config.model_copy()
- config.config["host"] = "fake"
- tool = HttpTool.load_component(config)
-
- with pytest.raises((httpx.ConnectError, httpx.ConnectTimeout)):
- await tool.run_json({"query": "test query", "value": 42}, CancellationToken())
-
-
- def test_config_serialization(test_config: ComponentModel) -> None:
- tool = HttpTool.load_component(test_config)
- config = tool.dump_component()
-
- assert config.config["name"] == test_config.config["name"]
- assert config.config["description"] == test_config.config["description"]
- assert config.config["host"] == test_config.config["host"]
- assert config.config["port"] == test_config.config["port"]
- assert config.config["path"] == test_config.config["path"]
- assert config.config["scheme"] == test_config.config["scheme"]
- assert config.config["method"] == test_config.config["method"]
- assert config.config["headers"] == test_config.config["headers"]
-
-
- def test_config_deserialization(test_config: ComponentModel) -> None:
- tool = HttpTool.load_component(test_config)
-
- assert tool.name == test_config.config["name"]
- assert tool.description == test_config.config["description"]
- assert tool.server_params.host == test_config.config["host"]
- assert tool.server_params.port == test_config.config["port"]
- assert tool.server_params.path == test_config.config["path"]
- assert tool.server_params.scheme == test_config.config["scheme"]
- assert tool.server_params.method == test_config.config["method"]
- assert tool.server_params.headers == test_config.config["headers"]
|