A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
200 lines
7.1 KiB
Python
200 lines
7.1 KiB
Python
"""
|
|
Tests für Playbook Service.
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime
|
|
from llm_gateway.services.playbook_service import (
|
|
PlaybookService,
|
|
Playbook,
|
|
get_playbook_service,
|
|
)
|
|
|
|
|
|
class TestPlaybookService:
|
|
"""Tests für PlaybookService."""
|
|
|
|
def setup_method(self):
|
|
"""Setup für jeden Test."""
|
|
self.service = PlaybookService()
|
|
|
|
def test_list_playbooks_returns_default_playbooks(self):
|
|
"""Test dass Default-Playbooks geladen werden."""
|
|
playbooks = self.service.list_playbooks()
|
|
assert len(playbooks) > 0
|
|
# Prüfe dass bekannte Playbooks existieren
|
|
ids = [p.id for p in playbooks]
|
|
assert "pb_default" in ids
|
|
assert "pb_elternbrief" in ids
|
|
assert "pb_arbeitsblatt" in ids
|
|
|
|
def test_list_playbooks_filter_by_status(self):
|
|
"""Test Status-Filter."""
|
|
# Alle Default-Playbooks sind published
|
|
published = self.service.list_playbooks(status="published")
|
|
assert len(published) > 0
|
|
|
|
# Keine Draft-Playbooks
|
|
drafts = self.service.list_playbooks(status="draft")
|
|
assert len(drafts) == 0
|
|
|
|
def test_get_playbook_existing(self):
|
|
"""Test Playbook abrufen."""
|
|
playbook = self.service.get_playbook("pb_default")
|
|
assert playbook is not None
|
|
assert playbook.id == "pb_default"
|
|
assert playbook.name == "Standard-Assistent"
|
|
assert len(playbook.system_prompt) > 0
|
|
|
|
def test_get_playbook_not_found(self):
|
|
"""Test nicht existierendes Playbook."""
|
|
playbook = self.service.get_playbook("non_existent")
|
|
assert playbook is None
|
|
|
|
def test_get_system_prompt(self):
|
|
"""Test System Prompt abrufen."""
|
|
prompt = self.service.get_system_prompt("pb_elternbrief")
|
|
assert prompt is not None
|
|
assert "Elternbrief" in prompt or "Elternkommunikation" in prompt
|
|
|
|
def test_get_system_prompt_not_found(self):
|
|
"""Test System Prompt für nicht existierendes Playbook."""
|
|
prompt = self.service.get_system_prompt("non_existent")
|
|
assert prompt is None
|
|
|
|
def test_create_playbook(self):
|
|
"""Test neues Playbook erstellen."""
|
|
new_playbook = Playbook(
|
|
id="pb_test_new",
|
|
name="Test Playbook",
|
|
description="Ein Test Playbook",
|
|
system_prompt="Du bist ein Test-Assistent.",
|
|
prompt_version="1.0.0",
|
|
)
|
|
created = self.service.create_playbook(new_playbook)
|
|
assert created.id == "pb_test_new"
|
|
|
|
# Prüfe dass es abrufbar ist
|
|
retrieved = self.service.get_playbook("pb_test_new")
|
|
assert retrieved is not None
|
|
assert retrieved.name == "Test Playbook"
|
|
|
|
def test_create_playbook_duplicate_id(self):
|
|
"""Test Playbook mit existierender ID erstellen."""
|
|
duplicate = Playbook(
|
|
id="pb_default", # Existiert bereits
|
|
name="Duplicate",
|
|
description="Test",
|
|
system_prompt="Test",
|
|
prompt_version="1.0.0",
|
|
)
|
|
with pytest.raises(ValueError):
|
|
self.service.create_playbook(duplicate)
|
|
|
|
def test_update_playbook(self):
|
|
"""Test Playbook aktualisieren."""
|
|
original = self.service.get_playbook("pb_default")
|
|
original_name = original.name
|
|
|
|
updated = self.service.update_playbook(
|
|
"pb_default",
|
|
name="Aktualisierter Name",
|
|
)
|
|
assert updated is not None
|
|
assert updated.name == "Aktualisierter Name"
|
|
|
|
# Reset
|
|
self.service.update_playbook("pb_default", name=original_name)
|
|
|
|
def test_update_playbook_not_found(self):
|
|
"""Test nicht existierendes Playbook aktualisieren."""
|
|
result = self.service.update_playbook("non_existent", name="Test")
|
|
assert result is None
|
|
|
|
def test_delete_playbook(self):
|
|
"""Test Playbook löschen."""
|
|
# Erst erstellen
|
|
new_playbook = Playbook(
|
|
id="pb_to_delete",
|
|
name="To Delete",
|
|
description="Test",
|
|
system_prompt="Test",
|
|
prompt_version="1.0.0",
|
|
)
|
|
self.service.create_playbook(new_playbook)
|
|
|
|
# Dann löschen
|
|
result = self.service.delete_playbook("pb_to_delete")
|
|
assert result is True
|
|
|
|
# Prüfen dass gelöscht
|
|
assert self.service.get_playbook("pb_to_delete") is None
|
|
|
|
def test_delete_playbook_not_found(self):
|
|
"""Test nicht existierendes Playbook löschen."""
|
|
result = self.service.delete_playbook("non_existent")
|
|
assert result is False
|
|
|
|
|
|
class TestPlaybookContent:
|
|
"""Tests für Playbook-Inhalte."""
|
|
|
|
def setup_method(self):
|
|
"""Setup für jeden Test."""
|
|
self.service = PlaybookService()
|
|
|
|
def test_elternbrief_playbook_has_guidelines(self):
|
|
"""Test dass Elternbrief-Playbook Richtlinien enthält."""
|
|
playbook = self.service.get_playbook("pb_elternbrief")
|
|
assert playbook is not None
|
|
prompt = playbook.system_prompt.lower()
|
|
# Sollte wichtige Richtlinien enthalten
|
|
assert "ton" in prompt or "sprache" in prompt
|
|
assert "brief" in prompt or "eltern" in prompt
|
|
|
|
def test_rechtlich_playbook_has_disclaimer(self):
|
|
"""Test dass Rechtlich-Playbook Disclaimer enthält."""
|
|
playbook = self.service.get_playbook("pb_rechtlich")
|
|
assert playbook is not None
|
|
prompt = playbook.system_prompt.lower()
|
|
# Sollte Hinweis auf keine Rechtsberatung enthalten
|
|
assert "rechtsberatung" in prompt or "fachanwalt" in prompt
|
|
|
|
def test_foerderplan_playbook_mentions_privacy(self):
|
|
"""Test dass Förderplan-Playbook Datenschutz erwähnt."""
|
|
playbook = self.service.get_playbook("pb_foerderplan")
|
|
assert playbook is not None
|
|
prompt = playbook.system_prompt.lower()
|
|
# Sollte sensible Daten erwähnen
|
|
assert "sensib" in prompt or "vertraulich" in prompt or "daten" in prompt
|
|
|
|
def test_all_playbooks_have_required_fields(self):
|
|
"""Test dass alle Playbooks Pflichtfelder haben."""
|
|
playbooks = self.service.list_playbooks(status=None)
|
|
for playbook in playbooks:
|
|
assert playbook.id is not None
|
|
assert len(playbook.id) > 0
|
|
assert playbook.name is not None
|
|
assert len(playbook.name) > 0
|
|
assert playbook.system_prompt is not None
|
|
assert len(playbook.system_prompt) > 0
|
|
assert playbook.prompt_version is not None
|
|
|
|
def test_playbooks_have_tool_policy(self):
|
|
"""Test dass Playbooks Tool Policy haben."""
|
|
playbooks = self.service.list_playbooks()
|
|
for playbook in playbooks:
|
|
assert hasattr(playbook, "tool_policy")
|
|
# no_pii_in_output sollte standardmäßig true sein
|
|
assert playbook.tool_policy.get("no_pii_in_output") is True
|
|
|
|
|
|
class TestGetPlaybookServiceSingleton:
|
|
"""Tests für Singleton Pattern."""
|
|
|
|
def test_singleton_returns_same_instance(self):
|
|
"""Test dass get_playbook_service Singleton zurückgibt."""
|
|
service1 = get_playbook_service()
|
|
service2 = get_playbook_service()
|
|
assert service1 is service2
|