from __future__ import annotations from typing import Any from sbom_nexus import projection def test_projection_sync_is_projection_only_and_reconciles(monkeypatch) -> None: source = [ { "slug": "active-repo", "status": "active", "local_path": "/fallback/active", "host_paths": {"build-host": "/repos/active"}, }, { "slug": "retired-repo", "status": "retired", "local_path": "/repos/retired", }, ] target: dict[str, dict[str, Any]] = {} calls: list[tuple[str, str, str]] = [] def fake_request( base_url: str, path: str, *, method: str = "GET", body: dict[str, Any] | None = None, ) -> Any: calls.append((base_url, method, path)) if base_url == "source" and path == "/repos/": return source if base_url == "target" and method == "PUT": assert body is not None slug = path.rsplit("/", 1)[1] target[slug] = {"slug": slug, **body} return target[slug] if base_url == "target" and path == "/repositories/": return list(target.values()) raise AssertionError((base_url, method, path)) monkeypatch.setattr(projection, "request_json", fake_request) result = projection.sync_repository_projections( "source", "target", dry_run=False, host_id="build-host" ) assert result["ok"] is True assert result["source_repo_count"] == 2 assert result["counts"] == { "active": 1, "with_checkout_path": 2, "inactive": 1, } assert result["reconciliation"]["matched_repo_count"] == 2 assert target["active-repo"]["checkout_path"] == "/repos/active" assert target["retired-repo"]["active"] is False assert all("/sbom/" not in path for _, _, path in calls) def test_projection_dry_run_does_not_contact_target(monkeypatch) -> None: def fake_request( base_url: str, path: str, *, method: str = "GET", body: dict[str, Any] | None = None, ) -> Any: assert base_url == "source" assert method == "GET" assert path == "/repos/" return [{"slug": "demo", "status": "active", "local_path": "/repos/demo"}] monkeypatch.setattr(projection, "request_json", fake_request) result = projection.sync_repository_projections( "source", "unreachable-target", dry_run=True, host_id="build-host" ) assert result["ok"] is True assert result["would_upsert"] == 1 assert result["reconciliation"] is None