"""Focused tests for pure URL resolution behavior in the executable module.""" import importlib.machinery import importlib.util import os import pathlib import subprocess import sys import tempfile import unittest from unittest import mock SCRIPT_PATH = pathlib.Path(__file__).parents[1] / "git-tui" LOADER = importlib.machinery.SourceFileLoader("git_tui", str(SCRIPT_PATH)) SPEC = importlib.util.spec_from_loader(LOADER.name, LOADER) assert SPEC is not None git_tui = importlib.util.module_from_spec(SPEC) sys.modules[LOADER.name] = git_tui LOADER.exec_module(git_tui) class GiteaRemoteUrlTests(unittest.TestCase): def setUp(self) -> None: self.app = git_tui.GitTuiApp.__new__(git_tui.GitTuiApp) def test_exact_custom_ssh_clone_url_is_preserved(self) -> None: expected_url = "ssh://forge@git.example.com:2222/owner/project.git" self.app.prompt_input = lambda *_args: expected_url remote_url = self.app.prompt_gitea_existing_remote_url() self.assertEqual(remote_url, expected_url) def test_api_resolution_uses_giteas_advertised_ssh_url(self) -> None: self.app.prompt_secret = lambda *_args: "token" self.app.select_gitea_transport = lambda: "ssh" requested_urls = [] def fake_get(url: str, token: str): requested_urls.append((url, token)) return 200, "", { "ssh_url": "ssh://forge@ssh.example.com:2222/owner/project.git", "clone_url": "https://git.example.com/owner/project.git", } self.app.gitea_get_json = fake_get with mock.patch.dict( os.environ, {"GITEA_TOKEN": "", "GITEA_ACCESS_TOKEN": ""}, clear=False, ): remote_url = self.app.resolve_existing_gitea_url_via_api( "owner/project", "https://git.example.com" ) self.assertEqual( remote_url, "ssh://forge@ssh.example.com:2222/owner/project.git", ) self.assertEqual( requested_urls, [("https://git.example.com/api/v1/repos/owner/project", "token")], ) class RepositorySyncTests(unittest.TestCase): def setUp(self) -> None: self.app = git_tui.GitTuiApp.__new__(git_tui.GitTuiApp) self.app.status_message = "" self.app.show_output = lambda *_args: None self.app.show_command_result = lambda *_args: None self.original_cwd = pathlib.Path.cwd() self.temp_dir = tempfile.TemporaryDirectory() self.root = pathlib.Path(self.temp_dir.name) def tearDown(self) -> None: os.chdir(self.original_cwd) self.temp_dir.cleanup() def git(self, cwd: pathlib.Path, *args: str) -> str: completed = subprocess.run( ["git", *args], cwd=cwd, check=True, capture_output=True, text=True, ) return completed.stdout.strip() def init_worktree(self, path: pathlib.Path) -> None: path.mkdir() self.git(path, "init", "-b", "main") self.git(path, "config", "user.name", "Test User") self.git(path, "config", "user.email", "test@example.com") self.git(path, "config", "commit.gpgsign", "false") def test_sync_pushes_local_commit_to_empty_remote(self) -> None: remote = self.root / "remote.git" local = self.root / "local" remote.mkdir() self.git(remote, "init", "--bare") self.init_worktree(local) (local / "local.txt").write_text("local\n", encoding="utf-8") self.git(local, "add", "local.txt") self.git(local, "commit", "-m", "local") self.git(local, "remote", "add", "origin", str(remote)) os.chdir(local) self.assertTrue(self.app.sync_origin_repository()) self.assertEqual( self.git(remote, "rev-parse", "refs/heads/main"), self.git(local, "rev-parse", "HEAD"), ) def test_sync_populates_unborn_local_repository_from_remote(self) -> None: remote = self.root / "remote.git" seed = self.root / "seed" local = self.root / "local" remote.mkdir() self.git(remote, "init", "--bare") self.git(remote, "symbolic-ref", "HEAD", "refs/heads/main") self.init_worktree(seed) (seed / "remote.txt").write_text("remote\n", encoding="utf-8") self.git(seed, "add", "remote.txt") self.git(seed, "commit", "-m", "remote") self.git(seed, "remote", "add", "origin", str(remote)) self.git(seed, "push", "origin", "main") self.init_worktree(local) self.git(local, "remote", "add", "origin", str(remote)) os.chdir(local) self.assertTrue(self.app.sync_origin_repository()) self.assertEqual((local / "remote.txt").read_text(), "remote\n") self.assertEqual( self.git(local, "rev-parse", "HEAD"), self.git(remote, "rev-parse", "refs/heads/main"), ) def test_sync_merges_diverged_histories_and_pushes_result(self) -> None: remote = self.root / "remote.git" seed = self.root / "seed" local = self.root / "local" remote.mkdir() self.git(remote, "init", "--bare") self.git(remote, "symbolic-ref", "HEAD", "refs/heads/main") self.init_worktree(seed) (seed / "remote.txt").write_text("remote\n", encoding="utf-8") self.git(seed, "add", "remote.txt") self.git(seed, "commit", "-m", "remote") self.git(seed, "remote", "add", "origin", str(remote)) self.git(seed, "push", "origin", "main") self.init_worktree(local) (local / "local.txt").write_text("local\n", encoding="utf-8") self.git(local, "add", "local.txt") self.git(local, "commit", "-m", "local") self.git(local, "remote", "add", "origin", str(remote)) self.app.select_option_menu = lambda *_args: "merge" os.chdir(local) self.assertTrue(self.app.sync_origin_repository()) self.assertTrue((local / "local.txt").exists()) self.assertTrue((local / "remote.txt").exists()) self.assertEqual( self.git(local, "rev-parse", "HEAD"), self.git(remote, "rev-parse", "refs/heads/main"), ) class GiteaPublishTests(unittest.TestCase): def test_created_repository_can_keep_ssh_origin(self) -> None: app = git_tui.GitTuiApp.__new__(git_tui.GitTuiApp) app.status_message = "" prompt_values = iter(["owner/project", "https://git.example.com"]) app.prompt_input = lambda *_args: next(prompt_values) app.select_gitea_transport = lambda: "ssh" app.select_repository_visibility = lambda: False app.create_gitea_repository = lambda **_kwargs: ( True, { "clone_url": "https://git.example.com/owner/project.git", "ssh_url": "git@git.example.com:owner/project.git", "full_name": "owner/project", }, "", ) configured_urls = [] app.configure_origin_remote = lambda url: configured_urls.append(url) or True app.push_head_to_remote_branch = lambda *_args, **_kwargs: True app.current_local_branch = lambda: "main" app.show_output = lambda *_args: None with mock.patch.dict(os.environ, {"GITEA_TOKEN": "token"}, clear=False): self.assertTrue(app.publish_gitea_repository()) self.assertEqual( configured_urls, ["git@git.example.com:owner/project.git"], ) class MainMenuTests(unittest.TestCase): def test_remote_operations_and_disconnect_require_a_remote(self) -> None: app = git_tui.GitTuiApp.__new__(git_tui.GitTuiApp) app.has_any_remote = lambda: False action_names = [action for _, action in app.main_menu_items()] self.assertNotIn("push", action_names) self.assertNotIn("pull", action_names) self.assertNotIn("fetch", action_names) self.assertNotIn("disconnect_remote", action_names) def test_disconnect_is_available_when_a_remote_exists(self) -> None: app = git_tui.GitTuiApp.__new__(git_tui.GitTuiApp) app.has_any_remote = lambda: True action_names = [action for _, action in app.main_menu_items()] self.assertIn("push", action_names) self.assertIn("pull", action_names) self.assertIn("fetch", action_names) self.assertIn("disconnect_remote", action_names) if __name__ == "__main__": unittest.main()