mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-10 20:17:02 +01:00
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
Python
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."
|