Files
Gitea-Tools/tests/integration/test_gitea_live.py
T
2026-07-02 15:31:56 -05:00

116 lines
4.6 KiB
Python

"""Opt-in integration tests against a real (containerized) Gitea (#66).
Skipped by default. Enable with GITEA_INTEGRATION=1 plus a local instance and
token — see tests/integration/README.md. These prove real Gitea behavior that
the mocked unit suite can only simulate: pagination, targeted label edits,
permission fail-closed, and error payload surfacing — all through the shared
client (``gitea_auth.api_request`` / ``api_get_all``, #65/#67 shape).
No production credentials; tokens never appear in output or assertions.
"""
import os
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent))
from gitea_auth import api_request, api_get_all # noqa: E402
pytestmark = pytest.mark.skipif(
os.environ.get("GITEA_INTEGRATION") != "1",
reason="integration tests are opt-in: set GITEA_INTEGRATION=1 (see tests/integration/README.md)",
)
# --- issue listing + pagination --------------------------------------------
N_ISSUES = 7 # > page_size below, forcing a real multi-page walk
@pytest.fixture(scope="module")
def issues(gitea, seed_repo):
created = []
for i in range(N_ISSUES):
created.append(api_request(
"POST", f"{seed_repo['api']}/issues", gitea["auth"],
payload={"title": f"pagination seed {i}"}))
return created
def test_issue_pagination_walks_all_pages(gitea, seed_repo, issues):
got = api_get_all(f"{seed_repo['api']}/issues?state=open", gitea["auth"],
page_size=3)
titles = {i["title"] for i in got}
assert {f"pagination seed {i}" for i in range(N_ISSUES)} <= titles
assert len(got) >= N_ISSUES
def test_issue_pagination_honors_overall_limit(gitea, seed_repo, issues):
got = api_get_all(f"{seed_repo['api']}/issues?state=open", gitea["auth"],
page_size=3, limit=4)
assert len(got) == 4
# --- PR listing --------------------------------------------------------------
def test_pr_listing_via_shared_client(gitea, seed_repo, issues):
# Create a branch (via the contents API) and a real PR, then list.
api_request(
"POST", f"{seed_repo['api']}/contents/inttest.txt", gitea["auth"],
payload={"content": "aW50ZWdyYXRpb24gc2VlZAo=", # "integration seed"
"message": "seed PR branch", "new_branch": "inttest-pr"})
pr = api_request(
"POST", f"{seed_repo['api']}/pulls", gitea["auth"],
payload={"title": "integration seed PR", "head": "inttest-pr",
"base": "main"})
got = api_get_all(f"{seed_repo['api']}/pulls?state=open", gitea["auth"],
page_size=1)
assert any(p["number"] == pr["number"] for p in got)
# --- targeted label add/remove ----------------------------------------------
def test_targeted_label_add_and_remove(gitea, seed_repo, issues):
labels = {}
for name, color in (("keep-me", "#00ff00"), ("drop-me", "#ff0000")):
labels[name] = api_request(
"POST", f"{seed_repo['api']}/labels", gitea["auth"],
payload={"name": name, "color": color})
issue_no = issues[0]["number"]
issue_labels_url = f"{seed_repo['api']}/issues/{issue_no}/labels"
api_request("POST", issue_labels_url, gitea["auth"],
payload={"labels": [labels["keep-me"]["id"],
labels["drop-me"]["id"]]})
# Targeted removal of one label must not disturb the other.
api_request("DELETE", f"{issue_labels_url}/{labels['drop-me']['id']}",
gitea["auth"])
remaining = {l["name"] for l in api_request("GET", issue_labels_url,
gitea["auth"])}
assert "keep-me" in remaining
assert "drop-me" not in remaining
# --- permission denial / fail-closed -----------------------------------------
def test_bad_token_fails_closed_without_leaking_it(gitea):
bogus = "token 0123456789abcdef0123456789abcdef01234567"
with pytest.raises(RuntimeError) as exc:
api_request("GET", f"{gitea['base']}/api/v1/user", bogus)
msg = str(exc.value)
assert "401" in msg
assert "0123456789abcdef" not in msg # credential never echoed
def test_real_error_payload_surfaces_safely(gitea, seed_repo):
# A genuinely missing resource: Gitea's real 404 error payload must become
# a clear RuntimeError, not a stack trace, and must not echo the token.
with pytest.raises(RuntimeError) as exc:
api_request("GET", f"{seed_repo['api']}/issues/999999", gitea["auth"])
msg = str(exc.value)
assert "404" in msg
token = os.environ.get("GITEA_INTEGRATION_TOKEN", "")
if token:
assert token not in msg