diff --git a/document-templates/generators/test_betriebsvereinbarung.py b/document-templates/generators/test_betriebsvereinbarung.py new file mode 100644 index 0000000..af95215 --- /dev/null +++ b/document-templates/generators/test_betriebsvereinbarung.py @@ -0,0 +1,158 @@ +"""Tests for Betriebsvereinbarung template generator.""" + +import pytest +from betriebsvereinbarung_template import ( + generate_betriebsvereinbarung_draft, + DEFAULT_VERBOTENE_NUTZUNGEN, + AI_VERBOTENE_NUTZUNGEN, + DEFAULT_TOM, + DATENARTEN_MAP, +) + + +class TestGenerateBetriebsvereinbarung: + """Tests for generate_betriebsvereinbarung_draft().""" + + def test_minimal_context(self): + """Minimal context should produce valid output with placeholders.""" + ctx = { + "company_name": "Test GmbH", + "system_name": "Microsoft 365", + "system_description": "Office-Suite mit KI-Funktionen", + } + result = generate_betriebsvereinbarung_draft(ctx) + + assert result["UNTERNEHMEN_NAME"] == "Test GmbH" + assert result["SYSTEM_NAME"] == "Microsoft 365" + assert "{{BETRIEBSRAT_VORSITZ}}" in result["BETRIEBSRAT_VORSITZ"] + + def test_full_context(self): + """Full context should fill all placeholders.""" + ctx = { + "company_name": "Acme Corp", + "company_address": "Hamburg", + "employer_representative": "Dr. Schmidt", + "works_council_chair": "Fr. Mueller", + "system_name": "Copilot", + "system_description": "KI-Assistent", + "system_vendor": "Microsoft", + "locations": ["Hamburg", "Berlin"], + "departments": ["IT", "HR"], + "modules": ["Teams", "Outlook", "Word"], + "purposes": ["Texterstellung", "Zusammenfassung"], + "data_types": ["email", "chat", "login"], + "is_ai_system": True, + "dpo_name": "Dr. Datenschutz", + "dpo_contact": "dsb@acme.de", + "audit_interval": "6 Monate", + "duration": "2 Jahre", + "notice_period": "6 Monate", + } + result = generate_betriebsvereinbarung_draft(ctx) + + assert result["ARBEITGEBER_VERTRETER"] == "Dr. Schmidt" + assert result["BETRIEBSRAT_VORSITZ"] == "Fr. Mueller" + assert "Hamburg" in result["GELTUNGSBEREICH_STANDORTE"] + assert "Berlin" in result["GELTUNGSBEREICH_STANDORTE"] + assert "Teams" in result["GELTUNGSBEREICH_MODULE"] + assert result["AUDIT_INTERVALL"] == "6 Monate" + assert result["LAUFZEIT"] == "2 Jahre" + assert result["AI_SYSTEM"] is True + + def test_verbotene_nutzungen_default(self): + """Default forbidden uses should always be included.""" + ctx = {"company_name": "Test", "system_name": "Tool", "system_description": "x"} + result = generate_betriebsvereinbarung_draft(ctx) + + for nutzung in DEFAULT_VERBOTENE_NUTZUNGEN: + assert nutzung in result["VERBOTENE_NUTZUNGEN"] + + def test_verbotene_nutzungen_ai_system(self): + """AI-specific forbidden uses should be added for AI systems.""" + ctx = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "is_ai_system": True, + } + result = generate_betriebsvereinbarung_draft(ctx) + + for nutzung in AI_VERBOTENE_NUTZUNGEN: + assert nutzung in result["VERBOTENE_NUTZUNGEN"] + + def test_verbotene_nutzungen_no_ai(self): + """AI-specific forbidden uses should NOT be added for non-AI systems.""" + ctx = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "is_ai_system": False, + } + result = generate_betriebsvereinbarung_draft(ctx) + + for nutzung in AI_VERBOTENE_NUTZUNGEN: + assert nutzung not in result["VERBOTENE_NUTZUNGEN"] + + def test_datenarten_mapping(self): + """Data types should be resolved from DATENARTEN_MAP.""" + ctx = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "data_types": ["email", "prompt", "hr"], + } + result = generate_betriebsvereinbarung_draft(ctx) + + assert DATENARTEN_MAP["email"] in result["DATENARTEN_LISTE"] + assert DATENARTEN_MAP["prompt"] in result["DATENARTEN_LISTE"] + assert DATENARTEN_MAP["hr"] in result["DATENARTEN_LISTE"] + + def test_tom_high_conflict_score(self): + """High conflict score should add extra TOM measures.""" + ctx_low = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "betrvg_conflict_score": 20, + } + ctx_high = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "betrvg_conflict_score": 80, + } + + result_low = generate_betriebsvereinbarung_draft(ctx_low) + result_high = generate_betriebsvereinbarung_draft(ctx_high) + + # High score should have more TOM items + low_count = result_low["TOM_MASSNAHMEN"].count("- ") + high_count = result_high["TOM_MASSNAHMEN"].count("- ") + assert high_count > low_count, f"High conflict ({high_count} TOMs) should have more than low ({low_count})" + + def test_speicherfristen_defaults(self): + """Default retention periods should be set.""" + ctx = {"company_name": "Test", "system_name": "Tool", "system_description": "x"} + result = generate_betriebsvereinbarung_draft(ctx) + + assert result["SPEICHERFRIST_AUDIT_LOGS"] == "90 Tage" + assert result["SPEICHERFRIST_NUTZUNGSDATEN"] == "30 Tage" + assert result["SPEICHERFRIST_CHAT_PROMPTS"] == "deaktiviert" + + def test_custom_retention(self): + """Custom retention periods should override defaults.""" + ctx = { + "company_name": "Test", + "system_name": "Tool", + "system_description": "x", + "retention_audit_logs": "180 Tage", + "retention_prompts": "7 Tage", + } + result = generate_betriebsvereinbarung_draft(ctx) + + assert result["SPEICHERFRIST_AUDIT_LOGS"] == "180 Tage" + assert result["SPEICHERFRIST_CHAT_PROMPTS"] == "7 Tage" + + +if __name__ == "__main__": + pytest.main([__file__, "-v"])