Enhance the test suite for Git utilities by adding scenarios to check behavior when the HEAD is detached. This includes mocking the repository state to ensure proper handling in both attached and detached scenarios during branch push operations.
119 lines
5.2 KiB
Python
119 lines
5.2 KiB
Python
import unittest
|
|
from unittest.mock import patch
|
|
|
|
import git
|
|
|
|
from codeflash.code_utils.git_utils import check_and_push_branch, check_running_in_git_repo, get_repo_owner_and_name
|
|
|
|
|
|
class TestGitUtils(unittest.TestCase):
|
|
@patch("codeflash.code_utils.git_utils.get_remote_url")
|
|
def test_test_get_repo_owner_and_name(self, mock_get_remote_url):
|
|
# Test with a standard GitHub HTTPS URL
|
|
mock_get_remote_url.return_value = "https://github.com/owner/repo.git"
|
|
get_repo_owner_and_name.cache_clear()
|
|
owner, repo_name = get_repo_owner_and_name()
|
|
assert owner == "owner"
|
|
assert repo_name == "repo"
|
|
|
|
# Test with a GitHub SSH URL
|
|
mock_get_remote_url.return_value = "git@github.com:owner/repo.git"
|
|
get_repo_owner_and_name.cache_clear()
|
|
owner, repo_name = get_repo_owner_and_name()
|
|
assert owner == "owner"
|
|
assert repo_name == "repo"
|
|
|
|
# Test with another GitHub SSH URL
|
|
mock_get_remote_url.return_value = "git@github.com:codeflash-ai/posthog.git"
|
|
get_repo_owner_and_name.cache_clear()
|
|
owner, repo_name = get_repo_owner_and_name()
|
|
assert owner == "codeflash-ai"
|
|
assert repo_name == "posthog"
|
|
|
|
# Test with a URL without the .git suffix
|
|
mock_get_remote_url.return_value = "https://github.com/owner/repo"
|
|
get_repo_owner_and_name.cache_clear()
|
|
owner, repo_name = get_repo_owner_and_name()
|
|
assert owner == "owner"
|
|
assert repo_name == "repo"
|
|
|
|
# Test with another GitHub SSH URL
|
|
mock_get_remote_url.return_value = "git@github.com:codeflash-ai/posthog/"
|
|
get_repo_owner_and_name.cache_clear()
|
|
owner, repo_name = get_repo_owner_and_name()
|
|
assert owner == "codeflash-ai"
|
|
assert repo_name == "posthog"
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
def test_check_running_in_git_repo_in_git_repo(self, mock_repo):
|
|
mock_repo.return_value.git_dir = "/path/to/repo/.git"
|
|
assert check_running_in_git_repo("/path/to/repo")
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
@patch("codeflash.code_utils.git_utils.sys.__stdin__.isatty", return_value=True)
|
|
@patch("codeflash.code_utils.git_utils.confirm_proceeding_with_no_git_repo", return_value=True)
|
|
def test_check_running_in_git_repo_not_in_git_repo_interactive(self, mock_confirm, mock_isatty, mock_repo):
|
|
mock_repo.side_effect = git.InvalidGitRepositoryError # type: ignore
|
|
assert check_running_in_git_repo("/path/to/non-repo") == False
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
@patch("codeflash.code_utils.git_utils.sys.__stdin__.isatty", return_value=False)
|
|
def test_check_running_in_git_repo_not_in_git_repo_non_interactive(self, mock_isatty, mock_repo):
|
|
mock_repo.side_effect = git.exc.InvalidGitRepositoryError # type: ignore
|
|
assert check_running_in_git_repo("/path/to/non-repo") is False
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
@patch("codeflash.code_utils.git_utils.sys.__stdin__.isatty", return_value=True)
|
|
@patch("codeflash.code_utils.git_utils.Confirm.ask", return_value=True)
|
|
def test_check_and_push_branch(self, mock_confirm, mock_isatty, mock_repo):
|
|
mock_repo_instance = mock_repo.return_value
|
|
# Mock HEAD not being detached
|
|
mock_repo_instance.head.is_detached = False
|
|
mock_repo_instance.active_branch.name = "test-branch"
|
|
mock_repo_instance.refs = []
|
|
|
|
mock_origin = mock_repo_instance.remote.return_value
|
|
mock_origin.push.return_value = None
|
|
|
|
assert check_and_push_branch(mock_repo_instance)
|
|
mock_origin.push.assert_called_once_with(mock_repo_instance.active_branch)
|
|
mock_origin.push.reset_mock()
|
|
|
|
# Test when branch is already pushed
|
|
mock_repo_instance.refs = [f"origin/{mock_repo_instance.active_branch.name}"]
|
|
assert check_and_push_branch(mock_repo_instance)
|
|
mock_origin.push.assert_not_called()
|
|
mock_origin.push.reset_mock()
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
@patch("codeflash.code_utils.git_utils.sys.__stdin__.isatty", return_value=False)
|
|
def test_check_and_push_branch_non_tty(self, mock_isatty, mock_repo):
|
|
mock_repo_instance = mock_repo.return_value
|
|
# Mock HEAD not being detached
|
|
mock_repo_instance.head.is_detached = False
|
|
mock_repo_instance.active_branch.name = "test-branch"
|
|
mock_repo_instance.refs = []
|
|
|
|
mock_origin = mock_repo_instance.remote.return_value
|
|
mock_origin.push.return_value = None
|
|
|
|
assert not check_and_push_branch(mock_repo_instance)
|
|
mock_origin.push.assert_not_called()
|
|
mock_origin.push.reset_mock()
|
|
|
|
@patch("codeflash.code_utils.git_utils.git.Repo")
|
|
def test_check_and_push_branch_detached_head(self, mock_repo):
|
|
mock_repo_instance = mock_repo.return_value
|
|
# Mock HEAD being detached
|
|
mock_repo_instance.head.is_detached = True
|
|
|
|
mock_origin = mock_repo_instance.remote.return_value
|
|
mock_origin.push.return_value = None
|
|
|
|
# Should return False when HEAD is detached
|
|
assert not check_and_push_branch(mock_repo_instance)
|
|
mock_origin.push.assert_not_called()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|