gabriel / muse public
test_cmd_hooks.py python
93 lines 3.2 KB
Raw
sha256:4802c0281407b5de70ce1b34bbe1d1cd055533cbd4b8be35861a6a3eb545c1dc feat(#192): Phase 1 — .musehooks.toml parser + `muse hooks list` Sonnet 5 patch 3 days ago
1 """Tests for ``muse hooks`` CLI — musehub#192 Phase 1: HK_03 (`muse hooks list`).
2
3 Phase 1 scope only: reads the tracked ``.musehooks.toml`` and prints its
4 contents. No local activation state yet (Phase 2) and no ``muse commit``
5 integration yet (Phase 3).
6 """
7
8 from __future__ import annotations
9
10 import json
11 import pathlib
12
13 from tests.cli_test_helper import CliRunner
14
15 runner = CliRunner()
16
17
18 def _invoke(path: pathlib.Path, args: list[str]):
19 import os
20 saved = os.getcwd()
21 try:
22 os.chdir(path)
23 return runner.invoke(None, args)
24 finally:
25 os.chdir(saved)
26
27
28 def _init_repo(path: pathlib.Path, domain: str = "code") -> None:
29 r = _invoke(path, ["init", "--domain", domain])
30 assert r.exit_code == 0, r.output
31
32
33 def _write_hooks(path: pathlib.Path, content: str) -> None:
34 (path / ".musehooks.toml").write_text(content, encoding="utf-8")
35
36
37 class TestHooksListNoFile:
38 def test_no_musehooks_file_json_reports_empty(self, tmp_path: pathlib.Path) -> None:
39 _init_repo(tmp_path)
40 r = _invoke(tmp_path, ["hooks", "list", "--json"])
41 assert r.exit_code == 0, r.output
42 data = json.loads(r.output)
43 assert data["hooks"] == {}
44
45 def test_no_musehooks_file_text_says_none_defined(self, tmp_path: pathlib.Path) -> None:
46 _init_repo(tmp_path)
47 r = _invoke(tmp_path, ["hooks", "list"])
48 assert r.exit_code == 0, r.output
49 assert "no" in r.output.lower() or "none" in r.output.lower()
50
51
52 class TestHooksListWithFile:
53 def test_json_reports_pre_commit_commands(self, tmp_path: pathlib.Path) -> None:
54 _init_repo(tmp_path)
55 _write_hooks(
56 tmp_path,
57 '[pre-commit]\ncommands = ["muse agent-config status --json"]\n',
58 )
59 r = _invoke(tmp_path, ["hooks", "list", "--json"])
60 assert r.exit_code == 0, r.output
61 data = json.loads(r.output)
62 assert data["hooks"]["pre-commit"] == ["muse agent-config status --json"]
63
64 def test_text_mode_shows_hook_point_and_commands(self, tmp_path: pathlib.Path) -> None:
65 _init_repo(tmp_path)
66 _write_hooks(
67 tmp_path,
68 '[pre-commit]\ncommands = ["muse agent-config status --json"]\n',
69 )
70 r = _invoke(tmp_path, ["hooks", "list"])
71 assert r.exit_code == 0, r.output
72 assert "pre-commit" in r.output
73 assert "muse agent-config status --json" in r.output
74
75
76 class TestHooksListErrors:
77 def test_malformed_toml_exits_1_with_clear_message(self, tmp_path: pathlib.Path) -> None:
78 _init_repo(tmp_path)
79 _write_hooks(tmp_path, "[pre-commit\ncommands = [")
80 r = _invoke(tmp_path, ["hooks", "list", "--json"])
81 assert r.exit_code == 1
82 assert "parse error" in r.stderr.lower()
83
84 def test_unknown_hook_point_exits_1_with_clear_message(self, tmp_path: pathlib.Path) -> None:
85 _init_repo(tmp_path)
86 _write_hooks(tmp_path, '[bogus-point]\ncommands = ["echo hi"]\n')
87 r = _invoke(tmp_path, ["hooks", "list", "--json"])
88 assert r.exit_code == 1
89 assert "unknown hook point" in r.stderr.lower()
90
91 def test_not_a_repo_exits_2(self, tmp_path: pathlib.Path) -> None:
92 r = _invoke(tmp_path, ["hooks", "list", "--json"])
93 assert r.exit_code == 2
File History 1 commit
sha256:4802c0281407b5de70ce1b34bbe1d1cd055533cbd4b8be35861a6a3eb545c1dc feat(#192): Phase 1 — .musehooks.toml parser + `muse hooks list` Sonnet 5 patch 3 days ago