516 lines
17 KiB
Python
516 lines
17 KiB
Python
from typing import Any
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from nanoid import generate as generate_nanoid
|
|
|
|
from src.models import Peer, Workspace
|
|
|
|
|
|
def test_get_or_create_workspace(client: TestClient):
|
|
name = str(generate_nanoid())
|
|
|
|
# This should create the workspace using POST /v2/workspaces
|
|
response = client.post("/v2/workspaces", json={"name": name})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["id"] == name
|
|
assert "id" in data
|
|
|
|
|
|
def test_get_or_create_workspace_with_configuration(client: TestClient):
|
|
"""Test workspace creation with configuration parameter"""
|
|
name = str(generate_nanoid())
|
|
configuration = {"feature1": True, "feature2": False}
|
|
|
|
response = client.post(
|
|
"/v2/workspaces", json={"name": name, "configuration": configuration}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["id"] == name
|
|
assert data["configuration"] == configuration
|
|
|
|
|
|
def test_get_or_create_workspace_with_all_optional_params(client: TestClient):
|
|
"""Test workspace creation with all optional parameters"""
|
|
name = str(generate_nanoid())
|
|
metadata = {"key": "value", "number": 42}
|
|
configuration = {"experimental": True, "beta": False}
|
|
|
|
response = client.post(
|
|
"/v2/workspaces",
|
|
json={"name": name, "metadata": metadata, "configuration": configuration},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["id"] == name
|
|
assert data["metadata"] == metadata
|
|
assert data["configuration"] == configuration
|
|
|
|
|
|
def test_get_or_create_existing_workspace(client: TestClient):
|
|
name = str(generate_nanoid())
|
|
|
|
# Create the workspace
|
|
response = client.post(
|
|
"/v2/workspaces", json={"name": name, "metadata": {"key": "value"}}
|
|
)
|
|
assert response.status_code == 200
|
|
workspace1 = response.json()
|
|
|
|
# Try to create the same workspace again - should return existing workspace
|
|
response = client.post(
|
|
"/v2/workspaces", json={"name": name, "metadata": {"key": "value"}}
|
|
)
|
|
assert response.status_code == 200
|
|
workspace2 = response.json()
|
|
|
|
# Both should be the same workspace
|
|
assert workspace1["id"] == workspace2["id"]
|
|
assert workspace1["metadata"] == workspace2["metadata"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_workspaces(client: TestClient):
|
|
# create a test workspace with metadata
|
|
response = client.post(
|
|
"/v2/workspaces",
|
|
json={
|
|
"name": "test_workspace",
|
|
"metadata": {"test_key": "test_value"},
|
|
},
|
|
)
|
|
|
|
response = client.post(
|
|
"/v2/workspaces/list",
|
|
json={},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "items" in data
|
|
assert len(data["items"]) > 0
|
|
|
|
response = client.post(
|
|
"/v2/workspaces/list",
|
|
json={"filters": {"metadata": {"test_key": "test_value"}}},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "items" in data
|
|
assert len(data["items"]) == 1
|
|
assert data["items"][0]["metadata"] == {"test_key": "test_value"}
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_workspaces_with_empty_filter(client: TestClient):
|
|
"""Test workspace listing with empty filter object"""
|
|
response = client.post("/v2/workspaces/list", json={"filters": {}})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "items" in data
|
|
assert isinstance(data["items"], list)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_all_workspaces_with_null_filter(client: TestClient):
|
|
"""Test workspace listing with null filter"""
|
|
response = client.post("/v2/workspaces/list", json={"filters": None})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "items" in data
|
|
assert isinstance(data["items"], list)
|
|
|
|
|
|
def test_update_workspace(client: TestClient, sample_data: tuple[Workspace, Peer]):
|
|
test_workspace, _ = sample_data
|
|
_new_name = str(generate_nanoid())
|
|
response = client.put(
|
|
f"/v2/workspaces/{test_workspace.name}",
|
|
json={"metadata": {"new_key": "new_value"}},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["metadata"] == {"new_key": "new_value"}
|
|
|
|
|
|
def test_update_workspace_with_configuration(
|
|
client: TestClient, sample_data: tuple[Workspace, Peer]
|
|
):
|
|
"""Test workspace update with configuration parameter"""
|
|
test_workspace, _ = sample_data
|
|
configuration = {"new_feature": True, "legacy_feature": False}
|
|
|
|
response = client.put(
|
|
f"/v2/workspaces/{test_workspace.name}", json={"configuration": configuration}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["configuration"] == configuration
|
|
|
|
|
|
def test_update_workspace_with_all_optional_params(
|
|
client: TestClient, sample_data: tuple[Workspace, Peer]
|
|
):
|
|
"""Test workspace update with both metadata and configuration"""
|
|
test_workspace, _ = sample_data
|
|
metadata = {"updated_key": "updated_value", "count": 100}
|
|
configuration = {"experimental": True, "beta": True}
|
|
|
|
response = client.put(
|
|
f"/v2/workspaces/{test_workspace.name}",
|
|
json={"metadata": metadata, "configuration": configuration},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["metadata"] == metadata
|
|
assert data["configuration"] == configuration
|
|
|
|
|
|
def test_update_workspace_with_null_metadata(
|
|
client: TestClient, sample_data: tuple[Workspace, Peer]
|
|
):
|
|
"""Test workspace update with null metadata (should clear metadata)"""
|
|
test_workspace, _ = sample_data
|
|
|
|
# First set some metadata
|
|
client.put(
|
|
f"/v2/workspaces/{test_workspace.name}", json={"metadata": {"temp": "value"}}
|
|
)
|
|
|
|
# Then clear it with null
|
|
response = client.put(
|
|
f"/v2/workspaces/{test_workspace.name}", json={"metadata": None}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
# The behavior might be to keep existing metadata or clear it -
|
|
# adjust this assertion based on actual behavior
|
|
assert "metadata" in data
|
|
|
|
|
|
def test_update_workspace_with_null_configuration(
|
|
client: TestClient, sample_data: tuple[Workspace, Peer]
|
|
):
|
|
"""Test workspace update with null configuration"""
|
|
test_workspace, _ = sample_data
|
|
|
|
response = client.put(
|
|
f"/v2/workspaces/{test_workspace.name}", json={"configuration": None}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "configuration" in data
|
|
|
|
|
|
def test_create_duplicate_workspace_name(client: TestClient):
|
|
# Create an workspace
|
|
name = str(generate_nanoid())
|
|
response = client.post("/v2/workspaces", json={"name": name})
|
|
assert response.status_code == 200
|
|
|
|
# Try to create another workspace with the same name - should return existing workspace
|
|
response = client.post("/v2/workspaces", json={"name": name})
|
|
|
|
# Should return the existing workspace with 200 status (get_or_create behavior)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["id"] == name
|
|
|
|
|
|
def test_search_workspace(client: TestClient, sample_data: tuple[Workspace, Peer]):
|
|
"""Test the workspace search functionality"""
|
|
test_workspace, _ = sample_data
|
|
|
|
# Test search with a query
|
|
response = client.post(
|
|
f"/v2/workspaces/{test_workspace.name}/search",
|
|
json={"query": "test search query", "limit": 10},
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Response should be a direct list of messages
|
|
assert isinstance(data, list)
|
|
|
|
|
|
def test_search_workspace_empty_query(
|
|
client: TestClient, sample_data: tuple[Workspace, Peer]
|
|
):
|
|
"""Test the workspace search with empty query"""
|
|
test_workspace, _ = sample_data
|
|
|
|
# Test search with empty query
|
|
response = client.post(
|
|
f"/v2/workspaces/{test_workspace.name}/search", json={"query": "", "limit": 10}
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Response should be a direct list of messages
|
|
assert isinstance(data, list)
|
|
|
|
|
|
def test_search_workspace_nonexistent(client: TestClient):
|
|
"""Test searching a workspace that doesn't exist"""
|
|
nonexistent_workspace_id = str(generate_nanoid())
|
|
|
|
response = client.post(
|
|
f"/v2/workspaces/{nonexistent_workspace_id}/search",
|
|
json={"query": "test query", "limit": 10},
|
|
)
|
|
assert response.status_code == 200
|
|
data: list[dict[str, Any]] = response.json()
|
|
# Should return empty list for nonexistent workspace
|
|
assert isinstance(data, list)
|
|
assert len(data) == 0
|
|
|
|
|
|
def test_delete_workspace(client: TestClient):
|
|
"""Test deleting a workspace"""
|
|
name = str(generate_nanoid())
|
|
|
|
# Create a workspace
|
|
response = client.post("/v2/workspaces", json={"name": name})
|
|
assert response.status_code == 200
|
|
workspace = response.json()
|
|
assert workspace["id"] == name
|
|
|
|
# Delete the workspace
|
|
response = client.delete(f"/v2/workspaces/{name}")
|
|
assert response.status_code == 200
|
|
deleted_workspace = response.json()
|
|
assert deleted_workspace["id"] == name
|
|
|
|
# Verify the workspace no longer exists by trying to update it
|
|
response = client.put(
|
|
f"/v2/workspaces/{name}", json={"metadata": {"test": "value"}}
|
|
)
|
|
# Should create a new workspace since the old one was deleted
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_delete_nonexistent_workspace(client: TestClient):
|
|
"""Test deleting a workspace that doesn't exist"""
|
|
nonexistent_workspace_id = str(generate_nanoid())
|
|
|
|
response = client.delete(f"/v2/workspaces/{nonexistent_workspace_id}")
|
|
assert response.status_code == 404
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "not found" in data["detail"].lower()
|
|
|
|
|
|
def test_delete_workspace_with_peers(client: TestClient):
|
|
"""Test deleting a workspace that has peers"""
|
|
workspace_name = str(generate_nanoid())
|
|
|
|
# Create workspace
|
|
response = client.post("/v2/workspaces", json={"name": workspace_name})
|
|
assert response.status_code == 200
|
|
|
|
# Create peers
|
|
peer1_name = str(generate_nanoid())
|
|
peer2_name = str(generate_nanoid())
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/peers", json={"name": peer1_name}
|
|
)
|
|
assert response.status_code == 200
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/peers", json={"name": peer2_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Delete workspace
|
|
response = client.delete(f"/v2/workspaces/{workspace_name}")
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_delete_workspace_with_sessions(client: TestClient):
|
|
"""Test deleting a workspace that has sessions"""
|
|
workspace_name = str(generate_nanoid())
|
|
|
|
# Create workspace
|
|
response = client.post("/v2/workspaces", json={"name": workspace_name})
|
|
assert response.status_code == 200
|
|
|
|
# Create peer
|
|
peer_name = str(generate_nanoid())
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/peers", json={"name": peer_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create sessions
|
|
session1_name = str(generate_nanoid())
|
|
session2_name = str(generate_nanoid())
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions", json={"name": session1_name}
|
|
)
|
|
assert response.status_code == 200
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions", json={"name": session2_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Delete workspace
|
|
response = client.delete(f"/v2/workspaces/{workspace_name}")
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_delete_workspace_with_messages(client: TestClient):
|
|
"""Test deleting a workspace that has messages"""
|
|
workspace_name = str(generate_nanoid())
|
|
|
|
# Create workspace
|
|
response = client.post("/v2/workspaces", json={"name": workspace_name})
|
|
assert response.status_code == 200
|
|
|
|
# Create peer
|
|
peer_name = str(generate_nanoid())
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/peers", json={"name": peer_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create session
|
|
session_name = str(generate_nanoid())
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions", json={"name": session_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Add peer to session
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions/{session_name}/peers",
|
|
json={peer_name: {}},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create messages
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions/{session_name}/messages",
|
|
json={
|
|
"messages": [
|
|
{"content": "Test message 1", "peer_id": peer_name},
|
|
{"content": "Test message 2", "peer_id": peer_name},
|
|
]
|
|
},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Delete workspace
|
|
response = client.delete(f"/v2/workspaces/{workspace_name}")
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_delete_workspace_with_webhooks(client: TestClient):
|
|
"""Test deleting a workspace that has webhooks"""
|
|
workspace_name = str(generate_nanoid())
|
|
|
|
# Create workspace
|
|
response = client.post("/v2/workspaces", json={"name": workspace_name})
|
|
assert response.status_code == 200
|
|
|
|
# Create webhook
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/webhooks",
|
|
json={
|
|
"url": "https://example.com/webhook",
|
|
},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Delete workspace
|
|
response = client.delete(f"/v2/workspaces/{workspace_name}")
|
|
assert response.status_code == 200
|
|
|
|
# Verify webhook is deleted by checking workspace doesn't exist
|
|
response = client.get(f"/v2/workspaces/{workspace_name}/webhooks")
|
|
# This should either return 404 or empty list depending on implementation
|
|
assert response.status_code in [404, 200]
|
|
|
|
|
|
def test_delete_workspace_cascade(client: TestClient):
|
|
"""Test that deleting a workspace cascades to all related resources"""
|
|
workspace_name = str(generate_nanoid())
|
|
|
|
# Create workspace with complex structure
|
|
response = client.post(
|
|
"/v2/workspaces",
|
|
json={"name": workspace_name, "metadata": {"test": "cascade"}},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create multiple peers
|
|
peer_names = [str(generate_nanoid()) for _ in range(3)]
|
|
for peer_name in peer_names:
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/peers", json={"name": peer_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create multiple sessions
|
|
session_names = [str(generate_nanoid()) for _ in range(2)]
|
|
for session_name in session_names:
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions", json={"name": session_name}
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Add peers to sessions and create messages
|
|
for session_name in session_names:
|
|
for peer_name in peer_names[:2]: # Add 2 peers to each session
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions/{session_name}/peers",
|
|
json={peer_name: {}},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Create messages in session
|
|
response = client.post(
|
|
f"/v2/workspaces/{workspace_name}/sessions/{session_name}/messages",
|
|
json={
|
|
"messages": [
|
|
{
|
|
"content": f"Test message in {session_name}",
|
|
"peer_id": peer_names[0],
|
|
}
|
|
]
|
|
},
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Delete the workspace
|
|
response = client.delete(f"/v2/workspaces/{workspace_name}")
|
|
assert response.status_code == 200
|
|
deleted_workspace = response.json()
|
|
assert deleted_workspace["id"] == workspace_name
|
|
assert deleted_workspace["metadata"]["test"] == "cascade"
|
|
|
|
|
|
def test_delete_workspace_returns_workspace_data(client: TestClient):
|
|
"""Test that delete workspace returns the deleted workspace data"""
|
|
name = str(generate_nanoid())
|
|
metadata = {"key": "value", "number": 42}
|
|
configuration = {"feature": True}
|
|
|
|
# Create workspace with metadata and configuration
|
|
response = client.post(
|
|
"/v2/workspaces",
|
|
json={"name": name, "metadata": metadata, "configuration": configuration},
|
|
)
|
|
assert response.status_code == 200
|
|
created_workspace = response.json()
|
|
|
|
# Delete workspace
|
|
response = client.delete(f"/v2/workspaces/{name}")
|
|
assert response.status_code == 200
|
|
deleted_workspace = response.json()
|
|
|
|
# Verify returned data matches original workspace
|
|
assert deleted_workspace["id"] == created_workspace["id"]
|
|
assert deleted_workspace["metadata"] == metadata
|
|
assert deleted_workspace["configuration"] == configuration
|
|
assert "created_at" in deleted_workspace
|