214 lines
6.2 KiB
Python
214 lines
6.2 KiB
Python
"""Tests for DaemonClient.generate_message() and record_commit() RPC methods."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
import httpx
|
|
import pytest
|
|
from pytest_httpx import HTTPXMock
|
|
|
|
from auto_commit_service.tray.client import DaemonClient
|
|
|
|
|
|
BASE_URL = "http://localhost:8200"
|
|
|
|
|
|
@pytest.fixture
|
|
def client(httpx_mock: HTTPXMock) -> DaemonClient:
|
|
return DaemonClient(base_url=BASE_URL, timeout=5.0)
|
|
|
|
|
|
class TestGenerateMessage:
|
|
def test_happy_path_returns_dict_with_message(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/generate-message",
|
|
json={"message": "feat: add new endpoint"},
|
|
status_code=200,
|
|
)
|
|
|
|
result = client.generate_message(
|
|
diff="diff --git a/foo.py ...", repo_name="myrepo", branch="main"
|
|
)
|
|
|
|
assert result is not None
|
|
assert result["message"] == "feat: add new endpoint"
|
|
|
|
def test_sends_correct_payload(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/generate-message",
|
|
json={"message": "chore: update deps"},
|
|
status_code=200,
|
|
)
|
|
|
|
client.generate_message(
|
|
diff="+ new line", repo_name="my-service", branch="feature/xyz"
|
|
)
|
|
|
|
request = httpx_mock.get_request()
|
|
assert request is not None
|
|
body = json.loads(request.content)
|
|
assert body["diff"] == "+ new line"
|
|
assert body["repo_name"] == "my-service"
|
|
assert body["branch"] == "feature/xyz"
|
|
|
|
def test_server_400_returns_none(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/generate-message",
|
|
json={"detail": "diff cannot be empty"},
|
|
status_code=400,
|
|
)
|
|
|
|
result = client.generate_message(diff="", repo_name="myrepo", branch="main")
|
|
|
|
assert result is None
|
|
|
|
def test_server_500_returns_none(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/generate-message",
|
|
json={"detail": "internal error"},
|
|
status_code=500,
|
|
)
|
|
|
|
result = client.generate_message(diff="some diff", repo_name="r", branch="main")
|
|
|
|
assert result is None
|
|
|
|
def test_connection_refused_returns_none(self, httpx_mock: HTTPXMock) -> None:
|
|
httpx_mock.add_exception(
|
|
httpx.ConnectError("Connection refused"),
|
|
url=f"{BASE_URL}/generate-message",
|
|
)
|
|
c = DaemonClient(base_url=BASE_URL)
|
|
|
|
result = c.generate_message(diff="x", repo_name="r", branch="main")
|
|
|
|
assert result is None
|
|
|
|
def test_default_branch_is_main(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/generate-message",
|
|
json={"message": "fix: something"},
|
|
status_code=200,
|
|
)
|
|
|
|
client.generate_message(diff="x", repo_name="r")
|
|
|
|
request = httpx_mock.get_request()
|
|
body = json.loads(request.content)
|
|
assert body["branch"] == "main"
|
|
|
|
|
|
class TestRecordCommit:
|
|
def test_happy_path_sends_correct_payload(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/record-commit",
|
|
json={"status": "ok"},
|
|
status_code=200,
|
|
)
|
|
|
|
result = client.record_commit(
|
|
hash="abc123",
|
|
repo_name="my-repo",
|
|
message="feat: add feature",
|
|
timestamp="2026-04-17T12:00:00+00:00",
|
|
hostname="plum",
|
|
branch="main",
|
|
files_changed=3,
|
|
insertions=10,
|
|
deletions=2,
|
|
)
|
|
|
|
assert result is not None
|
|
assert result["status"] == "ok"
|
|
|
|
request = httpx_mock.get_request()
|
|
body = json.loads(request.content)
|
|
assert body["hash"] == "abc123"
|
|
assert body["repo_name"] == "my-repo"
|
|
assert body["message"] == "feat: add feature"
|
|
assert body["timestamp"] == "2026-04-17T12:00:00+00:00"
|
|
assert body["hostname"] == "plum"
|
|
assert body["branch"] == "main"
|
|
assert body["files_changed"] == 3
|
|
assert body["insertions"] == 10
|
|
assert body["deletions"] == 2
|
|
|
|
def test_optional_fields_omitted_when_none(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/record-commit",
|
|
json={"status": "ok"},
|
|
status_code=200,
|
|
)
|
|
|
|
client.record_commit(
|
|
hash="abc123",
|
|
repo_name="r",
|
|
message="m",
|
|
timestamp="2026-01-01T00:00:00+00:00",
|
|
hostname="plum",
|
|
)
|
|
|
|
request = httpx_mock.get_request()
|
|
body = json.loads(request.content)
|
|
assert "files_changed" not in body
|
|
assert "insertions" not in body
|
|
assert "deletions" not in body
|
|
|
|
def test_server_500_returns_none(
|
|
self, client: DaemonClient, httpx_mock: HTTPXMock
|
|
) -> None:
|
|
httpx_mock.add_response(
|
|
method="POST",
|
|
url=f"{BASE_URL}/record-commit",
|
|
json={"detail": "db error"},
|
|
status_code=500,
|
|
)
|
|
|
|
result = client.record_commit(
|
|
hash="x",
|
|
repo_name="r",
|
|
message="m",
|
|
timestamp="2026-01-01T00:00:00+00:00",
|
|
hostname="plum",
|
|
)
|
|
|
|
assert result is None
|
|
|
|
def test_network_error_returns_none(self, httpx_mock: HTTPXMock) -> None:
|
|
httpx_mock.add_exception(
|
|
httpx.ConnectTimeout("timed out"),
|
|
url=f"{BASE_URL}/record-commit",
|
|
)
|
|
c = DaemonClient(base_url=BASE_URL)
|
|
|
|
result = c.record_commit(
|
|
hash="x",
|
|
repo_name="r",
|
|
message="m",
|
|
timestamp="2026-01-01T00:00:00+00:00",
|
|
hostname="plum",
|
|
)
|
|
|
|
assert result is None
|