Newer
Older
gnexus-tasks / backend / tests / test_repo_readme.py
"""README.md репозитория для описаний-«только ссылка»: эвристики путей и кэш."""

import asyncio

import pytest

from app.services import readme


@pytest.fixture(autouse=True)
def clean_cache() -> None:
    readme._CACHE.clear()


def test_candidates_github() -> None:
    urls = readme.repo_candidates("https://github.com/o/r/")
    # raw-путь первым (без рейт-лимита GitHub API), API вторым (любит raw-мим)
    assert urls[0] == "https://github.com/o/r/raw/HEAD/README.md"
    assert urls[1] == "https://api.github.com/repos/o/r/readme"


def test_candidates_self_hosted_git_suffix() -> None:
    urls = readme.repo_candidates("https://git.corp/team/repo.git")
    assert (
        "https://git.corp/api/v4/projects/team%2Frepo/repository/files/README%2Emd/raw?ref=HEAD"
        in urls
    )
    assert "https://git.corp/team/repo/raw/HEAD/README.md" in urls
    # GitHub-API путь чужому хосту не предлагается
    assert not any("api.github.com" in u for u in urls)


def test_candidates_not_a_repo() -> None:
    # нет owner/repo — не похоже на репозиторий
    assert readme.repo_candidates("https://example.com") == []
    assert readme.repo_candidates("ftp://example.com/o/r") == []


def test_fetch_takes_first_working(monkeypatch: pytest.MonkeyPatch) -> None:
    tried: list[str] = []

    async def fake_try(client: object, url: str) -> str | None:
        tried.append(url)
        # первые кандидаты (raw/HEAD, gitlab-api) не работают, raw/main отдаёт README
        return "# Readme\n\nтекст" if url.endswith("raw/main/README.md") else None

    readme._try = fake_try
    assert asyncio.run(readme.fetch_readme("https://git.corp/t/r")) == "# Readme\n\nтекст"
    # до первого удачного кандидата перебор продолжался
    assert len(tried) > 1


def test_fetch_caches(monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[str] = []

    async def fake_try(client: object, url: str) -> str | None:
        calls.append(url)
        return "# R"

    readme._try = fake_try
    url = "https://git.corp/t/r"
    assert asyncio.run(readme.fetch_readme(url)) == "# R"
    assert asyncio.run(readme.fetch_readme(url)) == "# R"
    # второй вызов из кэша — кандидат лишь один фейково сработал
    assert len(calls) == 1


def test_fetch_not_found_cached(monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[str] = []

    async def fake_try(client: object, url: str) -> str | None:
        calls.append(url)
        return None

    readme._try = fake_try
    url = "https://git.corp/t/r"
    assert asyncio.run(readme.fetch_readme(url)) is None
    assert asyncio.run(readme.fetch_readme(url)) is None
    assert len(calls) == len(readme.repo_candidates(url))