From 0d5a2cf9935274dc6f1ebe82fe6a916429da36ad Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 15 May 2026 22:14:13 +0000 Subject: [PATCH] feat(api): add PATCH /api/graph/project/ to update project name Co-Authored-By: Claude Sonnet 4.6 --- backend/app/api/graph.py | 17 +++++++++++++ backend/tests/test_project_patch.py | 37 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 backend/tests/test_project_patch.py diff --git a/backend/app/api/graph.py b/backend/app/api/graph.py index eb5313ce..6b5bcf0d 100644 --- a/backend/app/api/graph.py +++ b/backend/app/api/graph.py @@ -91,6 +91,23 @@ def delete_project(project_id: str): }) +@graph_bp.route('/project/', methods=['PATCH']) +def patch_project(project_id: str): + """Update mutable project fields (currently: name).""" + project = ProjectManager.get_project(project_id) + if not project: + return jsonify({"success": False, "error": t('api.projectNotFound', id=project_id)}), 404 + + body = request.get_json(silent=True) or {} + name = body.get("name", "").strip() + if not name: + return jsonify({"success": False, "error": "name cannot be empty"}), 400 + + ProjectManager.save_project({"id": project_id, "name": name}) + updated = ProjectManager.get_project(project_id) + return jsonify({"success": True, "data": updated}) + + @graph_bp.route('/project//reset', methods=['POST']) def reset_project(project_id: str): """ diff --git a/backend/tests/test_project_patch.py b/backend/tests/test_project_patch.py new file mode 100644 index 00000000..2079902d --- /dev/null +++ b/backend/tests/test_project_patch.py @@ -0,0 +1,37 @@ +import pytest +from unittest.mock import patch, MagicMock +from app import create_app + + +@pytest.fixture +def app(): + return create_app({'TESTING': True}) + + +@pytest.fixture +def client(app): + return app.test_client() + + +def test_patch_project_name_success(client): + mock_project = {"id": "proj_123", "project_id": "proj_123", "name": "Old Name"} + updated = {**mock_project, "name": "New Name"} + with patch('app.api.graph.ProjectManager.get_project', side_effect=[mock_project, updated]), \ + patch('app.api.graph.ProjectManager.save_project'): + resp = client.patch('/api/graph/project/proj_123', json={"name": "New Name"}) + assert resp.status_code == 200 + data = resp.get_json() + assert data["success"] is True + + +def test_patch_project_name_not_found(client): + with patch('app.api.graph.ProjectManager.get_project', return_value=None): + resp = client.patch('/api/graph/project/nonexistent', json={"name": "X"}) + assert resp.status_code == 404 + + +def test_patch_project_name_empty_rejected(client): + mock_project = {"id": "proj_123", "project_id": "proj_123", "name": "Old"} + with patch('app.api.graph.ProjectManager.get_project', return_value=mock_project): + resp = client.patch('/api/graph/project/proj_123', json={"name": " "}) + assert resp.status_code == 400