100% Coverage

This commit is contained in:
Renn F
2026-05-06 21:02:31 +02:00
parent 64c48356d0
commit 9aa30fb945
106 changed files with 28143 additions and 423 deletions
@@ -2,6 +2,8 @@
from __future__ import annotations
from unittest.mock import patch
import pytest
from roboco.enforcement.channel_access import (
ChannelAccessDeniedError,
@@ -57,3 +59,19 @@ def test_channel_access_denied_error_has_attributes() -> None:
assert err.agent_id == "be-dev-1"
assert err.channel_slug == "ghost"
assert err.action == "write"
def test_validate_channel_access_wildcard_allows_anyone() -> None:
"""Line 72: '*' in allowed list grants access to anyone."""
with patch(
"roboco.enforcement.channel_access.CHANNEL_ACCESS",
{"public-channel": {"read": ["*"], "write": [], "silent": []}},
):
assert validate_channel_access("ghost-agent", "public-channel", "read") is True
def test_validate_channel_access_silent_observer_can_read() -> None:
"""Line 80: silent observers can read."""
# backend-cell has 'auditor' as silent observer.
assert validate_channel_access("auditor", "backend-cell", "read") is True
@@ -94,3 +94,10 @@ def test_get_readable_journals_for_developer() -> None:
def test_get_readable_journals_for_unknown() -> None:
info = get_readable_journals("ghost-agent")
assert info["scope"] == "none"
def test_auditor_can_read_other_auditor_protected_journal() -> None:
"""Line 72: ceo/auditor reader → True for protected journal."""
can, reason = can_read_journal("auditor", "ceo")
assert can is True
assert reason == "OK"
@@ -5,6 +5,7 @@ from __future__ import annotations
import pytest
from roboco.enforcement.notification_perms import (
NotificationPermissionError,
_can_send_to_recipient,
get_notification_scope,
validate_notification_permission,
)
@@ -65,3 +66,23 @@ def test_validate_fails_on_first_unreachable() -> None:
def test_unknown_agent_cannot_send() -> None:
with pytest.raises(NotificationPermissionError):
validate_notification_permission("ghost-agent", ["be-pm"])
def test_can_send_to_recipient_developer_role_blocked() -> None:
"""_can_send_to_recipient with no can_send → role-blocked reason (line 51)."""
can_send, reason = _can_send_to_recipient("be-dev-1", "be-pm")
assert can_send is False
assert "developer" in reason
def test_board_member_list_scope_can_notify_listed_target() -> None:
"""Lines 73-75: list-scope sender notifies recipient in list."""
# product_owner has list scope including 'main-pm'.
assert validate_notification_permission("product-owner", ["main-pm"]) is True
def test_board_member_list_scope_cannot_notify_unlisted_target() -> None:
"""Lines 76-77: list-scope sender to unlisted target → False reason."""
with pytest.raises(NotificationPermissionError):
validate_notification_permission("product-owner", ["be-dev-1"])
@@ -0,0 +1,119 @@
"""Coverage for roboco.enforcement.task_ownership."""
from __future__ import annotations
import pytest
from roboco.enforcement.task_ownership import (
TaskOwnershipError,
can_review_task,
validate_task_ownership,
)
def test_reassign_by_main_pm_allowed() -> None:
assert (
validate_task_ownership(
agent_id="main-pm",
task_id="t1",
task_assigned_to=None,
task_team="backend",
action="reassign",
)
is True
)
def test_reassign_by_cell_pm_in_their_cell_allowed() -> None:
assert (
validate_task_ownership(
agent_id="be-pm",
task_id="t1",
task_assigned_to=None,
task_team="backend",
action="reassign",
)
is True
)
def test_reassign_by_developer_denied() -> None:
"""Non-PM cannot reassign (lines 69-75)."""
with pytest.raises(TaskOwnershipError) as exc:
validate_task_ownership(
agent_id="be-dev-1",
task_id="t1",
task_assigned_to=None,
task_team="backend",
action="reassign",
)
assert "Only PMs" in exc.value.message
def test_reassign_by_cell_pm_outside_cell_denied() -> None:
"""Cell PM trying to reassign tasks in another cell (lines 77-83)."""
with pytest.raises(TaskOwnershipError) as exc:
validate_task_ownership(
agent_id="be-pm",
task_id="t1",
task_assigned_to=None,
task_team="frontend",
action="reassign",
)
assert "their cell" in exc.value.message
def test_view_action_always_allowed() -> None:
"""View action returns True for any agent (line 88)."""
assert (
validate_task_ownership(
agent_id="be-dev-1",
task_id="t1",
task_assigned_to="someone-else",
task_team="backend",
action="view",
)
is True
)
def test_other_action_assigned_to_agent_allowed() -> None:
assert (
validate_task_ownership(
agent_id="be-dev-1",
task_id="t1",
task_assigned_to="be-dev-1",
task_team="backend",
action="update",
)
is True
)
def test_other_action_not_assigned_denied() -> None:
"""Action by non-assignee raises TaskOwnershipError."""
with pytest.raises(TaskOwnershipError) as exc:
validate_task_ownership(
agent_id="be-dev-1",
task_id="t1",
task_assigned_to="be-dev-2",
task_team="backend",
action="update",
)
assert "be-dev-2" in exc.value.message
def test_can_review_task_self_review_denied() -> None:
"""Cannot review your own work (line 118)."""
assert can_review_task("be-qa", "be-qa") is False
def test_can_review_task_other_agent_allowed() -> None:
assert can_review_task("be-qa", "be-dev-1") is True
def test_task_ownership_error_default_message() -> None:
err = TaskOwnershipError(agent_id="a", task_id="t", action="claim")
assert "claim" in err.message
assert err.agent_id == "a"
assert err.task_id == "t"
assert err.action == "claim"