Files
Advanced-Community-Bot/tests/test_template_rendering.py
Dome edd3eee178 feat: native matrix URI pills for {user}/{room} + major rendering & codebase refactor
This change introduces native `matrix:` URI-based rendering for `{user}` and `{room}` placeholders,
replacing previous plaintext and matrix.to-based links. Users and rooms are now rendered as clickable
pills in supporting clients, with a clean display using display names and room names (no @/# prefixes).

Reporting, moderation, and auto-redaction messages have been updated to use the same rendering logic.
Inspect and event links now also use native `matrix:` URIs for direct in-client navigation.

Internally, URI generation and rendering logic have been unified via central helper functions,
ensuring consistent handling of user IDs, room IDs, aliases, and event IDs.

This commit also includes a broader refactor of the codebase:
- decomposed complex flows (e.g. join handling) into smaller helpers
- moved mutable class-level state to instance-level
- reduced duplicate API calls and redundant logic
- improved overall structure and maintainability

Test coverage has been extended for URI helpers and rendering logic to prevent regressions.

No breaking changes to existing template parameters like `{user_link}` or `{room_link}`.
2026-04-11 20:21:33 +02:00

105 lines
3.4 KiB
Python

"""Tests for notification and greeting template rendering."""
from unittest.mock import AsyncMock, Mock
import pytest
from mautrix.types import EventType, RoomID
from community.bot import CommunityBot
@pytest.fixture
def bot():
bot = CommunityBot.__new__(CommunityBot)
bot.client = Mock()
bot.config = {
"matrix_to_base_url": "https://matrix.to",
"user_pill_prefix": "@",
"room_pill_prefix": "#",
}
return bot
@pytest.mark.asyncio
async def test_get_user_display_name_uses_member_displayname(bot):
member_state = Mock()
member_state.displayname = "Alice"
bot.client.get_state_event = AsyncMock(return_value=member_state)
result = await bot._get_user_display_name(RoomID("!room:example.org"), "@alice:example.org")
assert result == "Alice"
bot.client.get_state_event.assert_awaited_once_with(
RoomID("!room:example.org"),
EventType.ROOM_MEMBER,
state_key="@alice:example.org",
)
@pytest.mark.asyncio
async def test_get_user_display_name_falls_back_to_localpart(bot):
bot.client.get_state_event = AsyncMock(side_effect=Exception("missing"))
bot.client.parse_user_id = Mock(return_value=("alice", "example.org"))
result = await bot._get_user_display_name(RoomID("!room:example.org"), "@alice:example.org")
assert result == "alice"
def test_render_message_template_supports_user_id_and_user_link(bot):
plain, html = bot._render_message_template(
"{user} / {user_id} / {user_link}",
"@alice:example.org",
"Alice",
"!room:example.org",
"General",
)
assert plain == "@Alice / @alice:example.org / https://matrix.to/#/@alice:example.org"
assert "@Alice / @alice:example.org / " in html
assert '<a href=' in html
assert '>Alice</a>' in html
def test_render_message_template_uses_configurable_user_and_room_pill_prefixes(bot):
bot.config["user_pill_prefix"] = ""
bot.config["room_pill_prefix"] = ""
plain, html = bot._render_message_template(
"{user} has joined {room}.",
"@alice:example.org",
"Alice",
"!room:example.org",
"General",
)
assert plain == "Alice has joined General."
assert "<a href='matrix:u/alice:example.org?action=chat'>Alice</a>" in html
assert "<a href='matrix:roomid/room:example.org'>General</a>" in html
def test_render_message_template_defaults_to_prefixed_user_and_room_pills(bot):
plain, html = bot._render_message_template(
"{user} has joined {room}.",
"@alice:example.org",
"Alice",
"!room:example.org",
"General",
)
assert plain == "@Alice has joined #General."
assert "<a href='matrix:u/alice:example.org?action=chat'>@Alice</a>" in html
assert "<a href='matrix:roomid/room:example.org'>#General</a>" in html
def test_matrix_uri_helpers_are_consistent():
from community.bot import CommunityBot
bot = CommunityBot.__new__(CommunityBot)
bot.config = {}
assert bot._matrix_user_uri("@alice:example.org") == "matrix:u/alice:example.org?action=chat"
assert bot._matrix_room_uri("!roomid:example.org", "#general:example.org") == "matrix:r/general:example.org"
assert bot._matrix_room_uri("!roomid:example.org", None) == "matrix:roomid/roomid:example.org"
assert bot._matrix_event_uri("!roomid:example.org", "$eventid") == "matrix:roomid/roomid:example.org/e/eventid"