Clear every read-only marker when the store becomes writable again

"Erneut prüfen" refreshed the banner but left the window title and the status bar
reading "NUR LESEN" -- both were built once and never updated -- while the banner
itself asked for a restart that the recheck exists to avoid.

Title, status bar and banner are refreshed from one place now, so none of them can
be left behind, and the main window owns the title instead of app.py setting it
once at startup. The banner points at "Erneut prüfen" and says outright that no
restart is needed. Since the startup pass was skipped, its task list is empty
rather than current, so a successful recheck offers the housekeeper run that
fills it.

UI tests cover both directions of the recheck; their Tk root moved into a shared
conftest fixture, because a second root in another module invalidates the icon
images bound to the first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Marcel Peterkau
2026-08-29 00:01:37 +02:00
co-authored by Claude Opus 5
parent ae53c168fd
commit 528c24ad42
6 changed files with 164 additions and 43 deletions
+1 -17
View File
@@ -3,7 +3,7 @@ from email.policy import default
import pytest
tk = pytest.importorskip("tkinter")
pytest.importorskip("tkinter")
from ccma.config import AppConfig # noqa: E402
from ccma.domain.mail_templates import placeholder_entries # noqa: E402
@@ -11,22 +11,6 @@ from ccma.services.welcome_mail import generate_and_send_welcome_mail # noqa: E
from ccma.storage.repository import MemberRepository, RepositoryError # noqa: E402
# One root for the whole session: the icon library binds its images to the first
# Tk instance, so tearing a root down between tests would invalidate them.
@pytest.fixture(scope="session")
def tk_root():
from ccma.ui.theme import load_theme
try:
root = tk.Tk()
except tk.TclError as exc: # headless CI has no display to build widgets on
pytest.skip(f"kein Display verfügbar: {exc}")
root.withdraw()
load_theme(root, "dark")
yield root
root.destroy()
@pytest.fixture
def repository(tmp_path):
repository = MemberRepository(tmp_path / "store")