"""TDD — Phase 4 of issue #40: dedup intel provider BFS into _load_commit_walk. P4-1 Structural — each provider delegates to _load_commit_walk; no inline BFS P4-2 Behavioural — _load_commit_walk returns correct BFS order for a 4-commit chain P4-3 Behavioural — _load_commit_walk respects max_walk cap """ from __future__ import annotations import inspect from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock import pytest # --------------------------------------------------------------------------- # P4-1 Structural — each provider delegates to _load_commit_walk # --------------------------------------------------------------------------- def test_p4_1_coupling_provider_delegates_to_load_commit_walk() -> None: """CouplingProvider.compute must call _load_commit_walk; no inline walk_dag.""" from musehub.services import musehub_intel_providers as mod src = inspect.getsource(mod.CouplingProvider.compute) assert "_load_commit_walk" in src, ( "CouplingProvider.compute must delegate to _load_commit_walk." ) assert "walk_dag" not in src, ( "CouplingProvider.compute still has an inline walk_dag call." ) def test_p4_1_entangle_provider_delegates_to_load_commit_walk() -> None: """EntangleProvider.compute must call _load_commit_walk; no inline walk_dag.""" from musehub.services import musehub_intel_providers as mod src = inspect.getsource(mod.EntangleProvider.compute) assert "_load_commit_walk" in src, ( "EntangleProvider.compute must delegate to _load_commit_walk." ) assert "walk_dag" not in src, ( "EntangleProvider.compute still has an inline walk_dag call." ) def test_p4_1_velocity_provider_delegates_to_load_commit_walk() -> None: """VelocityProvider.compute must call _load_commit_walk; no inline walk_dag.""" from musehub.services import musehub_intel_providers as mod src = inspect.getsource(mod.VelocityProvider.compute) assert "_load_commit_walk" in src, ( "VelocityProvider.compute must delegate to _load_commit_walk." ) assert "walk_dag" not in src, ( "VelocityProvider.compute still has an inline walk_dag call." ) # --------------------------------------------------------------------------- # Helpers for behavioural tests # --------------------------------------------------------------------------- def _row(commit_id: str, parent_ids: list[str]) -> None: return SimpleNamespace(commit_id=commit_id, parent_ids=parent_ids) def _make_session(rows: list[SimpleNamespace]) -> MagicMock: """Fake session whose execute() returns an iterable of row SimpleNamespaces.""" session = MagicMock() session.execute = AsyncMock(return_value=rows) return session # --------------------------------------------------------------------------- # P4-2 Behavioural — correct BFS order for a 4-commit diamond # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_p4_2_load_commit_walk_bfs_order() -> None: """_load_commit_walk returns commits in BFS order for a diamond graph. Diamond: A → B, A → C; B → D; C → D. BFS from A: [A, B, C, D] (level-by-level). """ from musehub.services.musehub_intel_providers import _load_commit_walk rows = [ _row("A", ["B", "C"]), _row("B", ["D"]), _row("C", ["D"]), _row("D", []), ] session = _make_session(rows) result = await _load_commit_walk(session, "repo1", "A", max_walk=100) assert result == ["A", "B", "C", "D"], ( f"Expected BFS order [A, B, C, D], got {result}" ) # --------------------------------------------------------------------------- # P4-3 Behavioural — max_walk cap # --------------------------------------------------------------------------- @pytest.mark.asyncio async def test_p4_3_load_commit_walk_max_walk_cap() -> None: """_load_commit_walk stops after max_walk commits have been collected. Linear chain: A→B→C→D→E. max_walk=3 → [A, B, C]. """ from musehub.services.musehub_intel_providers import _load_commit_walk rows = [ _row("A", ["B"]), _row("B", ["C"]), _row("C", ["D"]), _row("D", ["E"]), _row("E", []), ] session = _make_session(rows) result = await _load_commit_walk(session, "repo1", "A", max_walk=3) assert len(result) == 3, f"Expected exactly 3 commits, got {len(result)}" assert result == ["A", "B", "C"], f"Expected [A, B, C], got {result}"