"""Tests for the chanmgmt plugin (invite-join).""" import asyncio import importlib.util import sys from pathlib import Path from derp.irc import Message # plugins/ is not a Python package -- load the module from file path _spec = importlib.util.spec_from_file_location( "plugins.chanmgmt", Path(__file__).resolve().parent.parent / "plugins" / "chanmgmt.py", ) _mod = importlib.util.module_from_spec(_spec) sys.modules[_spec.name] = _mod _spec.loader.exec_module(_mod) from plugins.chanmgmt import on_invite # noqa: E402 # isort: skip # -- Helpers ----------------------------------------------------------------- class _FakeConn: """Minimal connection stand-in.""" def __init__(self): self.sent: list[str] = [] async def send(self, raw: str) -> None: self.sent.append(raw) class _FakeState: """In-memory stand-in for bot.state.""" def __init__(self): self._store: dict[str, dict[str, str]] = {} def get(self, plugin: str, key: str, default: str | None = None) -> str | None: return self._store.get(plugin, {}).get(key, default) def set(self, plugin: str, key: str, value: str) -> None: self._store.setdefault(plugin, {})[key] = value def delete(self, plugin: str, key: str) -> bool: try: del self._store[plugin][key] return True except KeyError: return False class _FakeBot: """Minimal bot stand-in.""" def __init__(self, *, admin: bool = False): self.joined: list[str] = [] self._admin = admin self.conn = _FakeConn() self.state = _FakeState() def _is_admin(self, message) -> bool: return self._admin async def join(self, channel: str) -> None: self.joined.append(channel) def _invite(nick: str, channel: str) -> Message: """Create an INVITE message: :nick!user@host INVITE botname #channel.""" return Message( raw="", prefix=f"{nick}!~{nick}@host", nick=nick, command="INVITE", params=["derp", channel], tags={}, ) # -- Tests ------------------------------------------------------------------- class TestOnInvite: def test_admin_joins(self): bot = _FakeBot(admin=True) asyncio.run(on_invite(bot, _invite("oper", "#secret"))) assert "#secret" in bot.joined def test_non_admin_ignored(self): bot = _FakeBot(admin=False) asyncio.run(on_invite(bot, _invite("rando", "#trap"))) assert bot.joined == [] def test_missing_channel_ignored(self): bot = _FakeBot(admin=True) msg = Message( raw="", prefix="oper!~oper@host", nick="oper", command="INVITE", params=["derp"], tags={}, ) asyncio.run(on_invite(bot, msg)) assert bot.joined == []