# -*- coding: utf-8 -*- """Automatisierte Tests für Doku-Prompt-System.""" from __future__ import annotations import json import os import tempfile import unittest from unittest.mock import patch class TestDokuPromptSystem(unittest.TestCase): def setUp(self): self._tmpdir = tempfile.mkdtemp() self._orig_path_fn = None def tearDown(self): import shutil shutil.rmtree(self._tmpdir, ignore_errors=True) def _patch_templates_path(self): import aza_doku_vorlagen as dv path = os.path.join(self._tmpdir, "aza_document_templates.json") dv._templates_json_path = lambda: path # type: ignore return path, dv def test_doc_types_order(self): from aza_doku_vorlagen import DOC_TYPES labels = [l for _, l in DOC_TYPES] self.assertEqual(labels[0], "Krankengeschichte") self.assertEqual(labels[1], "Verlauf") self.assertEqual(labels[-1], "Eigenes Dokument") self.assertEqual(len(DOC_TYPES), 8) def test_verlauf_default_present(self): from aza_doku_vorlagen import AZA_DEFAULT_TEMPLATES, VERLAUF_DEFAULT_PROMPT self.assertIn("verlauf", AZA_DEFAULT_TEMPLATES) self.assertIn("Verlaufsbericht", VERLAUF_DEFAULT_PROMPT) def test_migration_v1_to_v2(self): path, dv = self._patch_templates_path() old = { "schema_version": 1, "active": {"kg": "aza_default", "brief": "aza_default"}, "templates": { "kg": [{"id": "aza_default", "name": "AzA-Grundvorlage", "is_system": True, "content": "KG alt", "created_at": "t", "updated_at": "t"}], "brief": [{"id": "aza_default", "name": "AzA-Grundvorlage", "is_system": True, "content": "Brief alt", "created_at": "t", "updated_at": "t"}], }, } with open(path, "w", encoding="utf-8") as f: json.dump(old, f) data = dv._load() self.assertEqual(data["schema_version"], 2) self.assertEqual(data["templates"]["kg"][0]["content"], "KG alt") self.assertIn("verlauf", data["templates"]) self.assertIn("eigenes_dokument", data["templates"]) def test_sanitize_strips_script(self): from aza_doku_vorlagen import sanitize_prompt_text s = sanitize_prompt_text("Verlauf") self.assertNotIn("script", s.lower()) self.assertIn("Verlauf", s) def test_dynamic_button_labels(self): from aza_doku_vorlagen import DOC_TYPE_CREATE_LABELS, DOC_TYPE_COPY_LABELS self.assertEqual(DOC_TYPE_CREATE_LABELS["verlauf"], "Verlauf erstellen") self.assertEqual(DOC_TYPE_COPY_LABELS["brief"], "Brief kopieren") def test_get_active_no_override_for_default(self): path, dv = self._patch_templates_path() dv._save(dv._default_structure()) from aza_text_windows_mixin import _get_doku_vorlage_for self.assertEqual(_get_doku_vorlage_for("kg"), "") self.assertEqual(_get_doku_vorlage_for("verlauf"), "") def test_get_active_user_template(self): path, dv = self._patch_templates_path() data = dv._default_structure() data["templates"]["verlauf"].append({ "id": "user_test", "name": "Mein Verlauf", "is_system": False, "content": "Custom Verlauf", "created_at": "t", "updated_at": "t", "revision": 1, }) data["active"]["verlauf"] = "user_test" dv._save(data) from aza_text_windows_mixin import _get_doku_vorlage_for self.assertEqual(_get_doku_vorlage_for("verlauf"), "Custom Verlauf") def test_copy_public_template(self): path, dv = self._patch_templates_path() dv._save(dv._default_structure()) new_id = dv.copy_public_template_as_own( "brief", content="Pub", title="Pub Brief", source_author="Dr. X", source_server_id="s1", ) self.assertTrue(new_id) data = dv._load() tpl = next(t for t in data["templates"]["brief"] if t["id"] == new_id) self.assertEqual(tpl["content"], "Pub") self.assertEqual(tpl["source_author"], "Dr. X") def test_atomic_save(self): path, dv = self._patch_templates_path() dv._save(dv._default_structure()) self.assertTrue(os.path.isfile(path)) self.assertFalse(os.path.isfile(path + ".tmp")) def test_merge_sync_newest_revision(self): from aza_doku_prompt_sync import merge_server_doku_items_local data = { "schema_version": 2, "active": {"kg": "aza_default"}, "templates": {"kg": []}, "sync_meta": {"conflicts": []}, } server_items = [{ "id": "user_1_kg", "item_type": "doku_prompt", "trigger": "kg", "content": json.dumps({ "doc_type": "kg", "name": "Sync KG", "content": "Synced", "revision": 2, "updated_at": "2026-01-02T00:00:00+00:00", }), }] data, changed = merge_server_doku_items_local(data, server_items) self.assertTrue(changed) self.assertEqual(data["templates"]["kg"][0]["content"], "Synced") def test_sync_serialization_private_only(self): from aza_doku_prompt_sync import local_private_templates_to_sync_items path, dv = self._patch_templates_path() data = dv._default_structure() data["templates"]["verlauf"].append({ "id": "user_v1", "name": "Privat", "is_system": False, "content": "Verlauf privat", "created_at": "t", "updated_at": "t", "revision": 3, }) dv._save(data) items = local_private_templates_to_sync_items(dv._load()) self.assertEqual(len(items), 1) self.assertEqual(items[0]["item_type"], "doku_prompt") self.assertEqual(items[0]["trigger"], "verlauf") payload = json.loads(items[0]["content"]) self.assertEqual(payload["content"], "Verlauf privat") self.assertEqual(payload["revision"], 3) def test_merge_conflict_keeps_local_when_newer(self): from aza_doku_prompt_sync import merge_server_doku_items_local data = { "schema_version": 2, "active": {"kg": "user_1_kg"}, "templates": {"kg": [{ "id": "user_1_kg", "name": "Lokal", "is_system": False, "content": "Lokal neu", "revision": 5, "updated_at": "2026-06-10T12:00:00+00:00", "created_at": "t", }]}, "sync_meta": {"conflicts": []}, } server_items = [{ "id": "user_1_kg", "item_type": "doku_prompt", "trigger": "kg", "content": json.dumps({ "doc_type": "kg", "name": "Server alt", "content": "Server alt", "revision": 2, "updated_at": "2026-01-01T00:00:00+00:00", }), }] merged, changed = merge_server_doku_items_local(data, server_items) self.assertEqual(merged["templates"]["kg"][0]["content"], "Lokal neu") self.assertTrue(len(merged["sync_meta"]["conflicts"]) >= 1) def test_publish_payload_fields(self): from aza_doku_prompt_sync import PublishDokuPromptIn p = PublishDokuPromptIn( doc_type="verlauf", title="Test", content="Prompt ohne Patientendaten", description="Demo", author_display="Dr. Test", ) self.assertEqual(p.doc_type, "verlauf") d = p.model_dump() self.assertNotIn("patient_name", d) self.assertNotIn("transcript", d) def test_load_all_templates_alias(self): path, dv = self._patch_templates_path() dv._save(dv._default_structure()) self.assertEqual(dv._load_all_templates()["schema_version"], 2) def test_active_per_doc_type(self): path, dv = self._patch_templates_path() data = dv._default_structure() for dt, _ in dv.DOC_TYPES: self.assertIn(dt, data["active"]) self.assertIn(dt, data["templates"]) def test_no_patient_fields_in_template_schema(self): path, dv = self._patch_templates_path() data = dv._default_structure() blob = json.dumps(data).lower() for forbidden in ("patient_name", "transcript", "geburtsdatum", "sozialversicherung"): self.assertNotIn(forbidden, blob) def test_office_shell_kg_section_markers(self): path = os.path.join(os.path.dirname(__file__), "aza_office_shell_v1.py") with open(path, encoding="utf-8") as f: src = f.read() self.assertIn('"Doku-Prompt"', src) self.assertIn("DocTypePicker", src) self.assertIn("app._doc_type_picker", src) self.assertNotIn("app._doc_type_combo", src) self.assertNotIn('("Doku-Prompt", "_open_doku_vorlage_fenster")', src) self.assertNotIn('actions, "Kommentare"', src) self.assertIn('"autotext"', src) self.assertIn('"folder"', src) self.assertIn('"library"', src) def test_main_doc_type_persistence(self): import tempfile import aza_persistence as ap with tempfile.TemporaryDirectory() as td: cfg = os.path.join(td, "autotext.json") with patch.object(ap, "_autotext_config_path", return_value=cfg): self.assertEqual(ap.load_main_doc_type(), "kg") ap.save_main_doc_type("verlauf") self.assertEqual(ap.load_main_doc_type(), "verlauf") ap.save_main_doc_type("invalid_type") self.assertEqual(ap.load_main_doc_type(), "kg") ap.save_main_doc_type("brief") data = ap.load_autotext() self.assertEqual(data.get("main_doc_type"), "brief") if __name__ == "__main__": unittest.main()