forked from retoor/devplacepy
chore: reorganize test files into domain-specific subdirectories under tests/
Split the monolithic test directory into three tiers (unit, api, e2e) with a path-mirroring directory structure. Added corresponding Makefile targets (test-unit, test-api, test-e2e) and updated all documentation references (CLAUDE.md, README.md, testing-cicd.html, testing-framework.html, testing-make.html) to reflect the new layout and naming conventions.
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import asyncio
|
||||
import pytest
|
||||
from devplacepy.database import (
|
||||
get_table,
|
||||
init_db,
|
||||
refresh_snapshot,
|
||||
set_setting,
|
||||
)
|
||||
from devplacepy.services.gitea import runtime, store
|
||||
from devplacepy.services.gitea.config import gitea_config
|
||||
from devplacepy.services.gitea.enhance import enhance_ticket
|
||||
from devplacepy.services.gitea.fake import FakeGiteaClient
|
||||
from devplacepy.services.gitea.service import BugTrackerService
|
||||
from devplacepy.services.jobs import queue
|
||||
from devplacepy.services.jobs.bug_create_service import BugCreateService
|
||||
from tests.conftest import run_async
|
||||
_counter_bugs_gitea = [0]
|
||||
@pytest.fixture(autouse=True)
|
||||
def _init_db_bugs_gitea():
|
||||
init_db()
|
||||
yield
|
||||
@pytest.fixture
|
||||
def gitea_env():
|
||||
fake = FakeGiteaClient()
|
||||
runtime.set_client(fake)
|
||||
set_setting("gitea_base_url", "https://gitea.test")
|
||||
set_setting("gitea_owner", "retoor")
|
||||
set_setting("gitea_repo", "pydevplace")
|
||||
set_setting("gitea_token", "test-token")
|
||||
set_setting("bug_ai_enhance", "0")
|
||||
yield fake
|
||||
runtime.set_client(None)
|
||||
for table in ("bug_tickets", "bug_comment_authors"):
|
||||
for row in list(get_table(table).find()):
|
||||
get_table(table).delete(uid=row["uid"])
|
||||
for row in list(get_table("jobs").find(kind="bug_create")):
|
||||
get_table("jobs").delete(uid=row["uid"])
|
||||
def _make_user_bugs_gitea():
|
||||
_counter_bugs_gitea[0] += 1
|
||||
uid = f"bugtest-user-{_counter_bugs_gitea[0]}"
|
||||
username = f"bugtester{_counter_bugs_gitea[0]}"
|
||||
get_table("users").insert(
|
||||
{
|
||||
"uid": uid,
|
||||
"username": username,
|
||||
"role": "member",
|
||||
"xp": 0,
|
||||
"level": 1,
|
||||
"is_active": True,
|
||||
}
|
||||
)
|
||||
return uid, username
|
||||
def _unread(user_uid):
|
||||
return [
|
||||
n
|
||||
for n in get_table("notifications").find(user_uid=user_uid)
|
||||
if n.get("type") == "bug"
|
||||
]
|
||||
def _drive_jobs():
|
||||
async def run():
|
||||
svc = BugCreateService()
|
||||
for _ in range(200):
|
||||
await svc.run_once()
|
||||
refresh_snapshot()
|
||||
pending = [
|
||||
r
|
||||
for r in get_table("jobs").find(kind="bug_create")
|
||||
if r["status"] in ("pending", "running")
|
||||
]
|
||||
if not pending and not svc._inflight:
|
||||
return
|
||||
await asyncio.sleep(0.02)
|
||||
|
||||
run_async(run())
|
||||
def _role_user(role: str):
|
||||
uid, username = _make_user_bugs_gitea()
|
||||
get_table("users").update({"uid": uid, "role": role}, ["uid"])
|
||||
return uid, username
|
||||
def _open_ticket(fake, role: str):
|
||||
import devplacepy.main as m
|
||||
from starlette.testclient import TestClient
|
||||
from devplacepy.utils import create_session
|
||||
|
||||
uid, _ = _role_user(role)
|
||||
issue = run_async(fake.create_issue("Submit does nothing", "details"))
|
||||
number = int(issue["number"])
|
||||
store.record_ticket(
|
||||
number=number,
|
||||
author_uid=uid,
|
||||
original_title="Submit does nothing",
|
||||
original_description="details",
|
||||
enhanced_title="Submit does nothing",
|
||||
html_url=issue.get("html_url", ""),
|
||||
status="open",
|
||||
)
|
||||
client = TestClient(m.app)
|
||||
client.cookies.set("session", create_session(uid))
|
||||
return number, client
|
||||
|
||||
|
||||
def test_fake_client_create_and_list(gitea_env):
|
||||
async def go():
|
||||
issue = await gitea_env.create_issue("Crash on save", "details")
|
||||
assert issue["number"] == 1
|
||||
assert issue["state"] == "open"
|
||||
issues, total = await gitea_env.list_issues(state="open")
|
||||
assert total == 1
|
||||
assert issues[0]["number"] == 1
|
||||
|
||||
run_async(go())
|
||||
|
||||
|
||||
def test_fake_client_state_and_comments(gitea_env):
|
||||
async def go():
|
||||
issue = await gitea_env.create_issue("t", "b")
|
||||
number = issue["number"]
|
||||
await gitea_env.create_comment(number, "first")
|
||||
fetched = await gitea_env.get_issue(number)
|
||||
assert fetched["comments"] == 1
|
||||
closed = await gitea_env.set_state(number, "closed")
|
||||
assert closed["state"] == "closed"
|
||||
open_issues, _ = await gitea_env.list_issues(state="open")
|
||||
assert open_issues == []
|
||||
all_issues, total = await gitea_env.list_issues(state="all")
|
||||
assert total == 1
|
||||
|
||||
run_async(go())
|
||||
|
||||
|
||||
def test_store_records_and_maps(gitea_env):
|
||||
uid, _ = _make_user_bugs_gitea()
|
||||
store.record_ticket(7, uid, "orig", "desc", "Better", "https://x/7", "open")
|
||||
assert store.author_uid_for_issue(7) == uid
|
||||
assert store.author_map([7, 8]) == {7: uid}
|
||||
cid = store.record_comment_author(99, 7, uid)
|
||||
assert cid
|
||||
assert store.comment_author_map([99, 100]) == {99: uid}
|
||||
assert store.local_comment_ids(7) == {99}
|
||||
|
||||
|
||||
def test_enhance_fallback_when_disabled(gitea_env):
|
||||
result = run_async(enhance_ticket("Title", "Body text", gitea_config()))
|
||||
assert result.enhanced is False
|
||||
assert "## Summary" in result.body
|
||||
assert "## Steps to Reproduce" in result.body
|
||||
assert result.title == "Title"
|
||||
|
||||
|
||||
def test_create_job_files_issue(gitea_env):
|
||||
uid, username = _make_user_bugs_gitea()
|
||||
job_uid = queue.enqueue(
|
||||
"bug_create",
|
||||
{"author_uid": uid, "title": "Login broken", "description": "cannot log in"},
|
||||
"user",
|
||||
uid,
|
||||
"Login broken",
|
||||
)
|
||||
_drive_jobs()
|
||||
job = queue.get_job(job_uid)
|
||||
assert job["status"] == "done"
|
||||
number = job["result"]["number"]
|
||||
assert number == 1
|
||||
ticket = store.get_ticket(number)
|
||||
assert ticket["author_uid"] == uid
|
||||
assert _unread(uid)
|
||||
issue = run_async(gitea_env.get_issue(number))
|
||||
assert username in issue["body"]
|
||||
|
||||
|
||||
def test_create_job_fails_without_config(gitea_env):
|
||||
set_setting("gitea_token", "")
|
||||
uid, _ = _make_user_bugs_gitea()
|
||||
job_uid = queue.enqueue(
|
||||
"bug_create",
|
||||
{"author_uid": uid, "title": "x", "description": "y"},
|
||||
"user",
|
||||
uid,
|
||||
"x",
|
||||
)
|
||||
_drive_jobs()
|
||||
job = queue.get_job(job_uid)
|
||||
assert job["status"] == "failed"
|
||||
assert "not configured" in job["error"].lower()
|
||||
|
||||
|
||||
def test_poller_notifies_on_developer_reply(gitea_env):
|
||||
uid, _ = _make_user_bugs_gitea()
|
||||
issue = run_async(gitea_env.create_issue("bug", "body"))
|
||||
number = issue["number"]
|
||||
store.record_ticket(number, uid, "bug", "body", "bug", issue["html_url"], "open")
|
||||
store.update_ticket_cache(number, "open", 0)
|
||||
|
||||
gitea_env.add_external_comment(number, "developer", "looking into it")
|
||||
before = len(_unread(uid))
|
||||
run_async(BugTrackerService().run_once())
|
||||
refresh_snapshot()
|
||||
assert len(_unread(uid)) == before + 1
|
||||
assert int(store.get_ticket(number)["last_comment_count"]) == 1
|
||||
|
||||
|
||||
def test_poller_ignores_local_comment(gitea_env):
|
||||
uid, _ = _make_user_bugs_gitea()
|
||||
issue = run_async(gitea_env.create_issue("bug", "body"))
|
||||
number = issue["number"]
|
||||
store.record_ticket(number, uid, "bug", "body", "bug", issue["html_url"], "open")
|
||||
store.update_ticket_cache(number, "open", 0)
|
||||
|
||||
comment = run_async(gitea_env.create_comment(number, "me again"))
|
||||
store.record_comment_author(comment["id"], number, uid)
|
||||
before = len(_unread(uid))
|
||||
run_async(BugTrackerService().run_once())
|
||||
refresh_snapshot()
|
||||
assert len(_unread(uid)) == before
|
||||
|
||||
|
||||
def test_poller_notifies_on_status_change(gitea_env):
|
||||
uid, _ = _make_user_bugs_gitea()
|
||||
issue = run_async(gitea_env.create_issue("bug", "body"))
|
||||
number = issue["number"]
|
||||
store.record_ticket(number, uid, "bug", "body", "bug", issue["html_url"], "open")
|
||||
store.update_ticket_cache(number, "open", 0)
|
||||
|
||||
run_async(gitea_env.set_state(number, "closed"))
|
||||
before = len(_unread(uid))
|
||||
run_async(BugTrackerService().run_once())
|
||||
refresh_snapshot()
|
||||
assert len(_unread(uid)) == before + 1
|
||||
assert store.get_ticket(number)["last_status"] == "closed"
|
||||
Reference in New Issue
Block a user