Files
pyssh-client/tests/test_session_dialog_compact.py
Florian ef059647fa
Some checks failed
CI / lint (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / build (push) Has been cancelled
Reduire la taille du formulaire de session (connexion rapide SFTP/SSH)
Signale par l'utilisateur : le dialogue de "SFTP sur cette connexion" ne
tenait pas sur l'ecran. Deux causes distinctes, verifiees par capture d'ecran
avant de conclure (rendu hors-ecran + grab()) :

1. Bug reel, dans les deux dialogues qui ont une section Bastion (SessionDialog
   et GroupSettingsDialog) : leur QStackedWidget reservait par defaut la
   hauteur de sa PLUS GRANDE page (Configuration manuelle, 5 champs) meme
   quand la page vide "Aucun" etait affichee - environ 200px de vide pur,
   visible sur la premiere capture. Nouveau app/ui/auto_height_stack.py
   (AutoHeightStackedWidget) : le sizeHint suit la page COURANTE, pas la plus
   grande de toutes: -186px des l'ouverture, a bastion desactive.

2. Choix d'ergonomie : une connexion rapide sert a aller vite (souvent un
   serveur de test en DHCP, cf. le README) - Bastion/Keepalive/Reconnexion y
   sont maintenant repliees par defaut derriere un bouton "Options
   avancees...", toujours accessibles mais qui n'allongent plus le dialogue
   pour le cas courant. Se deplient automatiquement si "Heriter du groupe"
   ramene un bastion herite, pour ne pas cacher un changement silencieux.
   Le dialogue complet ("Nouvelle session" depuis le panneau lateral) est
   inchange : tout reste visible d'emblee, c'est une operation reflechie, pas
   une connexion a la volee.

Resultat mesure : dialogue de connexion rapide 1026px -> 492px replie (-52%),
876px si depliees (au lieu de 1026, meme contenu, sans le vide). Le dialogue
"Nouvelle session" complet passe de meme a 816px grace au seul correctif (1).

tests/test_session_dialog_compact.py (5 verifications) : sizeHint de
AutoHeightStackedWidget sur la page courante, repli par defaut en connexion
rapide, redimensionnement au depli, absence de repli hors connexion rapide,
depli automatique sur heritage de groupe. Suite complete revalidee (35/35),
ruff propre.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 08:54:31 +02:00

126 lines
4.8 KiB
Python

"""Compacite du formulaire de session : signale par l'utilisateur ("trop grand,
ne rentre pas dans l'ecran") sur le dialogue de connexion SFTP rapide.
Deux causes distinctes corrigees ensemble :
1. AutoHeightStackedWidget : le QStackedWidget de la section Bastion reservait
par defaut la hauteur de sa PLUS GRANDE page (Configuration manuelle, 5
champs) meme quand la page vide ("Aucun") etait affichee - un rectangle
vide d'environ 200px, repere en comparant une capture d'ecran avant/apres.
2. En connexion rapide (quick_mode), Bastion/Keepalive/Reconnexion sont
repliees par defaut derriere un bouton "Options avancees..." : peu
pertinentes pour une connexion ponctuelle (souvent un serveur de test)."""
import pathlib
import sys
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent))
import tempfile
from pathlib import Path
from PySide6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget
from app.dialogs.session_dialog import SessionDialog
from app.groups import GroupSettings, GroupSettingsStore
from app.key_manager import KeyManager
from app.session_manager import AUTH_AUTO, BASTION_MANUAL, BastionConfig, Session, SessionStore
from app.ui.auto_height_stack import AutoHeightStackedWidget
app = QApplication.instance() or QApplication(sys.argv)
tmp = Path(tempfile.mkdtemp())
key_manager = KeyManager(registry_path=tmp / "keys.json")
store = SessionStore(path=tmp / "sessions.json")
def make_page(height: int) -> QWidget:
page = QWidget()
layout = QVBoxLayout(page)
label = QLabel("x")
label.setFixedHeight(height)
layout.addWidget(label)
return page
print("=== 1. AutoHeightStackedWidget : sizeHint suit la page courante, pas la plus grande ===")
stack = AutoHeightStackedWidget()
small_page = make_page(10)
tall_page = make_page(300)
stack.addWidget(small_page)
stack.addWidget(tall_page)
stack.setCurrentIndex(0)
height_on_small = stack.sizeHint().height()
stack.setCurrentIndex(1)
height_on_tall = stack.sizeHint().height()
print(f" hauteur sur petite page: {height_on_small}, sur grande page: {height_on_tall}")
assert height_on_small < height_on_tall, "la page courante doit determiner la hauteur, pas la plus grande des deux"
assert height_on_tall >= 300
print(" OK")
print()
print("=== 2. Connexion rapide : les options avancees sont repliees par defaut ===")
dlg = SessionDialog(
key_manager, session=Session(), parent=None, connect_label="Se connecter",
title="Connexion SFTP", session_store=store,
)
assert hasattr(dlg, "advanced_toggle"), "le bouton de repli doit exister en mode connexion rapide"
assert not dlg.advanced_toggle.isChecked()
assert not dlg.advanced_container.isVisible()
collapsed_height = dlg.sizeHint().height()
print(" hauteur repliee:", collapsed_height)
dlg.close()
print(" OK")
print()
print("=== 3. Deplier affiche les reglages avances et agrandit le dialogue ===")
dlg = SessionDialog(
key_manager, session=Session(), parent=None, connect_label="Se connecter",
title="Connexion SFTP", session_store=store,
)
dlg.show() # isVisible() se compose avec les ancetres : il en faut un reellement affiche
dlg.adjustSize()
collapsed = dlg.height()
dlg.advanced_toggle.setChecked(True)
app.processEvents()
expanded = dlg.height()
print(f" hauteur repliee: {collapsed}, depliee: {expanded}")
assert dlg.advanced_container.isVisible()
assert "▾" in dlg.advanced_toggle.text()
assert expanded > collapsed
dlg.close()
print(" OK")
print()
print("=== 4. Nouvelle session complete (pas de connexion rapide) : tout est visible, pas de repli ===")
dlg = SessionDialog(key_manager, session=Session(), parent=None, session_store=store)
dlg.show()
assert not hasattr(dlg, "advanced_toggle"), "pas de bouton de repli hors connexion rapide"
assert dlg.advanced_container.isVisible()
dlg.close()
print(" OK")
print()
print("=== 5. Heriter du groupe en connexion rapide deplie automatiquement si un bastion est herite ===")
group_store = GroupSettingsStore(path=tmp / "groups.json")
group_store.set(GroupSettings(
path="Prod", username="deploy", auth_type=AUTH_AUTO,
bastion=BastionConfig(mode=BASTION_MANUAL, host="bastion.example.com", username="jump"),
))
dlg = SessionDialog(
key_manager, session=Session(), parent=None, connect_label="Se connecter",
title="Connexion SFTP", session_store=store, group_store=group_store,
)
dlg.show()
assert not dlg.advanced_toggle.isChecked()
assert not dlg.advanced_container.isVisible()
dlg.group_edit.setText("Prod")
dlg._apply_group_defaults()
print(" bouton avance coche apres heritage:", dlg.advanced_toggle.isChecked())
assert dlg.advanced_toggle.isChecked(), "l'heritage d'un bastion doit reveler les options avancees"
assert dlg.advanced_container.isVisible()
assert dlg.bastion_host_edit.text() == "bastion.example.com"
dlg.close()
print(" OK")
print()
print("SESSION DIALOG - COMPACITE : TOUS LES TESTS OK")