diff --git a/gsd-openclaw/tests/test_skill_md.py b/gsd-openclaw/tests/test_skill_md.py new file mode 100644 index 0000000..bc2bdf4 --- /dev/null +++ b/gsd-openclaw/tests/test_skill_md.py @@ -0,0 +1,67 @@ +""" +Tests for SKILL.md validation. +Task 1: Test SKILL.md file exists. +Task 2: Test SKILL.md has valid YAML frontmatter. +Task 3: Test SKILL.md has name field. +Task 4: Test SKILL.md has description field. +Task 5: Test description contains /gsd: pattern for triggering. +""" +import pytest +from pathlib import Path +import yaml + + +class TestSkillMd: + """Tests for SKILL.md structure and trigger patterns.""" + + @property + def skill_path(self) -> Path: + """Get path to SKILL.md.""" + return Path(__file__).parent.parent / "skill" / "SKILL.md" + + def test_skill_md_exists(self): + """SKILL.md file exists at skill/SKILL.md.""" + assert self.skill_path.exists(), f"SKILL.md not found at {self.skill_path}" + + def test_skill_md_has_valid_frontmatter(self): + """SKILL.md has valid YAML frontmatter between --- delimiters.""" + content = self.skill_path.read_text(encoding="utf-8") + + # Check file starts with --- + assert content.startswith("---\n"), "SKILL.md must start with '---' frontmatter delimiter" + + # Find closing delimiter + parts = content.split("---\n", 2) + assert len(parts) >= 3, "SKILL.md must have opening and closing '---' delimiters" + + # Parse frontmatter as YAML + frontmatter_text = parts[1].strip() + frontmatter = yaml.safe_load(frontmatter_text) + assert isinstance(frontmatter, dict), "Frontmatter must be valid YAML" + + def test_skill_md_has_name_field(self): + """SKILL.md frontmatter contains 'name' field.""" + frontmatter = self._parse_frontmatter() + assert "name" in frontmatter, "Frontmatter must contain 'name' field" + assert isinstance(frontmatter["name"], str), "'name' must be a string" + assert len(frontmatter["name"]) > 0, "'name' must not be empty" + + def test_skill_md_has_description_field(self): + """SKILL.md frontmatter contains 'description' field.""" + frontmatter = self._parse_frontmatter() + assert "description" in frontmatter, "Frontmatter must contain 'description' field" + assert isinstance(frontmatter["description"], str), "'description' must be a string" + assert len(frontmatter["description"]) > 0, "'description' must not be empty" + + def test_skill_md_description_contains_gsd_pattern(self): + """SKILL.md description contains /gsd: pattern for trigger matching.""" + frontmatter = self._parse_frontmatter() + description = frontmatter.get("description", "") + assert "/gsd:" in description, "Description must contain '/gsd:' pattern for OpenClaw trigger matching" + + def _parse_frontmatter(self) -> dict: + """Parse and return frontmatter from SKILL.md.""" + content = self.skill_path.read_text(encoding="utf-8") + parts = content.split("---\n", 2) + frontmatter_text = parts[1].strip() + return yaml.safe_load(frontmatter_text)