55import pytest
66
77import code_assistant_manager .cli .skills_commands as skills_commands
8+ from code_assistant_manager .skills import Skill
89
910
1011@pytest .fixture
@@ -17,19 +18,38 @@ def __init__(self):
1718 self .installs = []
1819 self .uninstalls = []
1920 self .skills = {}
21+ self .created_skills = []
22+ self .updated_skills = []
23+ self .deleted_skills = []
2024
2125 def sync_installed_status (self , app ):
2226 self .synced .append (app )
2327
2428 def get_all (self ):
2529 return self .skills
2630
31+ def get (self , key ):
32+ return self .skills .get (key )
33+
2734 def install (self , key , app ):
2835 self .installs .append ((key , app ))
2936
3037 def uninstall (self , key , app ):
3138 self .uninstalls .append ((key , app ))
3239
40+ def create (self , skill ):
41+ self .created_skills .append (skill )
42+ self .skills [skill .key ] = skill
43+
44+ def update (self , skill ):
45+ self .updated_skills .append (skill )
46+ self .skills [skill .key ] = skill
47+
48+ def delete (self , key ):
49+ self .deleted_skills .append (key )
50+ if key in self .skills :
51+ del self .skills [key ]
52+
3353 manager = DummyManager ()
3454 monkeypatch .setattr (skills_commands , "_get_skill_manager" , lambda : manager )
3555 return manager
@@ -73,3 +93,152 @@ def get_all(self):
7393 captured = capsys .readouterr ().out
7494 for app in skills_commands .VALID_APP_TYPES :
7595 assert f"{ app .capitalize ()} " in captured
96+
97+
98+ # Additional tests for skill commands
99+
100+
101+ def test_list_skills_empty (dummy_skill_manager , capsys ):
102+ """list_skills shows message when no skills exist."""
103+ skills_commands .list_skills (app_type = "claude" )
104+ captured = capsys .readouterr ().out
105+ assert "No skills found" in captured
106+
107+
108+ def test_list_skills_with_skills (dummy_skill_manager , capsys ):
109+ """list_skills shows all skills with their status."""
110+ dummy_skill_manager .skills = {
111+ "test-skill" : Skill (
112+ key = "test-skill" ,
113+ name = "Test Skill" ,
114+ description = "A test skill" ,
115+ directory = "/path/to/skill" ,
116+ installed = True ,
117+ ),
118+ "another-skill" : Skill (
119+ key = "another-skill" ,
120+ name = "Another Skill" ,
121+ description = "Another skill" ,
122+ directory = "/path/to/another" ,
123+ installed = False ,
124+ ),
125+ }
126+
127+ skills_commands .list_skills (app_type = "claude" )
128+ captured = capsys .readouterr ().out
129+ assert "Test Skill" in captured
130+ assert "Another Skill" in captured
131+ assert "test-skill" in captured
132+ assert "another-skill" in captured
133+
134+
135+ def test_view_skill_success (dummy_skill_manager , capsys ):
136+ """view_skill displays skill content."""
137+ dummy_skill_manager .skills = {
138+ "test-skill" : Skill (
139+ key = "test-skill" ,
140+ name = "Test Skill" ,
141+ description = "A test skill description" ,
142+ directory = "/path/to/skill" ,
143+ repo_owner = "owner" ,
144+ repo_name = "repo" ,
145+ installed = True ,
146+ )
147+ }
148+
149+ skills_commands .view_skill ("test-skill" )
150+ captured = capsys .readouterr ().out
151+ assert "Test Skill" in captured
152+ assert "A test skill description" in captured
153+ assert "owner/repo" in captured
154+
155+
156+ def test_view_skill_not_found (dummy_skill_manager , capsys ):
157+ """view_skill raises exit when skill not found."""
158+ with pytest .raises (skills_commands .typer .Exit ):
159+ skills_commands .view_skill ("nonexistent" )
160+
161+ captured = capsys .readouterr ().out
162+ assert "not found" in captured
163+
164+
165+ def test_create_skill_success (dummy_skill_manager , capsys ):
166+ """create_skill creates a new skill."""
167+ skills_commands .create_skill (
168+ skill_key = "new-skill" ,
169+ name = "New Skill" ,
170+ description = "A new skill" ,
171+ directory = "/path/to/skill" ,
172+ )
173+
174+ captured = capsys .readouterr ().out
175+ assert "created" in captured .lower ()
176+ assert len (dummy_skill_manager .created_skills ) == 1
177+ assert dummy_skill_manager .created_skills [0 ].key == "new-skill"
178+
179+
180+ def test_delete_skill_success (dummy_skill_manager , capsys ):
181+ """delete_skill removes a skill."""
182+ dummy_skill_manager .skills = {
183+ "test-skill" : Skill (
184+ key = "test-skill" ,
185+ name = "Test Skill" ,
186+ description = "A test skill" ,
187+ directory = "/path/to/skill" ,
188+ )
189+ }
190+
191+ skills_commands .delete_skill ("test-skill" , force = True )
192+ captured = capsys .readouterr ().out
193+ assert "deleted" in captured .lower ()
194+ assert "test-skill" in dummy_skill_manager .deleted_skills
195+
196+
197+ def test_delete_skill_not_found (dummy_skill_manager , capsys ):
198+ """delete_skill fails when skill not found."""
199+ with pytest .raises (skills_commands .typer .Exit ):
200+ skills_commands .delete_skill ("nonexistent" , force = True )
201+
202+ captured = capsys .readouterr ().out
203+ assert "not found" in captured
204+
205+
206+ def test_uninstall_skill_success (dummy_skill_manager , tmp_path , monkeypatch ):
207+ """uninstall_skill removes skill from app."""
208+ install_dirs = {app : tmp_path / app for app in skills_commands .VALID_APP_TYPES }
209+ for directory in install_dirs .values ():
210+ directory .mkdir ()
211+ monkeypatch .setattr (skills_commands , "SKILL_INSTALL_DIRS" , install_dirs )
212+
213+ skills_commands .uninstall_skill ("test-skill" , app_type = "claude" )
214+ assert dummy_skill_manager .uninstalls == [("test-skill" , "claude" )]
215+
216+
217+ def test_uninstall_skill_multiple_apps (dummy_skill_manager , tmp_path , monkeypatch ):
218+ """uninstall_skill removes skill from multiple apps."""
219+ install_dirs = {app : tmp_path / app for app in skills_commands .VALID_APP_TYPES }
220+ for directory in install_dirs .values ():
221+ directory .mkdir ()
222+ monkeypatch .setattr (skills_commands , "SKILL_INSTALL_DIRS" , install_dirs )
223+
224+ skills_commands .uninstall_skill ("test-skill" , app_type = "claude,codex" )
225+ assert dummy_skill_manager .uninstalls == [
226+ ("test-skill" , "claude" ),
227+ ("test-skill" , "codex" ),
228+ ]
229+
230+
231+ def test_list_repos (dummy_skill_manager , capsys , monkeypatch ):
232+ """list_repos shows configured skill repositories."""
233+
234+ # Create a mock repos file
235+ class MockManager :
236+ def get_repos (self ):
237+ return []
238+
239+ monkeypatch .setattr (skills_commands , "_get_skill_manager" , lambda : MockManager ())
240+
241+ skills_commands .list_repos ()
242+ captured = capsys .readouterr ().out
243+ # Should show header or "No repositories" message
244+ assert "repo" in captured .lower () or captured .strip () != ""
0 commit comments