Post-merge / detect-type (push) Successful in 53s
Post-merge / release (push) Successful in 1m14s
Post-merge / validate-commit-msg (push) Successful in 1m25s
Post-merge / vikunja (push) Successful in 1m21s
Post-merge / badges (push) Successful in 1m45s
Post-merge / configure-repo (push) Successful in 1m15s
Post-merge / sync-wiki (push) Successful in 3m5s
Post-merge / publish (push) Successful in 1m1s
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
"""Unit tests for the operation report tracker."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from grm.exceptions import AnsibleError
|
|
from grm.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) -> None:
|
|
with patch("grm.report.say") as mock_say:
|
|
with track_steps() as tracker:
|
|
tracker.begin("step1")
|
|
tracker.done()
|
|
tracker.begin("step2")
|
|
tracker.done()
|
|
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert any("Operation Report" in msg for msg in messages)
|
|
assert any("step1" in msg for msg in messages)
|
|
assert any("step2" in msg for msg in messages)
|
|
assert any("✓" in msg for msg in messages)
|
|
assert any("completed" in msg for msg in messages)
|
|
|
|
def test_failure_marks_step(self) -> None:
|
|
with patch("grm.report.say") as mock_say:
|
|
with pytest.raises(AnsibleError, match="fail"):
|
|
with track_steps() as tracker:
|
|
tracker.begin("step1")
|
|
tracker.done()
|
|
tracker.begin("step2")
|
|
raise AnsibleError("fail")
|
|
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert any("step1" in msg for msg in messages)
|
|
assert any("step2" in msg for msg in messages)
|
|
assert any("✓" in msg for msg in messages)
|
|
assert any("✗" in msg for msg in messages)
|
|
assert any("completed" in msg for msg in messages)
|
|
assert any("failed" in msg for msg in messages)
|
|
|
|
def test_pending_shown_on_failure(self) -> None:
|
|
with patch("grm.report.say") as mock_say:
|
|
with pytest.raises(AnsibleError, match="fail"):
|
|
with track_steps() as tracker:
|
|
tracker.begin("step1")
|
|
raise AnsibleError("fail")
|
|
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert any("✗" in msg for msg in messages)
|
|
assert any("failed" in msg for msg in messages)
|
|
|
|
def test_multiple_in_progress_marked_failed(self) -> None:
|
|
"""All in-progress steps should be marked as failed on exception."""
|
|
with patch("grm.report.say") as mock_say:
|
|
with pytest.raises(AnsibleError, match="fail"):
|
|
with track_steps() as tracker:
|
|
tracker.begin("step1")
|
|
tracker.begin("step2")
|
|
raise AnsibleError("fail")
|
|
|
|
assert tracker.steps[0].status == "failed"
|
|
assert tracker.steps[1].status == "failed"
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert messages.count("✗") >= 2 or sum(1 for m in messages if "✗" in m) >= 2
|
|
|
|
def test_empty_report(self) -> None:
|
|
with patch("grm.report.say") as mock_say:
|
|
with track_steps():
|
|
pass
|
|
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert any("Operation Report" in msg for msg in messages)
|
|
|
|
def test_translated_report(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setenv("GRM_LANG", "bg")
|
|
with patch("grm.report.say") as mock_say:
|
|
with track_steps() as tracker:
|
|
tracker.begin("step1")
|
|
tracker.done()
|
|
|
|
messages = [call.args[0] for call in mock_say.call_args_list]
|
|
assert any("Отчет за операцията" in msg for msg in messages)
|
|
assert any("завършено" in msg for msg in messages)
|