"""Tests API endpoints scraping logs.""" from datetime import datetime from unittest.mock import MagicMock import pytest from fastapi import HTTPException from sqlalchemy.exc import SQLAlchemyError from pricewatch.app.api.main import create_log, update_log, delete_log from pricewatch.app.api.schemas import ScrapingLogCreate, ScrapingLogUpdate class MockScrapingLog: """Mock ScrapingLog model.""" def __init__(self, **kwargs): self.id = kwargs.get("id", 1) self.product_id = kwargs.get("product_id") self.url = kwargs.get("url", "https://example.com") self.source = kwargs.get("source", "amazon") self.reference = kwargs.get("reference", "REF123") self.fetch_method = kwargs.get("fetch_method", "http") self.fetch_status = kwargs.get("fetch_status", "success") self.fetched_at = kwargs.get("fetched_at", datetime.now()) self.duration_ms = kwargs.get("duration_ms", 1500) self.html_size_bytes = kwargs.get("html_size_bytes", 50000) self.errors = kwargs.get("errors", []) self.notes = kwargs.get("notes", []) class TestCreateLog: """Tests create_log endpoint.""" def test_create_log_db_error(self): """Erreur DB lors de creation log leve 500.""" from unittest.mock import patch session = MagicMock() session.add = MagicMock() session.commit = MagicMock(side_effect=SQLAlchemyError("error")) session.rollback = MagicMock() payload = ScrapingLogCreate( url="https://amazon.fr/dp/TEST", source="amazon", reference="TEST123", fetch_method="http", fetch_status="success", fetched_at=datetime.now(), ) with patch("pricewatch.app.api.main.ScrapingLog"): with pytest.raises(HTTPException) as exc_info: create_log(payload, session) assert exc_info.value.status_code == 500 class TestUpdateLog: """Tests update_log endpoint.""" def test_update_log_not_found(self): """Update log non trouve leve 404.""" session = MagicMock() mock_query = MagicMock() mock_query.filter.return_value.one_or_none.return_value = None session.query.return_value = mock_query payload = ScrapingLogUpdate(fetch_status="failed") with pytest.raises(HTTPException) as exc_info: update_log(99999, payload, session) assert exc_info.value.status_code == 404 def test_update_log_db_error(self): """Erreur DB lors d'update log leve 500.""" from unittest.mock import patch session = MagicMock() mock_log = MockScrapingLog() mock_query = MagicMock() mock_query.filter.return_value.one_or_none.return_value = mock_log session.query.return_value = mock_query session.commit = MagicMock(side_effect=SQLAlchemyError("error")) session.rollback = MagicMock() payload = ScrapingLogUpdate(fetch_status="failed") with patch("pricewatch.app.api.main._log_to_out"): with pytest.raises(HTTPException) as exc_info: update_log(1, payload, session) assert exc_info.value.status_code == 500 class TestDeleteLog: """Tests delete_log endpoint.""" def test_delete_log_not_found(self): """Delete log non trouve leve 404.""" session = MagicMock() mock_query = MagicMock() mock_query.filter.return_value.one_or_none.return_value = None session.query.return_value = mock_query with pytest.raises(HTTPException) as exc_info: delete_log(99999, session) assert exc_info.value.status_code == 404 def test_delete_log_success(self): """Delete log avec succes.""" session = MagicMock() mock_log = MockScrapingLog() mock_query = MagicMock() mock_query.filter.return_value.one_or_none.return_value = mock_log session.query.return_value = mock_query session.delete = MagicMock() session.commit = MagicMock() result = delete_log(1, session) assert result == {"status": "deleted"} session.delete.assert_called_once() def test_delete_log_db_error(self): """Erreur DB lors de delete log leve 500.""" session = MagicMock() mock_log = MockScrapingLog() mock_query = MagicMock() mock_query.filter.return_value.one_or_none.return_value = mock_log session.query.return_value = mock_query session.delete = MagicMock() session.commit = MagicMock(side_effect=SQLAlchemyError("error")) session.rollback = MagicMock() with pytest.raises(HTTPException) as exc_info: delete_log(1, session) assert exc_info.value.status_code == 500