Files
grm/tests/unit/test_report.py
T
Emil Simeonov 815b59c537 GRM-12: feat: add translated operation report for success and failure cases
- Create StepTracker context manager in new report.py module
- Track each step of lifecycle operations (install, update, start, stop, enable,
  disable, status, remove) with begin/done markers
- On success: report lists all completed steps with ✓ icons
- On failure: report shows failed step (✗), completed steps before failure (✓),
  and pending steps that never started (○)
- Add translations for report header, status labels, and registry step names
  in all 5 supported languages (EN/BG/DE/RU/ZH)
- 105 tests, 100% coverage, pyright clean, ruff clean
2026-06-19 01:16:39 +02:00

103 lines
3.3 KiB
Python

"""Unit tests for the operation report tracker."""
from __future__ import annotations
import pytest
from gitea_runner_manager.exceptions import AnsibleError
from gitea_runner_manager.report import Step, StepTracker, track_steps
class TestStep:
def test_init(self) -> None:
step = Step("test")
assert step.name == "test"
assert step.status == "pending"
class TestStepTracker:
def test_begin(self) -> None:
tracker = StepTracker()
tracker.begin("step1")
assert len(tracker.steps) == 1
assert tracker.steps[0].name == "step1"
assert tracker.steps[0].status == "in_progress"
def test_done(self) -> None:
tracker = StepTracker()
tracker.begin("step1")
tracker.done()
assert tracker.steps[0].status == "completed"
def test_done_no_steps(self) -> None:
tracker = StepTracker()
tracker.done() # should not raise
assert tracker.steps == []
def test_done_last_not_in_progress(self) -> None:
tracker = StepTracker()
tracker.begin("step1")
tracker.done()
tracker.done() # second done is a no-op
assert tracker.steps[0].status == "completed"
class TestTrackSteps:
def test_success(self, capsys: pytest.CaptureFixture[str]) -> None:
with track_steps() as tracker:
tracker.begin("step1")
tracker.done()
tracker.begin("step2")
tracker.done()
captured = capsys.readouterr()
assert "Operation Report" in captured.out
assert "step1" in captured.out
assert "step2" in captured.out
assert "✓" in captured.out
assert "completed" in captured.out
def test_failure_marks_step(self, capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(AnsibleError, match="fail"):
with track_steps() as tracker:
tracker.begin("step1")
tracker.done()
tracker.begin("step2")
raise AnsibleError("fail")
captured = capsys.readouterr()
assert "Operation Report" in captured.out
assert "step1" in captured.out
assert "step2" in captured.out
assert "✓" in captured.out
assert "✗" in captured.out
assert "completed" in captured.out
assert "failed" in captured.out
def test_pending_shown_on_failure(self, capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(AnsibleError, match="fail"):
with track_steps() as tracker:
tracker.begin("step1")
raise AnsibleError("fail")
captured = capsys.readouterr()
assert "✗" in captured.out
assert "failed" in captured.out
def test_empty_report(self, capsys: pytest.CaptureFixture[str]) -> None:
with track_steps():
pass
captured = capsys.readouterr()
assert "Operation Report" in captured.out
def test_translated_report(self, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
monkeypatch.setenv("GRM_LANG", "bg")
with track_steps() as tracker:
tracker.begin("step1")
tracker.done()
captured = capsys.readouterr()
assert "Отчет за операцията" in captured.out
assert "завършено" in captured.out