Files
AIPass/src/skills/tests/test_validator.py
T
AIOSAI 330708695d ✨ feat(skills): implement full skills system with three-tier architecture
- add foundational directory structure under src/skills with apps, modules, handlers, catalog, templates, tests, and trinity files
- support three skill tiers: markdown-only, markdown+handler.py, and full 3-layer apps/modules/handlers
- implement skill discovery scanning search paths (.aipass/skills, ~/.aipass/skills, src/skills/catalog)
- support SKILL.md with YAML frontmatter, compatible with OpenClaw format
- implement loader to parse full SKILL.md and optionally import handler.py module
- implement runner to execute skill handlers or display markdown instructions if no handler
- add skill creator scaffolding from tiered templates with placeholder substitution
- add skill registry for caching discovered skills and lookup by name
- add validator handler to check pip packages, CLI binaries, and environment config requirements
- add built-in test skills: github (markdown), system_status (handler), drone_commands (full 3-layer)
- implement drone_commands skill with subprocess executor, output parser, and command runner modules
- provide detailed README documenting architecture, usage, SKILL.md format, and commands
- add comprehensive unit and integration tests covering discovery, loading, running, validation, and lifecycle
- create seedgo standards pack with skill format, handler contract, and structure checks and documentation
- use consistent coding standards: handlers return dicts and never print; modules can print for orchestration
- enable drone routing with `drone @skills <command>` supporting list, info, run, create, validate commands
2026-03-07 12:15:29 -08:00

90 lines
3.0 KiB
Python

# ===================AIPASS====================
# META DATA HEADER
# Name: test_validator.py - Unit tests for skills validator
# Date: 2026-03-07
# Version: 1.0.0
# Category: skills/tests
# =============================================
"""Tests for the skills validator handler."""
import sys
from pathlib import Path
import pytest
skills_root = Path(__file__).resolve().parent.parent.parent
if str(skills_root) not in sys.path:
sys.path.insert(0, str(skills_root))
from skills.apps.handlers.validator import validate_skill
class TestValidateSkill:
def test_no_requirements(self):
result = validate_skill({})
assert result["valid"] is True
assert result["missing_pip"] == []
assert result["missing_bins"] == []
assert result["missing_config"] == []
def test_empty_requirements(self):
result = validate_skill({"requires": {"pip": [], "bins": [], "config": []}})
assert result["valid"] is True
def test_installed_pip_package(self):
# sys is always available
result = validate_skill({"requires": {"pip": ["sys"]}})
assert result["valid"] is True
assert result["missing_pip"] == []
def test_missing_pip_package(self):
result = validate_skill({"requires": {"pip": ["nonexistent_pkg_xyz_123"]}})
assert result["valid"] is False
assert "nonexistent_pkg_xyz_123" in result["missing_pip"]
def test_available_binary(self):
# python3 should be on PATH
result = validate_skill({"requires": {"bins": ["python3"]}})
assert result["valid"] is True
assert result["missing_bins"] == []
def test_missing_binary(self):
result = validate_skill({"requires": {"bins": ["nonexistent_bin_xyz"]}})
assert result["valid"] is False
assert "nonexistent_bin_xyz" in result["missing_bins"]
def test_missing_config(self):
result = validate_skill({"requires": {"config": ["NONEXISTENT_VAR_XYZ"]}})
assert result["valid"] is False
assert "NONEXISTENT_VAR_XYZ" in result["missing_config"]
def test_set_config(self):
import os
os.environ["_TEST_SKILLS_VAR"] = "value"
try:
result = validate_skill({"requires": {"config": ["_TEST_SKILLS_VAR"]}})
assert result["valid"] is True
assert result["missing_config"] == []
finally:
del os.environ["_TEST_SKILLS_VAR"]
def test_mixed_pass_fail(self):
result = validate_skill({
"requires": {
"pip": ["sys"],
"bins": ["nonexistent_bin_xyz"],
"config": [],
}
})
assert result["valid"] is False
assert result["missing_pip"] == []
assert "nonexistent_bin_xyz" in result["missing_bins"]
def test_return_structure(self):
result = validate_skill({})
assert "valid" in result
assert "missing_pip" in result
assert "missing_bins" in result
assert "missing_config" in result