2026-06-16 02:39:36 +02:00
|
|
|
import pytest
|
|
|
|
|
from sqlalchemy import select
|
|
|
|
|
|
|
|
|
|
from hub_core.models.domain import Domain
|
2026-07-11 01:26:47 +02:00
|
|
|
from hub_core.utils import (
|
|
|
|
|
PageParams,
|
|
|
|
|
apply_pagination,
|
|
|
|
|
normalize_trailing_slash,
|
|
|
|
|
resolve_repo_path,
|
|
|
|
|
slugify,
|
|
|
|
|
slugify_or_default,
|
|
|
|
|
)
|
2026-06-16 02:39:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class RepoStub:
|
|
|
|
|
local_path = "/fallback/path"
|
|
|
|
|
host_paths = {"workstation": "/host/path"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_slugify_normalizes_text() -> None:
|
|
|
|
|
assert slugify(" The Custodian: Hub Core! ") == "the-custodian-hub-core"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_slugify_rejects_empty_slug() -> None:
|
|
|
|
|
with pytest.raises(ValueError, match="slug cannot be empty"):
|
|
|
|
|
slugify(" !!! ")
|
|
|
|
|
|
|
|
|
|
|
2026-07-11 01:26:47 +02:00
|
|
|
def test_slugify_or_default_matches_core_hub_bootstrap() -> None:
|
|
|
|
|
assert slugify_or_default("ops-hub") == "ops-hub"
|
|
|
|
|
assert slugify_or_default("Ops Hub Bootstrap") == "ops-hub-bootstrap"
|
|
|
|
|
assert slugify_or_default("!!!") == "resource"
|
|
|
|
|
assert slugify_or_default("!!!", default="fallback") == "fallback"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_slugify_or_default_aligns_with_core_hub_api_v2_name_field() -> None:
|
|
|
|
|
# core-hub: slug=body.get("slug") or slugify(body["name"])
|
|
|
|
|
assert slugify_or_default("ops-hub") == "ops-hub"
|
|
|
|
|
|
|
|
|
|
|
2026-06-16 02:39:36 +02:00
|
|
|
def test_page_params_bounds() -> None:
|
|
|
|
|
assert PageParams(limit=10, offset=20).limit == 10
|
|
|
|
|
with pytest.raises(ValueError, match="limit"):
|
|
|
|
|
PageParams(limit=0)
|
|
|
|
|
with pytest.raises(ValueError, match="offset"):
|
|
|
|
|
PageParams(offset=-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_apply_pagination_sets_limit_and_offset() -> None:
|
|
|
|
|
query = apply_pagination(select(Domain), PageParams(limit=25, offset=50))
|
|
|
|
|
compiled = str(query.compile(compile_kwargs={"literal_binds": True}))
|
|
|
|
|
assert "LIMIT 25" in compiled
|
|
|
|
|
assert "OFFSET 50" in compiled
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_resolve_repo_path_prefers_host_path() -> None:
|
|
|
|
|
repo = RepoStub()
|
|
|
|
|
assert resolve_repo_path(repo, "workstation") == "/host/path"
|
|
|
|
|
assert resolve_repo_path(repo, "unknown-host") == "/fallback/path"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_trailing_slash_preserves_query_and_fragment() -> None:
|
|
|
|
|
assert normalize_trailing_slash("/repos?status=active#top") == "/repos/?status=active#top"
|
|
|
|
|
assert normalize_trailing_slash("/repos/?status=active", trailing=False) == "/repos?status=active"
|