"""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))