"""Tests pour les outils de gestion des dépenses."""
from __future__ import annotations
import pytest
from unittest.mock import patch, MagicMock
# Mock les variables d'environnement avant l'import
with patch.dict("os.environ", {
"ODOO_URL": "https://test.odoo.com",
"ODOO_DB": "test_db",
"ODOO_USERNAME": "test_user",
"ODOO_API_KEY": "test_key",
}):
with patch("server.OdooClient"):
from server import (
list_expense_categories,
list_expenses,
create_expense,
update_expense,
delete_expense,
ExpenseState,
)
class TestListExpenseCategories:
"""Tests pour list_expense_categories."""
def test_list_categories_success(self, mock_odoo_client, sample_expense_categories):
"""Test listage des catégories avec succès."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = sample_expense_categories
result = list_expense_categories()
assert "# Catégories de dépenses" in result
assert "Transport" in result
assert "Restauration" in result
def test_list_categories_empty(self, mock_odoo_client):
"""Test listage sans catégories."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = []
result = list_expense_categories()
assert "Aucune catégorie" in result
class TestListExpenses:
"""Tests pour list_expenses."""
def test_list_expenses_success(self, mock_odoo_client, sample_expenses):
"""Test listage des dépenses avec succès."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = sample_expenses
result = list_expenses()
assert "# Dépenses" in result
assert "Déplacement client" in result
assert "150.0" in result or "150" in result
assert "Brouillon" in result
assert "Approuvée" in result
def test_list_expenses_with_state_filter(self, mock_odoo_client, sample_expenses):
"""Test listage avec filtre d'état."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [sample_expenses[0]]
result = list_expenses(state="draft")
assert "Déplacement client" in result
def test_list_expenses_invalid_state(self, mock_odoo_client):
"""Test avec état invalide."""
with patch("server.odoo", mock_odoo_client):
result = list_expenses(state="invalid_state")
assert "Erreur" in result
assert "État invalide" in result
def test_list_expenses_with_date_filter(self, mock_odoo_client, sample_expenses):
"""Test listage avec filtre de date."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = sample_expenses
result = list_expenses(date_from="2024-01-01", date_to="2024-01-31")
assert "# Dépenses" in result
class TestCreateExpense:
"""Tests pour create_expense."""
def test_create_expense_success(self, mock_odoo_client, sample_employees):
"""Test création de dépense avec succès."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.exists.return_value = True
mock_odoo_client.search_read.return_value = sample_employees
mock_odoo_client.create.return_value = 10
result = create_expense(
name="Test dépense",
product_id=1,
total_amount=100.0,
)
assert "créée avec succès" in result
assert "10" in result
def test_create_expense_empty_name(self, mock_odoo_client):
"""Test avec nom vide."""
with patch("server.odoo", mock_odoo_client):
result = create_expense(
name=" ",
product_id=1,
total_amount=100.0,
)
assert "Erreur" in result
assert "vide" in result
def test_create_expense_negative_amount(self, mock_odoo_client):
"""Test avec montant négatif."""
with patch("server.odoo", mock_odoo_client):
result = create_expense(
name="Test",
product_id=1,
total_amount=-50.0,
)
assert "Erreur" in result
assert "positif" in result
def test_create_expense_category_not_found(self, mock_odoo_client):
"""Test avec catégorie inexistante."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.exists.return_value = False
result = create_expense(
name="Test",
product_id=999,
total_amount=100.0,
)
assert "Erreur" in result
assert "non trouvée" in result
def test_create_expense_no_employee(self, mock_odoo_client):
"""Test sans employé lié."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.exists.return_value = True
mock_odoo_client.search_read.return_value = [] # Pas d'employé
result = create_expense(
name="Test",
product_id=1,
total_amount=100.0,
)
assert "Erreur" in result
assert "employé" in result.lower()
class TestUpdateExpense:
"""Tests pour update_expense."""
def test_update_expense_success(self, mock_odoo_client):
"""Test modification avec succès."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [{"state": "draft"}]
result = update_expense(
expense_id=1,
name="Nouveau nom",
total_amount=200.0,
)
assert "modifiée avec succès" in result
def test_update_expense_not_found(self, mock_odoo_client):
"""Test avec dépense inexistante."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = []
result = update_expense(expense_id=999, name="Test")
assert "Erreur" in result
assert "non trouvée" in result
def test_update_expense_not_draft(self, mock_odoo_client):
"""Test modification d'une dépense non brouillon."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [{"state": "approved"}]
result = update_expense(expense_id=1, name="Test")
assert "Erreur" in result
assert "brouillon" in result
def test_update_expense_no_changes(self, mock_odoo_client):
"""Test sans modifications."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [{"state": "draft"}]
result = update_expense(expense_id=1)
assert "Aucune modification" in result
class TestDeleteExpense:
"""Tests pour delete_expense."""
def test_delete_expense_success(self, mock_odoo_client):
"""Test suppression avec succès."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [
{"state": "draft", "name": "Ma dépense"}
]
result = delete_expense(expense_id=1)
assert "supprimée avec succès" in result
mock_odoo_client.unlink.assert_called_once()
def test_delete_expense_not_found(self, mock_odoo_client):
"""Test avec dépense inexistante."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = []
result = delete_expense(expense_id=999)
assert "Erreur" in result
assert "non trouvée" in result
def test_delete_expense_not_draft(self, mock_odoo_client):
"""Test suppression d'une dépense non brouillon."""
with patch("server.odoo", mock_odoo_client):
mock_odoo_client.search_read.return_value = [
{"state": "done", "name": "Ma dépense"}
]
result = delete_expense(expense_id=1)
assert "Erreur" in result
assert "brouillon" in result
class TestExpenseState:
"""Tests pour l'enum ExpenseState."""
def test_expense_states(self):
"""Test des valeurs de l'enum."""
assert ExpenseState.DRAFT == "draft"
assert ExpenseState.REPORTED == "reported"
assert ExpenseState.APPROVED == "approved"
assert ExpenseState.DONE == "done"
assert ExpenseState.REFUSED == "refused"