feat: smart git URL parsing for browser URLs
- Add git URL parsing utilities (extract_base_repo_url, parse_git_url) - Support GitHub, GitLab, Bitbucket browser URL detection - Add /projects/repositories/parse-url endpoint - Enhance repository creation to detect browser URLs and suggest corrections - Add real-time URL validation in frontend with debouncing - Show visual indicators (green/yellow/red) for URL validity - Display inline suggestions with 'Use Suggested' button - Add comprehensive unit tests for URL parsing - Quality gates: ruff ✓, mypy ✓, typecheck ✓, lint ✓, build ✓
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
"""Tests for git URL parsing utilities."""
|
||||
|
||||
import pytest
|
||||
|
||||
from src.utils.git_url_parser import extract_base_repo_url, is_valid_clone_url, parse_git_url
|
||||
|
||||
|
||||
class TestExtractBaseRepoUrl:
|
||||
"""Tests for extract_base_repo_url function."""
|
||||
|
||||
def test_github_tree_url(self):
|
||||
url = "https://github.com/owner/repo/tree/main"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_github_blob_url(self):
|
||||
url = "https://github.com/owner/repo/blob/main/README.md"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_github_pull_url(self):
|
||||
url = "https://github.com/owner/repo/pull/123"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_github_issues_url(self):
|
||||
url = "https://github.com/owner/repo/issues/456"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_github_valid_url(self):
|
||||
url = "https://github.com/owner/repo.git"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_github_url_with_query_params(self):
|
||||
url = "https://github.com/owner/repo?tab=readme-ov-file"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://github.com/owner/repo.git"
|
||||
|
||||
def test_gitlab_tree_url(self):
|
||||
url = "https://gitlab.com/owner/repo/-/tree/main"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://gitlab.com/owner/repo.git"
|
||||
|
||||
def test_gitlab_blob_url(self):
|
||||
url = "https://gitlab.com/owner/repo/-/blob/main/README.md"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://gitlab.com/owner/repo.git"
|
||||
|
||||
def test_gitlab_merge_request_url(self):
|
||||
url = "https://gitlab.com/owner/repo/-/merge_requests/123"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://gitlab.com/owner/repo.git"
|
||||
|
||||
def test_gitlab_valid_url(self):
|
||||
url = "https://gitlab.com/owner/repo.git"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://gitlab.com/owner/repo.git"
|
||||
|
||||
def test_bitbucket_src_url(self):
|
||||
url = "https://bitbucket.org/owner/repo/src/main/"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://bitbucket.org/owner/repo.git"
|
||||
|
||||
def test_bitbucket_valid_url(self):
|
||||
url = "https://bitbucket.org/owner/repo.git"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "https://bitbucket.org/owner/repo.git"
|
||||
|
||||
def test_ssh_url(self):
|
||||
url = "git@github.com:owner/repo.git"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "git@github.com:owner/repo.git"
|
||||
|
||||
def test_ssh_url_without_git_suffix(self):
|
||||
url = "git@github.com:owner/repo"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result == "git@github.com:owner/repo.git"
|
||||
|
||||
def test_invalid_url(self):
|
||||
url = "not-a-url"
|
||||
result = extract_base_repo_url(url)
|
||||
assert result is None
|
||||
|
||||
def test_empty_url(self):
|
||||
url = ""
|
||||
result = extract_base_repo_url(url)
|
||||
assert result is None
|
||||
|
||||
|
||||
class TestIsValidCloneUrl:
|
||||
"""Tests for is_valid_clone_url function."""
|
||||
|
||||
def test_valid_ssh_url(self):
|
||||
assert is_valid_clone_url("git@github.com:owner/repo.git") is True
|
||||
|
||||
def test_valid_https_url(self):
|
||||
assert is_valid_clone_url("https://github.com/owner/repo.git") is True
|
||||
|
||||
def test_browser_url(self):
|
||||
assert is_valid_clone_url("https://github.com/owner/repo/tree/main") is False
|
||||
|
||||
def test_url_without_git_suffix(self):
|
||||
assert is_valid_clone_url("https://github.com/owner/repo") is False
|
||||
|
||||
def test_invalid_url(self):
|
||||
assert is_valid_clone_url("not-a-url") is False
|
||||
|
||||
|
||||
class TestParseGitUrl:
|
||||
"""Tests for parse_git_url function."""
|
||||
|
||||
def test_valid_git_url(self):
|
||||
result = parse_git_url("https://github.com/owner/repo.git")
|
||||
assert result["is_valid_clone_url"] is True
|
||||
assert result["needs_parsing"] is False
|
||||
assert result["base_url"] == "https://github.com/owner/repo.git"
|
||||
assert result["host"] == "github.com"
|
||||
assert "Valid" in result["message"]
|
||||
|
||||
def test_browser_url(self):
|
||||
result = parse_git_url("https://github.com/owner/repo/tree/main")
|
||||
assert result["is_valid_clone_url"] is False
|
||||
assert result["needs_parsing"] is True
|
||||
assert result["base_url"] == "https://github.com/owner/repo.git"
|
||||
assert result["host"] == "github.com"
|
||||
assert result["error_code"] == "URL_NEEDS_PARSING"
|
||||
assert "browser URL" in result["message"]
|
||||
|
||||
def test_invalid_url(self):
|
||||
result = parse_git_url("not-a-url")
|
||||
assert result["is_valid_clone_url"] is False
|
||||
assert result["base_url"] is None
|
||||
assert result["error_code"] == "INVALID_URL"
|
||||
|
||||
def test_empty_url(self):
|
||||
result = parse_git_url("")
|
||||
assert result["is_valid_clone_url"] is False
|
||||
assert result["base_url"] is None
|
||||
assert result["error_code"] == "INVALID_URL"
|
||||
|
||||
def test_ssh_url(self):
|
||||
result = parse_git_url("git@github.com:owner/repo.git")
|
||||
assert result["is_valid_clone_url"] is True
|
||||
assert result["needs_parsing"] is False
|
||||
assert result["host"] == "github.com"
|
||||
Reference in New Issue
Block a user