Files
gitea-dashboard/tests/test_display.py
sylvain 50768db31f fix(audit): sort milestones, sort JSON export, extract test helper
- Fix milestone section using unsorted repos list
- Apply --sort to --format json output
- Rename _sort_repos to sort_repos (now used by cli.py)
- Extract shared make_repo helper to tests/helpers.py
- Move exporter import to module level in cli.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 04:07:41 +01:00

319 lines
9.9 KiB
Python

"""Tests for Rich dashboard display."""
from io import StringIO
from rich.console import Console
from gitea_dashboard.display import (
render_dashboard,
sort_repos,
)
from tests.helpers import make_repo as _make_repo
def _make_console():
"""Create a console that captures output for testing.
highlight=False desactive le highlighting automatique de Rich
qui fragmente les nombres et noms avec des codes ANSI.
"""
buf = StringIO()
return Console(file=buf, force_terminal=True, width=120, highlight=False), buf
class TestRenderDashboardTable:
"""Test the main repos table rendering."""
def test_basic_repo_displayed(self):
"""Repo name and issues count appear in output."""
console, buf = _make_console()
repos = [
_make_repo(
name="mon-projet",
open_issues=3,
latest_release={"tag_name": "v1.2.0", "published_at": "2026-03-08T10:00:00Z"},
),
]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "mon-projet" in output
assert "v1.2.0" in output
def test_repo_without_release_shows_dash(self):
"""Repo with no release shows a dash character."""
console, buf = _make_console()
repos = [_make_repo(name="no-release", latest_release=None)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "no-release" in output
# The dash character for "no release"
assert "\u2014" in output or "" in output
def test_fork_indicator(self):
"""Fork repos show [F] indicator."""
console, buf = _make_console()
repos = [_make_repo(name="forked-repo", is_fork=True)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "forked-repo" in output
assert "[F]" in output
def test_archive_indicator(self):
"""Archived repos show [A] indicator."""
console, buf = _make_console()
repos = [_make_repo(name="old-repo", is_archived=True)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "[A]" in output
def test_mirror_indicator(self):
"""Mirror repos show [M] indicator."""
console, buf = _make_console()
repos = [_make_repo(name="mirror-repo", is_mirror=True)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "[M]" in output
def test_multiple_indicators(self):
"""Repo with multiple flags shows all indicators."""
console, buf = _make_console()
repos = [_make_repo(name="special", is_fork=True, is_archived=True)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "[F]" in output
assert "[A]" in output
def test_issues_zero(self):
"""Repos with 0 issues display 0."""
console, buf = _make_console()
repos = [_make_repo(name="clean-repo", open_issues=0)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "0" in output
def test_multiple_repos(self):
"""Multiple repos all appear in the output."""
console, buf = _make_console()
repos = [
_make_repo(name="repo-alpha", open_issues=1),
_make_repo(name="repo-beta", open_issues=5),
]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "repo-alpha" in output
assert "repo-beta" in output
class TestRenderDashboardLastCommit:
"""Test the last commit column rendering."""
def test_last_commit_column_displayed(self):
"""Column 'Dernier commit' appears in the table."""
console, buf = _make_console()
repos = [_make_repo(name="projet", last_commit_date="2026-03-10T14:30:00Z")]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "Dernier commit" in output
def test_last_commit_shows_relative_date(self):
"""Last commit date is shown as relative date."""
console, buf = _make_console()
repos = [_make_repo(name="projet", last_commit_date="2026-03-10T14:30:00Z")]
render_dashboard(repos, console=console)
output = buf.getvalue()
# Should show some relative date (il y a Xj, etc.)
assert "il y a" in output or "aujourd'hui" in output
def test_last_commit_none_shows_dash(self):
"""Repo without commit shows dash."""
console, buf = _make_console()
repos = [_make_repo(name="vide", last_commit_date=None)]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "\u2014" in output or "" in output
class TestRenderDashboardMilestones:
"""Test the milestones section rendering."""
def test_milestones_displayed(self):
"""Repos with milestones show milestone info."""
console, buf = _make_console()
repos = [
_make_repo(
name="mon-projet",
milestones=[
{
"title": "v2.0",
"open_issues": 2,
"closed_issues": 3,
"due_on": "2026-04-01T00:00:00Z",
},
],
),
]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "v2.0" in output
assert "3/5" in output # closed/total
assert "60%" in output
def test_milestone_without_due_date(self):
"""Milestone without due_on omits the deadline."""
console, buf = _make_console()
repos = [
_make_repo(
name="projet",
milestones=[
{
"title": "backlog",
"open_issues": 5,
"closed_issues": 1,
"due_on": None,
},
],
),
]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "backlog" in output
assert "1/6" in output
def test_no_milestones_section_when_none(self):
"""When no repos have milestones, milestone section is absent."""
console, buf = _make_console()
repos = [_make_repo(name="simple", milestones=[])]
render_dashboard(repos, console=console)
output = buf.getvalue()
assert "Milestones" not in output
class TestRenderDashboardEmpty:
"""Test empty repo list handling."""
def test_empty_list_shows_message(self):
"""Empty repo list shows informative message."""
console, buf = _make_console()
render_dashboard([], console=console)
output = buf.getvalue()
assert "Aucun repo" in output
class TestColorizeMilestoneDue:
"""Test _colorize_milestone_due function."""
def test_overdue(self):
"""Past due date returns 'red'."""
from gitea_dashboard.display import _colorize_milestone_due
assert _colorize_milestone_due("2020-01-01T00:00:00Z") == "red"
def test_soon(self):
"""Due date within 7 days returns 'yellow'."""
from datetime import datetime, timedelta, timezone
from gitea_dashboard.display import _colorize_milestone_due
soon = datetime.now(timezone.utc) + timedelta(days=3)
assert _colorize_milestone_due(soon.isoformat()) == "yellow"
def test_ok(self):
"""Due date more than 7 days away returns 'green'."""
from datetime import datetime, timedelta, timezone
from gitea_dashboard.display import _colorize_milestone_due
future = datetime.now(timezone.utc) + timedelta(days=15)
assert _colorize_milestone_due(future.isoformat()) == "green"
def test_no_due(self):
"""No due date returns empty string."""
from gitea_dashboard.display import _colorize_milestone_due
assert _colorize_milestone_due(None) == ""
class TestSortRepos:
"""Test sort_repos function."""
def test_sort_by_name(self):
"""Sorts alphabetically by name (case-insensitive)."""
repos = [
_make_repo(name="Charlie"),
_make_repo(name="alpha"),
_make_repo(name="Bravo"),
]
result = sort_repos(repos, "name")
assert [r.name for r in result] == ["alpha", "Bravo", "Charlie"]
def test_sort_by_issues(self):
"""Sorts by issues count descending."""
repos = [
_make_repo(name="low", open_issues=1),
_make_repo(name="high", open_issues=10),
_make_repo(name="mid", open_issues=5),
]
result = sort_repos(repos, "issues")
assert [r.name for r in result] == ["high", "mid", "low"]
def test_sort_by_release(self):
"""Sorts by release date descending; repos without release last."""
repos = [
_make_repo(name="no-rel", latest_release=None),
_make_repo(
name="old",
latest_release={"tag_name": "v1.0", "published_at": "2025-01-01T00:00:00Z"},
),
_make_repo(
name="new",
latest_release={"tag_name": "v2.0", "published_at": "2026-03-01T00:00:00Z"},
),
]
result = sort_repos(repos, "release")
assert [r.name for r in result] == ["new", "old", "no-rel"]
def test_sort_by_activity(self):
"""Sorts by last commit date descending; repos without commit last."""
repos = [
_make_repo(name="inactive", last_commit_date=None),
_make_repo(name="old-commit", last_commit_date="2025-06-01T00:00:00Z"),
_make_repo(name="recent", last_commit_date="2026-03-10T00:00:00Z"),
]
result = sort_repos(repos, "activity")
assert [r.name for r in result] == ["recent", "old-commit", "inactive"]