blob: b3a1ce638fb47c15a3a386e38df17f1eb0027a19 [file]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2026 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import unittest
import skill_linter
class TestSkillLinter(unittest.TestCase):
def test_suggest_valid_name(self) -> None:
self.assertEqual(
skill_linter._suggest_valid_name("Valid-Name"), "valid-name"
)
self.assertEqual(
skill_linter._suggest_valid_name("Name_With_Underscores"),
"name-with-underscores",
)
self.assertEqual(
skill_linter._suggest_valid_name("Invalid@Chars!"), "invalidchars"
)
self.assertEqual(skill_linter._suggest_valid_name("a" * 100), "a" * 64)
def test_pre_process(self) -> None:
# Test list item indentation standardization
text = "- item"
self.assertEqual(skill_linter._pre_process(text, 4), "- item")
text = "1. item"
self.assertEqual(skill_linter._pre_process(text, 2), "1. item")
self.assertEqual(skill_linter._pre_process(text, 4), "1. item")
# Test that code blocks are ignored
text = '```diff\ndeps = [\n- "//src/lib/ddk"\n]\n```'
self.assertEqual(skill_linter._pre_process(text, 4), text)
text = "```markdown\n- Item 1\n* Item 2\n+ Item 3\n1. Numbered\n```"
self.assertEqual(skill_linter._pre_process(text, 4), text)
text = "```markdown\n# Header 1\n## Header 2\n```"
self.assertEqual(skill_linter._pre_process(text, 4), text)
def test_post_process(self) -> None:
# Test trailing whitespace removal and newlines
text = "line with spaces \nline 2"
self.assertEqual(
skill_linter._post_process(text), "line with spaces \nline 2\n"
)
text = "line\n\n\nline2"
self.assertEqual(skill_linter._post_process(text), "line\n\nline2\n")
def test_validate_name(self) -> None:
meta = {"name": "valid-name"}
errors, fixes = skill_linter._validate_name(meta, fixit=False)
self.assertEqual(errors, [])
self.assertEqual(fixes, [])
meta = {"name": "Invalid Name"}
errors, fixes = skill_linter._validate_name(meta, fixit=False)
self.assertTrue(len(errors) > 0)
meta = {"name": "Invalid Name"}
errors, fixes = skill_linter._validate_name(meta, fixit=True)
self.assertEqual(meta["name"], "invalidname")
self.assertTrue(len(fixes) > 0)
def test_validate_description(self) -> None:
meta = {"description": "Valid description"}
errors, fixes = skill_linter._validate_description(meta, fixit=False)
self.assertEqual(errors, [])
self.assertEqual(fixes, [])
meta = {"description": "Invalid description with <tags>"}
errors, fixes = skill_linter._validate_description(meta, fixit=False)
self.assertTrue(len(errors) > 0)
meta = {"description": "Invalid description with <tags>"}
errors, fixes = skill_linter._validate_description(meta, fixit=True)
self.assertEqual(meta["description"], "Invalid description with")
self.assertTrue(len(fixes) > 0)
def test_format_markdown_paragraphs(self) -> None:
# Test paragraph wrapping
text = "This is a long paragraph that should be wrapped to fit within the eighty character limit that is imposed by the linter."
formatted = skill_linter.format_markdown(text, width=40)
expected = (
"This is a long paragraph that should be\n"
"wrapped to fit within the eighty\n"
"character limit that is imposed by the\n"
"linter.\n"
)
self.assertEqual(formatted, expected)
def test_format_markdown_lists(self) -> None:
# Test list formatting and indentation
text = "- Item 1\n- Item 2 with a very long description that should wrap correctly under the marker."
formatted = skill_linter.format_markdown(text, width=20)
# Note: textwrap behavior might differ slightly from hand-calculated expected
expected = (
"- Item 1\n"
"- Item 2 with a very\n"
" long description\n"
" that should wrap\n"
" correctly under\n"
" the marker.\n"
)
self.assertEqual(formatted, expected)
def test_format_markdown_code_blocks(self) -> None:
# Test that code blocks are preserved
text = "Para before.\n\n```python\ndef foo():\n pass\n```\n\nPara after."
formatted = skill_linter.format_markdown(text)
self.assertIn("```python\ndef foo():\n pass\n```", formatted)
# Test complex markdown structures inside a code block
text = "```markdown\n- item 1\n\n| col 1 | col 2 |\n|---|---|\n| a | b |\n\n# Header\n```"
formatted = skill_linter.format_markdown(text)
self.assertEqual(formatted, text + "\n")
# Test preservation of purely whitespace lines in code blocks
text = "```rust\nfn main() {\n let x = 5;\n \n println!(x);\n}\n```"
formatted = skill_linter.format_markdown(text)
self.assertEqual(formatted, text + "\n")
def test_format_markdown_tables(self) -> None:
# Test that tables are preserved and not wrapped
text = "| Header 1 | Header 2 |\n| --- | --- |\n| Cell 1 | Cell 2 |"
formatted = skill_linter.format_markdown(text, width=10)
# Width 10 should normally wrap lines, but tables should be skipped
self.assertEqual(formatted, text + "\n")
def test_format_markdown_headers(self) -> None:
# Test that headers are preserved
text = "# Header 1\n\n## Header 2\n\nContent."
formatted = skill_linter.format_markdown(text)
self.assertIn("# Header 1\n", formatted)
self.assertIn("## Header 2\n", formatted)
def test_format_markdown_hard_breaks(self) -> None:
# Test that Markdown hard line breaks (two spaces) are preserved
text = "Line 1 \nLine 2"
formatted = skill_linter.format_markdown(text)
self.assertEqual(formatted, "Line 1 \nLine 2\n")
def test_format_markdown_with_issues_table_boundaries(self) -> None:
# Test that lines immediately following a table are correctly validated for width
text = "| Header |\n| --- |\n| Cell |\nThis is a very long text line immediately following the table with no newline."
_, issues = skill_linter.format_markdown_with_issues(text, width=20)
self.assertIn("lines exceeding 20 characters", issues)
def test_format_markdown_with_issues_tables_ignored(self) -> None:
text = "| Extremely long table header that exceeds eighty characters |\n| --- |\n| Cell without trailing spaces |\n"
_, issues = skill_linter.format_markdown_with_issues(text, width=20)
self.assertEqual(issues, [])
def test_format_markdown_with_issues_code_blocks_ignored(self) -> None:
text = "```python\ndef foo():\n\n\n print('Trailing space here: ')\n```\n"
_, issues = skill_linter.format_markdown_with_issues(text, width=80)
self.assertEqual(issues, [])
def test_format_markdown_with_issues_normal_text(self) -> None:
text = "Normal paragraph.\n\n\nAnother normal paragraph with trailing space \n"
_, issues = skill_linter.format_markdown_with_issues(text, width=80)
self.assertIn("consecutive empty lines", issues)
self.assertIn("trailing whitespace", issues)
if __name__ == "__main__":
unittest.main()