ifcurl/tests/test_git.py
Bruno Postle 7f92cadc50 Authentication and test coverage
- ifcurl/auth.py: token config (~/.config/ifcurl/tokens.json),
  get_token_for_host(), inject_token() for HTTPS URL credential injection
- ifcurl/git.py: thread token= through fetch_ifc/fetch_ifc_bytes/_open_remote;
  authenticated fetch uses 'git fetch <auth_url> +refs/*:refs/*' so the
  token is never written to on-disk git config
- ifcurl/service.py: optional token field in PreviewRequest; request token
  takes precedence over config-file token; get_token_for_host imported at
  module level for clean monkeypatching in tests
- tests

Generated with the assistance of an AI coding tool.
2026-04-15 23:21:13 +01:00

91 lines
3.4 KiB
Python

"""Tests for ifcurl.git — git repository access."""
from __future__ import annotations
import pytest
from ifcurl.git import fetch_ifc, fetch_ifc_bytes
from ifcurl.url import IfcUrl
def _local_url(repo_path: str, ref: str = "HEAD", path: str = "model.ifc") -> IfcUrl:
"""Build an ifc:// URL pointing at a local repo fixture."""
return IfcUrl.parse(f"ifc://{repo_path}@{ref}?path={path}")
class TestFetchIfc:
def test_returns_hexsha_and_bytes(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"])
hexsha, data = fetch_ifc(url)
assert len(hexsha) == 40
assert all(c in "0123456789abcdef" for c in hexsha)
assert isinstance(data, bytes)
assert len(data) > 0
def test_hexsha_matches_commit(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"])
hexsha, _ = fetch_ifc(url)
assert hexsha == local_ifc_repo["hexsha"]
def test_bytes_match_committed_file(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"])
_, data = fetch_ifc(url)
assert data == local_ifc_repo["bytes"]
def test_explicit_commit_hash_ref(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"], ref=local_ifc_repo["hexsha"])
hexsha, data = fetch_ifc(url)
assert hexsha == local_ifc_repo["hexsha"]
assert data == local_ifc_repo["bytes"]
def test_tag_ref(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"], ref="tags/v1.0")
hexsha, data = fetch_ifc(url)
assert hexsha == local_ifc_repo["hexsha"]
def test_bad_ref_raises(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"], ref="heads/nonexistent")
with pytest.raises(ValueError, match="not found"):
fetch_ifc(url)
def test_bad_path_raises(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"], path="missing.ifc")
with pytest.raises(ValueError, match="not found"):
fetch_ifc(url)
def test_directory_path_raises(self, local_ifc_repo):
# Committing a subdir would be complex; test that asking for a
# non-blob raises — here we ask for the root tree entry.
url = _local_url(local_ifc_repo["path"], path=".")
with pytest.raises((ValueError, KeyError)):
fetch_ifc(url)
def test_no_path_raises(self, local_ifc_repo):
url = IfcUrl.parse(f"ifc://{local_ifc_repo['path']}@HEAD")
with pytest.raises(ValueError, match="'path' parameter"):
fetch_ifc(url)
class TestFetchIfcBytes:
def test_returns_bytes(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"])
data = fetch_ifc_bytes(url)
assert data == local_ifc_repo["bytes"]
def test_backwards_compat_with_fetch_ifc(self, local_ifc_repo):
url = _local_url(local_ifc_repo["path"])
_, expected = fetch_ifc(url)
assert fetch_ifc_bytes(url) == expected
class TestInvalidRepo:
def test_nonexistent_path_raises(self, tmp_path):
url = IfcUrl.parse(f"ifc://{tmp_path / 'no_such_repo'}@HEAD?path=m.ifc")
with pytest.raises(ValueError):
fetch_ifc(url)
def test_non_git_directory_raises(self, tmp_path):
(tmp_path / "model.ifc").write_text("not a repo")
url = IfcUrl.parse(f"ifc://{tmp_path}@HEAD?path=model.ifc")
with pytest.raises(ValueError):
fetch_ifc(url)