test(slack): collapse the subtype allowlist tests to two invariants

Drop tests/gateway/test_slack_conversational_senders.py (12 parametrized
cases driving _handle_slack_message end-to-end for allow_bots policies and
canvas mentions — the allow_bots matrix is already covered by the existing
bot-filter tests in test_slack.py) and fold the remaining coverage into two
_prefilter_inbound tests: every housekeeping subtype is dropped, and every
conversational subtype (absent, file_share, thread_broadcast, me_message,
document_mention, bot_message under allow_bots=all) still passes. Distinct
ts per event: the prefilter dedups by (team, ts) before the subtype gate.

Adds the contributor email mapping for the second author.
This commit is contained in:
teknium1
2026-09-14 18:34:33 -07:00
committed by Teknium
parent a019976430
commit e31466bc5d
3 changed files with 20 additions and 147 deletions

View File

@@ -0,0 +1 @@
teo-nex

View File

@@ -6057,67 +6057,31 @@ class TestAgentSessionsApiRouting:
class TestNonConversationalSubtypeAllowlist:
"""#110778 — housekeeping subtypes must not start a turn in free-response
channels. The gate is an allowlist so subtypes Slack adds later are dropped
instead of silently readmitted."""
"""#110778 — Slack system messages must not start a turn in free-response channels; the
gate is an allowlist so subtypes Slack adds later are dropped instead of readmitted."""
@staticmethod
def _event(subtype):
event = {
"type": "message",
"user": "U_HUMAN",
"text": "hello",
"ts": "12345.6789",
"channel": "C_FREE",
}
def _event(subtype, **extra):
# Distinct ts per subtype: the prefilter dedups by (team, ts) before the subtype gate.
event = {"type": "message", "user": "U_HUMAN", "text": "hello",
"ts": f"12345.{abs(hash(subtype)) % 10**6}", "channel": "C_FREE",
"client_msg_id": "m1", **extra}
if subtype is not None:
event["subtype"] = subtype
return event
@pytest.mark.asyncio
@pytest.mark.parametrize(
"subtype",
[
"channel_join",
"channel_leave",
"channel_topic",
"channel_purpose",
"channel_name",
"channel_convert_to_private",
"channel_convert_to_public",
"pinned_item",
"unpinned_item",
"message_deleted",
"file_comment",
],
)
async def test_housekeeping_subtypes_are_dropped(self, adapter, subtype):
assert await adapter._prefilter_inbound(self._event(subtype), None) is None
async def test_housekeeping_subtypes_are_dropped(self, adapter):
for subtype in ("channel_join", "channel_topic", "channel_convert_to_private",
"pinned_item", "file_comment", "message_deleted"):
assert await adapter._prefilter_inbound(self._event(subtype), None) is None, subtype
@pytest.mark.asyncio
@pytest.mark.parametrize(
"subtype", [None, "file_share", "thread_broadcast", "me_message"]
)
async def test_conversational_subtypes_pass(self, adapter, subtype):
accepted = await adapter._prefilter_inbound(self._event(subtype), None)
assert accepted is not None
assert accepted[0].get("channel") == "C_FREE"
@pytest.mark.asyncio
async def test_edited_message_still_wakes_the_bot(self, adapter):
event = {
"type": "message",
"subtype": "message_changed",
"channel": "C_FREE",
"ts": "12340.0000",
"message": {
"type": "message",
"user": "U_HUMAN",
"text": "edited hello",
"ts": "12345.6789",
"edited": {"ts": "12346.0000"},
},
}
accepted = await adapter._prefilter_inbound(event, None)
assert accepted is not None
assert accepted[0].get("text") == "edited hello"
async def test_conversational_subtypes_still_pass(self, adapter):
adapter.config.extra["allow_bots"] = "all"
events = [self._event(s) for s in (None, "file_share", "thread_broadcast", "me_message",
"document_mention")]
events.append(self._event("bot_message", bot_id="B_OTHER"))
for event in events:
accepted = await adapter._prefilter_inbound(event, None)
assert accepted is not None and accepted[0]["channel"] == "C_FREE", event.get("subtype")

View File

@@ -1,92 +0,0 @@
"""Preserve conversational senders through the subtype filter in PR #110780."""
from types import SimpleNamespace
from unittest.mock import AsyncMock
import pytest
from gateway.config import PlatformConfig
from plugins.platforms.slack.adapter import SlackAdapter
@pytest.fixture
def adapter():
instance = SlackAdapter(PlatformConfig(
enabled=True,
token="xoxb-test",
extra={"free_response_channels": ["C_TEST"], "allow_bots": "all"},
))
instance._bot_user_id = "U_BOT"
instance._running = True
instance._app = SimpleNamespace(client=SimpleNamespace(
users_info=AsyncMock(return_value={
"ok": True, "user": {"is_bot": False, "real_name": "Test User"},
}),
conversations_info=AsyncMock(return_value={
"ok": True, "channel": {"name": "test"},
}),
conversations_replies=AsyncMock(return_value={"ok": True, "messages": []}),
))
instance.handle_message = AsyncMock()
return instance
def _event(subtype, text, *, edited):
message = {
"type": "app_mention" if subtype == "document_mention" else "message",
"subtype": subtype, "user": "U_TEST", "text": text,
"channel": "C_TEST", "channel_type": "channel", "team": "T_TEST",
"ts": "100.000001",
}
if subtype == "bot_message":
message["bot_id"] = "B_OTHER"
else:
message["document_mention"] = {
"file_id": "F_CANVAS", "section_id": "section-1",
"mentioning_user_ids": ["U_TEST"],
}
if not edited:
return message
return {
"type": "message", "subtype": "message_changed",
"channel": "C_TEST", "channel_type": "channel", "team": "T_TEST",
"ts": "101.000001", "event_ts": "101.000001", "message": message,
}
@pytest.mark.asyncio
@pytest.mark.parametrize("edited", [False, True], ids=["original", "edited"])
@pytest.mark.parametrize(("policy", "mentioned", "accepted"), [
("none", False, False),
("none", True, False),
("mentions", False, False),
("mentions", True, True),
("all", False, True),
])
async def test_bot_messages_retain_the_configured_policy(adapter, policy, mentioned, accepted, edited):
adapter.config.extra["allow_bots"] = policy
text = "<@U_BOT> A message" if mentioned else "A message"
await adapter._handle_slack_message(_event("bot_message", text, edited=edited))
assert adapter.handle_message.await_count == int(accepted)
if accepted:
delivered = adapter.handle_message.await_args.args[0]
assert delivered.text == "A message"
assert delivered.source.is_bot is True
@pytest.mark.asyncio
@pytest.mark.parametrize("edited", [False, True], ids=["original", "edited"])
async def test_canvas_mentions_reach_the_agent(adapter, edited):
adapter.config.extra = {"allow_bots": "none"}
await adapter._handle_slack_message(
_event("document_mention", "<@U_BOT> Summarize this canvas", edited=edited)
)
adapter.handle_message.assert_awaited_once()
delivered = adapter.handle_message.await_args.args[0]
assert delivered.text == "Summarize this canvas"
assert delivered.source.user_id == "U_TEST"
assert delivered.raw_message["document_mention"]["file_id"] == "F_CANVAS"