Files
eco/tests/test_qt_lifecycle.py
2026-08-21 15:10:25 +02:00

86 lines
2.0 KiB
Python

import pytest
pytest.importorskip("qtpy")
from qtpy import QtCore, QtWidgets
from eco.widgets.qt_lifecycle import close_calls_stop
@pytest.fixture(scope="module")
def qapp():
return QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
def _run_event_loop(app, ms=150):
QtCore.QTimer.singleShot(ms, app.quit)
app.exec_()
def test_close_calls_stop_sets_delete_on_close(qapp):
w = QtWidgets.QWidget()
close_calls_stop(w, lambda: None)
assert w.testAttribute(QtCore.Qt.WA_DeleteOnClose) is True
def test_close_calls_stop_runs_stop_fn_on_native_close(qapp):
w = QtWidgets.QWidget()
calls = []
close_calls_stop(w, lambda: calls.append(True))
w.show()
w.close()
assert calls == [True]
def test_close_calls_stop_is_idempotent_when_stop_fn_recloses_the_window(qapp):
"""The established convention in this codebase: .stop() itself calls
window.close(). Without a reentrancy guard, that would recurse back
into this same closeEvent."""
w = QtWidgets.QWidget()
calls = []
def stop_fn():
calls.append(True)
w.close()
close_calls_stop(w, stop_fn)
w.show()
w.close()
assert calls == [True]
def test_close_calls_stop_preserves_existing_closeevent_override(qapp):
seen = []
class W(QtWidgets.QWidget):
def closeEvent(self, event):
seen.append("class")
super().closeEvent(event)
w = W()
close_calls_stop(w, lambda: seen.append("stop_fn"))
w.show()
w.close()
assert seen == ["stop_fn", "class"]
def test_close_calls_stop_does_not_crash_when_stop_fn_raises(qapp):
w = QtWidgets.QWidget()
def boom():
raise RuntimeError("nope")
close_calls_stop(w, boom)
w.show()
w.close() # must not raise
def test_destroyed_fires_after_close_with_a_real_event_loop(qapp):
w = QtWidgets.QWidget()
close_calls_stop(w, lambda: None)
destroyed = []
w.destroyed.connect(lambda *a: destroyed.append(True))
w.show()
w.close()
_run_event_loop(qapp)
assert destroyed == [True]