edd3eee178
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}`.
164 lines
5.5 KiB
Python
164 lines
5.5 KiB
Python
"""Tests for report utility functions."""
|
|
|
|
import pytest
|
|
|
|
from community.helpers.report_utils import (
|
|
generate_activity_report, split_doctor_report, format_ban_results,
|
|
format_sync_results
|
|
)
|
|
|
|
|
|
class TestReportUtils:
|
|
"""Test cases for report utility functions."""
|
|
|
|
def test_generate_activity_report_success(self):
|
|
"""Test generating activity report successfully."""
|
|
database_results = {
|
|
"active": [{"mxid": "@user1:example.com"}, {"mxid": "@user2:example.com"}],
|
|
"inactive": [{"mxid": "@user3:example.com"}],
|
|
"ignored": [{"mxid": "@user4:example.com"}]
|
|
}
|
|
|
|
result = generate_activity_report(database_results)
|
|
|
|
assert result["active"] == ["@user1:example.com", "@user2:example.com"]
|
|
assert result["inactive"] == ["@user3:example.com"]
|
|
assert result["ignored"] == ["@user4:example.com"]
|
|
|
|
def test_generate_activity_report_empty(self):
|
|
"""Test generating activity report with empty results."""
|
|
database_results = {
|
|
"active": [],
|
|
"inactive": [],
|
|
"ignored": []
|
|
}
|
|
|
|
result = generate_activity_report(database_results)
|
|
|
|
assert result["active"] == ["none"]
|
|
assert result["inactive"] == ["none"]
|
|
assert result["ignored"] == ["none"]
|
|
|
|
def test_generate_activity_report_missing_keys(self):
|
|
"""Test generating activity report with missing keys."""
|
|
database_results = {}
|
|
|
|
result = generate_activity_report(database_results)
|
|
|
|
assert result["active"] == ["none"]
|
|
assert result["inactive"] == ["none"]
|
|
assert result["ignored"] == ["none"]
|
|
|
|
def test_split_doctor_report_small(self):
|
|
"""Test splitting small report that doesn't need splitting."""
|
|
report_text = "This is a small report that fits in one chunk."
|
|
|
|
result = split_doctor_report(report_text, 1000)
|
|
|
|
assert len(result) == 1
|
|
assert result[0] == report_text
|
|
|
|
def test_split_doctor_report_large(self):
|
|
"""Test splitting large report into chunks."""
|
|
# Create a large report
|
|
lines = [f"Line {i}: This is a test line for splitting" for i in range(100)]
|
|
report_text = "\n".join(lines)
|
|
|
|
result = split_doctor_report(report_text, 100) # Small chunk size
|
|
|
|
assert len(result) > 1
|
|
assert all(len(chunk) <= 100 for chunk in result)
|
|
|
|
# Verify all content is preserved (account for newlines)
|
|
combined = "\n".join(result)
|
|
assert combined == report_text
|
|
|
|
def test_split_doctor_report_with_sections(self):
|
|
"""Test splitting report with section headers."""
|
|
report_text = """<h3>Section 1</h3>
|
|
This is section 1 content.
|
|
<h3>Section 2</h3>
|
|
This is section 2 content.
|
|
<h3>Section 3</h3>
|
|
This is section 3 content."""
|
|
|
|
result = split_doctor_report(report_text, 50) # Small chunk size
|
|
|
|
assert len(result) > 1
|
|
assert all(len(chunk) <= 50 for chunk in result)
|
|
|
|
def test_format_ban_results_success(self):
|
|
"""Test formatting ban results with successful bans."""
|
|
ban_event_map = {
|
|
"ban_list": {
|
|
"@user1:example.com": ["Room 1", "Room 2"],
|
|
"@user2:example.com": ["Room 3"]
|
|
},
|
|
"error_list": {}
|
|
}
|
|
|
|
result = format_ban_results(ban_event_map)
|
|
|
|
assert "Banned @user1:example.com from: Room 1, Room 2" in result
|
|
assert "Banned @user2:example.com from: Room 3" in result
|
|
|
|
def test_format_ban_results_with_errors(self):
|
|
"""Test formatting ban results with errors."""
|
|
ban_event_map = {
|
|
"ban_list": {
|
|
"@user1:example.com": ["Room 1"]
|
|
},
|
|
"error_list": {
|
|
"@user2:example.com": ["Room 2", "Room 3"]
|
|
}
|
|
}
|
|
|
|
result = format_ban_results(ban_event_map)
|
|
|
|
assert "Banned @user1:example.com from: Room 1" in result
|
|
assert "Failed to ban @user2:example.com from: Room 2, Room 3" in result
|
|
|
|
def test_format_ban_results_empty(self):
|
|
"""Test formatting empty ban results."""
|
|
ban_event_map = {
|
|
"ban_list": {},
|
|
"error_list": {}
|
|
}
|
|
|
|
result = format_ban_results(ban_event_map)
|
|
|
|
assert result == "No ban operations performed"
|
|
|
|
def test_format_sync_results_success(self):
|
|
"""Test formatting sync results with data."""
|
|
sync_results = {
|
|
"added": ["@user1:example.com", "@user2:example.com"],
|
|
"dropped": ["@user3:example.com"]
|
|
}
|
|
|
|
result = format_sync_results(sync_results)
|
|
|
|
assert "Added: @user1:example.com<br />@user2:example.com" in result
|
|
assert "Dropped: @user3:example.com" in result
|
|
|
|
def test_format_sync_results_empty(self):
|
|
"""Test formatting empty sync results."""
|
|
sync_results = {
|
|
"added": [],
|
|
"dropped": []
|
|
}
|
|
|
|
result = format_sync_results(sync_results)
|
|
|
|
assert "Added: none" in result
|
|
assert "Dropped: none" in result
|
|
|
|
def test_format_sync_results_missing_keys(self):
|
|
"""Test formatting sync results with missing keys."""
|
|
sync_results = {}
|
|
|
|
result = format_sync_results(sync_results)
|
|
|
|
assert "Added: none" in result
|
|
assert "Dropped: none" in result
|