Files
meshcore-bot/tests/unit/test_joke_text.py
T
agessaman 295d757914 refactor(commands): share joke and dadjoke length handling
The two commands carried near-identical copies of fetch-until-short, split-at-a-natural-break and two-part send. modules/joke_text.py now holds them as plain functions (a mixin module under modules/commands would be loaded as a plugin and recorded as a failure). Each command keeps its public method names, its emoji, its own split points (joke also splits on newlines) and its own pause: joke still waits 2 s between the two parts, dadjoke does not. Lengths stay counted in characters against 130, as before.
2026-10-01 02:16:16 -07:00

46 lines
2.2 KiB
Python

"""modules.joke_text: fetch-until-short, split, and two-part send."""
from unittest.mock import AsyncMock, Mock, patch
from modules.joke_text import JOKE_CHAR_LIMIT, fetch_fitting_joke, send_joke, split_joke_text
LONG = "x" * (JOKE_CHAR_LIMIT + 5)
async def test_fetch_retries_until_short_unless_long_allowed():
fetch = AsyncMock(side_effect=[{"t": LONG}, {"t": "short"}])
fmt = lambda d: d["t"] # noqa: E731
assert await fetch_fitting_joke(fetch, fmt, allow_long=False, logger=Mock(), label="joke") == {"t": "short"}
fetch = AsyncMock(return_value={"t": LONG})
assert await fetch_fitting_joke(fetch, fmt, allow_long=True, logger=Mock(), label="joke") == {"t": LONG}
assert fetch.await_count == 1
async def test_fetch_gives_up_with_the_last_long_joke_or_none():
logger = Mock()
fetch = AsyncMock(return_value={"t": LONG})
got = await fetch_fitting_joke(fetch, lambda d: d["t"], allow_long=False, logger=logger, label="dad joke")
assert got == {"t": LONG} and fetch.await_count == 5
logger.warning.assert_called_once_with("Could not get short dad joke after 5 attempts")
assert await fetch_fitting_joke(AsyncMock(return_value=None), str, allow_long=False, logger=logger, label="j") is None
def test_split_prefers_listed_points_then_middle_space():
assert split_joke_text("🎭 Why? Because.", "🎭", ("? ",)) == ["🎭 Why? ", "🎭 Because."]
assert split_joke_text("🥸 aaaa bbbb cccc", "🥸", ()) == ["🥸 aaaa bbbb", "🥸 cccc"]
async def test_send_splits_long_jokes_and_pauses_only_when_asked():
send = AsyncMock()
long_joke = "🎭 " + "a" * 100 + ". " + "b" * 100
with patch("modules.joke_text.asyncio.sleep", AsyncMock()) as sleep:
await send_joke(send, "msg", long_joke, lambda t: split_joke_text(t, "🎭", (". ",)), pause_seconds=2.0)
sleep.assert_awaited_once_with(2.0)
assert send.await_count == 2
assert send.await_args_list[1].kwargs == {"skip_user_rate_limit": True}
send = AsyncMock()
with patch("modules.joke_text.asyncio.sleep", AsyncMock()) as sleep:
await send_joke(send, "msg", "🥸 short", lambda t: [t])
sleep.assert_not_awaited()
send.assert_awaited_once_with("msg", "🥸 short")