test_project_clone.py
1 import random 2 import pytest 3 from fastapi.testclient import TestClient 4 5 from restai.config import RESTAI_DEFAULT_PASSWORD 6 from restai.main import app 7 8 suffix = str(random.randint(0, 10000000)) 9 team_name = f"clone_team_{suffix}" 10 llm_name = f"clone_llm_{suffix}" 11 project_name = f"clone_proj_{suffix}" 12 cloned_name = f"cloned_proj_{suffix}" 13 14 team_id = None 15 project_id = None 16 cloned_id = None 17 18 ADMIN = ("admin", RESTAI_DEFAULT_PASSWORD) 19 20 21 @pytest.fixture(scope="module") 22 def client(): 23 with TestClient(app) as c: 24 yield c 25 26 27 def test_setup(client): 28 """Create a team, LLM, and block project with system prompt and censorship.""" 29 global team_id, project_id 30 # Create LLM 31 client.post( 32 "/llms", 33 json={ 34 "name": llm_name, 35 "class_name": "OpenAI", 36 "options": {"model": "gpt-test", "api_key": "sk-fake"}, 37 "privacy": "public", 38 }, 39 auth=ADMIN, 40 ) 41 42 # Create team with the LLM 43 resp = client.post( 44 "/teams", 45 json={"name": team_name, "users": [], "admins": [], "llms": [llm_name]}, 46 auth=ADMIN, 47 ) 48 assert resp.status_code == 201 49 team_id = resp.json()["id"] 50 51 # Create block project (no LLM required) 52 resp = client.post( 53 "/projects", 54 json={"name": project_name, "type": "block", "team_id": team_id}, 55 auth=ADMIN, 56 ) 57 assert resp.status_code == 201 58 project_id = resp.json()["project"] 59 60 # Set system prompt and censorship via PATCH 61 resp = client.patch( 62 f"/projects/{project_id}", 63 json={ 64 "system": "You are a helpful test assistant.", 65 "censorship": "This content is not allowed.", 66 }, 67 auth=ADMIN, 68 ) 69 assert resp.status_code == 200 70 71 72 def test_clone_project(client): 73 """Clone a project and verify settings are copied.""" 74 global cloned_id 75 resp = client.post( 76 f"/projects/{project_id}/clone", 77 json={"name": cloned_name}, 78 auth=ADMIN, 79 ) 80 assert resp.status_code == 201 81 cloned_id = resp.json()["project"] 82 assert cloned_id != project_id 83 84 # Verify cloned project exists and settings match 85 resp = client.get(f"/projects/{cloned_id}", auth=ADMIN) 86 assert resp.status_code == 200 87 data = resp.json() 88 assert data["system"] == "You are a helpful test assistant." 89 assert data["censorship"] == "This content is not allowed." 90 assert data["type"] == "block" 91 92 93 def test_clone_duplicate_name(client): 94 """Cloning with a name that already exists returns 409.""" 95 resp = client.post( 96 f"/projects/{project_id}/clone", 97 json={"name": cloned_name}, 98 auth=ADMIN, 99 ) 100 assert resp.status_code == 409 101 102 103 def test_clone_nonexistent(client): 104 """Cloning a project that doesn't exist returns 404.""" 105 resp = client.post( 106 "/projects/999999/clone", 107 json={"name": f"ghost_{suffix}"}, 108 auth=ADMIN, 109 ) 110 assert resp.status_code in (404, 403) 111 112 113 def test_cleanup(client): 114 """Remove all test resources.""" 115 if cloned_id: 116 client.delete(f"/projects/{cloned_id}", auth=ADMIN) 117 if project_id: 118 client.delete(f"/projects/{project_id}", auth=ADMIN) 119 if team_id: 120 client.delete(f"/teams/{team_id}", auth=ADMIN) 121 client.delete(f"/llms/{llm_name}", auth=ADMIN)