Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ovos_core/skill_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ def _load_plugin_skill(self, skill_id, skill_plugin):
skill_loader = self._get_plugin_skill_loader(skill_id, skill_class=skill_plugin)
try:
load_status = skill_loader.load(skill_plugin)
if load_status:
self.bus.emit(Message("mycroft.skill.loaded", {"skill_id": skill_id}))
except Exception:
LOG.exception(f'Load of skill {skill_id} failed!')
load_status = False
Expand Down
102 changes: 102 additions & 0 deletions test/unittests/test_skill_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,105 @@ def test_activate_skill(self):
self.skill_manager.activate_skill(message)
test_skill_loader.activate.assert_called_once()
message.response.assert_called_once()

def test_load_plugin_skill_success(self):
"""Test successful plugin skill loading emits the correct message."""
skill_id = 'test.plugin.skill'
mock_plugin = Mock()

# Setup mock loader following existing patterns
mock_loader = Mock(spec=SkillLoader)
mock_loader.skill_id = skill_id
mock_loader.load.return_value = True

# Mock _get_plugin_skill_loader to return our mock
self.skill_manager._get_plugin_skill_loader = Mock(return_value=mock_loader)

# Reset message tracking
self.message_bus_mock.message_types = []
self.message_bus_mock.message_data = []
self.skill_manager.plugin_skills = {}

# Call the method
result = self.skill_manager._load_plugin_skill(skill_id, mock_plugin)

# Verify message was emitted
self.assertIn('mycroft.skill.loaded', self.message_bus_mock.message_types)
loaded_msg_idx = self.message_bus_mock.message_types.index('mycroft.skill.loaded')
self.assertEqual(
{'skill_id': skill_id},
self.message_bus_mock.message_data[loaded_msg_idx]
)

# Verify loader was called
mock_loader.load.assert_called_once_with(mock_plugin)

# Verify skill was added to plugin_skills
self.assertIn(skill_id, self.skill_manager.plugin_skills)
self.assertEqual(mock_loader, self.skill_manager.plugin_skills[skill_id])

# Verify return value
self.assertEqual(result, mock_loader)

def test_load_plugin_skill_failure(self):
"""Test failed plugin skill loading is handled gracefully."""
skill_id = 'test.failing.skill'
mock_plugin = Mock()

# Setup mock loader to raise exception
mock_loader = Mock(spec=SkillLoader)
mock_loader.skill_id = skill_id
mock_loader.load.side_effect = Exception("Skill load failed!")

# Mock _get_plugin_skill_loader to return our mock
self.skill_manager._get_plugin_skill_loader = Mock(return_value=mock_loader)

# Reset message tracking
self.message_bus_mock.message_types = []
self.message_bus_mock.message_data = []
self.skill_manager.plugin_skills = {}

# Call the method
result = self.skill_manager._load_plugin_skill(skill_id, mock_plugin)

# Verify NO success message was emitted
self.assertNotIn('mycroft.skill.loaded', self.message_bus_mock.message_types)

# Verify exception was logged
self.log_mock.exception.assert_called_once()

# Verify skill was still added to plugin_skills (even on failure)
self.assertIn(skill_id, self.skill_manager.plugin_skills)
self.assertEqual(mock_loader, self.skill_manager.plugin_skills[skill_id])

# Verify return value is None on failure
self.assertIsNone(result)

def test_load_plugin_skill_returns_false(self):
"""Test plugin skill loading that returns False (load failed gracefully)."""
skill_id = 'test.false.skill'
mock_plugin = Mock()

# Setup mock loader to return False (failed but no exception)
mock_loader = Mock(spec=SkillLoader)
mock_loader.skill_id = skill_id
mock_loader.load.return_value = False

# Mock _get_plugin_skill_loader to return our mock
self.skill_manager._get_plugin_skill_loader = Mock(return_value=mock_loader)

# Reset message tracking
self.message_bus_mock.message_types = []
self.skill_manager.plugin_skills = {}

# Call the method
result = self.skill_manager._load_plugin_skill(skill_id, mock_plugin)

# Verify NO success message was emitted (load returned False)
self.assertNotIn('mycroft.skill.loaded', self.message_bus_mock.message_types)

# Verify skill was added to plugin_skills
self.assertIn(skill_id, self.skill_manager.plugin_skills)

# Verify return value is None when load returns False
self.assertIsNone(result)
Loading