from unittest.mock import patch, MagicMock from scripts.git_diff import ( resolve_default_branch, resolve_base_ref, changed_files_with_ranges, ) _DIFF = """\ diff --git a/src/api.py b/src/api.py index 1..2 100644 --- a/src/api.py +++ b/src/api.py @@ -12 +12,2 @@ -old line +new line one +new line two diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 3..4 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -5,0 +6,1 @@ + added line """ def test_resolve_default_branch_uses_symbolic_ref(): fake = MagicMock(returncode=0, stdout="refs/remotes/origin/main\n", stderr="") with patch("subprocess.run", return_value=fake): assert resolve_default_branch("/repo") == "main" def test_resolve_default_branch_falls_back_to_master(): def _fake(cmd, **kw): if "symbolic-ref" in cmd: return MagicMock(returncode=1, stdout="", stderr="") if "rev-parse" in cmd and "origin/main" in cmd: return MagicMock(returncode=1, stdout="", stderr="") if "rev-parse" in cmd and "origin/master" in cmd: return MagicMock(returncode=0, stdout="abc\n", stderr="") return MagicMock(returncode=1, stdout="", stderr="") with patch("subprocess.run", side_effect=_fake): assert resolve_default_branch("/repo") == "master" def test_resolve_base_ref_uses_origin_when_available(): def _fake(cmd, **kw): if "fetch" in cmd: return MagicMock(returncode=0, stdout="", stderr="") if "rev-parse" in cmd and "--verify" in cmd: return MagicMock(returncode=0, stdout="def\n", stderr="") return MagicMock(returncode=0, stdout="", stderr="") with patch("subprocess.run", side_effect=_fake): assert resolve_base_ref("/repo", "main") == "origin/main" def test_resolve_base_ref_falls_back_when_origin_missing(): def _fake(cmd, **kw): if "fetch" in cmd: return MagicMock(returncode=1, stdout="", stderr="no remote\n") if "rev-parse" in cmd and "--verify" in cmd: return MagicMock(returncode=1, stdout="", stderr="") return MagicMock(returncode=0, stdout="", stderr="") with patch("subprocess.run", side_effect=_fake): assert resolve_base_ref("/repo", "main") == "main" def test_changed_files_with_ranges_parses_unified0_diff(): fake = MagicMock(returncode=0, stdout=_DIFF, stderr="") with patch("subprocess.run", return_value=fake): out = changed_files_with_ranges("/repo", "origin/main", "HEAD") paths = {p: ranges for p, ranges in out} assert "src/api.py" in paths assert paths["src/api.py"] == [(12, 13)] assert "src/utils/helpers.ts" in paths assert paths["src/utils/helpers.ts"] == [(6, 6)] def test_changed_files_passes_no_ext_diff_flag(): fake = MagicMock(returncode=0, stdout="", stderr="") with patch("subprocess.run", return_value=fake) as p: changed_files_with_ranges("/repo", "origin/main", "HEAD") args = p.call_args[0][0] assert "--no-ext-diff" in args assert "--unified=0" in args assert "diff.noprefix=false" in " ".join(args)