Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: added docs for test files #104

Merged
merged 2 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def sample_query() -> dict[str, Any]:

@pytest.fixture
def temp_directory(tmp_path: Path) -> Path:
"""
# Creates the following structure:
# test_repo/
# ├── file1.txt
Expand All @@ -39,6 +40,7 @@ def temp_directory(tmp_path: Path) -> Path:
# | └── file_dir1.txt
# └── dir2/
# └── file_dir2.txt
"""

test_dir = tmp_path / "test_repo"
test_dir.mkdir()
Expand Down
44 changes: 44 additions & 0 deletions tests/test_clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

@pytest.mark.asyncio
async def test_clone_repo_with_commit() -> None:
"""
Test the `clone_repo` function when a specific commit hash is provided.
Verifies that the repository is cloned and checked out to the specified commit.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="/tmp/repo",
Expand All @@ -28,6 +32,10 @@ async def test_clone_repo_with_commit() -> None:

@pytest.mark.asyncio
async def test_clone_repo_without_commit() -> None:
"""
Test the `clone_repo` function when no commit hash is provided.
Verifies that only the repository clone operation is performed.
"""
query = CloneConfig(url="https://github.com/user/repo", local_path="/tmp/repo", commit=None, branch="main")

with patch("gitingest.clone._check_repo_exists", return_value=True) as mock_check:
Expand All @@ -43,6 +51,10 @@ async def test_clone_repo_without_commit() -> None:

@pytest.mark.asyncio
async def test_clone_repo_nonexistent_repository() -> None:
"""
Test the `clone_repo` function when the repository does not exist.
Verifies that a ValueError is raised with an appropriate error message.
"""
clone_config = CloneConfig(
url="https://github.com/user/nonexistent-repo",
local_path="/tmp/repo",
Expand All @@ -57,6 +69,10 @@ async def test_clone_repo_nonexistent_repository() -> None:

@pytest.mark.asyncio
async def test_check_repo_exists() -> None:
"""
Test the `_check_repo_exists` function to verify if a repository exists.
Covers cases for existing repositories, non-existing repositories (404), and failed requests.
"""
url = "https://github.com/user/repo"

with patch("asyncio.create_subprocess_exec", new_callable=AsyncMock) as mock_exec:
Expand All @@ -80,6 +96,10 @@ async def test_check_repo_exists() -> None:

@pytest.mark.asyncio
async def test_clone_repo_invalid_url() -> None:
"""
Test the `clone_repo` function when an invalid or empty URL is provided.
Verifies that a ValueError is raised with an appropriate error message.
"""
clone_config = CloneConfig(
url="",
local_path="/tmp/repo",
Expand All @@ -90,6 +110,10 @@ async def test_clone_repo_invalid_url() -> None:

@pytest.mark.asyncio
async def test_clone_repo_invalid_local_path() -> None:
"""
Test the `clone_repo` function when an invalid or empty local path is provided.
Verifies that a ValueError is raised with an appropriate error message.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="",
Expand All @@ -100,6 +124,10 @@ async def test_clone_repo_invalid_local_path() -> None:

@pytest.mark.asyncio
async def test_clone_repo_with_custom_branch() -> None:
"""
Test the `clone_repo` function when a custom branch is specified.
Verifies that the repository is cloned with the specified branch using a shallow clone.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="/tmp/repo",
Expand All @@ -122,6 +150,10 @@ async def test_clone_repo_with_custom_branch() -> None:

@pytest.mark.asyncio
async def test_git_command_failure() -> None:
"""
Test the `clone_repo` function when a Git command fails during execution.
Verifies that a RuntimeError is raised with an appropriate error message.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="/tmp/repo",
Expand All @@ -134,6 +166,10 @@ async def test_git_command_failure() -> None:

