""" Project Management Integration Tests for Dolibarr MCP Server. These tests verify complete CRUD operations for Dolibarr projects. Run with: pytest tests/test_project_operations.py -v """ import pytest import asyncio from datetime import datetime from unittest.mock import Mock, patch, AsyncMock # Add src to path for imports import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) from dolibarr_mcp import DolibarrClient, Config class TestProjectOperations: """Test complete CRUD operations for Dolibarr projects.""" @pytest.fixture def config(self): """Create a test configuration.""" return Config( dolibarr_url="https://test.dolibarr.com", dolibarr_api_key="test_api_key", log_level="INFO" ) @pytest.fixture def client(self, config): """Create a test client instance.""" return DolibarrClient(config) @pytest.mark.asyncio async def test_project_crud_lifecycle(self, client): """Test complete project CRUD lifecycle.""" with patch.object(client, 'request') as mock_request: # Create mock_request.return_value = {"id": 200} project_id = await client.create_project({ "title": "New Website", "description": "Website redesign project", "socid": 1, "status": 1 }) assert project_id == 200 # Read mock_request.return_value = { "id": 200, "ref": "PJ2401-001", "title": "New Website", "description": "Website redesign project" } project = await client.get_project_by_id(200) assert project["title"] == "New Website" assert project["ref"] == "PJ2401-001" # Update mock_request.return_value = {"id": 200, "title": "Updated Website Project"} result = await client.update_project(200, {"title": "Updated Website Project"}) assert result["title"] == "Updated Website Project" # Delete mock_request.return_value = {"success": True} result = await client.delete_project(200) assert result["success"] is True @pytest.mark.asyncio async def test_search_projects(self, client): """Test searching projects.""" with patch.object(client, 'request') as mock_request: mock_request.return_value = [ {"id": 200, "ref": "PJ2401-001", "title": "Website Redesign"}, {"id": 201, "ref": "PJ2401-002", "title": "Mobile App"} ] # Search by query results = await client.search_projects(sqlfilters="(t.title:like:'%Website%')", limit=10) assert len(results) == 2 assert results[0]["title"] == "Website Redesign" # Verify call arguments call_args = mock_request.call_args assert call_args is not None method, endpoint = call_args[0] kwargs = call_args[1] assert method == "GET" assert endpoint == "projects" assert kwargs["params"]["sqlfilters"] == "(t.title:like:'%Website%')" @pytest.mark.asyncio async def test_get_projects_with_filters(self, client): """Test getting projects with status filter.""" with patch.object(client, 'request') as mock_request: mock_request.return_value = [] await client.get_projects(limit=50, page=2, status=1) call_args = mock_request.call_args kwargs = call_args[1] params = kwargs["params"] assert params["limit"] == 50 assert params["page"] == 2 assert params["status"] == 1