"""Integration tests for ScaffoldForge.""" import tempfile from pathlib import Path from unittest.mock import Mock, patch from click.testing import CliRunner from scaffoldforge.cli import cli from scaffoldforge.generators import CodeGenerator, StructureGenerator from scaffoldforge.parsers import ChecklistItem, IssueData from scaffoldforge.templates import TemplateEngine class TestFullWorkflow: """Integration tests for the full workflow.""" @patch('scaffoldforge.cli.commands.IssueParser') @patch('scaffoldforge.cli.commands.TemplateEngine') @patch('scaffoldforge.cli.commands.StructureGenerator') @patch('scaffoldforge.cli.commands.CodeGenerator') def test_full_generate_workflow( self, mock_code_gen, mock_struct_gen, mock_tpl_engine, mock_parser ): """Test complete generate workflow.""" runner = CliRunner() mock_issue_data = Mock() mock_issue_data.number = 42 mock_issue_data.title = "Implement User Authentication" mock_issue_data.body = "Add user login and registration" mock_issue_data.labels = ["python", "security"] mock_issue_data.checklist = [ ChecklistItem(text="Create login form", completed=False), ChecklistItem(text="Add password hashing", completed=False), ] mock_issue_data.get_todo_items.return_value = [ "Create login form", "Add password hashing" ] mock_issue_data.requirements = ["Must be secure", "Must be fast"] mock_issue_data.acceptance_criteria = [] mock_issue_data.suggested_files = [] mock_issue_data.suggested_directories = [] mock_issue_data.repository = "user/repo" mock_issue_data.author = "testuser" mock_issue_data.created_at = "2024-01-01T00:00:00" 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 = { "main.py": "# content", "utils.py": "# utils" } mock_engine.get_template_context.return_value = { "project_name": "implement-user-authentication", "issue_number": 42 } mock_tpl_engine.return_value = mock_engine mock_code_gen_instance = Mock() mock_code_gen_instance.generate_all_files.return_value = [] mock_code_gen.return_value = mock_code_gen_instance mock_struct_gen_instance = Mock() mock_struct_gen.return_value = mock_struct_gen_instance with runner.isolated_filesystem(): result = runner.invoke( cli, [ "generate", "https://github.com/user/repo/issues/42", "--language", "python", "--output", "./test-project" ] ) assert result.exit_code == 0 def test_template_engine_with_real_templates(self): """Test TemplateEngine with real built-in templates.""" engine = TemplateEngine() languages = engine.list_available_languages() assert "python" in languages assert "javascript" in languages assert "go" in languages assert "rust" in languages python_templates = engine.list_available_templates("python") assert "default" in python_templates def test_issue_data_integration(self): """Test IssueData with real checklist items.""" checklist = [ ChecklistItem(text="First task", completed=False), ChecklistItem(text="Second task", completed=True), ChecklistItem(text="Third task", completed=False), ] issue_data = IssueData( number=100, title="Integration Test Issue", body="Test body for integration", body_html="

Test body

", labels=["test"], state="open", url="https://github.com/test/repo/issues/100", repository="test/repo", author="testuser", created_at="2024-01-01T00:00:00", updated_at="2024-01-02T00:00:00", checklist=checklist ) todos = issue_data.get_todo_items() completed = issue_data.get_completed_items() assert len(todos) == 2 assert len(completed) == 1 assert "First task" in todos assert "Second task" in completed def test_generator_with_real_templates(self): """Test code generation with real templates.""" issue_data = IssueData( number=1, title="Test Python Project", body="", body_html="", labels=["python"], state="open", url="", repository="", author="", created_at="", updated_at="", checklist=[ ChecklistItem(text="Task 1", completed=False), ChecklistItem(text="Task 2", completed=False), ] ) engine = TemplateEngine() gen = CodeGenerator(engine, issue_data) files = gen.generate_all_files("python", issue_data) assert len(files) > 0 for f in files: assert f.path is not None assert f.content is not None def test_structure_generator_preview_mode(self): """Test structure generator in preview mode.""" issue_data = IssueData( number=1, title="Preview Test", body="", body_html="", labels=["python"], state="open", url="", repository="", author="", created_at="", updated_at="", checklist=[] ) engine = TemplateEngine() code_gen = CodeGenerator(engine, issue_data) with tempfile.TemporaryDirectory() as tmpdir: gen = StructureGenerator(output_dir=tmpdir, preview=True) gen.generate("python", issue_data, code_gen) assert len(gen.created_files) == 0 assert len(gen.created_dirs) == 0 def test_multiple_language_templates(self): """Test that all language templates can be loaded.""" engine = TemplateEngine() for lang in ["python", "javascript", "go", "rust"]: templates = engine.list_available_templates(lang) assert len(templates) >= 1 context = engine.get_template_context( IssueData( number=1, title="Test", body="", body_html="", labels=[lang], state="open", url="", repository="", author="", created_at="", updated_at="" ) ) assert context is not None def test_cli_with_preview_flag(self): """Test CLI with preview flag doesn't create files.""" runner = CliRunner() with patch('scaffoldforge.cli.commands.IssueParser') as mock_parser, \ patch('scaffoldforge.cli.commands.TemplateEngine') as _mock_tpl_engine, \ patch('scaffoldforge.cli.commands.StructureGenerator') as _mock_struct_gen, \ patch('scaffoldforge.cli.commands.CodeGenerator') as _mock_code_gen: mock_issue_data = Mock() mock_issue_data.number = 1 mock_issue_data.title = "Test" 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_issue_data.repository = "" mock_issue_data.author = "" mock_issue_data.created_at = "" mock_parser.return_value.parse_issue.return_value = mock_issue_data mock_parser.return_value.detect_language.return_value = "python" with runner.isolated_filesystem(): result = runner.invoke( cli, ["generate", "https://github.com/test/repo/issues/1", "--preview"] ) assert result.exit_code == 0 def test_readme_generation(self): """Test README generation in structure generator.""" issue_data = IssueData( number=123, title="Test Project", body="This is a test project body", body_html="", labels=["python"], state="open", url="https://github.com/user/repo/issues/123", repository="user/repo", author="testuser", created_at="2024-01-01T00:00:00", updated_at="2024-01-02T00:00:00", checklist=[ ChecklistItem(text="Task 1", completed=False), ChecklistItem(text="Task 2", completed=True), ] ) engine = TemplateEngine() code_gen = CodeGenerator(engine, issue_data) with tempfile.TemporaryDirectory() as tmpdir: gen = StructureGenerator(output_dir=tmpdir, preview=False) gen.generate("python", issue_data, code_gen) readme_path = Path(tmpdir) / "test-project" / "README.md" if readme_path.exists(): content = readme_path.read_text() assert "Test Project" in content assert "123" in content class TestRepositoryIntegration: """Tests for repository integration features.""" def test_gitignore_content_by_language(self): """Test that gitignore content varies by language.""" issue_data = IssueData( number=1, title="Test", body="", body_html="", labels=[], state="open", url="", repository="", author="", created_at="", updated_at="" ) engine = TemplateEngine() code_gen = CodeGenerator(engine, issue_data) for lang in ["python", "javascript", "go", "rust"]: files = code_gen.generate_all_files(lang, issue_data) file_names = [f.path for f in files] if lang == "python": assert any("requirements" in f or "pyproject" in f for f in file_names) elif lang == "javascript": assert any("package.json" in f for f in file_names) elif lang == "go": assert any("go.mod" in f for f in file_names) elif lang == "rust": assert any("Cargo.toml" in f for f in file_names)