Files
handbook/docker/packages/slack/tests/test_channel_management.py
2026-06-29 10:08:59 -07:00

160 lines
6.0 KiB
Python

from __future__ import annotations
import pytest
from helpers import seed_state
from slack_mock.server import archive_channel, create_channel, list_channels, rename_channel, set_channel_topic
from slack_mock.state import get_state
def setup_function() -> None:
seed_state(
{
"users": {"U001": {"id": "U001", "name": "alice"}},
"channels": {
"C001": {
"id": "C001",
"name": "general",
"name_normalized": "general",
"is_general": True,
"context_team_id": "T_MOCK",
"updated": 1700000000,
"creator": "U001",
"num_members": 5,
"previous_names": [],
"topic": {"value": "General chat", "creator": "U001", "last_set": 1700000000},
"purpose": {"value": "Team comms", "creator": "U001", "last_set": 1700000000},
},
"C002": {
"id": "C002",
"name": "random",
"name_normalized": "random",
"is_archived": True,
"context_team_id": "T_MOCK",
"updated": 1700000000,
"creator": "U001",
"num_members": 3,
"previous_names": [],
"topic": {"value": "", "creator": "", "last_set": 0},
"purpose": {"value": "", "creator": "", "last_set": 0},
},
"C003": {
"id": "C003",
"name": "external",
"context_team_id": "T_MOCK",
"is_member": False,
},
"D001": {
"id": "D001",
"name": "alice",
"context_team_id": "T_MOCK",
"is_channel": False,
"is_im": True,
"is_private": True,
"user": "U001",
},
"G001": {
"id": "G001",
"name": "private",
"context_team_id": "T_MOCK",
"is_channel": False,
"is_group": True,
"is_private": True,
},
},
"messages": {"C001": [], "C002": [], "C003": [], "D001": [], "G001": []},
"counters": {"channelId": 1000},
}
)
@pytest.mark.asyncio
async def test_list_channels_filters_to_active_channel_memberships() -> None:
listed = await list_channels()
assert listed["ok"] is True
assert [channel["id"] for channel in listed["channels"]] == ["C001", "G001"]
@pytest.mark.asyncio
async def test_create_channel_public_private_and_messages() -> None:
public = await create_channel("engineering")
private = await create_channel("secret", is_private=True)
assert public["ok"] is True
assert public["channel"]["name"] == "engineering"
assert public["channel"]["is_private"] is False
assert public["channel"]["is_channel"] is True
assert get_state().messages[public["channel"]["id"]] == []
assert private["ok"] is True
assert private["channel"]["is_private"] is True
assert private["channel"]["is_group"] is True
assert private["channel"]["is_channel"] is False
@pytest.mark.asyncio
async def test_create_channel_normalizes_and_rejects_bad_names() -> None:
normalized = await create_channel("MyChannel")
duplicate = await create_channel("general")
empty = await create_channel(" ")
second = await create_channel("chan-b")
assert normalized["channel"]["name"] == "mychannel"
assert normalized["channel"]["name_normalized"] == "mychannel"
assert duplicate["ok"] is False
assert duplicate["error"] == "name_taken"
assert empty["ok"] is False
assert empty["error"] == "invalid_name"
assert normalized["channel"]["id"] != second["channel"]["id"]
@pytest.mark.asyncio
async def test_archive_channel() -> None:
before = get_state().channels["C001"].updated
archived = await archive_channel("C001")
already = await archive_channel("C002")
missing = await archive_channel("INVALID")
assert archived["ok"] is True
assert get_state().channels["C001"].is_archived is True
assert get_state().channels["C001"].updated >= before
assert already == {"ok": False, "error": "already_archived"}
assert missing == {"ok": False, "error": "channel_not_found"}
@pytest.mark.asyncio
async def test_rename_channel() -> None:
renamed = await rename_channel("C001", "announcements")
normalized = await rename_channel("C001", "NewName")
duplicate = await rename_channel("C001", "random")
missing = await rename_channel("INVALID", "test")
empty = await rename_channel("C001", " ")
assert renamed["ok"] is True
assert renamed["channel"]["name"] == "announcements"
previous_names = get_state().channels["C001"].previous_names
assert previous_names is not None
assert "general" in previous_names
assert normalized["channel"]["name"] == "newname"
assert duplicate["error"] == "name_taken"
assert missing["error"] == "channel_not_found"
assert empty["error"] == "invalid_name"
@pytest.mark.asyncio
async def test_set_channel_topic_and_purpose() -> None:
topic = await set_channel_topic("C001", topic="New topic")
assert topic["ok"] is True
assert topic["channel"]["topic"]["value"] == "New topic"
assert topic["channel"]["topic"]["creator"] == "U_MOCK_BOT"
assert topic["channel"]["purpose"]["value"] == "Team comms"
purpose = await set_channel_topic("C001", purpose="New purpose")
assert purpose["channel"]["purpose"]["value"] == "New purpose"
both = await set_channel_topic("C001", topic="T", purpose="P")
assert both["channel"]["topic"]["value"] == "T"
assert both["channel"]["purpose"]["value"] == "P"
assert (await set_channel_topic("INVALID", topic="test"))["error"] == "channel_not_found"