screen-locker/screen_locker/tests/_opt_in_fixtures.py
Krzysztof kuhy Rudnicki c1c73d43ba
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
Tests / test (3.10) (push) Has been cancelled
Tests / test (3.11) (push) Has been cancelled
Tests / test (3.12) (push) Has been cancelled
Tests / lock-popup-safety (push) Has been cancelled
release-apk / release (APK) (push) Has been cancelled
Stop the relaxed-day popup from re-firing every 30 minutes after Skip
workout-locker.timer (added in e5db254) re-runs the full lock-decision
chain every 30 minutes, but is_relaxed_day() is a pure date check with
no memory of an earlier same-day dismissal. Clicking "Skip — No
Penalty" only closed the window without persisting anything, so the
next tick re-derived reason=relaxed_day and rebuilt the same popup.

Now the skip button writes a relaxed_day_skip marker to the log
(excluded from weekly counting and sync, same treatment as heat_skip),
and the startup chain checks for it before re-entering the relaxed-day
branch. Also renames workout_log.json to log.json throughout the repo,
tests, docs, and Dart comments, since the fix touches that file anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qH2hJ6mvCJd3ZXpAJSaF7
2026-08-18 21:55:59 +02:00

65 lines
2.0 KiB
Python

"""Opt-in (non-autouse) fixtures for the screen_locker tests.
Split out of ``conftest.py`` to keep every file under the 250-line cap. These
are re-imported there, which is what keeps pytest discovering them by name --
a fixture is only visible to tests if it is reachable from ``conftest.py``.
Only fixtures a test must *request* live here. Every ``autouse`` fixture stays
in ``conftest.py``: pytest applies autouse fixtures from conftest only, so one
moved here would silently stop running and take its safety guard with it.
"""
from __future__ import annotations
from contextlib import ExitStack
from typing import TYPE_CHECKING
from unittest.mock import MagicMock, patch
import pytest
from screen_locker.tests._tk_mocks import _TK_MODULES, _make_mock_tk
if TYPE_CHECKING:
from collections.abc import Generator
from pathlib import Path
@pytest.fixture
def mock_tk() -> Generator[MagicMock]:
"""Mock the ``tkinter`` module across every UI module for display-free tests.
Patches the same single mock into all ``_TK_MODULES`` so assertions on
``mock_tk.Button`` capture widgets created by any of the split UI mixins
(``_ui_widgets``, ``_sick_dialog``, ...), not just ``screen_lock``.
"""
mock = _make_mock_tk()
with ExitStack() as stack:
for module in _TK_MODULES:
stack.enter_context(patch(f"{module}.tk", mock))
stack.enter_context(
patch(
"screen_locker.screen_lock.GateRoot",
return_value=mock.Tk.return_value,
)
)
yield mock
@pytest.fixture
def mock_sys_exit() -> Generator[MagicMock]:
"""Mock sys.exit to prevent test termination."""
with patch("screen_locker.screen_lock.sys.exit") as mock:
yield mock
@pytest.fixture
def _mock_sys_exit(mock_sys_exit: MagicMock) -> MagicMock:
"""Alias for mock_sys_exit when the return value is unused."""
return mock_sys_exit
@pytest.fixture
def temp_log_file(tmp_path: Path) -> Path:
"""Create a temporary log file path."""
return tmp_path / "log.json"