import asyncio from unittest.mock import AsyncMock, patch import pytest from tests.conftest import auth_header, login @pytest.mark.asyncio async def test_email_wird_bei_neuem_fehlbestand_an_verantwortliche_versendet( client, objekt_mit_position, mitarbeiter_user, materialverantwortlicher_user ): """Karte 05: asynchrone E-Mail-Benachrichtigung bei neuem Fehlbestand. Kein echter Test-Mailserver im Host-Runner (kein Docker) verfügbar - der tatsächliche SMTP-Versand wird gemockt, geprüft wird der korrekte Aufruf (Empfänger = aktive Materialverantwortliche mit hinterlegter E-Mail-Adresse).""" objekt, material = objekt_mit_position with patch("app.services.benachrichtigung.send_email", new=AsyncMock()) as mock_send: token = await login(client, "mitarbeiter1") start = await client.post( f"/api/v1/objekte/{objekt.id}/kontrollen", json={"uebernehmen": False}, headers=auth_header(token) ) kontrolle_id = start.json()["id"] await client.put( f"/api/v1/kontrollen/{kontrolle_id}/positionen/{material.id}", json={"istmenge": "6"}, headers=auth_header(token), ) for _ in range(20): await asyncio.sleep(0.01) if mock_send.await_count: break mock_send.assert_awaited_once() kwargs = mock_send.await_args.kwargs assert kwargs["to"] == ["mv1@example.org"] assert "Fehlbestand" in kwargs["subject"] @pytest.mark.asyncio async def test_kein_email_versand_ohne_empfaenger(client, objekt_mit_position, mitarbeiter_user): """Kein Materialverantwortlicher mit E-Mail vorhanden -> send_email wird gar nicht mit Empfängern aufgerufen (leere Liste), kein Fehler im Kontroll-Workflow.""" objekt, material = objekt_mit_position with patch("app.services.benachrichtigung.send_email", new=AsyncMock()) as mock_send: token = await login(client, "mitarbeiter1") start = await client.post( f"/api/v1/objekte/{objekt.id}/kontrollen", json={"uebernehmen": False}, headers=auth_header(token) ) kontrolle_id = start.json()["id"] response = await client.put( f"/api/v1/kontrollen/{kontrolle_id}/positionen/{material.id}", json={"istmenge": "6"}, headers=auth_header(token), ) assert response.status_code == 200 # Workflow funktioniert trotz fehlender Empfänger for _ in range(20): await asyncio.sleep(0.01) if mock_send.await_count: break mock_send.assert_awaited_once() assert mock_send.await_args.kwargs["to"] == []