|
| 1 | +from pathlib import Path |
| 2 | + |
| 3 | +import pytest |
| 4 | +from click.testing import CliRunner |
| 5 | + |
| 6 | +from shiny import _main_skills |
| 7 | +from shiny._main import main |
| 8 | + |
| 9 | +SKILLS_DIR = Path(_main_skills.__file__).parent / ".agents" / "skills" |
| 10 | + |
| 11 | + |
| 12 | +def test_skills_list_shows_names_and_descriptions() -> None: |
| 13 | + result = CliRunner().invoke(main, ["skills", "list"]) |
| 14 | + |
| 15 | + assert result.exit_code == 0 |
| 16 | + assert "debugging" in result.output |
| 17 | + # The one-line description from the skill's frontmatter is shown |
| 18 | + debugging_line = next( |
| 19 | + line for line in result.output.splitlines() if "debugging" in line |
| 20 | + ) |
| 21 | + assert "test mode" in debugging_line or "debugging a Shiny" in debugging_line |
| 22 | + |
| 23 | + |
| 24 | +def test_skills_get_prints_skill_md() -> None: |
| 25 | + result = CliRunner().invoke(main, ["skills", "get", "debugging"]) |
| 26 | + |
| 27 | + assert result.exit_code == 0 |
| 28 | + expected = (SKILLS_DIR / "debugging" / "SKILL.md").read_text() |
| 29 | + assert result.output == expected |
| 30 | + |
| 31 | + |
| 32 | +def test_skills_get_unknown_name_lists_available_skills() -> None: |
| 33 | + result = CliRunner().invoke(main, ["skills", "get", "does-not-exist"]) |
| 34 | + |
| 35 | + assert result.exit_code != 0 |
| 36 | + assert "does-not-exist" in result.output |
| 37 | + assert "debugging" in result.output |
| 38 | + |
| 39 | + |
| 40 | +def test_skills_path_prints_skill_directory() -> None: |
| 41 | + result = CliRunner().invoke(main, ["skills", "path", "debugging"]) |
| 42 | + |
| 43 | + assert result.exit_code == 0 |
| 44 | + assert result.output == f"{SKILLS_DIR / 'debugging'}\n" |
| 45 | + assert Path(result.output.strip()).is_absolute() |
| 46 | + |
| 47 | + |
| 48 | +def test_skills_path_unknown_name_lists_available_skills() -> None: |
| 49 | + result = CliRunner().invoke(main, ["skills", "path", "does-not-exist"]) |
| 50 | + |
| 51 | + assert result.exit_code != 0 |
| 52 | + assert "does-not-exist" in result.output |
| 53 | + assert "debugging" in result.output |
| 54 | + |
| 55 | + |
| 56 | +def test_skills_list_with_empty_skills_dir( |
| 57 | + monkeypatch: pytest.MonkeyPatch, tmp_path: Path |
| 58 | +) -> None: |
| 59 | + monkeypatch.setattr(_main_skills, "SKILLS_DIR", tmp_path) |
| 60 | + |
| 61 | + result = CliRunner().invoke(main, ["skills", "list"]) |
| 62 | + |
| 63 | + assert result.exit_code == 0 |
| 64 | + assert "No skills" in result.output |
| 65 | + |
| 66 | + |
| 67 | +def test_skills_get_with_missing_skills_dir( |
| 68 | + monkeypatch: pytest.MonkeyPatch, tmp_path: Path |
| 69 | +) -> None: |
| 70 | + monkeypatch.setattr(_main_skills, "SKILLS_DIR", tmp_path / "nope") |
| 71 | + |
| 72 | + result = CliRunner().invoke(main, ["skills", "get", "debugging"]) |
| 73 | + |
| 74 | + assert result.exit_code != 0 |
| 75 | + assert "No skills" in result.output |
0 commit comments