@pytest.mark.asyncio
async def test_clone_repo_default_shallow_clone() -> None:
"""
Test the `clone_repo` function with default shallow clone behavior.
Verifies that the repository is cloned with `--depth=1` and `--single-branch` options.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="/tmp/repo",
Expand All @@ -148,6 +184,10 @@ async def test_clone_repo_default_shallow_clone() -> None:

@pytest.mark.asyncio
async def test_clone_repo_commit_without_branch() -> None:
"""
Test the `clone_repo` function when a commit hash is provided but no branch is specified.
Verifies that the repository is cloned and checked out to the specified commit.
"""
clone_config = CloneConfig(
url="https://github.com/user/repo",
local_path="/tmp/repo",
Expand All @@ -163,6 +203,10 @@ async def test_clone_repo_commit_without_branch() -> None:

@pytest.mark.asyncio
async def test_check_repo_exists_with_redirect() -> None:
"""
Test the `_check_repo_exists` function for handling HTTP redirects (302 Found).
Verifies that it correctly identifies the repository's existence.
"""
url = "https://github.com/user/repo"
with patch("asyncio.create_subprocess_exec", new_callable=AsyncMock) as mock_exec:
mock_process = AsyncMock()
Expand Down
75 changes: 75 additions & 0 deletions tests/test_parse_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@


def test_parse_url_valid_https() -> None:
"""
Test `_parse_url` with valid HTTPS URLs from supported platforms (GitHub, GitLab, Bitbucket).
Verifies that user and repository names are correctly extracted.
"""
test_cases = [
"https://github.com/user/repo",
"https://gitlab.com/user/repo",
Expand All @@ -22,6 +26,10 @@ def test_parse_url_valid_https() -> None:


def test_parse_url_valid_http() -> None:
"""
Test `_parse_url` with valid HTTP URLs from supported platforms.
Verifies that user and repository names, as well as the slug, are correctly extracted.
"""
test_cases = [
"http://github.com/user/repo",
"http://gitlab.com/user/repo",
Expand All @@ -35,12 +43,20 @@ def test_parse_url_valid_http() -> None:


def test_parse_url_invalid() -> None:
"""
Test `_parse_url` with an invalid URL that does not include a repository structure.
Verifies that a ValueError is raised with an appropriate error message.
"""
url = "https://only-domain.com"
with pytest.raises(ValueError, match="Invalid repository URL"):
_parse_url(url)


def test_parse_query_basic() -> None:
"""
Test `parse_query` with basic inputs including valid repository URLs.
Verifies that user and repository names, URL, and ignore patterns are correctly parsed.
"""
test_cases = ["https://github.com/user/repo", "https://gitlab.com/user/repo"]
for url in test_cases:
result = parse_query(url, max_file_size=50, from_web=True, ignore_patterns="*.txt")
Expand All @@ -51,19 +67,31 @@ def test_parse_query_basic() -> None:


def test_parse_query_include_pattern() -> None:
"""
Test `parse_query` with an include pattern.
Verifies that the include pattern is set correctly and default ignore patterns are applied.
"""
url = "https://github.com/user/repo"
result = parse_query(url, max_file_size=50, from_web=True, include_patterns="*.py")
assert result["include_patterns"] == ["*.py"]
assert set(result["ignore_patterns"]) == set(DEFAULT_IGNORE_PATTERNS)


def test_parse_query_invalid_pattern() -> None:
"""
Test `parse_query` with an invalid pattern containing special characters.
Verifies that a ValueError is raised with an appropriate error message.
"""
url = "https://github.com/user/repo"
with pytest.raises(ValueError, match="Pattern.*contains invalid characters"):
parse_query(url, max_file_size=50, from_web=True, include_patterns="*.py;rm -rf")


def test_parse_url_with_subpaths() -> None:
"""
Test `_parse_url` with a URL containing a branch and subpath.
Verifies that user name, repository name, branch, and subpath are correctly extracted.
"""
url = "https://github.com/user/repo/tree/main/subdir/file"
result = _parse_url(url)
assert result["user_name"] == "user"
Expand All @@ -73,38 +101,62 @@ def test_parse_url_with_subpaths() -> None:


def test_parse_url_invalid_repo_structure() -> None:
"""
Test `_parse_url` with an invalid repository structure in the URL.
Verifies that a ValueError is raised with an appropriate error message.
"""
url = "https://github.com/user"
with pytest.raises(ValueError, match="Invalid repository URL"):
_parse_url(url)


def test_parse_patterns_valid() -> None:
"""
Test `_parse_patterns` with valid patterns separated by commas.
Verifies that the patterns are correctly parsed into a list.
"""
patterns = "*.py, *.md, docs/*"
result = _parse_patterns(patterns)
assert result == ["*.py", "*.md", "docs/*"]


def test_parse_patterns_invalid_characters() -> None:
"""
Test `_parse_patterns` with invalid patterns containing special characters.
Verifies that a ValueError is raised with an appropriate error message.
"""
patterns = "*.py;rm -rf"
with pytest.raises(ValueError, match="Pattern.*contains invalid characters"):
_parse_patterns(patterns)


def test_parse_query_with_large_file_size() -> None:
"""
Test `parse_query` with a very large file size limit.
Verifies that the file size limit and default ignore patterns are set correctly.
"""
url = "https://github.com/user/repo"
result = parse_query(url, max_file_size=10**9, from_web=True)
assert result["max_file_size"] == 10**9
assert result["ignore_patterns"] == DEFAULT_IGNORE_PATTERNS


def test_parse_query_empty_patterns() -> None:
"""
Test `parse_query` with empty include and ignore patterns.
Verifies that the include patterns are set to None and default ignore patterns are applied.
"""
url = "https://github.com/user/repo"
result = parse_query(url, max_file_size=50, from_web=True, include_patterns="", ignore_patterns="")
assert result["include_patterns"] is None
assert result["ignore_patterns"] == DEFAULT_IGNORE_PATTERNS


def test_parse_query_include_and_ignore_overlap() -> None:
"""
Test `parse_query` with overlapping include and ignore patterns.
Verifies that overlapping patterns are removed from the ignore patterns.
"""
url = "https://github.com/user/repo"
result = parse_query(
url,
Expand All @@ -119,6 +171,10 @@ def test_parse_query_include_and_ignore_overlap() -> None:


def test_parse_query_local_path() -> None:
"""
Test `parse_query` with a local file path.
Verifies that the local path is set, a unique ID is generated, and the slug is correctly created.
"""
path = "/home/user/project"
result = parse_query(path, max_file_size=100, from_web=False)
tail = Path("home/user/project")
Expand All @@ -128,6 +184,10 @@ def test_parse_query_local_path() -> None:


def test_parse_query_relative_path() -> None:
"""
Test `parse_query` with a relative file path.
Verifies that the local path and slug are correctly resolved.
"""
path = "./project"
result = parse_query(path, max_file_size=100, from_web=False)
tail = Path("project")
Expand All @@ -136,11 +196,19 @@ def test_parse_query_relative_path() -> None:


def test_parse_query_empty_source() -> None:
"""
Test `parse_query` with an empty source input.
Verifies that a ValueError is raised with an appropriate error message.
"""
with pytest.raises(ValueError, match="Invalid repository URL"):
parse_query("", max_file_size=100, from_web=True)


def test_parse_url_branch_and_commit_distinction() -> None:
"""
Test `_parse_url` with URLs containing either a branch name or a commit hash.
Verifies that the branch and commit are correctly distinguished.
"""
url_branch = "https://github.com/user/repo/tree/main"
url_commit = "https://github.com/user/repo/tree/abcd1234abcd1234abcd1234abcd1234abcd1234"

Expand All @@ -155,13 +223,20 @@ def test_parse_url_branch_and_commit_distinction() -> None:


def test_parse_query_uuid_uniqueness() -> None:
"""
Test `parse_query` to ensure that each call generates a unique UUID for the query result.
"""
path = "/home/user/project"
result1 = parse_query(path, max_file_size=100, from_web=False)
result2 = parse_query(path, max_file_size=100, from_web=False)
assert result1["id"] != result2["id"]


def test_parse_url_with_query_and_fragment() -> None:
"""
Test `_parse_url` with a URL containing query parameters and a fragment.
Verifies that the URL is cleaned and other fields are correctly extracted.
"""
url = "https://github.com/user/repo?arg=value#fragment"
result = _parse_url(url)
assert result["user_name"] == "user"
Expand Down
Loading