183 lines
6.1 KiB
Python
183 lines
6.1 KiB
Python
"""Unit tests for the CLI module."""
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from scaffoldforge.cli import cli
|
|
from scaffoldforge.cli.commands import parse_github_url
|
|
|
|
|
|
class TestParseGitHubUrl:
|
|
"""Tests for GitHub URL parsing."""
|
|
|
|
def test_parse_valid_url(self):
|
|
"""Test parsing a valid GitHub issue URL."""
|
|
owner, repo, issue_number = parse_github_url(
|
|
"https://github.com/owner/repo/issues/123"
|
|
)
|
|
assert owner == "owner"
|
|
assert repo == "repo"
|
|
assert issue_number == 123
|
|
|
|
def test_parse_url_with_www(self):
|
|
"""Test parsing URL with www prefix."""
|
|
owner, repo, issue_number = parse_github_url(
|
|
"https://www.github.com/owner/repo/issues/456"
|
|
)
|
|
assert owner == "owner"
|
|
assert repo == "repo"
|
|
assert issue_number == 456
|
|
|
|
def test_parse_url_with_trailing_slash(self):
|
|
"""Test parsing URL with trailing slash."""
|
|
owner, repo, issue_number = parse_github_url(
|
|
"https://github.com/owner/repo/issues/789/"
|
|
)
|
|
assert owner == "owner"
|
|
assert repo == "repo"
|
|
|
|
def test_parse_invalid_url(self):
|
|
"""Test parsing invalid URL raises exception."""
|
|
from click import ClickException
|
|
with pytest.raises(ClickException):
|
|
parse_github_url("https://invalid.com/owner/repo/issues/123")
|
|
|
|
def test_parse_url_without_issue_number(self):
|
|
"""Test parsing URL without issue number."""
|
|
from click import ClickException
|
|
with pytest.raises(ClickException):
|
|
parse_github_url("https://github.com/owner/repo")
|
|
|
|
|
|
class TestCLI:
|
|
"""Tests for CLI commands."""
|
|
|
|
@patch('scaffoldforge.cli.commands.IssueParser')
|
|
@patch('scaffoldforge.cli.commands.TemplateEngine')
|
|
@patch('scaffoldforge.cli.commands.StructureGenerator')
|
|
@patch('scaffoldforge.cli.commands.CodeGenerator')
|
|
def test_generate_command_preview_mode(
|
|
self, mock_code_gen, mock_struct_gen, mock_tpl_engine, mock_parser
|
|
):
|
|
"""Test generate command in preview mode."""
|
|
runner = CliRunner()
|
|
|
|
mock_issue_data = Mock()
|
|
mock_issue_data.number = 1
|
|
mock_issue_data.title = "Test Issue"
|
|
mock_issue_data.labels = ["python"]
|
|
mock_issue_data.checklist = []
|
|
mock_issue_data.get_todo_items.return_value = []
|
|
mock_issue_data.requirements = []
|
|
mock_issue_data.body = ""
|
|
|
|
mock_parser_instance = Mock()
|
|
mock_parser_instance.parse_issue.return_value = mock_issue_data
|
|
mock_parser_instance.detect_language.return_value = "python"
|
|
mock_parser.return_value = mock_parser_instance
|
|
|
|
mock_engine = Mock()
|
|
mock_engine.load_templates.return_value = {}
|
|
mock_engine.get_template_context.return_value = {}
|
|
mock_tpl_engine.return_value = mock_engine
|
|
|
|
result = runner.invoke(
|
|
cli,
|
|
["generate", "https://github.com/owner/repo/issues/1", "--preview"]
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert "PREVIEW" in result.output or "preview" in result.output.lower()
|
|
|
|
@patch('scaffoldforge.cli.commands.TemplateEngine')
|
|
def test_list_templates_command(self, mock_tpl_engine):
|
|
"""Test list-templates command."""
|
|
runner = CliRunner()
|
|
|
|
mock_engine = Mock()
|
|
mock_engine.list_available_templates.return_value = ["default", "cli"]
|
|
mock_tpl_engine.return_value = mock_engine
|
|
|
|
result = runner.invoke(cli, ["list-templates", "--language", "python"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "python" in result.output.lower()
|
|
|
|
@patch('scaffoldforge.cli.commands.TemplateEngine')
|
|
def test_list_templates_all_languages(self, mock_tpl_engine):
|
|
"""Test list-templates without language filter."""
|
|
runner = CliRunner()
|
|
|
|
mock_engine = Mock()
|
|
mock_engine.list_available_templates.side_effect = [
|
|
["default"], ["default"], ["default"], ["default"]
|
|
]
|
|
mock_tpl_engine.return_value = mock_engine
|
|
|
|
result = runner.invoke(cli, ["list-templates"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_cli_help(self):
|
|
"""Test CLI help output."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "ScaffoldForge" in result.output
|
|
|
|
def test_generate_help(self):
|
|
"""Test generate command help."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(cli, ["generate", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--output" in result.output or "-o" in result.output
|
|
assert "--language" in result.output or "-l" in result.output
|
|
assert "--preview" in result.output or "-p" in result.output
|
|
|
|
|
|
class TestCLIErrorHandling:
|
|
"""Tests for CLI error handling."""
|
|
|
|
def test_generate_invalid_url(self):
|
|
"""Test generate with invalid URL."""
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cli,
|
|
["generate", "https://invalid.com/issue/123"]
|
|
)
|
|
|
|
assert result.exit_code != 0
|
|
assert "Invalid" in result.output or "error" in result.output.lower()
|
|
|
|
@patch('scaffoldforge.cli.commands.IssueParser')
|
|
def test_generate_missing_language(
|
|
self, mock_parser
|
|
):
|
|
"""Test generate without specifying language when it can't be detected."""
|
|
runner = CliRunner()
|
|
|
|
mock_issue_data = Mock()
|
|
mock_issue_data.number = 1
|
|
mock_issue_data.title = "Test Issue"
|
|
mock_issue_data.labels = []
|
|
mock_issue_data.checklist = []
|
|
mock_issue_data.get_todo_items.return_value = []
|
|
mock_issue_data.requirements = []
|
|
mock_issue_data.body = ""
|
|
|
|
mock_parser_instance = Mock()
|
|
mock_parser_instance.parse_issue.return_value = mock_issue_data
|
|
mock_parser_instance.detect_language.return_value = None
|
|
mock_parser.return_value = mock_parser_instance
|
|
|
|
result = runner.invoke(
|
|
cli,
|
|
["generate", "https://github.com/owner/repo/issues/1"]
|
|
)
|
|
|
|
assert result.exit_code != 0
|