mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-11-10 21:27:13 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (flutter, flutter-analyze, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint,flutter-analyze) (push) Waiting to run
Tests / test (push) Waiting to run
Tests / lock-popup-safety (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (0) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (1) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (2) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (3) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (4) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (5) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (6) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (7) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (8) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (9) (push) Waiting to run
Tests / flutter-coverage (push) Blocked by required conditions
Tests / web-coverage (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
A 5+ workout week no longer banks (count - 4)h, and the every-4-week streak milestone +1h is gone. The streak counter and the 09:00 early-bird extension stay. The applying path is untouched, so 2026-W41's already-banked 2h keeps applying through Sunday 2026-10-11; old weekly_shutdown_bonus_hours keys load and are preserved as-is. The next-week status preview no longer promises bonus hours. Claude-Session: https://claude.ai/code/session_01WfVGhY8XcsQsC7qz9UU8xb Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
131 lines
4.7 KiB
Python
131 lines
4.7 KiB
Python
"""Tests for the read-only status snapshot layer in _status_data.py."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
import json
|
|
from typing import TYPE_CHECKING
|
|
from unittest.mock import patch
|
|
|
|
from screen_locker._status_data import format_summary_line, gather_status
|
|
from screen_locker.tests.test_status_data import _files
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
# Fixed reference instant: Friday 2024-01-05, 12:00 UTC == 13:00 Europe/Warsaw.
|
|
# Outside the 05:00-09:00 early-bird window and not a Tue/Wed/Thu relaxed day,
|
|
# so lock-decision branches are fully deterministic regardless of wall clock.
|
|
_FRIDAY_NOON_UTC = datetime(2024, 1, 5, 12, 0, tzinfo=UTC)
|
|
# Monday of that same ISO week, for Mon-Wed shutdown-band assertions.
|
|
_MONDAY_NOON_UTC = datetime(2024, 1, 1, 12, 0, tzinfo=UTC)
|
|
|
|
|
|
class TestFormatSummaryLine:
|
|
"""format_summary_line variants."""
|
|
|
|
def test_checkmark_when_week_complete(self, tmp_path: Path) -> None:
|
|
"""Checkmark when week complete."""
|
|
files = _files(tmp_path)
|
|
files["log_file"].write_text(
|
|
json.dumps(
|
|
{
|
|
d: {"workout_data": {"type": "phone_verified"}}
|
|
for d in (
|
|
"2024-01-01",
|
|
"2024-01-02",
|
|
"2024-01-03",
|
|
"2024-01-04",
|
|
"2024-01-05",
|
|
)
|
|
}
|
|
)
|
|
)
|
|
with patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
):
|
|
snap = gather_status(**files, now=_FRIDAY_NOON_UTC)
|
|
|
|
assert format_summary_line(snap).startswith("✓")
|
|
|
|
def test_ellipsis_when_week_incomplete(self, tmp_path: Path) -> None:
|
|
"""Ellipsis when week incomplete."""
|
|
files = _files(tmp_path)
|
|
with patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
):
|
|
snap = gather_status(**files, now=_FRIDAY_NOON_UTC)
|
|
|
|
assert format_summary_line(snap).startswith("…")
|
|
|
|
def test_question_mark_when_no_shutdown_config(self, tmp_path: Path) -> None:
|
|
"""Question mark when no shutdown config."""
|
|
files = _files(tmp_path)
|
|
with patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
):
|
|
snap = gather_status(**files, now=_FRIDAY_NOON_UTC)
|
|
|
|
assert "?:00 tonight" not in format_summary_line(snap)
|
|
assert "? tonight" in format_summary_line(snap)
|
|
|
|
def test_mon_wed_band_used_on_monday(self, tmp_path: Path) -> None:
|
|
"""Mon wed band used on monday."""
|
|
files = _files(tmp_path)
|
|
files["shutdown_config_file"].write_text(
|
|
"MON_WED_MINUTES=1200\nTHU_SUN_MINUTES=1380\nMORNING_END_MINUTES=300\n"
|
|
)
|
|
with patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
):
|
|
snap = gather_status(**files, now=_MONDAY_NOON_UTC)
|
|
|
|
assert "20:00 tonight" in format_summary_line(snap)
|
|
|
|
def test_thu_sun_band_used_on_friday(self, tmp_path: Path) -> None:
|
|
"""Thu sun band used on friday."""
|
|
files = _files(tmp_path)
|
|
files["shutdown_config_file"].write_text(
|
|
"MON_WED_MINUTES=1200\nTHU_SUN_MINUTES=1380\nMORNING_END_MINUTES=300\n"
|
|
)
|
|
with patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
):
|
|
snap = gather_status(**files, now=_FRIDAY_NOON_UTC)
|
|
|
|
assert "23:00 tonight" in format_summary_line(snap)
|
|
|
|
|
|
class TestNextWeekPreviewHasNoWeeklyBonus:
|
|
"""A 5+ workout week no longer promises next week a later shutdown."""
|
|
|
|
def test_five_workouts_and_a_streak_preview_the_plain_base(
|
|
self, tmp_path: Path
|
|
) -> None:
|
|
"""5 workouts + streak 3 (old rule: +2h next week) -> next week is base."""
|
|
files = _files(tmp_path)
|
|
files["log_file"].write_text(
|
|
json.dumps(
|
|
{
|
|
f"2024-01-0{day}": {"workout_data": {"type": "phone_verified"}}
|
|
for day in range(1, 6)
|
|
}
|
|
)
|
|
)
|
|
files["extra_benefits_file"].write_text(
|
|
json.dumps({"consecutive_5plus_weeks": 3})
|
|
)
|
|
with (
|
|
patch(
|
|
"screen_locker._status_data.has_workout_skip_today", return_value=False
|
|
),
|
|
patch(
|
|
"screen_locker._compliance_predicates.verify_entry_hmac",
|
|
return_value=True,
|
|
),
|
|
):
|
|
snap = gather_status(**files, now=_FRIDAY_NOON_UTC)
|
|
|
|
assert snap.week.counted_count == 5
|
|
assert [d.minutes for d in snap.shutdown.next_week_preview] == [20 * 60] * 7
|