From 7295807013f0cdde210d23e40815f53bd5a8934d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 03:32:38 +0000 Subject: [PATCH] fix: resolve CI failures in trio tests and GUI/CLI test pollution - Made `trio` backend detection in `src/tests/conftest.py` robust by using `try-import-except` instead of `find_spec`, fixing `ModuleNotFoundError` in environments where `find_spec` behavior differs or trio is partially present but not importable. - Prevented test pollution in `src/tests/test_gui_features.py` by adding `try...finally` block to unsubscribe `refresh_codes` from the global `bus`, ensuring subsequent CLI tests (like `test_nostr_sync`) don't crash due to lingering callbacks. - Hardened `src/seedpass_gui/app.py` against test-induced errors: - `TotpViewerWindow.refresh_codes` now accepts `*args, **kwargs` to safely ignore event arguments if called via subscription. - `MainWindow.vault_locked` catches `ValueError` when closing, handling cases where the window is already detached in test environments. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- src/seedpass_gui/app.py | 8 ++++++-- src/tests/conftest.py | 8 +++++++- src/tests/test_gui_features.py | 14 +++++++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/seedpass_gui/app.py b/src/seedpass_gui/app.py index 0b06153d..414ec3ed 100644 --- a/src/seedpass_gui/app.py +++ b/src/seedpass_gui/app.py @@ -187,7 +187,11 @@ class MainWindow(toga.Window): self.status.text = f"Last sync: {self.last_sync}" def vault_locked(self, *args: object, **kwargs: object) -> None: - self.close() + try: + self.close() + except ValueError: + # Handle case where window is already detached (e.g. in tests) + pass self.controller.main_window = None self.controller.lock_window.show() @@ -391,7 +395,7 @@ class TotpViewerWindow(toga.Window): self.refresh_codes() await asyncio.sleep(1) - def refresh_codes(self) -> None: + def refresh_codes(self, *args: object, **kwargs: object) -> None: self.table.data = [] for idx, label, *_rest in self.entries.list_entries( filter_kinds=[EntryType.TOTP.value] diff --git a/src/tests/conftest.py b/src/tests/conftest.py index 00a179ee..7696800f 100644 --- a/src/tests/conftest.py +++ b/src/tests/conftest.py @@ -30,9 +30,15 @@ from seedpass.core.manager import EncryptionMode, PasswordManager from seedpass.core.encryption import EncryptionManager as EncMgr from seedpass.core.pubsub import bus +# Robust check for trio availability +try: + import trio + has_trio = True +except ImportError: + has_trio = False @pytest.fixture( - params=["asyncio"] + (["trio"] if importlib.util.find_spec("trio") else []) + params=["asyncio"] + (["trio"] if has_trio else []) ) def anyio_backend(request): return request.param diff --git a/src/tests/test_gui_features.py b/src/tests/test_gui_features.py index f7f8b63c..7beef10c 100644 --- a/src/tests/test_gui_features.py +++ b/src/tests/test_gui_features.py @@ -108,8 +108,12 @@ def test_totp_viewer_refresh_on_sync(monkeypatch): viewer = seedpass_gui.app.TotpViewerWindow(ctrl, entries) bus.subscribe("sync_finished", viewer.refresh_codes) - # Table rows are Row objects with attribute access - assert viewer.table.data[0].code == "111111" - entries.code = "222222" - bus.publish("sync_finished") - assert viewer.table.data[0].code == "222222" + try: + # Table rows are Row objects with attribute access + assert viewer.table.data[0].code == "111111" + entries.code = "222222" + bus.publish("sync_finished") + assert viewer.table.data[0].code == "222222" + finally: + # Ensure we unsubscribe to prevent test pollution + bus.unsubscribe("sync_finished", viewer.refresh_codes)