import unittest import os import shutil import json from unittest.mock import patch # --- FIX: Import der KORREKTEN Funktion und Klassen --- from app.services.edge_registry import EdgeRegistry from app.core.retriever import _compute_total_score, _get_status_multiplier class TestWP22Intelligence(unittest.TestCase): def setUp(self): # 1. Test-Vault Struktur definieren self.test_vault_root = os.path.abspath("tests/temp_vault") self.user_manual_dir = os.path.join(self.test_vault_root, "01_User_Manual") self.log_dir = os.path.abspath("tests/logs") # 2. Verzeichnisse erstellen os.makedirs(self.user_manual_dir, exist_ok=True) os.makedirs(self.log_dir, exist_ok=True) # 3. Dummy Vocabulary File am korrekten Ort erstellen # Der Ort muss exakt '01_User_Manual/01_edge_vocabulary.md' relativ zum vault_root sein self.vocab_file = os.path.join(self.user_manual_dir, "01_edge_vocabulary.md") with open(self.vocab_file, "w", encoding="utf-8") as f: f.write(""" | **canonical** | Aliases | | :--- | :--- | | **caused_by** | ursache_ist, wegen | | **next** | danach, folgt | """) # 4. Registry Reset & Init mit explizitem Vault Root # Wir setzen das Singleton zurück, um sicherzustellen, dass es unseren Pfad nutzt EdgeRegistry._instance = None # Hier übergeben wir den Test-Vault-Pfad! Das Skript ignoriert jetzt die .env für den Test. self.registry = EdgeRegistry(vault_root=self.test_vault_root) self.registry.unknown_log_path = os.path.join(self.log_dir, "unknown_edges.jsonl") def tearDown(self): if os.path.exists(self.test_vault_root): shutil.rmtree(self.test_vault_root) if os.path.exists("tests/logs"): shutil.rmtree("tests/logs") EdgeRegistry._instance = None def test_registry_resolution(self): print("\n--- Test A: Registry & Alias Resolution ---") # Prüfen ob Pfad korrekt übernommen wurde expected_path = os.path.join(self.test_vault_root, "01_User_Manual", "01_edge_vocabulary.md") # Da wir abspath nutzen, vergleichen wir normalized paths self.assertTrue(os.path.exists(expected_path), "Test fixture file was not created correctly") if not self.registry.valid_types: self.fail(f"Registry empty! Root used: {self.registry.vault_root}") self.assertEqual(self.registry.resolve("caused_by"), "caused_by") self.assertEqual(self.registry.resolve("ursache_ist"), "caused_by") unknown = self.registry.resolve("mystery_link") self.assertEqual(unknown, "mystery_link") # Prüfen ob Logging funktioniert if os.path.exists(self.registry.unknown_log_path): with open(self.registry.unknown_log_path, "r") as f: self.assertIn("mystery_link", f.read()) print("✅ Registry loaded from custom vault root & validated.") else: self.fail("Logfile was not created.") def test_lifecycle_scoring(self): print("\n--- Test B: Lifecycle Scoring Math ---") base_sem = 0.9 payload_draft = {"status": "draft"} payload_stable = {"status": "stable"} with patch("app.core.retriever._get_scoring_weights", return_value=(1.0, 0.5, 0.0)): mult_draft = _get_status_multiplier(payload_draft) mult_stable = _get_status_multiplier(payload_stable) score_draft = base_sem * mult_draft score_stable = base_sem * mult_stable self.assertLess(score_draft, base_sem) self.assertGreater(score_stable, base_sem) print("✅ Lifecycle scoring math verified.") def test_dynamic_boosting(self): print("\n--- Test C: Dynamic Edge Boosting ---") semantic_score = 0.5 raw_edge_bonus = 1.0 payload = {"status": "active"} with patch("app.core.retriever._get_scoring_weights", return_value=(1.0, 1.0, 0.0)): score_normal, _, _ = _compute_total_score( semantic_score, payload, edge_bonus=raw_edge_bonus, dynamic_edge_boosts=None ) boost_map = {"caused_by": 2.0} score_boosted, _, _ = _compute_total_score( semantic_score, payload, edge_bonus=raw_edge_bonus, dynamic_edge_boosts=boost_map ) self.assertGreater(score_boosted, score_normal) print("✅ Dynamic Boosting logic verified.") if __name__ == '__main__': unittest.main()