signal-bot/tests/test_counting.py
2026-08-29 15:30:08 +02:00

62 lines
1.9 KiB
Python

# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence.
"""Scoping and tally predicates."""
from __future__ import annotations
from typing import TYPE_CHECKING
import pytest
from signal_bot.counting import format_tally, should_count, watched_group
from signal_bot.models import parse_envelope
from tests.conftest import OTHER_GROUP, SECOND_GROUP, WATCHED_GROUP, envelope
if TYPE_CHECKING:
from signal_bot.discovery import GroupDirectory
def _message(**kwargs: object) -> object:
parsed = parse_envelope(envelope(**kwargs))
assert parsed is not None
return parsed
@pytest.mark.parametrize("group", [WATCHED_GROUP, SECOND_GROUP])
async def test_every_watched_group_is_accepted_as_itself(
directory: GroupDirectory, group: str
) -> None:
"""Each watched group resolves to itself, never to the first one listed."""
assert watched_group(_message(group_id=group), directory) == group
async def test_other_group_is_rejected(directory: GroupDirectory) -> None:
assert watched_group(_message(group_id=OTHER_GROUP), directory) is None
async def test_direct_message_is_rejected(directory: GroupDirectory) -> None:
"""The dangerous case: a DM must never reach a handler."""
assert watched_group(_message(group_id=None), directory) is None
def test_plain_text_counts() -> None:
assert should_count(_message(text="hello"))
@pytest.mark.parametrize("kwargs", [{"sticker": True}, {"reaction": True}])
def test_stickers_and_reactions_do_not_count(kwargs: dict[str, bool]) -> None:
assert not should_count(_message(**kwargs))
@pytest.mark.parametrize("text", [None, ""])
def test_empty_text_does_not_count(text: str | None) -> None:
assert not should_count(_message(text=text))
def test_format_tally_pads_names() -> None:
rendered = format_tally([("Alice", 5), ("Bo", 2)])
assert rendered == "Alice 5\nBo 2"
def test_format_tally_when_nobody_spoke() -> None:
assert format_tally([]) == "Brak wiadomosci dzisiaj."