"""Tests for DebugLogger (backend/managers/debug_logger.py).""" import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).parent.parent)) from backend.managers._debug_logger import DebugLogger # ── Fixtures ────────────────────────────────────────────────────────────────── @pytest.fixture def logger(): """Return a fresh DebugLogger for each test.""" return DebugLogger() # ── log() ───────────────────────────────────────────────────────────────────── class TestLog: """Tests for log(): each call appends an INFO-level entry with message.""" def test_log_appends_entry(self, logger): logger.log("started") assert len(logger.logs) == 1 def test_log_sets_level_info(self, logger): logger.log("started") assert logger.logs[0]["level"] == "INFO" def test_log_stores_message(self, logger): logger.log("executing file.py") assert logger.logs[0]["message"] == "executing file.py" # ── log_error() ─────────────────────────────────────────────────────────────── class TestLogError: """Tests for log_error(): level is ERROR, not INFO.""" def test_log_error_sets_level_error(self, logger): logger.log_error("something broke") assert logger.logs[0]["level"] == "ERROR" def test_log_and_log_error_are_distinct_levels(self, logger): logger.log("info message") logger.log_error("error message") assert logger.logs[0]["level"] == "INFO" assert logger.logs[1]["level"] == "ERROR" # ── get_logs() ──────────────────────────────────────────────────────────────── class TestGetLogs: """Tests for get_logs().""" def test_get_logs_returns_all_entries(self, logger): logger.log("first") logger.log_error("second") assert len(logger.get_logs()) == 2 # ── clear() ─────────────────────────────────────────────────────────────────── class TestClear: """Tests for clear().""" def test_clear_removes_all_entries(self, logger): logger.log("first") logger.log_error("second") logger.clear() assert logger.logs == [] # ── format_debug_output() ───────────────────────────────────────────────────── class TestFormatDebugOutput: """Tests for format_debug_output(): renders rc, stdout, stderr, and log entries.""" def test_success_exit_code_shows_success(self, logger): result = logger.format_debug_output({"rc": 0, "stdout": "", "stderr": ""}) assert "[SUCCESS]" in result def test_nonzero_exit_code_shows_failed(self, logger): result = logger.format_debug_output({"rc": 1, "stdout": "", "stderr": ""}) assert "[FAILED]" in result def test_stdout_included_when_present(self, logger): result = logger.format_debug_output({"rc": 0, "stdout": "Hello", "stderr": ""}) assert "Hello" in result assert "stdout" in result def test_stderr_included_when_present(self, logger): result = logger.format_debug_output({"rc": 1, "stdout": "", "stderr": "NameError"}) assert "NameError" in result assert "stderr" in result def test_log_entries_appended_to_output(self, logger): logger.log("Executing file.py...") logger.log_error("exit code 1") result = logger.format_debug_output({"rc": 1, "stdout": "", "stderr": ""}) assert "Executing file.py..." in result assert "exit code 1" in result def test_missing_keys_do_not_raise(self, logger): # Defensive: format_debug_output uses .get() so missing keys are safe result = logger.format_debug_output({}) assert isinstance(result, str)