fed8b2eed7
Build and push multi-arch DocsGPT Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Has been cancelled
Backend release / release (push) Has been cancelled
Bandit Security Scan / bandit_scan (push) Has been cancelled
Build and push multi-arch DocsGPT Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Has been cancelled
Build and push multi-arch DocsGPT Docker image / manifest (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / build (linux/amd64, ubuntu-latest, amd64) (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Has been cancelled
Build and push DocsGPT FE Docker image for development / manifest (push) Has been cancelled
Python linting / ruff (push) Has been cancelled
Run python tests with pytest / Run tests and count coverage (3.12) (push) Has been cancelled
React Widget Build / build (push) Has been cancelled
525 lines
19 KiB
Python
525 lines
19 KiB
Python
"""Tests for application/api/user/agents/folders.py.
|
|
|
|
Uses the ephemeral ``pg_conn`` fixture to exercise real PG repository code.
|
|
"""
|
|
|
|
from contextlib import contextmanager
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from flask import Flask
|
|
|
|
|
|
@pytest.fixture
|
|
def app():
|
|
return Flask(__name__)
|
|
|
|
|
|
@contextmanager
|
|
def _patch_folders_db(conn):
|
|
@contextmanager
|
|
def _yield():
|
|
yield conn
|
|
|
|
with patch(
|
|
"application.api.user.agents.folders.db_session", _yield
|
|
), patch(
|
|
"application.api.user.agents.folders.db_readonly", _yield
|
|
):
|
|
yield
|
|
|
|
|
|
def _seed_folder(pg_conn, user, name="F", parent_id=None):
|
|
from application.storage.db.repositories.agent_folders import (
|
|
AgentFoldersRepository,
|
|
)
|
|
return AgentFoldersRepository(pg_conn).create(user, name, parent_id=parent_id)
|
|
|
|
|
|
def _seed_agent(pg_conn, user, folder_id=None):
|
|
from application.storage.db.repositories.agents import AgentsRepository
|
|
repo = AgentsRepository(pg_conn)
|
|
agent = repo.create(user, "test-agent", "published", description="x")
|
|
if folder_id:
|
|
repo.set_folder(str(agent["id"]), user, folder_id)
|
|
return agent
|
|
|
|
|
|
class TestAgentFoldersGet:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
with app.test_request_context("/api/agents/folders/"):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = AgentFolders().get()
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_folders_list(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
user = "u-folders-list"
|
|
_seed_folder(pg_conn, user, name="A")
|
|
_seed_folder(pg_conn, user, name="B")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/"
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolders().get()
|
|
assert response.status_code == 200
|
|
names = [f["name"] for f in response.json["folders"]]
|
|
assert "A" in names and "B" in names
|
|
|
|
|
|
class TestAgentFoldersPost:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/", method="POST", json={"name": "F"}
|
|
):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = AgentFolders().post()
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_400_missing_name(self, app):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/", method="POST", json={}
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = AgentFolders().post()
|
|
assert response.status_code == 400
|
|
|
|
def test_creates_folder_at_root(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/", method="POST",
|
|
json={"name": "Root Folder"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u-create"}
|
|
response = AgentFolders().post()
|
|
assert response.status_code == 201
|
|
assert response.json["name"] == "Root Folder"
|
|
assert response.json["parent_id"] is None
|
|
|
|
def test_creates_nested_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
user = "u-nested"
|
|
parent = _seed_folder(pg_conn, user, name="parent")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/", method="POST",
|
|
json={"name": "child", "parent_id": str(parent["id"])},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolders().post()
|
|
assert response.status_code == 201
|
|
assert response.json["parent_id"] == str(parent["id"])
|
|
|
|
def test_returns_404_for_missing_parent(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolders
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/", method="POST",
|
|
json={
|
|
"name": "child",
|
|
"parent_id": "00000000-0000-0000-0000-000000000000",
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = AgentFolders().post()
|
|
assert response.status_code == 404
|
|
|
|
|
|
class TestAgentFolderGet:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with app.test_request_context("/api/agents/folders/abc"):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = AgentFolder().get("abc")
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_404_missing_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/00000000-0000-0000-0000-000000000000"
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = AgentFolder().get(
|
|
"00000000-0000-0000-0000-000000000000"
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
def test_returns_folder_with_agents_and_subfolders(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-folder-detail"
|
|
parent = _seed_folder(pg_conn, user, name="parent")
|
|
_seed_folder(pg_conn, user, name="sub", parent_id=str(parent["id"]))
|
|
_seed_agent(pg_conn, user, folder_id=str(parent["id"]))
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{parent['id']}"
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().get(str(parent["id"]))
|
|
assert response.status_code == 200
|
|
data = response.json
|
|
assert data["name"] == "parent"
|
|
assert len(data["agents"]) == 1
|
|
assert len(data["subfolders"]) == 1
|
|
|
|
|
|
class TestAgentFolderPut:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/abc", method="PUT", json={"name": "new"}
|
|
):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = AgentFolder().put("abc")
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_404_missing_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/00000000-0000-0000-0000-000000000000",
|
|
method="PUT",
|
|
json={"name": "new"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = AgentFolder().put(
|
|
"00000000-0000-0000-0000-000000000000"
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
def test_renames_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-rename"
|
|
folder = _seed_folder(pg_conn, user, name="old")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{folder['id']}",
|
|
method="PUT",
|
|
json={"name": "renamed"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().put(str(folder["id"]))
|
|
assert response.status_code == 200
|
|
|
|
def test_prevents_setting_self_as_parent(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-self-parent"
|
|
folder = _seed_folder(pg_conn, user, name="f1")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{folder['id']}",
|
|
method="PUT",
|
|
json={"parent_id": str(folder["id"])},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().put(str(folder["id"]))
|
|
assert response.status_code == 400
|
|
|
|
def test_sets_parent_to_other_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-moveparent"
|
|
f1 = _seed_folder(pg_conn, user, name="f1")
|
|
f2 = _seed_folder(pg_conn, user, name="f2")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{f1['id']}",
|
|
method="PUT",
|
|
json={"parent_id": str(f2["id"])},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().put(str(f1["id"]))
|
|
assert response.status_code == 200
|
|
|
|
def test_returns_404_for_missing_parent(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-missingparent"
|
|
folder = _seed_folder(pg_conn, user, name="f")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{folder['id']}",
|
|
method="PUT",
|
|
json={"parent_id": "00000000-0000-0000-0000-000000000000"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().put(str(folder["id"]))
|
|
assert response.status_code == 404
|
|
|
|
def test_clears_parent_id_when_null(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-clear"
|
|
parent = _seed_folder(pg_conn, user, name="p")
|
|
child = _seed_folder(
|
|
pg_conn, user, name="c", parent_id=str(parent["id"])
|
|
)
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{child['id']}",
|
|
method="PUT",
|
|
json={"parent_id": None},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().put(str(child["id"]))
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestAgentFolderDelete:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/abc", method="DELETE"
|
|
):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = AgentFolder().delete("abc")
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_404_missing_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/00000000-0000-0000-0000-000000000000",
|
|
method="DELETE",
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = AgentFolder().delete(
|
|
"00000000-0000-0000-0000-000000000000"
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
def test_deletes_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import AgentFolder
|
|
|
|
user = "u-del"
|
|
folder = _seed_folder(pg_conn, user, name="tbd")
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
f"/api/agents/folders/{folder['id']}", method="DELETE"
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = AgentFolder().delete(str(folder["id"]))
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestMoveAgentToFolder:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={"agent_id": "x"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_400_missing_agent_id(self, app):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 400
|
|
|
|
def test_returns_404_agent_not_found(self, app, pg_conn):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={"agent_id": "00000000-0000-0000-0000-000000000000"},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 404
|
|
|
|
def test_moves_agent_into_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
user = "u-move"
|
|
folder = _seed_folder(pg_conn, user, name="target")
|
|
agent = _seed_agent(pg_conn, user)
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={
|
|
"agent_id": str(agent["id"]),
|
|
"folder_id": str(folder["id"]),
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 200
|
|
|
|
def test_returns_404_folder_not_found(self, app, pg_conn):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
user = "u-move-nofolder"
|
|
agent = _seed_agent(pg_conn, user)
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={
|
|
"agent_id": str(agent["id"]),
|
|
"folder_id": "00000000-0000-0000-0000-000000000000",
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 404
|
|
|
|
def test_removes_agent_from_folder(self, app, pg_conn):
|
|
from application.api.user.agents.folders import MoveAgentToFolder
|
|
|
|
user = "u-remove"
|
|
folder = _seed_folder(pg_conn, user, name="target")
|
|
agent = _seed_agent(pg_conn, user, folder_id=str(folder["id"]))
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/move_agent",
|
|
method="POST",
|
|
json={"agent_id": str(agent["id"]), "folder_id": None},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = MoveAgentToFolder().post()
|
|
assert response.status_code == 200
|
|
|
|
|
|
class TestBulkMoveAgents:
|
|
def test_returns_401_unauthenticated(self, app):
|
|
from application.api.user.agents.folders import BulkMoveAgents
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/bulk_move",
|
|
method="POST",
|
|
json={"agent_ids": ["a"]},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = None
|
|
response = BulkMoveAgents().post()
|
|
assert response.status_code == 401
|
|
|
|
def test_returns_400_missing_agent_ids(self, app):
|
|
from application.api.user.agents.folders import BulkMoveAgents
|
|
|
|
with app.test_request_context(
|
|
"/api/agents/folders/bulk_move",
|
|
method="POST",
|
|
json={},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = BulkMoveAgents().post()
|
|
assert response.status_code == 400
|
|
|
|
def test_bulk_moves_agents(self, app, pg_conn):
|
|
from application.api.user.agents.folders import BulkMoveAgents
|
|
|
|
user = "u-bulk"
|
|
folder = _seed_folder(pg_conn, user, name="dest")
|
|
a1 = _seed_agent(pg_conn, user)
|
|
a2 = _seed_agent(pg_conn, user)
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/bulk_move",
|
|
method="POST",
|
|
json={
|
|
"agent_ids": [str(a1["id"]), str(a2["id"])],
|
|
"folder_id": str(folder["id"]),
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = BulkMoveAgents().post()
|
|
assert response.status_code == 200
|
|
|
|
def test_returns_404_when_folder_not_found(self, app, pg_conn):
|
|
from application.api.user.agents.folders import BulkMoveAgents
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/bulk_move",
|
|
method="POST",
|
|
json={
|
|
"agent_ids": ["a"],
|
|
"folder_id": "00000000-0000-0000-0000-000000000000",
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": "u"}
|
|
response = BulkMoveAgents().post()
|
|
assert response.status_code == 404
|
|
|
|
def test_bulk_move_tolerates_missing_agents(self, app, pg_conn):
|
|
from application.api.user.agents.folders import BulkMoveAgents
|
|
|
|
user = "u-bulk-partial"
|
|
folder = _seed_folder(pg_conn, user, name="f")
|
|
a1 = _seed_agent(pg_conn, user)
|
|
|
|
with _patch_folders_db(pg_conn), app.test_request_context(
|
|
"/api/agents/folders/bulk_move",
|
|
method="POST",
|
|
json={
|
|
"agent_ids": [
|
|
str(a1["id"]),
|
|
"00000000-0000-0000-0000-000000000000",
|
|
],
|
|
"folder_id": str(folder["id"]),
|
|
},
|
|
):
|
|
from flask import request
|
|
request.decoded_token = {"sub": user}
|
|
response = BulkMoveAgents().post()
|
|
assert response.status_code == 200
|