Files
skill-seekers-reference/tests/test_cli_parsers.py
yusyus 6fded977dd feat: add Kotlin language support for codebase analysis (#287)
Adds full C3.x pipeline support for Kotlin (.kt, .kts):
- Language detection patterns (40+ weighted patterns for data/sealed classes, coroutines, companion objects, KMP, etc.)
- AST regex parser in code_analyzer.py (classes, objects, functions, extension functions, suspend functions)
- Dependency extraction for Kotlin import statements (with alias support)
- Design pattern adaptations (object→Singleton, companion→Factory, sealed→Strategy, data→Builder, Flow→Observer)
- Test example extraction for JUnit 4/5, Kotest, MockK, Spek
- Config detection for build.gradle.kts / settings.gradle.kts
- Extension maps registered in codebase_scraper, unified_codebase_analyzer, github_scraper, generate_router

Also fixes pre-existing parser count tests (35→36 for doctor command added in previous commit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:25:12 +03:00

253 lines
8.5 KiB
Python

#!/usr/bin/env python3
"""
Tests for CLI Parser System
Tests the modular parser registration system.
"""
import argparse
import pytest
from skill_seekers.cli.parsers import (
PARSERS,
SubcommandParser,
get_parser_names,
register_parsers,
)
from skill_seekers.cli.parsers.scrape_parser import ScrapeParser
from skill_seekers.cli.parsers.github_parser import GitHubParser
from skill_seekers.cli.parsers.package_parser import PackageParser
class TestParserRegistry:
"""Test parser registry functionality."""
def test_all_parsers_registered(self):
"""Test that all parsers are registered."""
assert len(PARSERS) == 36, f"Expected 36 parsers, got {len(PARSERS)}"
def test_get_parser_names(self):
"""Test getting list of parser names."""
names = get_parser_names()
assert len(names) == 36
assert "scrape" in names
assert "github" in names
assert "package" in names
assert "upload" in names
assert "analyze" in names
assert "config" in names
assert "workflows" in names
assert "video" in names
def test_all_parsers_are_subcommand_parsers(self):
"""Test that all parsers inherit from SubcommandParser."""
for parser in PARSERS:
assert isinstance(parser, SubcommandParser)
def test_all_parsers_have_required_properties(self):
"""Test that all parsers have name, help, description."""
for parser in PARSERS:
assert hasattr(parser, "name")
assert hasattr(parser, "help")
assert hasattr(parser, "description")
assert isinstance(parser.name, str)
assert isinstance(parser.help, str)
assert isinstance(parser.description, str)
assert len(parser.name) > 0
assert len(parser.help) > 0
def test_all_parsers_have_add_arguments_method(self):
"""Test that all parsers implement add_arguments."""
for parser in PARSERS:
assert hasattr(parser, "add_arguments")
assert callable(parser.add_arguments)
def test_no_duplicate_parser_names(self):
"""Test that all parser names are unique."""
names = [p.name for p in PARSERS]
assert len(names) == len(set(names)), "Duplicate parser names found!"
class TestParserCreation:
"""Test parser creation functionality."""
def test_scrape_parser_creates_subparser(self):
"""Test that ScrapeParser creates valid subparser."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers()
scrape_parser = ScrapeParser()
subparser = scrape_parser.create_parser(subparsers)
assert subparser is not None
assert scrape_parser.name == "scrape"
assert scrape_parser.help == "Scrape documentation website"
def test_github_parser_creates_subparser(self):
"""Test that GitHubParser creates valid subparser."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers()
github_parser = GitHubParser()
subparser = github_parser.create_parser(subparsers)
assert subparser is not None
assert github_parser.name == "github"
def test_package_parser_creates_subparser(self):
"""Test that PackageParser creates valid subparser."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers()
package_parser = PackageParser()
subparser = package_parser.create_parser(subparsers)
assert subparser is not None
assert package_parser.name == "package"
def test_register_parsers_creates_all_subcommands(self):
"""Test that register_parsers creates all 19 subcommands."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="command")
# Register all parsers
register_parsers(subparsers)
# Test that all commands can be parsed
test_commands = [
"config --show",
"scrape --config test.json",
"github --repo owner/repo",
"package output/test/",
"upload test.zip",
"analyze --directory .",
"enhance output/test/",
"estimate test.json",
]
for cmd in test_commands:
args = main_parser.parse_args(cmd.split())
assert args.command is not None
class TestSpecificParsers:
"""Test specific parser implementations."""
def test_scrape_parser_arguments(self):
"""Test ScrapeParser has correct arguments."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="command")
scrape_parser = ScrapeParser()
scrape_parser.create_parser(subparsers)
# Test various argument combinations
args = main_parser.parse_args(["scrape", "--config", "test.json"])
assert args.command == "scrape"
assert args.config == "test.json"
args = main_parser.parse_args(["scrape", "--config", "test.json", "--max-pages", "100"])
assert args.max_pages == 100
args = main_parser.parse_args(["scrape", "--enhance-level", "2"])
assert args.enhance_level == 2
def test_github_parser_arguments(self):
"""Test GitHubParser has correct arguments."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="command")
github_parser = GitHubParser()
github_parser.create_parser(subparsers)
args = main_parser.parse_args(["github", "--repo", "owner/repo"])
assert args.command == "github"
assert args.repo == "owner/repo"
args = main_parser.parse_args(["github", "--repo", "owner/repo", "--non-interactive"])
assert args.non_interactive is True
def test_package_parser_arguments(self):
"""Test PackageParser has correct arguments."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="command")
package_parser = PackageParser()
package_parser.create_parser(subparsers)
args = main_parser.parse_args(["package", "output/test/"])
assert args.command == "package"
assert args.skill_directory == "output/test/"
args = main_parser.parse_args(["package", "output/test/", "--target", "gemini"])
assert args.target == "gemini"
args = main_parser.parse_args(["package", "output/test/", "--no-open"])
assert args.no_open is True
def test_analyze_parser_arguments(self):
"""Test AnalyzeParser has correct arguments."""
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="command")
from skill_seekers.cli.parsers.analyze_parser import AnalyzeParser
analyze_parser = AnalyzeParser()
analyze_parser.create_parser(subparsers)
args = main_parser.parse_args(["analyze", "--directory", "."])
assert args.command == "analyze"
assert args.directory == "."
args = main_parser.parse_args(["analyze", "--directory", ".", "--quick"])
assert args.quick is True
args = main_parser.parse_args(["analyze", "--directory", ".", "--comprehensive"])
assert args.comprehensive is True
args = main_parser.parse_args(["analyze", "--directory", ".", "--skip-patterns"])
assert args.skip_patterns is True
class TestBackwardCompatibility:
"""Test backward compatibility with old CLI."""
def test_all_original_commands_still_work(self):
"""Test that all original commands are still registered."""
names = get_parser_names()
# Original commands from old main.py
original_commands = [
"config",
"scrape",
"github",
"pdf",
"unified",
"enhance",
"enhance-status",
"package",
"upload",
"estimate",
"extract-test-examples",
"install-agent",
"analyze",
"install",
"resume",
"stream",
"update",
"multilang",
"quality",
]
for cmd in original_commands:
assert cmd in names, f"Command '{cmd}' not found in parser registry!"
def test_command_count_matches(self):
"""Test that we have exactly 35 commands (25 original + 10 new source types)."""
assert len(PARSERS) == 36
assert len(get_parser_names()) == 36
if __name__ == "__main__":
pytest.main([__file__, "-v"])