mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
c7e6eab02f
Signed-off-by: phernandez <paul@basicmachines.co> Co-authored-by: Claude <noreply@anthropic.com>
721 lines
25 KiB
Python
721 lines
25 KiB
Python
"""Tests for the project router API endpoints."""
|
|
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from basic_memory.schemas.project_info import ProjectItem
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_item(test_graph, client, project_config, test_project, project_url):
|
|
"""Test the project item endpoint returns correctly structured data."""
|
|
# Set up some test data in the database
|
|
|
|
# Call the endpoint
|
|
response = await client.get(f"{project_url}/project/item")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
project_info = ProjectItem.model_validate(response.json())
|
|
assert project_info.name == test_project.name
|
|
assert project_info.path == test_project.path
|
|
assert project_info.is_default == test_project.is_default
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_item_not_found(
|
|
test_graph, client, project_config, test_project, project_url
|
|
):
|
|
"""Test the project item endpoint returns correctly structured data."""
|
|
# Set up some test data in the database
|
|
|
|
# Call the endpoint
|
|
response = await client.get("/not-found/project/item")
|
|
|
|
# Verify response
|
|
assert response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_default_project(test_graph, client, project_config, test_project, project_url):
|
|
"""Test the default project item endpoint returns the default project."""
|
|
# Set up some test data in the database
|
|
|
|
# Call the endpoint
|
|
response = await client.get("/projects/default")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
project_info = ProjectItem.model_validate(response.json())
|
|
assert project_info.name == test_project.name
|
|
assert project_info.path == test_project.path
|
|
assert project_info.is_default == test_project.is_default
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_info_endpoint(test_graph, client, project_config, project_url):
|
|
"""Test the project-info endpoint returns correctly structured data."""
|
|
# Set up some test data in the database
|
|
|
|
# Call the endpoint
|
|
response = await client.get(f"{project_url}/project/info")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check top-level keys
|
|
assert "project_name" in data
|
|
assert "project_path" in data
|
|
assert "available_projects" in data
|
|
assert "default_project" in data
|
|
assert "statistics" in data
|
|
assert "activity" in data
|
|
assert "system" in data
|
|
|
|
# Check statistics
|
|
stats = data["statistics"]
|
|
assert "total_entities" in stats
|
|
assert stats["total_entities"] >= 0
|
|
assert "total_observations" in stats
|
|
assert stats["total_observations"] >= 0
|
|
assert "total_relations" in stats
|
|
assert stats["total_relations"] >= 0
|
|
|
|
# Check activity
|
|
activity = data["activity"]
|
|
assert "recently_created" in activity
|
|
assert "recently_updated" in activity
|
|
assert "monthly_growth" in activity
|
|
|
|
# Check system
|
|
system = data["system"]
|
|
assert "version" in system
|
|
assert "database_path" in system
|
|
assert "database_size" in system
|
|
assert "timestamp" in system
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_info_content(test_graph, client, project_config, project_url):
|
|
"""Test that project-info contains actual data from the test database."""
|
|
# Call the endpoint
|
|
response = await client.get(f"{project_url}/project/info")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check that test_graph content is reflected in statistics
|
|
stats = data["statistics"]
|
|
|
|
# Our test graph should have at least a few entities
|
|
assert stats["total_entities"] > 0
|
|
|
|
# It should also have some observations
|
|
assert stats["total_observations"] > 0
|
|
|
|
# And relations
|
|
assert stats["total_relations"] > 0
|
|
|
|
# Check that entity types include 'test'
|
|
assert "test" in stats["entity_types"] or "entity" in stats["entity_types"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_projects_endpoint(test_config, test_graph, client, project_config, project_url):
|
|
"""Test the list projects endpoint returns correctly structured data."""
|
|
# Call the endpoint
|
|
response = await client.get("/projects/projects")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check that the response contains expected fields
|
|
assert "projects" in data
|
|
assert "default_project" in data
|
|
|
|
# Check that projects is a list
|
|
assert isinstance(data["projects"], list)
|
|
|
|
# There should be at least one project (the test project)
|
|
assert len(data["projects"]) > 0
|
|
|
|
# Verify project item structure
|
|
if data["projects"]:
|
|
project = data["projects"][0]
|
|
assert "name" in project
|
|
assert "path" in project
|
|
assert "is_default" in project
|
|
|
|
# Default project should be marked
|
|
default_project = next((p for p in data["projects"] if p["is_default"]), None)
|
|
assert default_project is not None
|
|
assert default_project["name"] == data["default_project"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_project_endpoint(test_config, client, project_service):
|
|
"""Test the remove project endpoint."""
|
|
# First create a test project to remove
|
|
test_project_name = "test-remove-project"
|
|
await project_service.add_project(test_project_name, "/tmp/test-remove-project")
|
|
|
|
# Verify it exists
|
|
project = await project_service.get_project(test_project_name)
|
|
assert project is not None
|
|
|
|
# Remove the project
|
|
response = await client.delete(f"/projects/{test_project_name}")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "message" in data
|
|
assert "status" in data
|
|
assert data["status"] == "success"
|
|
assert "old_project" in data
|
|
assert data["old_project"]["name"] == test_project_name
|
|
|
|
# Verify project is actually removed
|
|
removed_project = await project_service.get_project(test_project_name)
|
|
assert removed_project is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_set_default_project_endpoint(test_config, client, project_service):
|
|
"""Test the set default project endpoint."""
|
|
# Create a test project to set as default
|
|
test_project_name = "test-default-project"
|
|
await project_service.add_project(test_project_name, "/tmp/test-default-project")
|
|
|
|
# Set it as default
|
|
response = await client.put(f"/projects/{test_project_name}/default")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "message" in data
|
|
assert "status" in data
|
|
assert data["status"] == "success"
|
|
assert "new_project" in data
|
|
assert data["new_project"]["name"] == test_project_name
|
|
|
|
# Verify it's actually set as default
|
|
assert project_service.default_project == test_project_name
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_path_endpoint(test_config, client, project_service, project_url):
|
|
"""Test the update project endpoint for changing project path."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-project"
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
test_root = Path(temp_dir)
|
|
old_path = (test_root / "old-location").as_posix()
|
|
new_path = (test_root / "new-location").as_posix()
|
|
|
|
await project_service.add_project(test_project_name, old_path)
|
|
|
|
try:
|
|
# Verify initial state
|
|
project = await project_service.get_project(test_project_name)
|
|
assert project is not None
|
|
assert project.path == old_path
|
|
|
|
# Update the project path
|
|
response = await client.patch(
|
|
f"{project_url}/project/{test_project_name}", json={"path": new_path}
|
|
)
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "message" in data
|
|
assert "status" in data
|
|
assert data["status"] == "success"
|
|
assert "old_project" in data
|
|
assert "new_project" in data
|
|
|
|
# Check old project data
|
|
assert data["old_project"]["name"] == test_project_name
|
|
assert data["old_project"]["path"] == old_path
|
|
|
|
# Check new project data
|
|
assert data["new_project"]["name"] == test_project_name
|
|
assert data["new_project"]["path"] == new_path
|
|
|
|
# Verify project was actually updated in database
|
|
updated_project = await project_service.get_project(test_project_name)
|
|
assert updated_project is not None
|
|
assert updated_project.path == new_path
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_is_active_endpoint(test_config, client, project_service, project_url):
|
|
"""Test the update project endpoint for changing is_active status."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-active-project"
|
|
test_path = "/tmp/test-update-active"
|
|
|
|
await project_service.add_project(test_project_name, test_path)
|
|
|
|
try:
|
|
# Update the project is_active status
|
|
response = await client.patch(
|
|
f"{project_url}/project/{test_project_name}", json={"is_active": False}
|
|
)
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "message" in data
|
|
assert "status" in data
|
|
assert data["status"] == "success"
|
|
assert f"Project '{test_project_name}' updated successfully" == data["message"]
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_both_params_endpoint(
|
|
test_config, client, project_service, project_url
|
|
):
|
|
"""Test the update project endpoint with both path and is_active parameters."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-both-project"
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
test_root = Path(temp_dir)
|
|
old_path = (test_root / "old-location").as_posix()
|
|
new_path = (test_root / "new-location").as_posix()
|
|
|
|
await project_service.add_project(test_project_name, old_path)
|
|
|
|
try:
|
|
# Update both path and is_active (path should take precedence)
|
|
response = await client.patch(
|
|
f"{project_url}/project/{test_project_name}",
|
|
json={"path": new_path, "is_active": False},
|
|
)
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check that path update was performed (takes precedence)
|
|
assert data["new_project"]["path"] == new_path
|
|
|
|
# Verify project was actually updated in database
|
|
updated_project = await project_service.get_project(test_project_name)
|
|
assert updated_project is not None
|
|
assert updated_project.path == new_path
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_nonexistent_endpoint(client, project_url):
|
|
"""Test the update project endpoint with a nonexistent project."""
|
|
# Try to update a project that doesn't exist
|
|
response = await client.patch(
|
|
f"{project_url}/project/nonexistent-project", json={"path": "/tmp/new-path"}
|
|
)
|
|
|
|
# Should return 400 error
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "not found in configuration" in data["detail"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_relative_path_error_endpoint(
|
|
test_config, client, project_service, project_url
|
|
):
|
|
"""Test the update project endpoint with relative path (should fail)."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-relative-project"
|
|
test_path = "/tmp/test-update-relative"
|
|
|
|
await project_service.add_project(test_project_name, test_path)
|
|
|
|
try:
|
|
# Try to update with relative path
|
|
response = await client.patch(
|
|
f"{project_url}/project/{test_project_name}", json={"path": "./relative-path"}
|
|
)
|
|
|
|
# Should return 400 error
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "Path must be absolute" in data["detail"]
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_no_params_endpoint(test_config, client, project_service, project_url):
|
|
"""Test the update project endpoint with no parameters (should fail)."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-no-params-project"
|
|
test_path = "/tmp/test-update-no-params"
|
|
|
|
await project_service.add_project(test_project_name, test_path)
|
|
proj_info = await project_service.get_project(test_project_name)
|
|
assert proj_info.name == test_project_name
|
|
# On Windows the path is prepended with a drive letter
|
|
assert test_path in proj_info.path
|
|
|
|
try:
|
|
# Try to update with no parameters
|
|
response = await client.patch(f"{project_url}/project/{test_project_name}", json={})
|
|
|
|
# Should return 200 (no-op)
|
|
assert response.status_code == 200
|
|
proj_info = await project_service.get_project(test_project_name)
|
|
assert proj_info.name == test_project_name
|
|
# On Windows the path is prepended with a drive letter
|
|
assert test_path in proj_info.path
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_project_empty_path_endpoint(
|
|
test_config, client, project_service, project_url
|
|
):
|
|
"""Test the update project endpoint with empty path parameter."""
|
|
# Create a test project to update
|
|
test_project_name = "test-update-empty-path-project"
|
|
test_path = "/tmp/test-update-empty-path"
|
|
|
|
await project_service.add_project(test_project_name, test_path)
|
|
|
|
try:
|
|
# Try to update with empty/null path - should be treated as no path update
|
|
response = await client.patch(
|
|
f"{project_url}/project/{test_project_name}", json={"path": None, "is_active": True}
|
|
)
|
|
|
|
# Should succeed and perform is_active update
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_sync_project_endpoint(test_graph, client, project_url):
|
|
"""Test the project sync endpoint initiates background sync."""
|
|
# Call the sync endpoint
|
|
response = await client.post(f"{project_url}/project/sync")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "status" in data
|
|
assert "message" in data
|
|
assert data["status"] == "sync_started"
|
|
assert "Filesystem sync initiated" in data["message"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_sync_project_endpoint_not_found(client):
|
|
"""Test the project sync endpoint with nonexistent project."""
|
|
# Call the sync endpoint for a project that doesn't exist
|
|
response = await client.post("/nonexistent-project/project/sync")
|
|
|
|
# Should return 404
|
|
assert response.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_default_project_fails(test_config, client, project_service):
|
|
"""Test that removing the default project returns an error."""
|
|
# Get the current default project
|
|
default_project_name = project_service.default_project
|
|
|
|
# Try to remove the default project
|
|
response = await client.delete(f"/projects/{default_project_name}")
|
|
|
|
# Should return 400 with helpful error message
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "Cannot delete default project" in data["detail"]
|
|
assert default_project_name in data["detail"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_default_project_with_alternatives(test_config, client, project_service):
|
|
"""Test that error message includes alternative projects when trying to delete default."""
|
|
# Get the current default project
|
|
default_project_name = project_service.default_project
|
|
|
|
# Create another project so there are alternatives
|
|
test_project_name = "test-alternative-project"
|
|
await project_service.add_project(test_project_name, "/tmp/test-alternative")
|
|
|
|
try:
|
|
# Try to remove the default project
|
|
response = await client.delete(f"/projects/{default_project_name}")
|
|
|
|
# Should return 400 with helpful error message including alternatives
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "Cannot delete default project" in data["detail"]
|
|
assert "Set another project as default first" in data["detail"]
|
|
assert test_project_name in data["detail"]
|
|
|
|
finally:
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_non_default_project_succeeds(test_config, client, project_service):
|
|
"""Test that removing a non-default project succeeds."""
|
|
# Create a test project to remove
|
|
test_project_name = "test-remove-non-default"
|
|
await project_service.add_project(test_project_name, "/tmp/test-remove-non-default")
|
|
|
|
# Verify it's not the default
|
|
assert project_service.default_project != test_project_name
|
|
|
|
# Remove the project
|
|
response = await client.delete(f"/projects/{test_project_name}")
|
|
|
|
# Should succeed
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
# Verify project is removed
|
|
removed_project = await project_service.get_project(test_project_name)
|
|
assert removed_project is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_set_nonexistent_project_as_default_fails(test_config, client, project_service):
|
|
"""Test that setting a non-existent project as default returns 404."""
|
|
# Try to set a project that doesn't exist as default
|
|
response = await client.put("/projects/nonexistent-project/default")
|
|
|
|
# Should return 404
|
|
assert response.status_code == 404
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert "does not exist" in data["detail"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_project_idempotent_same_path(test_config, client, project_service):
|
|
"""Test that creating a project with same name and same path is idempotent."""
|
|
# Create a project with platform-independent path
|
|
test_project_name = "test-idempotent"
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
test_project_path = (Path(temp_dir) / "test-idempotent").as_posix()
|
|
|
|
response1 = await client.post(
|
|
"/projects/projects",
|
|
json={"name": test_project_name, "path": test_project_path, "set_default": False},
|
|
)
|
|
|
|
# Should succeed with 201 Created
|
|
assert response1.status_code == 201
|
|
data1 = response1.json()
|
|
assert data1["status"] == "success"
|
|
assert data1["new_project"]["name"] == test_project_name
|
|
|
|
# Try to create the same project again with same name and path
|
|
response2 = await client.post(
|
|
"/projects/projects",
|
|
json={"name": test_project_name, "path": test_project_path, "set_default": False},
|
|
)
|
|
|
|
# Should also succeed (idempotent)
|
|
assert response2.status_code == 200
|
|
data2 = response2.json()
|
|
assert data2["status"] == "success"
|
|
assert "already exists" in data2["message"]
|
|
assert data2["new_project"]["name"] == test_project_name
|
|
# Normalize paths for cross-platform comparison
|
|
assert Path(data2["new_project"]["path"]).resolve() == Path(test_project_path).resolve()
|
|
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_project_fails_different_path(test_config, client, project_service):
|
|
"""Test that creating a project with same name but different path fails."""
|
|
# Create a project
|
|
test_project_name = "test-path-conflict"
|
|
test_project_path1 = "/tmp/test-path-conflict-1"
|
|
|
|
response1 = await client.post(
|
|
"/projects/projects",
|
|
json={"name": test_project_name, "path": test_project_path1, "set_default": False},
|
|
)
|
|
|
|
# Should succeed with 201 Created
|
|
assert response1.status_code == 201
|
|
|
|
# Try to create the same project with different path
|
|
test_project_path2 = "/tmp/test-path-conflict-2"
|
|
response2 = await client.post(
|
|
"/projects/projects",
|
|
json={"name": test_project_name, "path": test_project_path2, "set_default": False},
|
|
)
|
|
|
|
# Should fail with 400
|
|
assert response2.status_code == 400
|
|
data2 = response2.json()
|
|
assert "detail" in data2
|
|
assert "already exists with different path" in data2["detail"]
|
|
assert test_project_path1 in data2["detail"]
|
|
assert test_project_path2 in data2["detail"]
|
|
|
|
# Clean up
|
|
try:
|
|
await project_service.remove_project(test_project_name)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_project_with_delete_notes_false(test_config, client, project_service):
|
|
"""Test that removing a project with delete_notes=False leaves directory intact."""
|
|
# Create a test project with actual directory
|
|
test_project_name = "test-remove-keep-files"
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
test_path = Path(temp_dir) / "test-project"
|
|
test_path.mkdir()
|
|
test_file = test_path / "test.md"
|
|
test_file.write_text("# Test Note")
|
|
|
|
await project_service.add_project(test_project_name, str(test_path))
|
|
|
|
# Remove the project without deleting files (default)
|
|
response = await client.delete(f"/projects/{test_project_name}")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
# Verify project is removed from config/db
|
|
removed_project = await project_service.get_project(test_project_name)
|
|
assert removed_project is None
|
|
|
|
# Verify directory still exists
|
|
assert test_path.exists()
|
|
assert test_file.exists()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_project_with_delete_notes_true(test_config, client, project_service):
|
|
"""Test that removing a project with delete_notes=True deletes the directory."""
|
|
# Create a test project with actual directory
|
|
test_project_name = "test-remove-delete-files"
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
test_path = Path(temp_dir) / "test-project"
|
|
test_path.mkdir()
|
|
test_file = test_path / "test.md"
|
|
test_file.write_text("# Test Note")
|
|
|
|
await project_service.add_project(test_project_name, str(test_path))
|
|
|
|
# Remove the project with delete_notes=True
|
|
response = await client.delete(f"/projects/{test_project_name}?delete_notes=true")
|
|
|
|
# Verify response
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
# Verify project is removed from config/db
|
|
removed_project = await project_service.get_project(test_project_name)
|
|
assert removed_project is None
|
|
|
|
# Verify directory is deleted
|
|
assert not test_path.exists()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remove_project_delete_notes_nonexistent_directory(
|
|
test_config, client, project_service
|
|
):
|
|
"""Test that removing a project with delete_notes=True handles missing directory gracefully."""
|
|
# Create a project pointing to a non-existent path
|
|
test_project_name = "test-remove-missing-dir"
|
|
test_path = "/tmp/this-directory-does-not-exist-12345"
|
|
|
|
await project_service.add_project(test_project_name, test_path)
|
|
|
|
# Remove the project with delete_notes=True (should not fail even if dir doesn't exist)
|
|
response = await client.delete(f"/projects/{test_project_name}?delete_notes=true")
|
|
|
|
# Should succeed
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["status"] == "success"
|
|
|
|
# Verify project is removed
|
|
removed_project = await project_service.get_project(test_project_name)
|
|
assert removed_project is None
|