feat(forgejo): add DB models, CRUD APIs, client service, and Git Projects nav (Issues 1-4, FI2)
Backend:
- ForgejoConnection + ForgejoRepository SQLModel models with migration
- Admin CRUD API for connections (GET/POST/PATCH/DELETE)
- Admin CRUD API for repositories (GET/POST/PATCH/DELETE)
- Token redaction, URL normalization, duplicate prevention
- ForgejoAPIClient service (httpx async, list_issues, close_issue, get_repository)
- Removed stale feast import that crashed startup
Frontend:
- Git Projects sidebar nav item (FolderGit icon)
- /git-projects shell page with empty/loading/error states
Verified: all endpoints live, CRUD tested, migration applied.
2026-05-19 02:46:27 -05:00
|
|
|
"""Tests for Forgejo client service."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
from app.services.forgejo_client import ForgejoAPIClient, get_forgejo_client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_forgejo_client_base_url_normalization() -> None:
|
|
|
|
|
"""Test base_url normalization."""
|
|
|
|
|
# Should strip trailing slash
|
|
|
|
|
client1 = ForgejoAPIClient(base_url="https://forgejo.example.com/")
|
|
|
|
|
assert client1.base_url == "https://forgejo.example.com"
|
|
|
|
|
|
|
|
|
|
# Should handle no trailing slash
|
|
|
|
|
client2 = ForgejoAPIClient(base_url="https://forgejo.example.com")
|
|
|
|
|
assert client2.base_url == "https://forgejo.example.com"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_forgejo_client_without_token() -> None:
|
|
|
|
|
"""Test client without auth token."""
|
|
|
|
|
client = ForgejoAPIClient(base_url="https://forgejo.example.com", token=None)
|
|
|
|
|
assert client.token is None
|
|
|
|
|
assert client.base_url == "https://forgejo.example.com"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_forgejo_client_with_token() -> None:
|
|
|
|
|
"""Test client with auth token."""
|
|
|
|
|
client = ForgejoAPIClient(base_url="https://forgejo.example.com", token="ghp_testtoken123")
|
|
|
|
|
assert client.token == "ghp_testtoken123"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Test factory function
|
|
|
|
|
def test_get_forgejo_client_factory() -> None:
|
|
|
|
|
"""Test get_forgejo_client factory function."""
|
|
|
|
|
# Create a mock connection object
|
|
|
|
|
class MockConnection:
|
|
|
|
|
base_url = "https://forgejo.example.com"
|
|
|
|
|
token = "ghp_testtoken123"
|
|
|
|
|
|
2026-05-19 21:18:18 -05:00
|
|
|
client = get_forgejo_client(MockConnection())
|
|
|
|
|
assert client.base_url == "https://forgejo.example.com"
|
|
|
|
|
assert client.token == "ghp_testtoken123"
|
feat(forgejo): add DB models, CRUD APIs, client service, and Git Projects nav (Issues 1-4, FI2)
Backend:
- ForgejoConnection + ForgejoRepository SQLModel models with migration
- Admin CRUD API for connections (GET/POST/PATCH/DELETE)
- Admin CRUD API for repositories (GET/POST/PATCH/DELETE)
- Token redaction, URL normalization, duplicate prevention
- ForgejoAPIClient service (httpx async, list_issues, close_issue, get_repository)
- Removed stale feast import that crashed startup
Frontend:
- Git Projects sidebar nav item (FolderGit icon)
- /git-projects shell page with empty/loading/error states
Verified: all endpoints live, CRUD tested, migration applied.
2026-05-19 02:46:27 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_forgejo_client_with_api_path() -> None:
|
|
|
|
|
"""Test factory normalizes /api/v1 path."""
|
|
|
|
|
class MockConnection:
|
|
|
|
|
base_url = "https://forgejo.example.com/api/v1"
|
|
|
|
|
|
2026-05-19 21:18:18 -05:00
|
|
|
client = get_forgejo_client(MockConnection())
|
|
|
|
|
assert client.base_url == "https://forgejo.example.com"
|