mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-04-25 11:18:22 +00:00
* fix(skills): support parsing multiline YAML strings in SKILL.md frontmatter * test(skills): add tests for multiline YAML descriptions
120 lines
4.7 KiB
Python
120 lines
4.7 KiB
Python
"""Tests for skill file parser."""
|
|
|
|
from pathlib import Path
|
|
|
|
from deerflow.skills.parser import parse_skill_file
|
|
|
|
|
|
def _write_skill(tmp_path: Path, content: str) -> Path:
|
|
"""Write a SKILL.md file and return its path."""
|
|
skill_file = tmp_path / "SKILL.md"
|
|
skill_file.write_text(content, encoding="utf-8")
|
|
return skill_file
|
|
|
|
|
|
class TestParseSkillFile:
|
|
def test_valid_skill_file(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: my-skill\ndescription: A test skill\nlicense: MIT\n---\n\n# My Skill\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "public")
|
|
assert result is not None
|
|
assert result.name == "my-skill"
|
|
assert result.description == "A test skill"
|
|
assert result.license == "MIT"
|
|
assert result.category == "public"
|
|
assert result.enabled is True
|
|
assert result.skill_dir == tmp_path
|
|
assert result.skill_file == skill_file
|
|
|
|
def test_missing_name_returns_none(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\ndescription: A test skill\n---\n\nBody\n",
|
|
)
|
|
assert parse_skill_file(skill_file, "public") is None
|
|
|
|
def test_missing_description_returns_none(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: my-skill\n---\n\nBody\n",
|
|
)
|
|
assert parse_skill_file(skill_file, "public") is None
|
|
|
|
def test_no_front_matter_returns_none(self, tmp_path):
|
|
skill_file = _write_skill(tmp_path, "# Just a markdown file\n\nNo front matter here.\n")
|
|
assert parse_skill_file(skill_file, "public") is None
|
|
|
|
def test_nonexistent_file_returns_none(self, tmp_path):
|
|
skill_file = tmp_path / "SKILL.md"
|
|
assert parse_skill_file(skill_file, "public") is None
|
|
|
|
def test_wrong_filename_returns_none(self, tmp_path):
|
|
wrong_file = tmp_path / "README.md"
|
|
wrong_file.write_text("---\nname: test\ndescription: test\n---\n", encoding="utf-8")
|
|
assert parse_skill_file(wrong_file, "public") is None
|
|
|
|
def test_optional_license_field(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: my-skill\ndescription: A test skill\n---\n\nBody\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "custom")
|
|
assert result is not None
|
|
assert result.license is None
|
|
assert result.category == "custom"
|
|
|
|
def test_custom_relative_path(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: nested-skill\ndescription: Nested\n---\n\nBody\n",
|
|
)
|
|
rel = Path("group/nested-skill")
|
|
result = parse_skill_file(skill_file, "public", relative_path=rel)
|
|
assert result is not None
|
|
assert result.relative_path == rel
|
|
|
|
def test_default_relative_path_is_parent_name(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: my-skill\ndescription: Test\n---\n\nBody\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "public")
|
|
assert result is not None
|
|
assert result.relative_path == Path(tmp_path.name)
|
|
|
|
def test_colons_in_description(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: my-skill\ndescription: A skill: does things\n---\n\nBody\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "public")
|
|
assert result is not None
|
|
assert result.description == "A skill: does things"
|
|
|
|
def test_multiline_yaml_folded_description(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: multiline-skill\ndescription: >\n This is a multiline\n description for a skill.\n\n It spans multiple lines.\nlicense: MIT\n---\n\nBody\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "public")
|
|
assert result is not None
|
|
assert result.name == "multiline-skill"
|
|
assert result.description == "This is a multiline description for a skill.\n\nIt spans multiple lines."
|
|
assert result.license == "MIT"
|
|
|
|
def test_multiline_yaml_literal_description(self, tmp_path):
|
|
skill_file = _write_skill(
|
|
tmp_path,
|
|
"---\nname: pipe-skill\ndescription: |\n First line.\n Second line.\n---\n\nBody\n",
|
|
)
|
|
result = parse_skill_file(skill_file, "public")
|
|
assert result is not None
|
|
assert result.name == "pipe-skill"
|
|
assert result.description == "First line.\nSecond line."
|
|
|
|
def test_empty_front_matter_returns_none(self, tmp_path):
|
|
skill_file = _write_skill(tmp_path, "---\n\n---\n\nBody\n")
|
|
assert parse_skill_file(skill_file, "public") is None
|