"""Detection de la cible ssh "en cours" dans un terminal local : signale par l'utilisateur (bouton "SFTP sur cette connexion" revenant a un formulaire vide alors qu'une session ssh etait bien active a l'ecran). Cause reelle : detect_ssh_target() ne scrutait le texte du terminal qu'au moment du clic, en repartant du buffer/historique ACTUEL - si la ligne `ssh user@hote` tapee par l'utilisateur en etait sortie entre-temps (beaucoup de sortie, ecran efface...), plus rien n'etait detectable, meme si la connexion ssh etait toujours active. Corrige en memorisant la cible des qu'elle apparait dans la sortie (BaseTerminalTab._track_ssh_target), pour ne plus dependre de ce qui est encore present dans le buffer au moment du clic. Important : on alimente le terminal via connection.data_received.emit(...), pas terminal.feed(...) directement - _track_ssh_target est cablee sur ce signal (comme terminal.feed lui-meme), l'appeler directement contournerait le suivi et ne testerait que le repli (deja fonctionnel avant ce correctif).""" import pathlib import sys sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent)) from unittest.mock import patch from PySide6.QtWidgets import QApplication from app.local_terminal import LocalTerminalConnection from app.ui.tabs import LocalTerminalTabWidget app = QApplication.instance() or QApplication(sys.argv) def make_tab(): return LocalTerminalTabWidget() def feed(tab, data: bytes) -> None: tab.connection.data_received.emit(data) print("=== 1. Une commande ssh tapee est memorisee des qu'elle apparait a l'ecran ===") with patch.object(LocalTerminalConnection, "start", lambda self: None): tab = make_tab() assert tab.detect_current_ssh_target() is None feed(tab, b"user@PC MINGW64 ~\r\n$ ssh root@debian\r\n") target = tab.detect_current_ssh_target() print(" cible detectee:", target) assert target == {"user": "root", "host": "debian", "port": 22} tab.close_connection() print(" OK") print() print("=== 2. La cible reste memorisee meme si la commande disparait du buffer ensuite ===") with patch.object(LocalTerminalConnection, "start", lambda self: None): tab = make_tab() feed(tab, b"$ ssh root@debian\r\n") assert tab._last_ssh_target == {"user": "root", "host": "debian", "port": 22} # simule la perte de la ligne d'origine (beaucoup de sortie, ecran efface...) : # buffer_text() ne renvoie plus rien d'exploitable, mais la cible reste connue with patch.object(type(tab.terminal), "buffer_text", return_value="root@debian:~# "): target = tab.detect_current_ssh_target() print(" cible apres 'perte' du buffer:", target) assert target == {"user": "root", "host": "debian", "port": 22} tab.close_connection() print(" OK") print() print("=== 3. Une nouvelle commande ssh remplace bien l'ancienne cible memorisee ===") with patch.object(LocalTerminalConnection, "start", lambda self: None): tab = make_tab() feed(tab, b"$ ssh root@debian\r\n") assert tab._last_ssh_target["host"] == "debian" feed(tab, b"logout\r\n$ ssh admin@192.168.1.50\r\n") target = tab.detect_current_ssh_target() print(" nouvelle cible:", target) assert target == {"user": "admin", "host": "192.168.1.50", "port": 22} tab.close_connection() print(" OK") print() print("=== 4. Bouton 'SFTP sur cette connexion' : emet la cible memorisee, pas un formulaire vide ===") with patch.object(LocalTerminalConnection, "start", lambda self: None): tab = make_tab() feed(tab, b"$ ssh root@debian\r\n") with patch.object(type(tab.terminal), "buffer_text", return_value="root@debian:~# "): received = [] tab.sftp_requested.connect(lambda t: received.append(t)) tab.sftp_btn.click() print(" emis par le bouton:", received) assert received == [{"user": "root", "host": "debian", "port": 22}] tab.close_connection() print(" OK") print() print("SSH TARGET TRACKING : TOUS LES TESTS OK")