"""Confirmations de securite avant envoi a l'assistant IA : avis de principe affiche une seule fois (persist dans app_settings, redirige vers un fichier temporaire), et verification des secrets a chaque envoi. QMessageBox est simule (exec()/clickedButton() patches) : aucune boite modale reelle ne doit bloquer les tests.""" import sys, pathlib sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent)) import tempfile from pathlib import Path from unittest.mock import patch from PySide6.QtWidgets import QApplication, QMessageBox import app.app_settings as app_settings from app.dialogs.ai_prompts import ensure_ai_notice_acknowledged, confirm_sensitive_content, MASK, SEND, CANCEL app = QApplication.instance() or QApplication(sys.argv) tmp = Path(tempfile.mkdtemp()) settings_redirect = patch.object(app_settings, "SETTINGS_FILE", tmp / "settings.json") settings_redirect.start() def click(button_text): """Simule un clic sur le bouton `button_text` d'une QMessageBox construite avec addButton(), sans faire tourner de boucle d'evenements reelle.""" def fake_clicked(self): for b in self.buttons(): if b.text() == button_text: return b return None return fake_clicked print("=== 1. Avis de principe : affiche la premiere fois, refus -> False ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec", return_value=QMessageBox.Cancel) as mocked_exec: result = ensure_ai_notice_acknowledged(None) assert mocked_exec.called assert result is False assert app_settings.get_setting("ai_notice_acknowledged", False) is False print(" OK") print() print("=== 2. Avis de principe : acceptation -> True, persiste ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec", return_value=QMessageBox.Ok) as mocked_exec: result = ensure_ai_notice_acknowledged(None) assert mocked_exec.called assert result is True assert app_settings.get_setting("ai_notice_acknowledged", False) is True print(" OK") print() print("=== 3. Avis de principe : deja accepte -> plus jamais affiche ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec") as mocked_exec: result = ensure_ai_notice_acknowledged(None) assert not mocked_exec.called, "la boite ne doit plus s'afficher une fois l'accord persiste" assert result is True print(" OK") print() print("=== 4. Aucun secret detecte : SEND direct, aucune boite affichee ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec") as mocked_exec: result = confirm_sensitive_content(None, "systemctl status nginx") assert not mocked_exec.called assert result == SEND print(" OK") print() print("=== 5. Secret detecte + 'Masquer automatiquement' -> MASK ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec", return_value=0), \ patch("app.dialogs.ai_prompts.QMessageBox.clickedButton", click("Masquer automatiquement")): result = confirm_sensitive_content(None, "password=Sup3rSecret!") assert result == MASK print(" OK") print() print("=== 6. Secret detecte + 'Voir le contenu' -> SEND (envoi tel quel) ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec", return_value=0), \ patch("app.dialogs.ai_prompts.QMessageBox.clickedButton", click("Voir le contenu")): result = confirm_sensitive_content(None, "password=Sup3rSecret!") assert result == SEND print(" OK") print() print("=== 7. Secret detecte + 'Annuler' -> CANCEL ===") with patch("app.dialogs.ai_prompts.QMessageBox.exec", return_value=0), \ patch("app.dialogs.ai_prompts.QMessageBox.clickedButton", click("Annuler")): result = confirm_sensitive_content(None, "password=Sup3rSecret!") assert result == CANCEL print(" OK") settings_redirect.stop() print() print("AI PROMPTS : TOUS LES TESTS OK")