Files
redmine-reporter/tests/test_client.py
Кокос Артем Николаевич 8bc8181ce3 Add Redmine API token authentication
2026-05-22 17:19:00 +07:00

179 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from unittest import mock
from redmine_reporter.client import fetch_issues_with_spent_time
from redmine_reporter.config import Config
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY=None,
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_aggregates_hours_per_issue(mock_redmine_class):
"""Два time entry на одну задачу -- часы суммируются."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 123
mock_redmine.user.get.return_value = mock_user
mock_entry1 = mock.MagicMock()
mock_entry1.issue.id = 101
mock_entry1.hours = 2.0
mock_entry2 = mock.MagicMock()
mock_entry2.issue.id = 101
mock_entry2.hours = 1.5
mock_redmine.time_entry.filter.return_value = [mock_entry1, mock_entry2]
mock_issue = mock.MagicMock()
mock_issue.id = 101
mock_issue.project = "Проект X"
mock_issue.subject = "Тестовая задача"
mock_issue.status = "New"
mock_redmine.issue.filter.return_value = [mock_issue]
result = fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
assert result is not None
assert len(result) == 1
issue, total_hours = result[0]
assert total_hours == 3.5
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY=None,
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_returns_none_when_no_entries(mock_redmine_class):
"""Нет time entries -- возвращается None."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 1
mock_redmine.user.get.return_value = mock_user
mock_redmine.time_entry.filter.return_value = []
result = fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
assert result is None
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY=None,
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_skips_entries_without_issue(mock_redmine_class):
"""Time entry без привязки к задаче игнорируется."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 1
mock_redmine.user.get.return_value = mock_user
# entry без issue атрибута
entry_no_issue = mock.MagicMock(spec=["hours"]) # нет .issue
entry_no_issue.hours = 1.0
mock_redmine.time_entry.filter.return_value = [entry_no_issue]
result = fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
assert result is None
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY=None,
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_multiple_issues(mock_redmine_class):
"""Несколько задач -- каждая с правильным суммарным временем."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 1
mock_redmine.user.get.return_value = mock_user
def make_entry(issue_id, hours):
e = mock.MagicMock()
e.issue.id = issue_id
e.hours = hours
return e
mock_redmine.time_entry.filter.return_value = [
make_entry(1, 1.0),
make_entry(2, 2.0),
make_entry(1, 0.5),
]
mock_issue1 = mock.MagicMock()
mock_issue1.id = 1
mock_issue1.project = "P"
mock_issue2 = mock.MagicMock()
mock_issue2.id = 2
mock_issue2.project = "P"
mock_redmine.issue.filter.return_value = [mock_issue1, mock_issue2]
result = fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
assert result is not None
assert len(result) == 2
hours_by_id = {issue.id: hours for issue, hours in result}
assert hours_by_id[1] == 1.5
assert hours_by_id[2] == 2.0
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY="api-token",
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_uses_api_key_when_present(mock_redmine_class):
"""Если задан API key, он используется вместо логина/пароля."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 1
mock_redmine.user.get.return_value = mock_user
mock_redmine.time_entry.filter.return_value = []
fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
_, kwargs = mock_redmine_class.call_args
assert kwargs["key"] == "api-token"
assert "username" not in kwargs
assert "password" not in kwargs
@mock.patch.multiple(
Config,
REDMINE_URL="https://red.eltex.loc",
REDMINE_API_KEY=None,
REDMINE_USER="user",
REDMINE_PASSWORD="password",
)
@mock.patch("redmine_reporter.client.Redmine")
def test_fetch_uses_username_password_when_no_api_key(mock_redmine_class):
"""Если API key не задан, остаётся старая схема логин/пароль."""
mock_redmine = mock_redmine_class.return_value
mock_user = mock.MagicMock()
mock_user.id = 1
mock_redmine.user.get.return_value = mock_user
mock_redmine.time_entry.filter.return_value = []
fetch_issues_with_spent_time("2026-01-01", "2026-01-31")
_, kwargs = mock_redmine_class.call_args
assert kwargs["username"] == "user"
assert kwargs["password"] == "password"
assert "key" not in kwargs