forked from LiveCarta/ContentAutomation
119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from content_automation.adapters.storage.base import StorageAdapterBase
|
|
from content_automation.controller import PublishController
|
|
from content_automation.models import PublishedContentRecord
|
|
from content_automation.settings import AppSettings
|
|
|
|
|
|
class FakeStorage(StorageAdapterBase):
|
|
def __init__(
|
|
self, exists_result: bool, public_url: str = "file:///tmp/video.mp4"
|
|
) -> None:
|
|
self._exists_result = exists_result
|
|
self._public_url = public_url
|
|
|
|
def exists(self, relative_path: str) -> bool:
|
|
return self._exists_result
|
|
|
|
def get_public_url(self, relative_path: str) -> str:
|
|
return self._public_url
|
|
|
|
|
|
class FakeAdapter:
|
|
def __init__(self, adapter_name: str) -> None:
|
|
self.name = adapter_name
|
|
|
|
def post_media(self, media_url: str, caption: str) -> str:
|
|
return f"{self.name}-post-id"
|
|
|
|
|
|
class FakeAdapterWithResponsePayload:
|
|
def __init__(self, payload: object) -> None:
|
|
self.name = "adapter-with-payload"
|
|
self._payload = payload
|
|
|
|
def post_media(self, media_url: str, caption: str) -> object:
|
|
return self._payload
|
|
|
|
|
|
class FakePublishedContentStore:
|
|
def __init__(self) -> None:
|
|
self.records: list[PublishedContentRecord] = []
|
|
|
|
def save(self, record: PublishedContentRecord) -> None:
|
|
self.records.append(record)
|
|
|
|
|
|
def test_controller_publishes_to_all_configured_networks() -> None:
|
|
settings = AppSettings.model_validate(
|
|
{"target_social_networks": ["instagram", "youtube"]}
|
|
)
|
|
controller = PublishController(
|
|
settings=settings,
|
|
storage=FakeStorage(exists_result=True),
|
|
social_adapters={
|
|
"instagram": FakeAdapter("instagram"),
|
|
"youtube": FakeAdapter("youtube"),
|
|
},
|
|
)
|
|
|
|
result = controller.publish(relative_path="video.mp4", caption="hello")
|
|
|
|
assert result == {"instagram": "instagram-post-id", "youtube": "youtube-post-id"}
|
|
|
|
|
|
def test_controller_stores_published_content_with_youtube_id_only() -> None:
|
|
settings = AppSettings.model_validate(
|
|
{"target_social_networks": ["instagram", "youtube"]}
|
|
)
|
|
published_content_store = FakePublishedContentStore()
|
|
controller = PublishController(
|
|
settings=settings,
|
|
storage=FakeStorage(exists_result=True),
|
|
social_adapters={
|
|
"instagram": FakeAdapterWithResponsePayload(
|
|
{"id": "ig-123", "status": "ok"}
|
|
),
|
|
"youtube": FakeAdapterWithResponsePayload(
|
|
{
|
|
"id": "yt-456",
|
|
"kind": "youtube#video",
|
|
"snippet": {"title": "hello"},
|
|
}
|
|
),
|
|
},
|
|
published_content_store=published_content_store,
|
|
)
|
|
|
|
result = controller.publish(relative_path="video.mp4", caption="hello")
|
|
|
|
assert result["youtube"] == {
|
|
"id": "yt-456",
|
|
"kind": "youtube#video",
|
|
"snippet": {"title": "hello"},
|
|
}
|
|
assert len(published_content_store.records) == 1
|
|
saved_record = published_content_store.records[0]
|
|
assert saved_record.relative_path == "video.mp4"
|
|
assert saved_record.caption == "hello"
|
|
assert saved_record.platform_responses["instagram"] == {
|
|
"id": "ig-123",
|
|
"status": "ok",
|
|
}
|
|
assert saved_record.platform_responses["youtube"] == "yt-456"
|
|
|
|
|
|
def test_controller_raises_when_file_missing() -> None:
|
|
settings = AppSettings.model_validate({"target_social_networks": ["youtube"]})
|
|
controller = PublishController(
|
|
settings=settings,
|
|
storage=FakeStorage(exists_result=False),
|
|
social_adapters={"youtube": FakeAdapter("youtube")},
|
|
)
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
controller.publish(relative_path="video.mp4", caption="hello")
|