mirror of
https://github.com/kuhyx/testsAndMisc-archive.git
synced 2026-07-04 20:23:14 +02:00
Fix ruff violations in ~15 source files and ~60+ test files to minimize per-file-ignores in pyproject.toml. Remaining ignores are justified with comments explaining why each suppression is necessary. Source fixes: FBT003 (keyword args), S310 (URL validation), SLF001 (private access), T201 (print→logging), C901 (complexity), E501 (line length), E402 (import order). Test fixes: SIM117 (combined with), FBT (boolean args), PERF203 (try in loop), S310/S607 (URLs/executables), E402/E501 (imports/lines), S108 (tmp paths), PLR0913 (too many args), ARG (unused args), ANN (type annotations), RUF059 (unused unpacked vars), PT019 (fixture naming). Remaining per-file-ignores (with justifications): - Tests: ARG, D, PLC0415, PLR2004, S101, SLF001 - music_gen sources: PLC0415 (heavy ML lazy imports) - moviepy_showcase: PLC0415 (circular dependency) - generate_images: PLR0913 (matplotlib helpers need many params) - praca_magisterska_video: E501, E402 (long paths, mpl.use)
233 lines
8.3 KiB
Python
233 lines
8.3 KiB
Python
"""Tests for brightness_controller module - part 2 (poll + main)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from python_pkg.brightness_controller import brightness_controller
|
|
|
|
MOD = "python_pkg.brightness_controller.brightness_controller"
|
|
|
|
|
|
def _make_controller(
|
|
devices: list[brightness_controller.Device] | None = None,
|
|
als_path: Path | None = None,
|
|
*,
|
|
daemon_state: bool = False,
|
|
) -> brightness_controller.BrightnessController:
|
|
"""Create a BrightnessController with all Tk operations mocked."""
|
|
if devices is None:
|
|
devices = [
|
|
brightness_controller.Device(
|
|
"intel_backlight", "backlight", 50, "50%", 120000
|
|
)
|
|
]
|
|
|
|
with (
|
|
patch(f"{MOD}._get_devices", return_value=devices),
|
|
patch(f"{MOD}._find_als_device", return_value=als_path),
|
|
patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=daemon_state,
|
|
),
|
|
patch(f"{MOD}.tk.Tk") as mock_tk,
|
|
patch(f"{MOD}.tk.StringVar") as mock_str_var,
|
|
patch(f"{MOD}.tk.IntVar") as mock_int_var,
|
|
patch(f"{MOD}.ttk"),
|
|
patch(f"{MOD}._get_brightness", return_value=50),
|
|
):
|
|
mock_root = MagicMock()
|
|
mock_tk.return_value = mock_root
|
|
mock_root.after = MagicMock()
|
|
mock_str_var.return_value = MagicMock()
|
|
mock_int_var.return_value = MagicMock()
|
|
|
|
return brightness_controller.BrightnessController()
|
|
|
|
|
|
# ── _sync_auto_ui ────────────────────────────────────────────────────
|
|
|
|
|
|
class TestSyncAutoUi:
|
|
"""Tests for _sync_auto_ui."""
|
|
|
|
def test_no_als_returns_early(self) -> None:
|
|
ctrl = _make_controller(als_path=None)
|
|
ctrl.als_path = None
|
|
ctrl.auto_btn_var = MagicMock()
|
|
ctrl.slider = MagicMock()
|
|
ctrl._sync_auto_ui()
|
|
ctrl.auto_btn_var.set.assert_not_called()
|
|
|
|
def test_auto_on(self) -> None:
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.auto_mode = True
|
|
ctrl.auto_btn_var = MagicMock()
|
|
ctrl.slider = MagicMock()
|
|
ctrl._sync_auto_ui()
|
|
ctrl.auto_btn_var.set.assert_called_once()
|
|
assert "ON" in ctrl.auto_btn_var.set.call_args[0][0]
|
|
ctrl.slider.state.assert_called_once_with(["disabled"])
|
|
|
|
def test_auto_off(self) -> None:
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.auto_mode = False
|
|
ctrl.auto_btn_var = MagicMock()
|
|
ctrl.slider = MagicMock()
|
|
ctrl._sync_auto_ui()
|
|
ctrl.auto_btn_var.set.assert_called_once()
|
|
assert "OFF" in ctrl.auto_btn_var.set.call_args[0][0]
|
|
ctrl.slider.state.assert_called_once_with(["!disabled"])
|
|
|
|
|
|
# ── _poll_als ────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestPollAls:
|
|
"""Tests for _poll_als."""
|
|
|
|
@patch(f"{MOD}._read_lux", return_value=42.5)
|
|
def test_updates_lux_display(self, mock_lux: MagicMock) -> None:
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.lux_var = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
with patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=False,
|
|
):
|
|
ctrl._poll_als()
|
|
assert "42.5 lux" in ctrl.lux_var.set.call_args[0][0]
|
|
ctrl.root.after.assert_called_once()
|
|
|
|
@patch(f"{MOD}._read_lux", side_effect=OSError("sensor fail"))
|
|
def test_sensor_error(self, mock_lux: MagicMock) -> None:
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.lux_var = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
with patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=False,
|
|
):
|
|
ctrl._poll_als()
|
|
ctrl.lux_var.set.assert_called_with("sensor error")
|
|
|
|
@patch(f"{MOD}._read_lux", side_effect=ValueError("bad value"))
|
|
def test_sensor_value_error(self, mock_lux: MagicMock) -> None:
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.lux_var = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
with patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=False,
|
|
):
|
|
ctrl._poll_als()
|
|
ctrl.lux_var.set.assert_called_with("sensor error")
|
|
|
|
@patch(f"{MOD}._read_lux", return_value=10.0)
|
|
def test_syncs_daemon_state_change(self, mock_lux: MagicMock) -> None:
|
|
"""When daemon state differs from auto_mode, syncs it."""
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.auto_mode = False
|
|
ctrl.lux_var = MagicMock()
|
|
ctrl.auto_btn_var = MagicMock()
|
|
ctrl.slider = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
with patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=True,
|
|
):
|
|
ctrl._poll_als()
|
|
assert ctrl.auto_mode is True
|
|
|
|
@patch(f"{MOD}._read_lux", return_value=10.0)
|
|
def test_no_sync_when_same(self, mock_lux: MagicMock) -> None:
|
|
"""When daemon state matches auto_mode, no sync needed."""
|
|
ctrl = _make_controller(als_path=Path("/fake"))
|
|
ctrl.auto_mode = False
|
|
ctrl.lux_var = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
with patch.object(
|
|
brightness_controller.BrightnessController,
|
|
"_read_daemon_state",
|
|
return_value=False,
|
|
):
|
|
ctrl._poll_als()
|
|
# No assertion on auto_btn_var since auto_mode didn't change
|
|
|
|
def test_no_als_path(self) -> None:
|
|
ctrl = _make_controller(als_path=None)
|
|
ctrl.als_path = None
|
|
ctrl.root = MagicMock()
|
|
ctrl._poll_als()
|
|
ctrl.root.after.assert_called_once()
|
|
|
|
|
|
# ── _poll_brightness ─────────────────────────────────────────────────
|
|
|
|
|
|
class TestPollBrightness:
|
|
"""Tests for _poll_brightness."""
|
|
|
|
@patch(f"{MOD}._get_brightness", return_value=60)
|
|
def test_refreshes_when_not_auto(self, mock_get: MagicMock) -> None:
|
|
ctrl = _make_controller()
|
|
ctrl.auto_mode = False
|
|
ctrl.pct_var = MagicMock()
|
|
ctrl.slider_var = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
ctrl._poll_brightness()
|
|
ctrl.pct_var.set.assert_called_with("60%")
|
|
ctrl.root.after.assert_called_once()
|
|
|
|
def test_skips_refresh_when_auto(self) -> None:
|
|
ctrl = _make_controller()
|
|
ctrl.auto_mode = True
|
|
ctrl._refresh_brightness = MagicMock()
|
|
ctrl.root = MagicMock()
|
|
ctrl._poll_brightness()
|
|
ctrl._refresh_brightness.assert_not_called()
|
|
ctrl.root.after.assert_called_once()
|
|
|
|
|
|
# ── run ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestRun:
|
|
"""Tests for run method."""
|
|
|
|
def test_calls_mainloop(self) -> None:
|
|
ctrl = _make_controller()
|
|
ctrl.root = MagicMock()
|
|
ctrl.run()
|
|
ctrl.root.mainloop.assert_called_once()
|
|
|
|
|
|
# ── main ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TestMain:
|
|
"""Tests for main() entry point."""
|
|
|
|
@patch(f"{MOD}.subprocess.run")
|
|
def test_brightnessctl_not_found(self, mock_run: MagicMock) -> None:
|
|
mock_run.side_effect = FileNotFoundError
|
|
with pytest.raises(SystemExit, match="1"):
|
|
brightness_controller.main()
|
|
|
|
@patch(f"{MOD}.BrightnessController")
|
|
@patch(f"{MOD}.subprocess.run")
|
|
def test_success(self, mock_run: MagicMock, mock_ctrl_cls: MagicMock) -> None:
|
|
mock_run.return_value = MagicMock()
|
|
mock_app = MagicMock()
|
|
mock_ctrl_cls.return_value = mock_app
|
|
brightness_controller.main()
|
|
mock_app.run.assert_called_once()
|