feat(errors): provide readable Redmine API error messages
- Introduce RedmineAPIError with human-friendly messages. - Distinguish AuthError, ForbiddenError, HTTP status codes, timeouts and connection errors in client.py. - Update CLI to print the readable message instead of generic "Redmine API error: ...". - Log original exception with traceback when --debug is enabled. - Add tests for all error paths and CLI output. Closes #39
This commit is contained in:
@@ -210,6 +210,46 @@ def test_total_issues_message_goes_to_stderr(mock_fetch, capsys):
|
||||
assert "Total issues" in captured.err
|
||||
|
||||
|
||||
@mock.patch.dict(os.environ, VALID_ENV, clear=True)
|
||||
@mock.patch("redmine_reporter.cli.fetch_issues_with_spent_time")
|
||||
def test_cli_prints_readable_auth_error(mock_fetch, capsys):
|
||||
"""CLI выводит понятное сообщение при ошибке аутентификации."""
|
||||
from redmine_reporter.client import RedmineAPIError
|
||||
|
||||
mock_fetch.side_effect = RedmineAPIError("Authentication failed: bad key")
|
||||
code = main(["--date", "2026-01-01--2026-01-31"])
|
||||
captured = capsys.readouterr()
|
||||
assert code == 1
|
||||
assert "Authentication failed" in captured.err
|
||||
assert "Redmine API error" not in captured.err
|
||||
|
||||
|
||||
@mock.patch.dict(os.environ, VALID_ENV, clear=True)
|
||||
@mock.patch("redmine_reporter.cli.fetch_issues_with_spent_time")
|
||||
def test_cli_prints_readable_forbidden_error(mock_fetch, capsys):
|
||||
"""CLI выводит понятное сообщение при недостаточных правах."""
|
||||
from redmine_reporter.client import RedmineAPIError
|
||||
|
||||
mock_fetch.side_effect = RedmineAPIError("Access denied: no permission")
|
||||
code = main(["--date", "2026-01-01--2026-01-31"])
|
||||
captured = capsys.readouterr()
|
||||
assert code == 1
|
||||
assert "Access denied" in captured.err
|
||||
|
||||
|
||||
@mock.patch.dict(os.environ, VALID_ENV, clear=True)
|
||||
@mock.patch("redmine_reporter.cli.fetch_issues_with_spent_time")
|
||||
def test_cli_prints_readable_timeout_error(mock_fetch, capsys):
|
||||
"""CLI выводит понятное сообщение при таймауте."""
|
||||
from redmine_reporter.client import RedmineAPIError
|
||||
|
||||
mock_fetch.side_effect = RedmineAPIError("Redmine request timed out after 30 seconds")
|
||||
code = main(["--date", "2026-01-01--2026-01-31"])
|
||||
captured = capsys.readouterr()
|
||||
assert code == 1
|
||||
assert "timed out" in captured.err
|
||||
|
||||
|
||||
@mock.patch.dict(os.environ, VALID_ENV, clear=True)
|
||||
@mock.patch("redmine_reporter.cli.fetch_issues_with_spent_time")
|
||||
def test_cli_no_time_passed_to_formatter(mock_fetch, tmp_path):
|
||||
|
||||
Reference in New Issue
Block a user