"""Pytest fixtures for MCP Odoo tests."""
from __future__ import annotations
import os
from typing import Any
from unittest.mock import MagicMock, patch
import pytest
# =============================================================================
# Environment Setup
# =============================================================================
@pytest.fixture(autouse=True)
def mock_env():
"""Set up mock environment variables for tests."""
env_vars = {
"ODOO_URL": "https://test.odoo.com",
"ODOO_DB": "test_db",
"ODOO_USERNAME": "test@example.com",
"ODOO_API_KEY": "test_api_key",
"REDIS_ENABLED": "false",
"LOG_LEVEL": "WARNING",
"LOG_FORMAT": "text",
}
with patch.dict(os.environ, env_vars):
yield
# =============================================================================
# Client Mocks
# =============================================================================
@pytest.fixture
def mock_odoo_client():
"""Mock the OdooClient for testing."""
with patch("mcp_odoo.client.OdooClient") as MockClient:
client = MagicMock()
client.uid = 1
client.search_read.return_value = []
client.search.return_value = []
client.read.return_value = []
client.create.return_value = 1
client.write.return_value = True
client.unlink.return_value = True
client.exists.return_value = True
client.get_record.return_value = {"id": 1, "name": "Test"}
client.test_connection.return_value = {
"status": "connected",
"server_version": "17.0",
"database": "test_db",
"user": "Test User",
"user_id": 1,
"company": "Test Company",
}
MockClient.return_value = client
yield client
@pytest.fixture
def mock_client_factory(mock_odoo_client):
"""Mock the OdooClientFactory."""
with patch("mcp_odoo.tools.base.get_odoo_client") as mock_get:
mock_get.return_value = mock_odoo_client
yield mock_odoo_client
# =============================================================================
# Sample Data Fixtures
# =============================================================================
@pytest.fixture
def sample_projects() -> list[dict[str, Any]]:
"""Sample project data."""
return [
{
"id": 1,
"name": "Project Alpha",
"partner_id": [10, "Client A"],
"user_id": [1, "Manager"],
"task_count": 5,
},
{
"id": 2,
"name": "Project Beta",
"partner_id": [20, "Client B"],
"user_id": [2, "Manager B"],
"task_count": 3,
},
{
"id": 3,
"name": "Project Gamma",
"partner_id": False,
"user_id": False,
"task_count": 0,
},
]
@pytest.fixture
def sample_tasks() -> list[dict[str, Any]]:
"""Sample task data."""
return [
{
"id": 1,
"name": "Task 1",
"project_id": [1, "Project Alpha"],
"stage_id": [1, "To Do"],
"user_ids": [1],
"date_deadline": "2024-02-15",
},
{
"id": 2,
"name": "Task 2",
"project_id": [1, "Project Alpha"],
"stage_id": [2, "In Progress"],
"user_ids": [1, 2],
"date_deadline": None,
},
]
@pytest.fixture
def sample_timesheets() -> list[dict[str, Any]]:
"""Sample timesheet data."""
return [
{
"id": 1,
"date": "2024-01-15",
"name": "Development work",
"unit_amount": 4.0,
"project_id": [1, "Project Alpha"],
"task_id": [1, "Task 1"],
"employee_id": [1, "John Doe"],
},
{
"id": 2,
"date": "2024-01-15",
"name": "Client meeting",
"unit_amount": 2.0,
"project_id": [1, "Project Alpha"],
"task_id": False,
"employee_id": [1, "John Doe"],
},
]
@pytest.fixture
def sample_expenses() -> list[dict[str, Any]]:
"""Sample expense data."""
return [
{
"id": 1,
"name": "Travel expense",
"date": "2024-01-10",
"total_amount": 150.0,
"state": "draft",
"product_id": [1, "Transport"],
"payment_mode": "company_account",
"currency_id": [1, "EUR"],
},
{
"id": 2,
"name": "Business lunch",
"date": "2024-01-12",
"total_amount": 85.0,
"state": "approved",
"product_id": [2, "Meals"],
"payment_mode": "own_account",
"currency_id": [1, "EUR"],
},
]
@pytest.fixture
def sample_expense_categories() -> list[dict[str, Any]]:
"""Sample expense category data."""
return [
{"id": 1, "name": "Transport", "standard_price": 0.0, "list_price": 0.0},
{"id": 2, "name": "Meals", "standard_price": 20.0, "list_price": 20.0},
{"id": 3, "name": "Accommodation", "standard_price": 100.0, "list_price": 100.0},
]
@pytest.fixture
def sample_employees() -> list[dict[str, Any]]:
"""Sample employee data."""
return [
{
"id": 1,
"name": "John Doe",
"job_title": "Developer",
"department_id": [1, "IT"],
"work_email": "john@example.com",
"work_phone": "+33 1 23 45 67 89",
"parent_id": [2, "Jane Manager"],
},
{
"id": 2,
"name": "Jane Manager",
"job_title": "Manager",
"department_id": [1, "IT"],
"work_email": "jane@example.com",
"work_phone": None,
"parent_id": False,
},
]
@pytest.fixture
def sample_contacts() -> list[dict[str, Any]]:
"""Sample contact data."""
return [
{
"id": 1,
"name": "ACME Corp",
"email": "contact@acme.com",
"phone": "+33 1 00 00 00 00",
"city": "Paris",
"country_id": [75, "France"],
"is_company": True,
},
{
"id": 2,
"name": "John Smith",
"email": "john.smith@acme.com",
"phone": None,
"city": "Lyon",
"country_id": [75, "France"],
"is_company": False,
},
]
@pytest.fixture
def sample_invoices() -> list[dict[str, Any]]:
"""Sample invoice data."""
return [
{
"id": 1,
"name": "INV/2024/0001",
"partner_id": [1, "ACME Corp"],
"invoice_date": "2024-01-15",
"invoice_date_due": "2024-02-15",
"amount_total": 1200.0,
"amount_residual": 1200.0,
"state": "posted",
"move_type": "out_invoice",
"currency_id": [1, "EUR"],
},
]
@pytest.fixture
def sample_sale_orders() -> list[dict[str, Any]]:
"""Sample sale order data."""
return [
{
"id": 1,
"name": "S00001",
"partner_id": [1, "ACME Corp"],
"date_order": "2024-01-10 10:00:00",
"amount_total": 5000.0,
"state": "sale",
"currency_id": [1, "EUR"],
"user_id": [1, "Salesperson"],
},
]
@pytest.fixture
def sample_products() -> list[dict[str, Any]]:
"""Sample product data."""
return [
{
"id": 1,
"name": "Product A",
"default_code": "PROD-A",
"list_price": 100.0,
"standard_price": 50.0,
"detailed_type": "consu",
"categ_id": [1, "All / Consumables"],
"qty_available": 0,
},
{
"id": 2,
"name": "Service B",
"default_code": "SERV-B",
"list_price": 200.0,
"standard_price": 0.0,
"detailed_type": "service",
"categ_id": [2, "All / Services"],
"qty_available": 0,
},
]