From bd0f242c0877d162d3a917ae903571edbf314eca Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 16 Dec 2024 00:28:34 +0100 Subject: [PATCH] tests baseline --- tests/test_main.py | 201 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 180 insertions(+), 21 deletions(-) diff --git a/tests/test_main.py b/tests/test_main.py index b59da16..cb157ed 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,31 +1,190 @@ import os -import subprocess +import tempfile +import shutil import pytest -import time +from pathlib import Path +from typing import Generator +from repo_to_text.main import ( + get_tree_structure, + load_ignore_specs, + should_ignore_file, + is_ignored_path, + remove_empty_dirs, + save_repo_to_text +) -def test_repo_to_text(): - # Remove any existing snapshot files to avoid conflicts - for file in os.listdir('.'): - if file.startswith('repo-to-text_') and file.endswith('.txt'): - os.remove(file) +@pytest.fixture +def temp_dir() -> Generator[str, None, None]: + """Create a temporary directory for testing.""" + temp_path = tempfile.mkdtemp() + yield temp_path + shutil.rmtree(temp_path) + +@pytest.fixture +def sample_repo(temp_dir: str) -> str: + """Create a sample repository structure for testing.""" + # Create directories + os.makedirs(os.path.join(temp_dir, "src")) + os.makedirs(os.path.join(temp_dir, "tests")) - # Run the repo-to-text command - result = subprocess.run(['repo-to-text'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # Create sample files + files = { + "README.md": "# Test Project", + ".gitignore": """ +*.pyc +__pycache__/ +.git/ +""", + "src/main.py": "print('Hello World')", + "tests/test_main.py": "def test_sample(): pass", + ".repo-to-text-settings.yaml": """ +gitignore-import-and-ignore: True +ignore-tree-and-content: + - ".git/" + - ".repo-to-text-settings.yaml" +ignore-content: + - "README.md" +""" + } - # Assert that the command ran without errors - assert result.returncode == 0, f"Command failed with error: {result.stderr.decode('utf-8')}" + for file_path, content in files.items(): + full_path = os.path.join(temp_dir, file_path) + os.makedirs(os.path.dirname(full_path), exist_ok=True) + with open(full_path, "w") as f: + f.write(content) - # Check for the existence of the new snapshot file - snapshot_files = [f for f in os.listdir('.') if f.startswith('repo-to-text_') and f.endswith('.txt')] - assert len(snapshot_files) == 1, "No snapshot file created or multiple files created" + return temp_dir + +def test_is_ignored_path() -> None: + """Test the is_ignored_path function.""" + assert is_ignored_path(".git/config") is True + assert is_ignored_path("repo-to-text_output.txt") is True + assert is_ignored_path("src/main.py") is False + assert is_ignored_path("normal_file.txt") is False + +def test_load_ignore_specs(sample_repo: str) -> None: + """Test loading ignore specifications from files.""" + gitignore_spec, content_ignore_spec, tree_and_content_ignore_spec = load_ignore_specs(sample_repo) - # Verify that the snapshot file is not empty - with open(snapshot_files[0], 'r') as f: + assert gitignore_spec is not None + assert content_ignore_spec is not None + assert tree_and_content_ignore_spec is not None + + # Test gitignore patterns + assert gitignore_spec.match_file("test.pyc") is True + assert gitignore_spec.match_file("__pycache__/cache.py") is True + assert gitignore_spec.match_file(".git/config") is True + + # Test content ignore patterns + assert content_ignore_spec.match_file("README.md") is True + + # Test tree and content ignore patterns + assert tree_and_content_ignore_spec.match_file(".git/config") is True + +def test_should_ignore_file(sample_repo: str) -> None: + """Test file ignoring logic.""" + gitignore_spec, content_ignore_spec, tree_and_content_ignore_spec = load_ignore_specs(sample_repo) + + # Test various file paths + assert should_ignore_file( + ".git/config", + ".git/config", + gitignore_spec, + content_ignore_spec, + tree_and_content_ignore_spec + ) is True + + assert should_ignore_file( + "src/main.py", + "src/main.py", + gitignore_spec, + content_ignore_spec, + tree_and_content_ignore_spec + ) is False + +def test_get_tree_structure(sample_repo: str) -> None: + """Test tree structure generation.""" + gitignore_spec, _, tree_and_content_ignore_spec = load_ignore_specs(sample_repo) + tree_output = get_tree_structure(sample_repo, gitignore_spec, tree_and_content_ignore_spec) + + # Basic structure checks + assert "src" in tree_output + assert "tests" in tree_output + assert "main.py" in tree_output + assert "test_main.py" in tree_output + assert ".git" not in tree_output + +def test_remove_empty_dirs(temp_dir: str) -> None: + """Test removal of empty directories from tree output.""" + # Create test directory structure + os.makedirs(os.path.join(temp_dir, "src")) + os.makedirs(os.path.join(temp_dir, "empty_dir")) + os.makedirs(os.path.join(temp_dir, "tests")) + + # Create some files + with open(os.path.join(temp_dir, "src/main.py"), "w") as f: + f.write("print('test')") + with open(os.path.join(temp_dir, "tests/test_main.py"), "w") as f: + f.write("def test(): pass") + + # Create a mock tree output that matches the actual tree command format + tree_output = ( + f"{temp_dir}\n" + f"├── {os.path.join(temp_dir, 'src')}\n" + f"│ └── {os.path.join(temp_dir, 'src/main.py')}\n" + f"├── {os.path.join(temp_dir, 'empty_dir')}\n" + f"└── {os.path.join(temp_dir, 'tests')}\n" + f" └── {os.path.join(temp_dir, 'tests/test_main.py')}\n" + ) + + filtered_output = remove_empty_dirs(tree_output, temp_dir) + + # Check that empty_dir is removed but other directories remain + assert "empty_dir" not in filtered_output + assert os.path.join(temp_dir, "src") in filtered_output + assert os.path.join(temp_dir, "tests") in filtered_output + assert os.path.join(temp_dir, "src/main.py") in filtered_output + assert os.path.join(temp_dir, "tests/test_main.py") in filtered_output + +def test_save_repo_to_text(sample_repo: str) -> None: + """Test the main save_repo_to_text function.""" + # Create output directory + output_dir = os.path.join(sample_repo, "output") + os.makedirs(output_dir, exist_ok=True) + + # Create .git directory to ensure it's properly ignored + os.makedirs(os.path.join(sample_repo, ".git")) + with open(os.path.join(sample_repo, ".git/config"), "w") as f: + f.write("[core]\n\trepositoryformatversion = 0\n") + + # Test file output + output_file = save_repo_to_text(sample_repo, output_dir=output_dir) + assert os.path.exists(output_file) + assert os.path.dirname(output_file) == output_dir + + # Check file contents + with open(output_file, 'r') as f: content = f.read() - assert len(content) > 0, "Snapshot file is empty" - - # Clean up the generated snapshot file - os.remove(snapshot_files[0]) + + # Basic content checks + assert "Directory Structure:" in content + + # Check for expected files + assert "src/main.py" in content + assert "tests/test_main.py" in content + + # Check for file contents + assert "print('Hello World')" in content + assert "def test_sample(): pass" in content + + # Ensure ignored patterns are not in output + assert ".git/config" not in content # Check specific file + assert "repo-to-text_" not in content + assert ".repo-to-text-settings.yaml" not in content + + # Check that .gitignore content is not included + assert "*.pyc" not in content + assert "__pycache__" not in content if __name__ == "__main__": - pytest.main() + pytest.main([__file__])