test: lift coverage 41% → 76% (+1068 tests across 36 files)

Service-level tests now exercise provider, permissions, project, journal,
messaging, work_session, metrics, kanban, extraction, learning, notification,
dashboard, llm_routing, a2a, task, repository_base, audit, db_seed,
branch_name, indexed_document, query_helpers, agent. API route tests cover
provider, journal, project, sessions, dashboard, work_session, tasks, a2a,
groups, notifications, agents, channels, messages, kanban, api_resources.
Pure-function helpers covered: handlers, deps_helpers, middleware,
middleware_docs, transcription, pr templates, agents_config, errors,
logging, journal/notification/channel/a2a access, task_lifecycle,
streaming, converters, crypto, schemas (common + websocket), events,
permissions extras.

pyproject ruff per-file-ignores extended for tests so PLR2004 (status code
magic values), PLC0415 (lazy imports), PLR0913 (fixture params), ARG001
(unused fixture deps), SIM105, and E501 don't fight test idioms.
This commit is contained in:
Renn F
2026-05-06 00:32:52 +02:00
parent b6903490f1
commit 64c48356d0
46 changed files with 2994 additions and 206 deletions
+127
View File
@@ -0,0 +1,127 @@
"""api.utils.resources coverage."""
from __future__ import annotations
from typing import TYPE_CHECKING
from uuid import uuid4
import pytest
from fastapi import HTTPException
from roboco.api.utils.resources import (
get_by_field_or_404,
get_or_404,
require_membership,
require_ownership,
require_recipient,
)
from roboco.db.tables import AgentTable
from roboco.models import AgentRole, AgentStatus, Team
if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
@pytest.mark.asyncio
async def test_get_or_404_finds_existing(db_session: AsyncSession) -> None:
agent = AgentTable(
id=uuid4(),
name="Dev",
slug=f"d-{uuid4().hex[:8]}",
role=AgentRole.DEVELOPER,
team=Team.BACKEND,
status=AgentStatus.ACTIVE,
model_config={},
system_prompt="x",
capabilities=[],
permissions={},
metrics={},
)
db_session.add(agent)
await db_session.flush()
fetched = await get_or_404(db_session, AgentTable, agent.id)
assert fetched.id == agent.id
@pytest.mark.asyncio
async def test_get_or_404_raises_when_missing(db_session: AsyncSession) -> None:
with pytest.raises(HTTPException) as exc:
await get_or_404(db_session, AgentTable, uuid4(), "Agent")
assert exc.value.status_code == 404
@pytest.mark.asyncio
async def test_get_by_field_or_404_finds(db_session: AsyncSession) -> None:
agent = AgentTable(
id=uuid4(),
name="Dev2",
slug=f"d2-{uuid4().hex[:8]}",
role=AgentRole.DEVELOPER,
team=Team.BACKEND,
status=AgentStatus.ACTIVE,
model_config={},
system_prompt="x",
capabilities=[],
permissions={},
metrics={},
)
db_session.add(agent)
await db_session.flush()
fetched = await get_by_field_or_404(
db_session, AgentTable, "slug", agent.slug, "Agent"
)
assert fetched.id == agent.id
@pytest.mark.asyncio
async def test_get_by_field_or_404_raises(db_session: AsyncSession) -> None:
with pytest.raises(HTTPException) as exc:
await get_by_field_or_404(db_session, AgentTable, "slug", "ghost-slug", "Agent")
assert exc.value.status_code == 404
# ---------------------------------------------------------------------------
# Ownership / Recipients / Membership
# ---------------------------------------------------------------------------
def test_require_ownership_passes_for_owner() -> None:
aid = uuid4()
resource = type("R", (), {"owner": aid})()
require_ownership(resource, "owner", aid, "edit")
def test_require_ownership_raises_for_other_agent() -> None:
resource = type("R", (), {"owner": uuid4()})()
with pytest.raises(HTTPException) as exc:
require_ownership(resource, "owner", uuid4(), "edit")
assert exc.value.status_code == 403
def test_require_ownership_no_owner_passes() -> None:
resource = type("R", (), {"owner": None})()
# Should not raise — no owner means open access.
require_ownership(resource, "owner", uuid4(), "edit")
def test_require_recipient_passes() -> None:
aid = uuid4()
require_recipient([uuid4(), aid, uuid4()], aid)
def test_require_recipient_raises() -> None:
with pytest.raises(HTTPException) as exc:
require_recipient([uuid4(), uuid4()], uuid4())
assert exc.value.status_code == 403
def test_require_membership_passes() -> None:
aid = uuid4()
require_membership([uuid4(), aid], aid, "channel")
def test_require_membership_raises() -> None:
with pytest.raises(HTTPException) as exc:
require_membership([uuid4()], uuid4(), "channel")
assert exc.value.status_code == 403