130 lines
4.1 KiB
Python
130 lines
4.1 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import Mock
|
|
|
|
from lai_automation.gitea import GiteaClient
|
|
from lai_automation.models import Issue, Label
|
|
|
|
|
|
def response(payload, status: int = 200) -> Mock:
|
|
result = Mock()
|
|
result.json.return_value = payload
|
|
result.status_code = status
|
|
result.text = ""
|
|
result.raise_for_status.return_value = None
|
|
return result
|
|
|
|
|
|
def test_list_queued_issues_filters_pull_requests(settings) -> None:
|
|
client = GiteaClient(settings)
|
|
client.session.request = Mock(
|
|
return_value=response(
|
|
[
|
|
{
|
|
"number": 7,
|
|
"title": "Wrong answer",
|
|
"body": "Details",
|
|
"html_url": "https://gitea.example.test/owner/lai/issues/7",
|
|
"labels": [{"id": 1, "name": "ai:queued"}],
|
|
},
|
|
{
|
|
"number": 8,
|
|
"title": "A pull request",
|
|
"body": "",
|
|
"html_url": "https://gitea.example.test/owner/lai/pulls/8",
|
|
"labels": [{"id": 1, "name": "ai:queued"}],
|
|
"pull_request": {"merged": False},
|
|
},
|
|
]
|
|
)
|
|
)
|
|
|
|
issues = client.list_queued_issues()
|
|
|
|
assert [issue.number for issue in issues] == [7]
|
|
assert client.session.request.call_args.kwargs["params"]["labels"] == "ai:queued"
|
|
|
|
|
|
def test_ensure_automation_labels_creates_only_missing_labels(settings) -> None:
|
|
client = GiteaClient(settings)
|
|
existing = [{"id": 1, "name": "ai:queued"}]
|
|
created = iter(
|
|
[
|
|
{"id": 2, "name": "ai:running"},
|
|
{"id": 3, "name": "ai:ready"},
|
|
{"id": 4, "name": "ai:failed"},
|
|
]
|
|
)
|
|
|
|
def request(method, _url, **kwargs):
|
|
if method == "GET":
|
|
return response(existing)
|
|
return response(next(created))
|
|
|
|
client.session.request = Mock(side_effect=request)
|
|
|
|
labels = client.ensure_automation_labels()
|
|
|
|
assert set(labels) == {"ai:queued", "ai:running", "ai:ready", "ai:failed"}
|
|
assert client.session.request.call_count == 4
|
|
|
|
|
|
def test_state_transition_preserves_manual_labels(settings) -> None:
|
|
client = GiteaClient(settings)
|
|
client.session.request = Mock(
|
|
side_effect=[
|
|
response(
|
|
[
|
|
{"id": 9, "name": "bug"},
|
|
{"id": 2, "name": "ai:running"},
|
|
]
|
|
),
|
|
response(
|
|
{
|
|
"number": 5,
|
|
"title": "Issue",
|
|
"body": "Body",
|
|
"html_url": "https://gitea.example.test/owner/lai/issues/5",
|
|
"labels": [
|
|
{"id": 9, "name": "bug"},
|
|
{"id": 2, "name": "ai:running"},
|
|
],
|
|
}
|
|
),
|
|
]
|
|
)
|
|
issue = Issue(
|
|
number=5,
|
|
title="Issue",
|
|
body="Body",
|
|
html_url="https://gitea.example.test/owner/lai/issues/5",
|
|
labels=(Label(9, "bug"), Label(1, "ai:queued")),
|
|
)
|
|
known = {
|
|
"ai:queued": Label(1, "ai:queued"),
|
|
"ai:running": Label(2, "ai:running"),
|
|
}
|
|
|
|
updated = client.set_automation_state(issue, "ai:running", known)
|
|
|
|
assert updated.has_label("ai:running")
|
|
replace_call = client.session.request.call_args_list[0]
|
|
assert replace_call.args[0] == "PUT"
|
|
assert replace_call.args[1].endswith("/issues/5/labels")
|
|
assert replace_call.kwargs["json"] == {"labels": [9, 2]}
|
|
assert client.session.request.call_args_list[1].args[0] == "GET"
|
|
|
|
|
|
def test_create_pull_request_returns_number_and_url(settings) -> None:
|
|
client = GiteaClient(settings)
|
|
client.session.request = Mock(
|
|
return_value=response(
|
|
{"number": 17, "html_url": "https://gitea.example.test/owner/lai/pulls/17"}
|
|
)
|
|
)
|
|
|
|
pull_request = client.create_pull_request("ai/issue-5", "Fix", "Fixes #5")
|
|
|
|
assert pull_request.number == 17
|
|
assert pull_request.html_url.endswith("/pulls/17")
|
|
assert client.session.request.call_args.kwargs["json"]["base"] == "main" |