test_plugin_registry.py
python
| 1 | """Unit tests for muse.plugins.registry — resolve_plugin, read_domain, registered_domains.""" |
| 2 | from __future__ import annotations |
| 3 | |
| 4 | import json |
| 5 | import pathlib |
| 6 | |
| 7 | import pytest |
| 8 | |
| 9 | from muse.core.errors import MuseCLIError |
| 10 | from muse.domain import MuseDomainPlugin |
| 11 | from muse.plugins.music.plugin import MusicPlugin |
| 12 | from muse.plugins.registry import read_domain, registered_domains, resolve_plugin |
| 13 | |
| 14 | |
| 15 | def _make_repo(tmp_path: pathlib.Path, domain: str = "music") -> pathlib.Path: |
| 16 | """Scaffold a minimal .muse/repo.json so registry helpers can run.""" |
| 17 | muse_dir = tmp_path / ".muse" |
| 18 | muse_dir.mkdir() |
| 19 | (muse_dir / "repo.json").write_text( |
| 20 | json.dumps({"repo_id": "test-id", "schema_version": "2", "domain": domain}) |
| 21 | ) |
| 22 | return tmp_path |
| 23 | |
| 24 | |
| 25 | class TestReadDomain: |
| 26 | def test_returns_stored_domain(self, tmp_path: pathlib.Path) -> None: |
| 27 | root = _make_repo(tmp_path, domain="music") |
| 28 | assert read_domain(root) == "music" |
| 29 | |
| 30 | def test_defaults_to_music_when_key_missing(self, tmp_path: pathlib.Path) -> None: |
| 31 | muse_dir = tmp_path / ".muse" |
| 32 | muse_dir.mkdir() |
| 33 | (muse_dir / "repo.json").write_text(json.dumps({"repo_id": "x"})) |
| 34 | assert read_domain(tmp_path) == "music" |
| 35 | |
| 36 | def test_defaults_to_music_when_repo_json_absent(self, tmp_path: pathlib.Path) -> None: |
| 37 | (tmp_path / ".muse").mkdir() |
| 38 | assert read_domain(tmp_path) == "music" |
| 39 | |
| 40 | def test_defaults_to_music_when_muse_dir_absent(self, tmp_path: pathlib.Path) -> None: |
| 41 | assert read_domain(tmp_path) == "music" |
| 42 | |
| 43 | |
| 44 | class TestResolvePlugin: |
| 45 | def test_returns_music_plugin_for_music_domain(self, tmp_path: pathlib.Path) -> None: |
| 46 | root = _make_repo(tmp_path, domain="music") |
| 47 | plugin = resolve_plugin(root) |
| 48 | assert isinstance(plugin, MusicPlugin) |
| 49 | |
| 50 | def test_returned_plugin_satisfies_protocol(self, tmp_path: pathlib.Path) -> None: |
| 51 | root = _make_repo(tmp_path, domain="music") |
| 52 | plugin = resolve_plugin(root) |
| 53 | assert isinstance(plugin, MuseDomainPlugin) |
| 54 | |
| 55 | def test_raises_for_unknown_domain(self, tmp_path: pathlib.Path) -> None: |
| 56 | root = _make_repo(tmp_path, domain="unknown-domain") |
| 57 | with pytest.raises(MuseCLIError, match="unknown-domain"): |
| 58 | resolve_plugin(root) |
| 59 | |
| 60 | def test_raises_error_mentions_registered_domains(self, tmp_path: pathlib.Path) -> None: |
| 61 | root = _make_repo(tmp_path, domain="bogus") |
| 62 | with pytest.raises(MuseCLIError, match="music"): |
| 63 | resolve_plugin(root) |
| 64 | |
| 65 | def test_defaults_to_music_plugin_when_no_domain_key(self, tmp_path: pathlib.Path) -> None: |
| 66 | muse_dir = tmp_path / ".muse" |
| 67 | muse_dir.mkdir() |
| 68 | (muse_dir / "repo.json").write_text(json.dumps({"repo_id": "x"})) |
| 69 | plugin = resolve_plugin(tmp_path) |
| 70 | assert isinstance(plugin, MusicPlugin) |
| 71 | |
| 72 | |
| 73 | class TestRegisteredDomains: |
| 74 | def test_includes_music(self) -> None: |
| 75 | assert "music" in registered_domains() |
| 76 | |
| 77 | def test_returns_sorted_list(self) -> None: |
| 78 | domains = registered_domains() |
| 79 | assert domains == sorted(domains) |
| 80 | |
| 81 | def test_returns_list_of_strings(self) -> None: |
| 82 | domains = registered_domains() |
| 83 | assert all(isinstance(d, str) for d in domains) |