Files
the-nexus/tests/test_gitea_safe_push.py
Alexander Whitestone c63d56dfb7
Some checks failed
Deploy Nexus / deploy (push) Failing after 5s
Staging Verification Gate / verify-staging (push) Failing after 6s
CI / test (pull_request) Failing after 1m43s
CI / validate (pull_request) Failing after 1m47s
Review Approval Gate / verify-review (pull_request) Successful in 13s
fix: add branch existence check before Gitea API file operations (#1441) (#1487)
Merge PR #1487
2026-04-14 22:18:06 +00:00

125 lines
5.5 KiB
Python

"""Tests for gitea_safe_push — Branch existence checks before file operations."""
import json
from unittest.mock import MagicMock, patch, call
from pathlib import Path
import pytest
import sys
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from bin.gitea_safe_push import GiteaSafePush, GiteaAPIError
class TestGiteaAPIError:
def test_creation(self):
e = GiteaAPIError(404, "not found", '{"message":"not found"}')
assert e.status == 404
assert "404" in str(e)
def test_is_exception(self):
e = GiteaAPIError(500, "internal")
assert isinstance(e, Exception)
class TestBranchExists:
def test_branch_exists(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "_api", return_value={"name": "main"}):
assert push.branch_exists("owner/repo", "main") is True
def test_branch_not_exists(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "_api", side_effect=GiteaAPIError(404, "not found")):
assert push.branch_exists("owner/repo", "nonexistent") is False
def test_api_error_propagates(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "_api", side_effect=GiteaAPIError(500, "server error")):
with pytest.raises(GiteaAPIError):
push.branch_exists("owner/repo", "main")
class TestEnsureBranch:
def test_already_exists(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", return_value=True):
assert push.ensure_branch("owner/repo", "my-branch") is True
def test_creates_branch(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", side_effect=[False, True]):
with patch.object(push, "_api", return_value={"name": "my-branch"}):
assert push.ensure_branch("owner/repo", "my-branch", base="main") is True
def test_creation_fails(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", return_value=False):
with patch.object(push, "_api", side_effect=GiteaAPIError(422, "invalid")):
assert push.ensure_branch("owner/repo", "bad-branch") is False
class TestPushFile:
def test_rejects_missing_branch(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", return_value=False):
result = push.push_file("owner/repo", "missing", "file.py", "content", "msg")
assert result is False
def test_creates_new_file(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", return_value=True):
with patch.object(push, "_api", side_effect=[
GiteaAPIError(404, "not found"), # GET existing file
{}, # POST new file
]):
result = push.push_file("owner/repo", "branch", "new.py", "content", "msg")
assert result is True
def test_updates_existing_file(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "branch_exists", return_value=True):
with patch.object(push, "_api", side_effect=[
{"sha": "abc123"}, # GET existing file
{}, # PUT update
]):
result = push.push_file("owner/repo", "branch", "existing.py", "new content", "msg")
assert result is True
def test_create_branch_when_missing(self):
push = GiteaSafePush("https://forge.example.com", "token123")
# Mock branch_exists: first call returns False (doesn't exist),
# second call (inside ensure_branch) returns True (created externally)
exists_calls = [False, True]
exists_idx = [0]
def mock_exists(repo, branch):
idx = min(exists_idx[0], len(exists_calls) - 1)
exists_idx[0] += 1
return exists_calls[idx]
with patch.object(push, "branch_exists", side_effect=mock_exists):
with patch.object(push, "_api") as mock_api:
mock_api.side_effect = [
GiteaAPIError(404, "not found"), # GET existing file (not found)
{"content": {"path": "f.py"}}, # POST new file
]
result = push.push_file("owner/repo", "new-branch", "f.py", "c", "m", create_branch=True)
assert result is True
class TestPushFiles:
def test_push_multiple_files(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "ensure_branch", return_value=True):
with patch.object(push, "push_file", return_value=True):
results = push.push_files("owner/repo", "branch", {
"a.py": "content a",
"b.py": "content b",
}, "message")
assert all(results.values())
assert len(results) == 2
def test_branch_creation_fails_aborts_all(self):
push = GiteaSafePush("https://forge.example.com", "token123")
with patch.object(push, "ensure_branch", return_value=False):
results = push.push_files("owner/repo", "bad", {"a.py": "x"}, "msg")
assert all(v is False for v in results.values())