diff --git a/mobilizon_reshare/publishers/abstract.py b/mobilizon_reshare/publishers/abstract.py index 53ceca2..4f507d4 100644 --- a/mobilizon_reshare/publishers/abstract.py +++ b/mobilizon_reshare/publishers/abstract.py @@ -169,6 +169,13 @@ class AbstractEventFormatter(LoggerMixin, ConfLoaderMixin): return False return True + def get_recap_header(self): + template_path = ( + self.conf.recap_header_template_path + or self.default_recap_header_template_path + ) + return JINJA_ENV.get_template(template_path).render() + def get_recap_fragment_template(self) -> Template: template_path = ( self.conf.recap_template_path or self.default_recap_template_path diff --git a/mobilizon_reshare/publishers/coordinator.py b/mobilizon_reshare/publishers/coordinator.py index 4cb74dd..19e2acd 100644 --- a/mobilizon_reshare/publishers/coordinator.py +++ b/mobilizon_reshare/publishers/coordinator.py @@ -176,7 +176,7 @@ class RecapCoordinator: for recap_publication in self.recap_publications: try: - fragments = [] + fragments = [recap_publication.formatter.get_recap_header()] for event in recap_publication.events: fragments.append( recap_publication.formatter.get_recap_fragment(event) diff --git a/mobilizon_reshare/publishers/platforms/telegram.py b/mobilizon_reshare/publishers/platforms/telegram.py index 20e76ca..e400517 100644 --- a/mobilizon_reshare/publishers/platforms/telegram.py +++ b/mobilizon_reshare/publishers/platforms/telegram.py @@ -25,6 +25,10 @@ class TelegramFormatter(AbstractEventFormatter): "mobilizon_reshare.publishers.templates", "telegram_recap.tmpl.j2" ) + default_recap_header_template_path = pkg_resources.resource_filename( + "mobilizon_reshare.publishers.templates", "telegram_recap_header.tmpl.j2" + ) + _conf = ("publisher", "telegram") @staticmethod diff --git a/mobilizon_reshare/publishers/platforms/twitter.py b/mobilizon_reshare/publishers/platforms/twitter.py index cba72ae..bd608a6 100644 --- a/mobilizon_reshare/publishers/platforms/twitter.py +++ b/mobilizon_reshare/publishers/platforms/twitter.py @@ -25,6 +25,10 @@ class TwitterFormatter(AbstractEventFormatter): "mobilizon_reshare.publishers.templates", "twitter_recap.tmpl.j2" ) + default_recap_header_template_path = pkg_resources.resource_filename( + "mobilizon_reshare.publishers.templates", "twitter_recap_header.tmpl.j2" + ) + def validate_event(self, event: MobilizonEvent) -> None: text = event.description if not (text and text.strip()): diff --git a/mobilizon_reshare/publishers/platforms/zulip.py b/mobilizon_reshare/publishers/platforms/zulip.py index 6ebf1a7..f74cbfc 100644 --- a/mobilizon_reshare/publishers/platforms/zulip.py +++ b/mobilizon_reshare/publishers/platforms/zulip.py @@ -29,6 +29,10 @@ class ZulipFormatter(AbstractEventFormatter): "mobilizon_reshare.publishers.templates", "zulip_recap.tmpl.j2" ) + default_recap_header_template_path = pkg_resources.resource_filename( + "mobilizon_reshare.publishers.templates", "zulip_recap_header.tmpl.j2" + ) + def validate_event(self, event: MobilizonEvent) -> None: text = event.description if not (text and text.strip()): diff --git a/mobilizon_reshare/publishers/templates/telegram_recap_header.tmpl.j2 b/mobilizon_reshare/publishers/templates/telegram_recap_header.tmpl.j2 new file mode 100644 index 0000000..a65d634 --- /dev/null +++ b/mobilizon_reshare/publishers/templates/telegram_recap_header.tmpl.j2 @@ -0,0 +1 @@ +Upcoming events \ No newline at end of file diff --git a/mobilizon_reshare/publishers/templates/twitter_recap_header.tmpl.j2 b/mobilizon_reshare/publishers/templates/twitter_recap_header.tmpl.j2 new file mode 100644 index 0000000..a65d634 --- /dev/null +++ b/mobilizon_reshare/publishers/templates/twitter_recap_header.tmpl.j2 @@ -0,0 +1 @@ +Upcoming events \ No newline at end of file diff --git a/mobilizon_reshare/publishers/templates/zulip_recap_header.tmpl.j2 b/mobilizon_reshare/publishers/templates/zulip_recap_header.tmpl.j2 new file mode 100644 index 0000000..a65d634 --- /dev/null +++ b/mobilizon_reshare/publishers/templates/zulip_recap_header.tmpl.j2 @@ -0,0 +1 @@ +Upcoming events \ No newline at end of file diff --git a/tests/publishers/conftest.py b/tests/publishers/conftest.py index bacfd9b..27afbf8 100644 --- a/tests/publishers/conftest.py +++ b/tests/publishers/conftest.py @@ -1,3 +1,4 @@ +from collections import UserList from datetime import timedelta from uuid import UUID @@ -45,9 +46,21 @@ def mock_formatter_valid(): def get_recap_fragment(self, event): return event.name + def get_recap_header(self): + return "Upcoming" + return MockFormatter() +@pytest.fixture() +def message_collector(): + class MessageCollector(UserList): + def collect_message(self, message): + self.append(message) + + return MessageCollector() + + @pytest.fixture def mock_formatter_invalid(): class MockFormatter(AbstractEventFormatter): @@ -64,10 +77,10 @@ def mock_formatter_invalid(): @pytest.fixture -def mock_publisher_valid(): +def mock_publisher_valid(message_collector): class MockPublisher(AbstractPlatform): def _send(self, message): - pass + message_collector.collect_message(message) def _validate_response(self, response): pass @@ -79,10 +92,11 @@ def mock_publisher_valid(): @pytest.fixture -def mock_publisher_invalid(): +def mock_publisher_invalid(message_collector): class MockPublisher(AbstractPlatform): def _send(self, message): - pass + + message_collector.collect_message(message) def _validate_response(self, response): return InvalidResponse("error") @@ -94,10 +108,10 @@ def mock_publisher_invalid(): @pytest.fixture -def mock_publisher_invalid_response(): +def mock_publisher_invalid_response(message_collector): class MockPublisher(AbstractPlatform): def _send(self, message): - pass + message_collector.collect_message(message) def _validate_response(self, response): raise InvalidResponse("Invalid response") diff --git a/tests/publishers/test_coordinator.py b/tests/publishers/test_coordinator.py index 8e2a006..bbfb71e 100644 --- a/tests/publishers/test_coordinator.py +++ b/tests/publishers/test_coordinator.py @@ -155,8 +155,17 @@ async def test_notifier_coordinator_publication_failed(mock_publisher_valid): @pytest.mark.parametrize("num_publications", [2]) @pytest.mark.asyncio -async def test_recap_coordinator_run_success(mock_recap_publications,): +async def test_recap_coordinator_run_success( + mock_recap_publications, message_collector +): coordinator = RecapCoordinator(recap_publications=mock_recap_publications) report = coordinator.run() + + # one recap per publication + assert len(message_collector) == 2 + + # check that header is in all messages + assert all(("Upcoming" in message) for message in message_collector) + assert len(report.reports) == 2 assert report.successful, "\n".join(map(lambda rep: rep.reason, report.reports))