"""Tests for tool connectors: Docs, DB, CodeRunner.""" from __future__ import annotations from pathlib import Path from fusionagi.tools.connectors.code_runner import CodeRunnerConnector from fusionagi.tools.connectors.db import DBConnector from fusionagi.tools.connectors.docs import DocsConnector class TestDocsConnector: def test_read_text_file(self, tmp_path: Path) -> None: (tmp_path / "test.txt").write_text("hello world") conn = DocsConnector(base_path=str(tmp_path)) result = conn.invoke("read", {"path": "test.txt"}) assert result["content"] == "hello world" assert result["error"] is None def test_read_missing_file(self, tmp_path: Path) -> None: conn = DocsConnector(base_path=str(tmp_path)) result = conn.invoke("read", {"path": "missing.txt"}) assert result["error"] is not None def test_search(self, tmp_path: Path) -> None: (tmp_path / "a.txt").write_text("foo bar baz") (tmp_path / "b.txt").write_text("no match here") conn = DocsConnector(base_path=str(tmp_path)) result = conn.invoke("search", {"query": "bar", "path": "."}) assert len(result["results"]) == 1 def test_list_files(self, tmp_path: Path) -> None: (tmp_path / "a.txt").write_text("x") (tmp_path / "b.md").write_text("y") conn = DocsConnector(base_path=str(tmp_path)) result = conn.invoke("list", {"path": ".", "pattern": "*"}) assert len(result["files"]) == 2 def test_schema(self) -> None: conn = DocsConnector() s = conn.schema() assert s["name"] == "docs" assert "read" in s["actions"] class TestDBConnector: def test_sqlite_crud(self) -> None: conn = DBConnector(connection_string=":memory:", driver="sqlite", allow_write=True) conn.invoke("execute", {"query": "CREATE TABLE t (id INTEGER, name TEXT)"}) conn.invoke("execute", {"query": "INSERT INTO t VALUES (1, 'alice')"}) result = conn.invoke("query", {"query": "SELECT * FROM t"}) assert result["count"] == 1 assert result["rows"][0]["name"] == "alice" def test_list_tables(self) -> None: conn = DBConnector(connection_string=":memory:", driver="sqlite", allow_write=True) conn.invoke("execute", {"query": "CREATE TABLE demo (id INTEGER)"}) result = conn.invoke("tables", {}) assert any(r.get("name") == "demo" for r in result["rows"]) def test_read_only_blocks_write(self) -> None: conn = DBConnector(connection_string=":memory:", driver="sqlite", allow_write=False) result = conn.invoke("execute", {"query": "CREATE TABLE t (id INTEGER)"}) assert "error" in result or "disallowed" in str(result.get("error", "")) def test_schema(self) -> None: conn = DBConnector() s = conn.schema() assert s["name"] == "db" class TestCodeRunnerConnector: def test_run_python(self) -> None: conn = CodeRunnerConnector(timeout=10.0) result = conn.invoke("run", {"code": "print('hello')", "language": "python"}) assert result["exit_code"] == 0 assert "hello" in result["stdout"] def test_run_empty_code(self) -> None: conn = CodeRunnerConnector() result = conn.invoke("run", {"code": "", "language": "python"}) assert result["error"] == "Empty code" def test_unsupported_language(self) -> None: conn = CodeRunnerConnector() result = conn.invoke("run", {"code": "x", "language": "cobol"}) assert result["error"] is not None assert "Unsupported" in str(result["error"]) def test_timeout(self) -> None: conn = CodeRunnerConnector(timeout=1.0) result = conn.invoke("run", {"code": "import time; time.sleep(10)", "language": "python", "timeout": 1.0}) assert result["error"] == "timeout" def test_list_languages(self) -> None: conn = CodeRunnerConnector() result = conn.invoke("languages", {}) assert "python" in result["languages"] def test_schema(self) -> None: conn = CodeRunnerConnector() s = conn.schema() assert s["name"] == "code_runner"