"""Tests for myagents.commands.uninstall.""" from pathlib import Path import pytest from click.testing import CliRunner from myagents.commands import uninstall as un_mod @pytest.fixture() def fake_home(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: home = tmp_path / "home" home.mkdir() monkeypatch.setattr(Path, "home", staticmethod(lambda: home)) monkeypatch.setattr(un_mod, "_pip_uninstall", lambda: []) monkeypatch.setattr( "myagents.commands.completion_install.uninstall_completions", lambda progs, **kw: [], ) return home def _populate(home: Path) -> None: local_bin = home / ".local" / "bin" (local_bin / "completions").mkdir(parents=True) for name in ("xiaohe", "myclaude", "mytoolkit", "metabot", "mb"): (local_bin / name).write_text("#!/bin/sh\n") (local_bin / "completions" / "metabot").write_text("comp") (local_bin / "completions" / "_metabot").write_text("comp") (home / ".xiaohe" / "agent").mkdir(parents=True) (home / ".xiaohe" / "agent" / "config.json").write_text("{}") (home / "workspace").mkdir() app = home / "Desktop" / "Xiaohe Agent.app" / "Contents" app.mkdir(parents=True) class TestUninstall: def test_removes_cli_layer_keeps_xiaohe_and_workspace( self, fake_home: Path ) -> None: _populate(fake_home) result = CliRunner().invoke(un_mod.uninstall_cmd, ["--yes"]) assert result.exit_code == 0 local_bin = fake_home / ".local" / "bin" assert not (local_bin / "xiaohe").exists() assert not (local_bin / "myclaude").exists() assert not (local_bin / "metabot").exists() assert not (local_bin / "completions").exists() # empty dir cleaned assert not (fake_home / "Desktop" / "Xiaohe Agent.app").exists() assert (fake_home / ".xiaohe" / "agent" / "config.json").is_file() assert (fake_home / "workspace").is_dir() def test_all_removes_xiaohe_dir(self, fake_home: Path) -> None: _populate(fake_home) result = CliRunner().invoke( un_mod.uninstall_cmd, ["--all", "--yes"], input="y\ndelete-all\n" ) assert result.exit_code == 0 assert not (fake_home / ".xiaohe").exists() assert (fake_home / "workspace").is_dir() # workspace never touched def test_all_requires_full_chain_even_with_yes(self, fake_home: Path) -> None: _populate(fake_home) # --yes skips only the first gate; declining the second cancels. result = CliRunner().invoke( un_mod.uninstall_cmd, ["--all", "--yes"], input="n\n" ) assert result.exit_code == 0 assert "Cancelled" in result.output assert (fake_home / ".xiaohe").exists() def test_all_aborts_on_wrong_phrase(self, fake_home: Path) -> None: _populate(fake_home) result = CliRunner().invoke( un_mod.uninstall_cmd, ["--all", "--yes"], input="y\nnope\n" ) assert result.exit_code == 0 assert "Cancelled" in result.output assert (fake_home / ".xiaohe").exists() def test_cancelled_keeps_everything(self, fake_home: Path) -> None: _populate(fake_home) result = CliRunner().invoke(un_mod.uninstall_cmd, [], input="n\n") assert result.exit_code == 0 assert "Cancelled" in result.output assert (fake_home / ".local" / "bin" / "xiaohe").exists()