2021-09-07 23:39:58 +02:00
|
|
|
import importlib.resources
|
2021-05-31 01:11:50 +02:00
|
|
|
import os
|
2021-11-11 15:18:04 +01:00
|
|
|
from collections import UserList
|
2021-05-31 01:11:50 +02:00
|
|
|
from datetime import datetime, timedelta, timezone
|
2021-08-29 14:51:52 +02:00
|
|
|
from uuid import UUID
|
2021-05-31 01:11:50 +02:00
|
|
|
|
2021-07-08 10:31:28 +02:00
|
|
|
import arrow
|
2021-05-05 14:29:13 +02:00
|
|
|
import pytest
|
2021-11-11 15:18:04 +01:00
|
|
|
import responses
|
2021-05-31 01:11:50 +02:00
|
|
|
from tortoise.contrib.test import finalizer, initializer
|
2021-05-05 14:29:13 +02:00
|
|
|
|
2021-09-07 23:39:58 +02:00
|
|
|
import mobilizon_reshare
|
2021-11-11 15:18:04 +01:00
|
|
|
from mobilizon_reshare.config.config import get_settings
|
2021-08-16 10:49:52 +02:00
|
|
|
from mobilizon_reshare.event.event import MobilizonEvent, EventPublicationStatus
|
|
|
|
from mobilizon_reshare.models.event import Event
|
|
|
|
from mobilizon_reshare.models.notification import Notification, NotificationStatus
|
|
|
|
from mobilizon_reshare.models.publication import Publication, PublicationStatus
|
|
|
|
from mobilizon_reshare.models.publisher import Publisher
|
2021-11-11 15:18:04 +01:00
|
|
|
from mobilizon_reshare.publishers.abstract import (
|
|
|
|
AbstractPlatform,
|
|
|
|
AbstractEventFormatter,
|
|
|
|
)
|
2021-11-11 16:20:50 +01:00
|
|
|
from mobilizon_reshare.publishers.exceptions import PublisherError, InvalidResponse
|
2021-05-05 14:29:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
def generate_publication_status(published):
|
|
|
|
return PublicationStatus.COMPLETED if published else PublicationStatus.WAITING
|
|
|
|
|
|
|
|
|
2021-07-15 18:13:11 +02:00
|
|
|
def generate_event_status(published):
|
|
|
|
return (
|
|
|
|
EventPublicationStatus.COMPLETED
|
|
|
|
if published
|
|
|
|
else EventPublicationStatus.WAITING
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-05-31 01:11:50 +02:00
|
|
|
def generate_notification_status(published):
|
|
|
|
return NotificationStatus.COMPLETED if published else NotificationStatus.WAITING
|
|
|
|
|
|
|
|
|
2021-09-07 23:39:58 +02:00
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
|
|
def set_dynaconf_environment(request) -> None:
|
|
|
|
os.environ["ENV_FOR_DYNACONF"] = "testing"
|
|
|
|
os.environ["FORCE_ENV_FOR_DYNACONF"] = "testing"
|
|
|
|
|
|
|
|
yield None
|
|
|
|
|
|
|
|
os.environ["ENV_FOR_DYNACONF"] = ""
|
|
|
|
os.environ["FORCE_ENV_FOR_DYNACONF"] = ""
|
|
|
|
|
|
|
|
|
2021-05-05 14:29:13 +02:00
|
|
|
@pytest.fixture
|
|
|
|
def event_generator():
|
|
|
|
def _event_generator(
|
2021-05-30 21:47:36 +02:00
|
|
|
begin_date=arrow.Arrow(year=2021, month=1, day=1, hour=11, minute=30),
|
2021-05-05 14:29:13 +02:00
|
|
|
published=False,
|
|
|
|
publication_time=None,
|
2021-08-29 14:51:52 +02:00
|
|
|
mobilizon_id=UUID(int=12345),
|
2021-05-05 14:29:13 +02:00
|
|
|
):
|
|
|
|
|
|
|
|
return MobilizonEvent(
|
|
|
|
name="test event",
|
|
|
|
description="description of the event",
|
|
|
|
begin_datetime=begin_date,
|
2021-05-30 21:47:36 +02:00
|
|
|
end_datetime=begin_date.shift(hours=2),
|
2021-05-05 14:29:13 +02:00
|
|
|
mobilizon_link="http://some_link.com/123",
|
2021-07-05 23:07:12 +02:00
|
|
|
mobilizon_id=mobilizon_id,
|
2021-05-05 14:29:13 +02:00
|
|
|
thumbnail_link="http://some_link.com/123.jpg",
|
|
|
|
location="location",
|
2021-07-15 18:13:11 +02:00
|
|
|
status=generate_event_status(published),
|
2021-05-05 14:29:13 +02:00
|
|
|
publication_time=publication_time
|
2021-05-30 21:47:36 +02:00
|
|
|
or (begin_date.shift(days=-1) if published else None),
|
2021-05-05 14:29:13 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
return _event_generator
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def event() -> MobilizonEvent:
|
2021-05-31 01:11:50 +02:00
|
|
|
begin_date = arrow.get(
|
|
|
|
datetime(
|
|
|
|
year=2021,
|
|
|
|
month=1,
|
|
|
|
day=1,
|
|
|
|
hour=11,
|
|
|
|
minute=30,
|
|
|
|
tzinfo=timezone(timedelta(hours=1)),
|
|
|
|
)
|
|
|
|
)
|
2021-05-05 14:29:13 +02:00
|
|
|
return MobilizonEvent(
|
|
|
|
name="test event",
|
|
|
|
description="description of the event",
|
2021-05-31 01:11:50 +02:00
|
|
|
begin_datetime=begin_date,
|
|
|
|
end_datetime=begin_date.shift(hours=1),
|
2021-05-05 14:29:13 +02:00
|
|
|
mobilizon_link="http://some_link.com/123",
|
2021-08-29 14:51:52 +02:00
|
|
|
mobilizon_id=UUID(int=12345),
|
2021-05-05 14:29:13 +02:00
|
|
|
thumbnail_link="http://some_link.com/123.jpg",
|
|
|
|
location="location",
|
|
|
|
)
|
2021-05-31 01:11:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
2021-09-07 23:39:58 +02:00
|
|
|
def initialize_db_tests() -> None:
|
2021-05-31 01:11:50 +02:00
|
|
|
db_url = os.environ.get("TORTOISE_TEST_DB", "sqlite://:memory:")
|
|
|
|
initializer(
|
|
|
|
[
|
2021-08-16 10:49:52 +02:00
|
|
|
"mobilizon_reshare.models.event",
|
|
|
|
"mobilizon_reshare.models.notification",
|
|
|
|
"mobilizon_reshare.models.publication",
|
|
|
|
"mobilizon_reshare.models.publisher",
|
2021-05-31 01:11:50 +02:00
|
|
|
],
|
|
|
|
db_url=db_url,
|
|
|
|
app_label="models",
|
|
|
|
)
|
2021-09-07 23:39:58 +02:00
|
|
|
with importlib.resources.path(
|
|
|
|
mobilizon_reshare, ".secrets.toml"
|
|
|
|
) as bundled_secrets_path:
|
|
|
|
os.environ["SECRETS_FOR_DYNACONF"] = str(bundled_secrets_path)
|
|
|
|
|
|
|
|
yield None
|
|
|
|
|
|
|
|
os.environ["SECRETS_FOR_DYNACONF"] = ""
|
|
|
|
finalizer()
|
2021-05-31 01:11:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def event_model_generator():
|
|
|
|
def _event_model_generator(
|
|
|
|
idx=1,
|
|
|
|
begin_date=datetime(
|
|
|
|
year=2021,
|
|
|
|
month=1,
|
|
|
|
day=1,
|
|
|
|
hour=11,
|
|
|
|
minute=30,
|
|
|
|
tzinfo=timezone(timedelta(hours=0)),
|
|
|
|
),
|
|
|
|
):
|
|
|
|
return Event(
|
|
|
|
name=f"event_{idx}",
|
|
|
|
description=f"desc_{idx}",
|
2021-08-29 14:51:52 +02:00
|
|
|
mobilizon_id=UUID(int=idx),
|
2021-05-31 01:11:50 +02:00
|
|
|
mobilizon_link=f"moblink_{idx}",
|
|
|
|
thumbnail_link=f"thumblink_{idx}",
|
|
|
|
location=f"loc_{idx}",
|
|
|
|
begin_datetime=begin_date,
|
|
|
|
end_datetime=begin_date + timedelta(hours=2),
|
|
|
|
)
|
|
|
|
|
|
|
|
return _event_model_generator
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def publisher_model_generator():
|
2021-11-11 15:18:04 +01:00
|
|
|
def _publisher_model_generator(idx=1,):
|
2021-07-05 23:07:12 +02:00
|
|
|
return Publisher(name=f"publisher_{idx}", account_ref=f"account_ref_{idx}")
|
2021-05-31 01:11:50 +02:00
|
|
|
|
|
|
|
return _publisher_model_generator
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def publication_model_generator():
|
|
|
|
def _publication_model_generator(
|
2021-11-11 15:18:04 +01:00
|
|
|
status=PublicationStatus.COMPLETED,
|
2021-05-31 01:11:50 +02:00
|
|
|
publication_time=datetime(year=2021, month=1, day=1, hour=11, minute=30),
|
|
|
|
event_id=None,
|
|
|
|
publisher_id=None,
|
|
|
|
):
|
|
|
|
return Publication(
|
|
|
|
status=status,
|
|
|
|
timestamp=publication_time,
|
|
|
|
event_id=event_id,
|
|
|
|
publisher_id=publisher_id,
|
|
|
|
)
|
|
|
|
|
|
|
|
return _publication_model_generator
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def notification_model_generator():
|
|
|
|
def _notification_model_generator(
|
|
|
|
idx=1, published=False, publication_id=None, target_id=None
|
|
|
|
):
|
|
|
|
return Notification(
|
|
|
|
status=generate_notification_status(published),
|
|
|
|
message=f"message_{idx}",
|
|
|
|
publication_id=publication_id,
|
|
|
|
target_id=target_id,
|
|
|
|
)
|
|
|
|
|
|
|
|
return _notification_model_generator
|
2021-11-11 15:18:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def message_collector():
|
|
|
|
class MessageCollector(UserList):
|
|
|
|
def collect_message(self, message):
|
|
|
|
self.append(message)
|
|
|
|
|
|
|
|
return MessageCollector()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_publisher_class(message_collector):
|
|
|
|
class MockPublisher(AbstractPlatform):
|
|
|
|
name = "mock"
|
|
|
|
|
2021-11-20 15:40:10 +01:00
|
|
|
def _send(self, message, event):
|
2021-11-11 15:18:04 +01:00
|
|
|
message_collector.append(message)
|
|
|
|
|
|
|
|
def _validate_response(self, response):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def validate_credentials(self) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return MockPublisher
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_publisher_valid(message_collector, mock_publisher_class):
|
|
|
|
|
|
|
|
return mock_publisher_class()
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mobilizon_url():
|
|
|
|
return get_settings()["source"]["mobilizon"]["url"]
|
|
|
|
|
|
|
|
|
|
|
|
@responses.activate
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_mobilizon_success_answer(mobilizon_answer, mobilizon_url):
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
|
|
|
|
|
|
rsps.add(
|
|
|
|
responses.POST, mobilizon_url, json=mobilizon_answer, status=200,
|
|
|
|
)
|
|
|
|
yield
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_publication_window(publication_window):
|
|
|
|
begin, end = publication_window
|
|
|
|
get_settings().update(
|
|
|
|
{"publishing.window.begin": begin, "publishing.window.end": end}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_formatter_class():
|
|
|
|
class MockFormatter(AbstractEventFormatter):
|
|
|
|
def validate_event(self, event) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def get_message_from_event(self, event) -> str:
|
|
|
|
return f"{event.name}|{event.description}"
|
|
|
|
|
|
|
|
def validate_message(self, event) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def get_recap_fragment(self, event):
|
|
|
|
return event.name
|
|
|
|
|
|
|
|
def get_recap_header(self):
|
|
|
|
return "Upcoming"
|
|
|
|
|
|
|
|
return MockFormatter
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_formatter_valid(mock_formatter_class):
|
|
|
|
|
|
|
|
return mock_formatter_class()
|
2021-11-11 16:20:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_publisher_invalid_class(message_collector):
|
|
|
|
class MockPublisher(AbstractPlatform):
|
|
|
|
|
|
|
|
name = "mock"
|
|
|
|
|
2021-11-20 15:40:10 +01:00
|
|
|
def _send(self, message, event):
|
2021-11-11 16:20:50 +01:00
|
|
|
message_collector.append(message)
|
|
|
|
|
|
|
|
def _validate_response(self, response):
|
|
|
|
return InvalidResponse("response error")
|
|
|
|
|
|
|
|
def validate_credentials(self) -> None:
|
|
|
|
raise PublisherError("credentials error")
|
|
|
|
|
|
|
|
return MockPublisher
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def mock_publisher_invalid(mock_publisher_invalid_class):
|
|
|
|
|
|
|
|
return mock_publisher_invalid_class()
|