mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 13:03:13 +02:00
Move every multi-line python heredoc/`-c` block into a dedicated .py file so ruff, mypy, pylint, bandit, and pytest can apply to it: - linux_configuration/zsh/calc-live.zsh → python_pkg/live_calc/calc_eval.py (100% branch cov, 46 tests) - meta/scripts/check_ai_evidence.sh → meta/scripts/validate_evidence.py - meta/scripts/check_agent_contract.sh → meta/scripts/validate_contract.py - phone_focus_mode/lib/monitor.sh → phone_focus_mode/lib/monitor_report.py - phone_focus_mode/deploy.sh → phone_focus_mode/strip_workout_hosts.py - linux_configuration/.../analyze_repo.sh → fast_count.py Also: add zsh-syntax pre-commit hook (zsh -n); exclude zsh from shellcheck; add tests for all 4 non-python_pkg helpers; update CLAUDE.md Shell Style with the no-inline-Python rule. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
157 lines
5.3 KiB
Python
157 lines
5.3 KiB
Python
"""Tests for phone_focus_mode/lib/monitor_report.py (report summary/severity)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import TYPE_CHECKING
|
|
|
|
import monitor_report
|
|
from monitor_report import _field, _has_severe, _load_checks, _render_summary, main
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
def _write(tmp_path: Path, obj: object) -> Path:
|
|
"""Write ``obj`` as JSON to a temp file and return its path."""
|
|
path = tmp_path / "report.json"
|
|
path.write_text(json.dumps(obj), encoding="utf-8")
|
|
return path
|
|
|
|
|
|
class TestLoadChecks:
|
|
"""``_load_checks`` tolerates malformed reports."""
|
|
|
|
def test_reads_checks(self, tmp_path: Path) -> None:
|
|
"""A well-formed report yields its checks list."""
|
|
path = _write(tmp_path, {"checks": [{"status": "ok"}]})
|
|
assert _load_checks(path) == [{"status": "ok"}]
|
|
|
|
def test_non_dict_report_yields_empty(self, tmp_path: Path) -> None:
|
|
"""A non-object report yields no checks."""
|
|
assert _load_checks(_write(tmp_path, [1, 2])) == []
|
|
|
|
def test_non_list_checks_yields_empty(self, tmp_path: Path) -> None:
|
|
"""A non-list ``checks`` value yields no checks."""
|
|
assert _load_checks(_write(tmp_path, {"checks": "nope"})) == []
|
|
|
|
|
|
class TestField:
|
|
"""``_field`` reads string fields with a default."""
|
|
|
|
def test_reads_present_string(self) -> None:
|
|
"""A present string field is returned."""
|
|
assert _field({"status": "ok"}, "status", "warn") == "ok"
|
|
|
|
def test_default_when_missing(self) -> None:
|
|
"""A missing field falls back to the default."""
|
|
assert _field({}, "status", "warn") == "warn"
|
|
|
|
def test_default_when_not_string(self) -> None:
|
|
"""A non-string field falls back to the default."""
|
|
assert _field({"status": 5}, "status", "warn") == "warn"
|
|
|
|
def test_default_when_check_not_dict(self) -> None:
|
|
"""A non-dict check falls back to the default."""
|
|
assert _field("nope", "status", "warn") == "warn"
|
|
|
|
|
|
class TestRenderSummary:
|
|
"""``_render_summary`` produces the counts header and issue list."""
|
|
|
|
def test_counts_and_issues(self) -> None:
|
|
"""Counts and a per-issue line are rendered."""
|
|
checks: list[object] = [
|
|
{"status": "ok", "check": "a", "message": ""},
|
|
{"status": "warn", "check": "b", "message": "drift"},
|
|
{"status": "error", "check": "c", "message": "boom"},
|
|
]
|
|
out = _render_summary(checks)
|
|
assert "ok=1" in out
|
|
assert "warn=1" in out
|
|
assert "error=1" in out
|
|
assert "[warn] b: drift" in out
|
|
assert "[error] c: boom" in out
|
|
|
|
def test_no_issues_section_when_all_ok(self) -> None:
|
|
"""With no problems, the issues section is omitted."""
|
|
out = _render_summary([{"status": "ok", "check": "a", "message": ""}])
|
|
assert "Issues found:" not in out
|
|
# Footer line plus a trailing blank line, matching the original output.
|
|
assert out.endswith("==========================\n\n")
|
|
|
|
|
|
class TestHasSevere:
|
|
"""``_has_severe`` flags fatal/error checks."""
|
|
|
|
def test_true_for_error(self) -> None:
|
|
"""An error status is severe."""
|
|
assert _has_severe([{"status": "error"}]) is True
|
|
|
|
def test_true_for_fatal(self) -> None:
|
|
"""A fatal status is severe."""
|
|
assert _has_severe([{"status": "fatal"}]) is True
|
|
|
|
def test_false_for_ok_warn(self) -> None:
|
|
"""ok/warn statuses are not severe."""
|
|
assert _has_severe([{"status": "ok"}, {"status": "warn"}]) is False
|
|
|
|
|
|
class TestMain:
|
|
"""The CLI dispatches on mode and reports severity via exit code."""
|
|
|
|
def test_bad_usage_returns_2(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""An unknown mode is a usage error (rc 2)."""
|
|
monkeypatch.setattr(
|
|
monitor_report.sys, "argv", ["monitor_report", "bogus", "x"]
|
|
)
|
|
assert main() == 2
|
|
|
|
def test_summary_prints_and_returns_0(
|
|
self,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
capsys: pytest.CaptureFixture[str],
|
|
) -> None:
|
|
"""Summary mode prints the report and returns 0."""
|
|
path = _write(
|
|
tmp_path, {"checks": [{"status": "warn", "check": "b", "message": "m"}]}
|
|
)
|
|
monkeypatch.setattr(
|
|
monitor_report.sys,
|
|
"argv",
|
|
["monitor_report", "summary", str(path)],
|
|
)
|
|
assert main() == 0
|
|
assert "Monitoring Summary" in capsys.readouterr().out
|
|
|
|
def test_severity_returns_1_on_error(
|
|
self,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Severity mode returns 1 when a severe check exists."""
|
|
path = _write(tmp_path, {"checks": [{"status": "error"}]})
|
|
monkeypatch.setattr(
|
|
monitor_report.sys,
|
|
"argv",
|
|
["monitor_report", "severity", str(path)],
|
|
)
|
|
assert main() == 1
|
|
|
|
def test_severity_returns_0_when_clean(
|
|
self,
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Severity mode returns 0 when no severe check exists."""
|
|
path = _write(tmp_path, {"checks": [{"status": "ok"}]})
|
|
monkeypatch.setattr(
|
|
monitor_report.sys,
|
|
"argv",
|
|
["monitor_report", "severity", str(path)],
|
|
)
|
|
assert main() == 0
|