"""L'assemblage commun aux deux lanceurs — sans jamais ouvrir de fenêtre ni de micro. Le transcripteur réel charge un modèle (opération lourde, parfois absente sur la machine de test) : on injecte donc toujours un `choisir_transcripteur` et un `detecter_moteur` doublés. L'overlay réel (Cocoa ou Qt), lui, est fait pour être construit sans effet visible tant que `show()` n'est pas appelé — les tests le laissent donc réel, et vérifient justement qu'aucune fenêtre ne s'affiche. """ import os import tempfile from assemblage import acquerir_verrou, construire from controller import ZonzaController from systeme import choisir_systeme class _TranscripteurFactice: def __init__(self, modele, langue, amorce): self.modele = modele self.langue = langue self.amorce = amorce def warmup(self): pass def transcrire(self, audio): return "texte factice" def _choisir_transcripteur_factice(nom, modele, langue, amorce): return _TranscripteurFactice(modele, langue, amorce) def _tmp_verrou(): return os.path.join(tempfile.mkdtemp(), "instance.lock") # --- construire() ------------------------------------------------------------ def test_construire_rend_un_controleur_cable_sur_les_bons_objets(): resultat = construire( plateforme="darwin", detecter_moteur=lambda: "mlx", choisir_transcripteur=_choisir_transcripteur_factice, ) assert isinstance(resultat["controller"], ZonzaController) # le contrôleur pointe vers CE système, CE transcripteur, CET overlay — # pas une copie recréée à côté. assert resultat["controller"].systeme is resultat["systeme"] assert resultat["controller"].transcripteur is resultat["transcripteur"] assert resultat["controller"].pulse is resultat["overlay"] assert isinstance(resultat["transcripteur"], _TranscripteurFactice) def test_construire_fonctionne_aussi_pour_win32(): resultat = construire( plateforme="win32", detecter_moteur=lambda: "faster-cpu", choisir_transcripteur=_choisir_transcripteur_factice, ) from interface.qt import OverlayQt assert isinstance(resultat["overlay"], OverlayQt) def test_construire_transmet_run_on_main_et_on_state(): appels = [] resultat = construire( plateforme="darwin", run_on_main=lambda fn: appels.append(fn) or fn(), on_state=lambda s: appels.append(s), detecter_moteur=lambda: "mlx", choisir_transcripteur=_choisir_transcripteur_factice, ) resultat["controller"].on_state("recording") assert "recording" in appels def test_construire_ne_leve_aucune_erreur_de_config(): # validate_config(CONFIG) est appelée à l'intérieur : si elle levait, le # test échouerait ici plutôt qu'au premier lancement réel. construire( plateforme="darwin", detecter_moteur=lambda: "mlx", choisir_transcripteur=_choisir_transcripteur_factice, ) # --- acquerir_verrou() -------------------------------------------------------- def test_acquerir_verrou_rend_un_handle_pour_la_premiere_instance(): systeme = choisir_systeme() handle = acquerir_verrou(systeme, _tmp_verrou()) assert handle is not None def test_acquerir_verrou_refuse_une_seconde_instance(): systeme = choisir_systeme() chemin = _tmp_verrou() premier = acquerir_verrou(systeme, chemin) assert premier is not None assert acquerir_verrou(systeme, chemin) is None def test_acquerir_verrou_sans_chemin_utilise_le_dossier_de_donnees_du_systeme(): # Pas de deuxième prise ici (on toucherait le verrou réel de l'utilisateur) : # on vérifie seulement que le chemin par défaut est bien dérivé du système. class _SystemeSonde: def __init__(self): self.chemin_demande = None def dossier_donnees(self): return "/tmp/zonza-sonde" def acquerir_verrou_instance(self, chemin): self.chemin_demande = chemin return "handle-factice" sonde = _SystemeSonde() resultat = acquerir_verrou(sonde) assert resultat == "handle-factice" assert sonde.chemin_demande == "/tmp/zonza-sonde/instance.lock"